Get rid of check_opaque_type_well_formed

This commit is contained in:
Michael Goulet 2024-11-08 03:46:23 +00:00
parent b91a3a0560
commit e4c1a0016c
25 changed files with 247 additions and 412 deletions

View File

@ -1,10 +1,7 @@
use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::ErrorGuaranteed; use rustc_errors::ErrorGuaranteed;
use rustc_hir::OpaqueTyOrigin;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LocalDefId;
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _}; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _};
use rustc_infer::traits::{Obligation, ObligationCause};
use rustc_macros::extension; use rustc_macros::extension;
use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{ use rustc_middle::ty::{
@ -12,7 +9,6 @@
TypingMode, TypingMode,
}; };
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::ObligationCtxt;
use tracing::{debug, instrument}; use tracing::{debug, instrument};
@ -303,91 +299,7 @@ fn infer_opaque_definition_from_instantiation(
return Ty::new_error(self.tcx, e); return Ty::new_error(self.tcx, e);
} }
// `definition_ty` does not live in of the current inference context, definition_ty
// so lets make sure that we don't accidentally misuse our current `infcx`.
match check_opaque_type_well_formed(
self.tcx,
self.next_trait_solver(),
opaque_type_key.def_id,
instantiated_ty.span,
definition_ty,
) {
Ok(hidden_ty) => hidden_ty,
Err(guar) => Ty::new_error(self.tcx, guar),
}
}
}
/// This logic duplicates most of `check_opaque_meets_bounds`.
/// FIXME(oli-obk): Also do region checks here and then consider removing
/// `check_opaque_meets_bounds` entirely.
fn check_opaque_type_well_formed<'tcx>(
tcx: TyCtxt<'tcx>,
next_trait_solver: bool,
def_id: LocalDefId,
definition_span: Span,
definition_ty: Ty<'tcx>,
) -> Result<Ty<'tcx>, ErrorGuaranteed> {
// Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs`
// on stable and we'd break that.
let opaque_ty_hir = tcx.hir().expect_opaque_ty(def_id);
let OpaqueTyOrigin::TyAlias { .. } = opaque_ty_hir.origin else {
return Ok(definition_ty);
};
let param_env = tcx.param_env(def_id);
let mut parent_def_id = def_id;
while tcx.def_kind(parent_def_id) == DefKind::OpaqueTy {
parent_def_id = tcx.local_parent(parent_def_id);
}
// FIXME(#132279): This should eventually use the already defined hidden types
// instead. Alternatively we'll entirely remove this function given we also check
// the opaque in `check_opaque_meets_bounds` later.
let infcx = tcx
.infer_ctxt()
.with_next_trait_solver(next_trait_solver)
.build(TypingMode::analysis_in_body(tcx, parent_def_id));
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let identity_args = GenericArgs::identity_for_item(tcx, def_id);
// Require that the hidden type actually fulfills all the bounds of the opaque type, even without
// the bounds that the function supplies.
let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), identity_args);
ocx.eq(&ObligationCause::misc(definition_span, def_id), param_env, opaque_ty, definition_ty)
.map_err(|err| {
infcx
.err_ctxt()
.report_mismatched_types(
&ObligationCause::misc(definition_span, def_id),
param_env,
opaque_ty,
definition_ty,
err,
)
.emit()
})?;
// Require the hidden type to be well-formed with only the generics of the opaque type.
// Defining use functions may have more bounds than the opaque type, which is ok, as long as the
// hidden type is well formed even without those bounds.
let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
definition_ty.into(),
)));
ocx.register_obligation(Obligation::misc(tcx, definition_span, def_id, param_env, predicate));
// Check that all obligations are satisfied by the implementation's
// version.
let errors = ocx.select_all_or_error();
// This is fishy, but we check it again in `check_opaque_meets_bounds`.
// Remove once we can prepopulate with known hidden types.
let _ = infcx.take_opaque_types();
if errors.is_empty() {
Ok(definition_ty)
} else {
Err(infcx.err_ctxt().report_fulfillment_errors(errors))
} }
} }

View File

@ -5,13 +5,14 @@
use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_errors::MultiSpan; use rustc_errors::MultiSpan;
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_hir::Node;
use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::{Node, intravisit};
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
use rustc_infer::traits::Obligation; use rustc_infer::traits::Obligation;
use rustc_lint_defs::builtin::{ use rustc_lint_defs::builtin::{
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS,
}; };
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
use rustc_middle::middle::stability::EvalResult; use rustc_middle::middle::stability::EvalResult;
use rustc_middle::span_bug; use rustc_middle::span_bug;
@ -190,7 +191,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
/// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo` /// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
/// projections that would result in "inheriting lifetimes". /// projections that would result in "inheriting lifetimes".
fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) { fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let hir::OpaqueTy { origin, .. } = tcx.hir().expect_opaque_ty(def_id); let hir::OpaqueTy { origin, .. } = *tcx.hir().expect_opaque_ty(def_id);
// HACK(jynelson): trying to infer the type of `impl trait` breaks documenting // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
// `async-std` (and `pub async fn` in general). // `async-std` (and `pub async fn` in general).
@ -200,23 +201,20 @@ fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) {
return; return;
} }
let span = tcx.def_span(def_id);
if tcx.type_of(def_id).instantiate_identity().references_error() { if tcx.type_of(def_id).instantiate_identity().references_error() {
return; return;
} }
if check_opaque_for_cycles(tcx, def_id, span).is_err() { if check_opaque_for_cycles(tcx, def_id).is_err() {
return; return;
} }
let _ = check_opaque_meets_bounds(tcx, def_id, span, origin); let _ = check_opaque_meets_bounds(tcx, def_id, origin);
} }
/// Checks that an opaque type does not contain cycles. /// Checks that an opaque type does not contain cycles.
pub(super) fn check_opaque_for_cycles<'tcx>( pub(super) fn check_opaque_for_cycles<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
def_id: LocalDefId, def_id: LocalDefId,
span: Span,
) -> Result<(), ErrorGuaranteed> { ) -> Result<(), ErrorGuaranteed> {
let args = GenericArgs::identity_for_item(tcx, def_id); let args = GenericArgs::identity_for_item(tcx, def_id);
@ -233,7 +231,7 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
.try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::No) .try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::No)
.is_err() .is_err()
{ {
let reported = opaque_type_cycle_error(tcx, def_id, span); let reported = opaque_type_cycle_error(tcx, def_id);
return Err(reported); return Err(reported);
} }
@ -267,10 +265,11 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
fn check_opaque_meets_bounds<'tcx>( fn check_opaque_meets_bounds<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
def_id: LocalDefId, def_id: LocalDefId,
span: Span, origin: hir::OpaqueTyOrigin<LocalDefId>,
origin: &hir::OpaqueTyOrigin<LocalDefId>,
) -> Result<(), ErrorGuaranteed> { ) -> Result<(), ErrorGuaranteed> {
let defining_use_anchor = match *origin { let span = span_of_opaque(tcx, def_id, origin).unwrap_or_else(|| tcx.def_span(def_id));
let defining_use_anchor = match origin {
hir::OpaqueTyOrigin::FnReturn { parent, .. } hir::OpaqueTyOrigin::FnReturn { parent, .. }
| hir::OpaqueTyOrigin::AsyncFn { parent, .. } | hir::OpaqueTyOrigin::AsyncFn { parent, .. }
| hir::OpaqueTyOrigin::TyAlias { parent, .. } => parent, | hir::OpaqueTyOrigin::TyAlias { parent, .. } => parent,
@ -281,7 +280,7 @@ fn check_opaque_meets_bounds<'tcx>(
let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, defining_use_anchor)); let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, defining_use_anchor));
let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let args = match *origin { let args = match origin {
hir::OpaqueTyOrigin::FnReturn { parent, .. } hir::OpaqueTyOrigin::FnReturn { parent, .. }
| hir::OpaqueTyOrigin::AsyncFn { parent, .. } | hir::OpaqueTyOrigin::AsyncFn { parent, .. }
| hir::OpaqueTyOrigin::TyAlias { parent, .. } => GenericArgs::identity_for_item( | hir::OpaqueTyOrigin::TyAlias { parent, .. } => GenericArgs::identity_for_item(
@ -308,6 +307,7 @@ fn check_opaque_meets_bounds<'tcx>(
let misc_cause = traits::ObligationCause::misc(span, def_id); let misc_cause = traits::ObligationCause::misc(span, def_id);
// FIXME: We should just register the item bounds here, rather than equating.
match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) { match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) {
Ok(()) => {} Ok(()) => {}
Err(ty_err) => { Err(ty_err) => {
@ -364,6 +364,97 @@ fn check_opaque_meets_bounds<'tcx>(
} }
} }
fn span_of_opaque<'tcx>(
tcx: TyCtxt<'tcx>,
opaque_def_id: LocalDefId,
origin: hir::OpaqueTyOrigin<LocalDefId>,
) -> Option<Span> {
struct TaitConstraintLocator<'tcx> {
opaque_def_id: LocalDefId,
tcx: TyCtxt<'tcx>,
}
impl<'tcx> TaitConstraintLocator<'tcx> {
fn check(&self, item_def_id: LocalDefId) -> ControlFlow<Span> {
if !self.tcx.has_typeck_results(item_def_id) {
return ControlFlow::Continue(());
}
if let Some(hidden_ty) =
self.tcx.mir_borrowck(item_def_id).concrete_opaque_types.get(&self.opaque_def_id)
{
ControlFlow::Break(hidden_ty.span)
} else {
ControlFlow::Continue(())
}
}
}
impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
type NestedFilter = nested_filter::All;
type Result = ControlFlow<Span>;
fn nested_visit_map(&mut self) -> Self::Map {
self.tcx.hir()
}
fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) -> Self::Result {
if let hir::ExprKind::Closure(closure) = ex.kind {
self.check(closure.def_id)?;
}
intravisit::walk_expr(self, ex)
}
fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) -> Self::Result {
self.check(it.owner_id.def_id)?;
intravisit::walk_item(self, it)
}
fn visit_impl_item(&mut self, it: &'tcx hir::ImplItem<'tcx>) -> Self::Result {
self.check(it.owner_id.def_id)?;
intravisit::walk_impl_item(self, it)
}
fn visit_trait_item(&mut self, it: &'tcx hir::TraitItem<'tcx>) -> Self::Result {
self.check(it.owner_id.def_id)?;
intravisit::walk_trait_item(self, it)
}
fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) -> Self::Result {
intravisit::walk_foreign_item(self, it)
}
}
let mut locator = TaitConstraintLocator { tcx, opaque_def_id };
match origin {
hir::OpaqueTyOrigin::FnReturn { parent, .. }
| hir::OpaqueTyOrigin::AsyncFn { parent, .. } => locator.check(parent).break_value(),
hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty: true } => {
let impl_def_id = tcx.local_parent(parent);
for assoc in tcx.associated_items(impl_def_id).in_definition_order() {
match assoc.kind {
ty::AssocKind::Const | ty::AssocKind::Fn => {
if let ControlFlow::Break(span) = locator.check(assoc.def_id.expect_local())
{
return Some(span);
}
}
ty::AssocKind::Type => {}
}
}
None
}
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => {
let scope = tcx.hir().get_defining_scope(tcx.local_def_id_to_hir_id(opaque_def_id));
let found = if scope == hir::CRATE_HIR_ID {
tcx.hir().walk_toplevel_module(&mut locator)
} else {
match tcx.hir_node(scope) {
Node::Item(it) => locator.visit_item(it),
Node::ImplItem(it) => locator.visit_impl_item(it),
Node::TraitItem(it) => locator.visit_trait_item(it),
Node::ForeignItem(it) => locator.visit_foreign_item(it),
other => bug!("{:?} is not a valid scope for an opaque type item", other),
}
};
found.break_value()
}
}
}
fn sanity_check_found_hidden_type<'tcx>( fn sanity_check_found_hidden_type<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
key: ty::OpaqueTypeKey<'tcx>, key: ty::OpaqueTypeKey<'tcx>,
@ -1535,11 +1626,8 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD
/// ///
/// If all the return expressions evaluate to `!`, then we explain that the error will go away /// If all the return expressions evaluate to `!`, then we explain that the error will go away
/// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder. /// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder.
fn opaque_type_cycle_error( fn opaque_type_cycle_error(tcx: TyCtxt<'_>, opaque_def_id: LocalDefId) -> ErrorGuaranteed {
tcx: TyCtxt<'_>, let span = tcx.def_span(opaque_def_id);
opaque_def_id: LocalDefId,
span: Span,
) -> ErrorGuaranteed {
let mut err = struct_span_code_err!(tcx.dcx(), span, E0720, "cannot resolve opaque type"); let mut err = struct_span_code_err!(tcx.dcx(), span, E0720, "cannot resolve opaque type");
let mut label = false; let mut label = false;

View File

@ -14,8 +14,8 @@ async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
fn foo(x: NotSync) -> impl Future + Send { fn foo(x: NotSync) -> impl Future + Send {
//~^ ERROR `*mut ()` cannot be shared between threads safely //~^ ERROR `*mut ()` cannot be shared between threads safely
//~| ERROR `*mut ()` cannot be shared between threads safely
async move { async move {
//~^ ERROR `*mut ()` cannot be shared between threads safely
baz(|| async { baz(|| async {
foo(x.clone()); foo(x.clone());
}).await; }).await;

View File

@ -1,8 +1,13 @@
error[E0277]: `*mut ()` cannot be shared between threads safely error[E0277]: `*mut ()` cannot be shared between threads safely
--> $DIR/issue-70935-complex-spans.rs:15:23 --> $DIR/issue-70935-complex-spans.rs:17:5
| |
LL | fn foo(x: NotSync) -> impl Future + Send { LL | / async move {
| ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely LL | |
LL | | baz(|| async {
LL | | foo(x.clone());
LL | | }).await;
LL | | }
| |_____^ `*mut ()` cannot be shared between threads safely
| |
= help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()` = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`
note: required because it appears within the type `PhantomData<*mut ()>` note: required because it appears within the type `PhantomData<*mut ()>`
@ -26,7 +31,7 @@ LL | async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
LL | | } LL | | }
| |_^ | |_^
note: required because it's used within this `async` block note: required because it's used within this `async` block
--> $DIR/issue-70935-complex-spans.rs:18:5 --> $DIR/issue-70935-complex-spans.rs:17:5
| |
LL | async move { LL | async move {
| ^^^^^^^^^^ | ^^^^^^^^^^
@ -59,11 +64,10 @@ LL | async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
LL | | } LL | | }
| |_^ | |_^
note: required because it's used within this `async` block note: required because it's used within this `async` block
--> $DIR/issue-70935-complex-spans.rs:18:5 --> $DIR/issue-70935-complex-spans.rs:17:5
| |
LL | async move { LL | async move {
| ^^^^^^^^^^ | ^^^^^^^^^^
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View File

@ -25,6 +25,20 @@ LL | _ => {}
| |
= note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
error[E0004]: non-exhaustive patterns: type `impl Copy` is non-empty
--> $DIR/impl-trait.rs:23:11
|
LL | match return_never_rpit(x) {}
| ^^^^^^^^^^^^^^^^^^^^
|
= note: the matched value is of type `impl Copy`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
|
LL ~ match return_never_rpit(x) {
LL + _ => todo!(),
LL + }
|
error: unreachable pattern error: unreachable pattern
--> $DIR/impl-trait.rs:45:13 --> $DIR/impl-trait.rs:45:13
| |
@ -93,6 +107,20 @@ LL | _ => {}
| |
= note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
error[E0004]: non-exhaustive patterns: type `T` is non-empty
--> $DIR/impl-trait.rs:37:11
|
LL | match return_never_tait(x) {}
| ^^^^^^^^^^^^^^^^^^^^
|
= note: the matched value is of type `T`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
|
LL ~ match return_never_tait(x) {
LL + _ => todo!(),
LL + }
|
error: unreachable pattern error: unreachable pattern
--> $DIR/impl-trait.rs:105:9 --> $DIR/impl-trait.rs:105:9
| |
@ -131,34 +159,6 @@ LL | _ => {}
| |
= note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
error[E0004]: non-exhaustive patterns: type `impl Copy` is non-empty
--> $DIR/impl-trait.rs:23:11
|
LL | match return_never_rpit(x) {}
| ^^^^^^^^^^^^^^^^^^^^
|
= note: the matched value is of type `impl Copy`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
|
LL ~ match return_never_rpit(x) {
LL + _ => todo!(),
LL + }
|
error[E0004]: non-exhaustive patterns: type `T` is non-empty
--> $DIR/impl-trait.rs:37:11
|
LL | match return_never_tait(x) {}
| ^^^^^^^^^^^^^^^^^^^^
|
= note: the matched value is of type `T`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
|
LL ~ match return_never_tait(x) {
LL + _ => todo!(),
LL + }
|
error: aborting due to 15 previous errors error: aborting due to 15 previous errors
For more information about this error, try `rustc --explain E0004`. For more information about this error, try `rustc --explain E0004`.

View File

@ -12,20 +12,19 @@
// requires `'a: 'b` bound // requires `'a: 'b` bound
mod test1 { mod test1 {
type Opaque<'a, 'b> = impl Sized + 'a + 'b; type Opaque<'a, 'b> = impl Sized + 'a + 'b;
//~^ ERROR lifetime bound not satisfied
fn define<'a, 'b>() -> Opaque<'a, 'b> fn define<'a, 'b>() -> Opaque<'a, 'b>
where where
'a: 'b, 'a: 'b,
{ {
|| {} || {}
//~^ ERROR lifetime bound not satisfied
} }
} }
// Same as the above but through indirection `'x` // Same as the above but through indirection `'x`
mod test2 { mod test2 {
type Opaque<'a, 'b> = impl Sized + 'a + 'b; type Opaque<'a, 'b> = impl Sized + 'a + 'b;
//~^ ERROR cannot infer an appropriate lifetime
fn define<'a, 'b, 'x>() -> Opaque<'a, 'b> fn define<'a, 'b, 'x>() -> Opaque<'a, 'b>
where where
@ -33,6 +32,7 @@ fn define<'a, 'b, 'x>() -> Opaque<'a, 'b>
'x: 'b, 'x: 'b,
{ {
|| {} || {}
//~^ ERROR cannot infer an appropriate lifetime
} }
} }
@ -52,13 +52,13 @@ fn define<'a, 'b, 'x>() -> Opaque<'a, 'b>
// requires `T: 'static` // requires `T: 'static`
mod test3 { mod test3 {
type Opaque<T> = impl Sized; type Opaque<T> = impl Sized;
//~^ ERROR the parameter type `T` may not live long enough
fn define<T>() -> Opaque<T> fn define<T>() -> Opaque<T>
where where
T: 'static, T: 'static,
{ {
|| {} || {}
//~^ ERROR the parameter type `T` may not live long enough
} }
} }

View File

@ -1,8 +1,8 @@
error[E0478]: lifetime bound not satisfied error[E0478]: lifetime bound not satisfied
--> $DIR/closure_wf_outlives.rs:14:27 --> $DIR/closure_wf_outlives.rs:20:9
| |
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; LL | || {}
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^
| |
note: lifetime parameter instantiated with the lifetime `'a` as defined here note: lifetime parameter instantiated with the lifetime `'a` as defined here
--> $DIR/closure_wf_outlives.rs:14:17 --> $DIR/closure_wf_outlives.rs:14:17
@ -16,10 +16,10 @@ LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
| ^^ | ^^
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> $DIR/closure_wf_outlives.rs:27:27 --> $DIR/closure_wf_outlives.rs:34:9
| |
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; LL | || {}
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^
| |
note: first, the lifetime cannot outlive the lifetime `'a` as defined here... note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
--> $DIR/closure_wf_outlives.rs:27:17 --> $DIR/closure_wf_outlives.rs:27:17
@ -27,32 +27,32 @@ note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
| ^^ | ^^
note: ...so that the declared lifetime parameter bounds are satisfied note: ...so that the declared lifetime parameter bounds are satisfied
--> $DIR/closure_wf_outlives.rs:27:27 --> $DIR/closure_wf_outlives.rs:34:9
| |
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; LL | || {}
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^
note: but, the lifetime must be valid for the lifetime `'b` as defined here... note: but, the lifetime must be valid for the lifetime `'b` as defined here...
--> $DIR/closure_wf_outlives.rs:27:21 --> $DIR/closure_wf_outlives.rs:27:21
| |
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
| ^^ | ^^
note: ...so that the declared lifetime parameter bounds are satisfied note: ...so that the declared lifetime parameter bounds are satisfied
--> $DIR/closure_wf_outlives.rs:27:27 --> $DIR/closure_wf_outlives.rs:34:9
| |
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; LL | || {}
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^
error[E0310]: the parameter type `T` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/closure_wf_outlives.rs:54:22 --> $DIR/closure_wf_outlives.rs:60:9
| |
LL | type Opaque<T> = impl Sized; LL | || {}
| ^^^^^^^^^^ | ^^^^^
| | | |
| the parameter type `T` must be valid for the static lifetime... | the parameter type `T` must be valid for the static lifetime...
| ...so that the type `T` will meet its required lifetime bounds... | ...so that the type `T` will meet its required lifetime bounds...
| |
note: ...that is required by this bound note: ...that is required by this bound
--> $DIR/closure_wf_outlives.rs:59:12 --> $DIR/closure_wf_outlives.rs:58:12
| |
LL | T: 'static, LL | T: 'static,
| ^^^^^^^ | ^^^^^^^

View File

@ -9,10 +9,9 @@ fn main() {}
fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> { fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
t t
//~^ ERROR `T` doesn't implement `Debug`
} }
fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> { fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
u u
//~^ ERROR `U` doesn't implement `Debug` //~^ ERROR concrete type differs
} }

View File

@ -1,25 +1,14 @@
error[E0277]: `T` doesn't implement `Debug` error: concrete type differs from previous defining opaque type use
--> $DIR/generic_duplicate_param_use3.rs:15:5
|
LL | u
| ^ expected `T`, got `U`
|
note: previous use here
--> $DIR/generic_duplicate_param_use3.rs:11:5 --> $DIR/generic_duplicate_param_use3.rs:11:5
| |
LL | t LL | t
| ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` | ^
|
help: consider restricting type parameter `T`
|
LL | type Two<T: std::fmt::Debug, U> = impl Debug;
| +++++++++++++++++
error[E0277]: `U` doesn't implement `Debug` error: aborting due to 1 previous error
--> $DIR/generic_duplicate_param_use3.rs:16:5
|
LL | u
| ^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
help: consider restricting type parameter `U`
|
LL | type Two<T, U: std::fmt::Debug> = impl Debug;
| +++++++++++++++++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -9,12 +9,9 @@ fn main() {}
fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> { fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
(t, u) (t, u)
//~^ ERROR `T` doesn't implement `Debug`
//~| ERROR `U` doesn't implement `Debug`
} }
fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> { fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
(u, t) (u, t)
//~^ ERROR `T` doesn't implement `Debug` //~^ ERROR concrete type differs
//~| ERROR `U` doesn't implement `Debug`
} }

View File

@ -1,51 +1,14 @@
error[E0277]: `T` doesn't implement `Debug` error: concrete type differs from previous defining opaque type use
--> $DIR/generic_duplicate_param_use5.rs:15:5
|
LL | (u, t)
| ^^^^^^ expected `(T, U)`, got `(U, T)`
|
note: previous use here
--> $DIR/generic_duplicate_param_use5.rs:11:5 --> $DIR/generic_duplicate_param_use5.rs:11:5
| |
LL | (t, u) LL | (t, u)
| ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` | ^^^^^^
|
= note: required for `(T, U)` to implement `Debug`
help: consider restricting type parameter `T`
|
LL | type Two<T: std::fmt::Debug, U> = impl Debug;
| +++++++++++++++++
error[E0277]: `U` doesn't implement `Debug` error: aborting due to 1 previous error
--> $DIR/generic_duplicate_param_use5.rs:11:5
|
LL | (t, u)
| ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
= note: required for `(T, U)` to implement `Debug`
help: consider restricting type parameter `U`
|
LL | type Two<T, U: std::fmt::Debug> = impl Debug;
| +++++++++++++++++
error[E0277]: `U` doesn't implement `Debug`
--> $DIR/generic_duplicate_param_use5.rs:17:5
|
LL | (u, t)
| ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
= note: required for `(U, T)` to implement `Debug`
help: consider restricting type parameter `U`
|
LL | type Two<T, U: std::fmt::Debug> = impl Debug;
| +++++++++++++++++
error[E0277]: `T` doesn't implement `Debug`
--> $DIR/generic_duplicate_param_use5.rs:17:5
|
LL | (u, t)
| ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
= note: required for `(U, T)` to implement `Debug`
help: consider restricting type parameter `T`
|
LL | type Two<T: std::fmt::Debug, U> = impl Debug;
| +++++++++++++++++
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -9,11 +9,9 @@ fn main() {}
fn two<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> { fn two<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
(t, t) (t, t)
//~^ ERROR `T` doesn't implement `Debug`
} }
fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> { fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
(u, t) (u, t)
//~^ ERROR `T` doesn't implement `Debug` //~^ ERROR concrete type differs
//~| ERROR `U` doesn't implement `Debug`
} }

View File

@ -1,39 +1,14 @@
error[E0277]: `T` doesn't implement `Debug` error: concrete type differs from previous defining opaque type use
--> $DIR/generic_duplicate_param_use6.rs:15:5
|
LL | (u, t)
| ^^^^^^ expected `(T, T)`, got `(U, T)`
|
note: previous use here
--> $DIR/generic_duplicate_param_use6.rs:11:5 --> $DIR/generic_duplicate_param_use6.rs:11:5
| |
LL | (t, t) LL | (t, t)
| ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` | ^^^^^^
|
= note: required for `(T, T)` to implement `Debug`
help: consider restricting type parameter `T`
|
LL | type Two<T: std::fmt::Debug, U> = impl Debug;
| +++++++++++++++++
error[E0277]: `U` doesn't implement `Debug` error: aborting due to 1 previous error
--> $DIR/generic_duplicate_param_use6.rs:16:5
|
LL | (u, t)
| ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
= note: required for `(U, T)` to implement `Debug`
help: consider restricting type parameter `U`
|
LL | type Two<T, U: std::fmt::Debug> = impl Debug;
| +++++++++++++++++
error[E0277]: `T` doesn't implement `Debug`
--> $DIR/generic_duplicate_param_use6.rs:16:5
|
LL | (u, t)
| ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
= note: required for `(U, T)` to implement `Debug`
help: consider restricting type parameter `T`
|
LL | type Two<T: std::fmt::Debug, U> = impl Debug;
| +++++++++++++++++
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -8,10 +8,9 @@ fn main() {}
fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> { fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
(t, 4u32) (t, 4u32)
//~^ ERROR `T` doesn't implement `Debug`
} }
fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> { fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
(u, 4u32) (u, 4u32)
//~^ ERROR `U` doesn't implement `Debug` //~^ concrete type differs
} }

View File

@ -1,27 +1,14 @@
error[E0277]: `T` doesn't implement `Debug` error: concrete type differs from previous defining opaque type use
--> $DIR/generic_duplicate_param_use8.rs:14:5
|
LL | (u, 4u32)
| ^^^^^^^^^ expected `(T, u32)`, got `(U, u32)`
|
note: previous use here
--> $DIR/generic_duplicate_param_use8.rs:10:5 --> $DIR/generic_duplicate_param_use8.rs:10:5
| |
LL | (t, 4u32) LL | (t, 4u32)
| ^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` | ^^^^^^^^^
|
= note: required for `(T, u32)` to implement `Debug`
help: consider restricting type parameter `T`
|
LL | type Two<T: std::fmt::Debug, U> = impl Debug;
| +++++++++++++++++
error[E0277]: `U` doesn't implement `Debug` error: aborting due to 1 previous error
--> $DIR/generic_duplicate_param_use8.rs:15:5
|
LL | (u, 4u32)
| ^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
= note: required for `(U, u32)` to implement `Debug`
help: consider restricting type parameter `U`
|
LL | type Two<T, U: std::fmt::Debug> = impl Debug;
| +++++++++++++++++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -13,13 +13,9 @@ trait Foo {
fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> { fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> {
(t, u, T::BAR) (t, u, T::BAR)
//~^ ERROR the trait bound `A: Foo` is not satisfied
//~| ERROR `A` doesn't implement `Debug`
//~| ERROR `B` doesn't implement `Debug`
} }
fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> { fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
(t, u, 42) (t, u, 42)
//~^ ERROR `A` doesn't implement `Debug` //~^ ERROR concrete type differs
//~| ERROR `B` doesn't implement `Debug`
} }

View File

@ -1,62 +1,14 @@
error[E0277]: the trait bound `A: Foo` is not satisfied error: concrete type differs from previous defining opaque type use
--> $DIR/generic_duplicate_param_use9.rs:15:5 --> $DIR/generic_duplicate_param_use9.rs:19:5
|
LL | (t, u, T::BAR)
| ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A`
|
help: consider restricting type parameter `A`
|
LL | type Two<A: Foo, B> = impl Debug;
| +++++
error[E0277]: `A` doesn't implement `Debug`
--> $DIR/generic_duplicate_param_use9.rs:15:5
|
LL | (t, u, T::BAR)
| ^^^^^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
= note: required for `(A, B, _)` to implement `Debug`
help: consider restricting type parameter `A`
|
LL | type Two<A: std::fmt::Debug, B> = impl Debug;
| +++++++++++++++++
error[E0277]: `B` doesn't implement `Debug`
--> $DIR/generic_duplicate_param_use9.rs:15:5
|
LL | (t, u, T::BAR)
| ^^^^^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
= note: required for `(A, B, _)` to implement `Debug`
help: consider restricting type parameter `B`
|
LL | type Two<A, B: std::fmt::Debug> = impl Debug;
| +++++++++++++++++
error[E0277]: `A` doesn't implement `Debug`
--> $DIR/generic_duplicate_param_use9.rs:22:5
| |
LL | (t, u, 42) LL | (t, u, 42)
| ^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug` | ^^^^^^^^^^ expected `(A, B, <A as Foo>::Bar)`, got `(A, B, i32)`
| |
= note: required for `(A, B, i32)` to implement `Debug` note: previous use here
help: consider restricting type parameter `A` --> $DIR/generic_duplicate_param_use9.rs:15:5
| |
LL | type Two<A: std::fmt::Debug, B> = impl Debug; LL | (t, u, T::BAR)
| +++++++++++++++++ | ^^^^^^^^^^^^^^
error[E0277]: `B` doesn't implement `Debug` error: aborting due to 1 previous error
--> $DIR/generic_duplicate_param_use9.rs:22:5
|
LL | (t, u, 42)
| ^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
= note: required for `(A, B, i32)` to implement `Debug`
help: consider restricting type parameter `B`
|
LL | type Two<A, B: std::fmt::Debug> = impl Debug;
| +++++++++++++++++
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -2,9 +2,9 @@
mod test_type_param_static { mod test_type_param_static {
pub type Ty<A> = impl Sized + 'static; pub type Ty<A> = impl Sized + 'static;
//~^ ERROR: the parameter type `A` may not live long enough
fn defining<A: 'static>(s: A) -> Ty<A> { fn defining<A: 'static>(s: A) -> Ty<A> {
s s
//~^ ERROR: the parameter type `A` may not live long enough
} }
pub fn assert_static<A: 'static>() {} pub fn assert_static<A: 'static>() {}
} }

View File

@ -1,11 +1,11 @@
error[E0310]: the parameter type `A` may not live long enough error[E0310]: the parameter type `A` may not live long enough
--> $DIR/implied_lifetime_wf_check4_static.rs:4:22 --> $DIR/implied_lifetime_wf_check4_static.rs:6:9
| |
LL | pub type Ty<A> = impl Sized + 'static; LL | s
| ^^^^^^^^^^^^^^^^^^^^ | ^
| | | |
| the parameter type `A` must be valid for the static lifetime... | the parameter type `A` must be valid for the static lifetime...
| ...so that the type `A` will meet its required lifetime bounds | ...so that the type `A` will meet its required lifetime bounds
| |
help: consider adding an explicit lifetime bound help: consider adding an explicit lifetime bound
| |

View File

@ -8,7 +8,6 @@ fn main() {}
fn three<T: Debug, U>(t: T) -> Two<T, U> { fn three<T: Debug, U>(t: T) -> Two<T, U> {
(t, 5i8) (t, 5i8)
//~^ ERROR `T` doesn't implement `Debug`
} }
trait Bar { trait Bar {
@ -23,8 +22,7 @@ impl Bar for u32 {
fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> { fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
(t, <U as Bar>::FOO) (t, <U as Bar>::FOO)
//~^ ERROR `U: Bar` is not satisfied //~^ ERROR concrete type differs
//~| ERROR `T` doesn't implement `Debug`
} }
fn is_sync<T: Sync>() {} fn is_sync<T: Sync>() {}

View File

@ -1,38 +1,14 @@
error[E0277]: `T` doesn't implement `Debug` error: concrete type differs from previous defining opaque type use
--> $DIR/not_a_defining_use.rs:24:5
|
LL | (t, <U as Bar>::FOO)
| ^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)`
|
note: previous use here
--> $DIR/not_a_defining_use.rs:10:5 --> $DIR/not_a_defining_use.rs:10:5
| |
LL | (t, 5i8) LL | (t, 5i8)
| ^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` | ^^^^^^^^
|
= note: required for `(T, i8)` to implement `Debug`
help: consider restricting type parameter `T`
|
LL | type Two<T: std::fmt::Debug, U> = impl Debug;
| +++++++++++++++++
error[E0277]: the trait bound `U: Bar` is not satisfied error: aborting due to 1 previous error
--> $DIR/not_a_defining_use.rs:25:5
|
LL | (t, <U as Bar>::FOO)
| ^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `U`
|
help: consider restricting type parameter `U`
|
LL | type Two<T, U: Bar> = impl Debug;
| +++++
error[E0277]: `T` doesn't implement `Debug`
--> $DIR/not_a_defining_use.rs:25:5
|
LL | (t, <U as Bar>::FOO)
| ^^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
= note: required for `(T, _)` to implement `Debug`
help: consider restricting type parameter `T`
|
LL | type Two<T: std::fmt::Debug, U> = impl Debug;
| +++++++++++++++++
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -13,11 +13,11 @@ fn convert<T: ?Sized>(_: PhantomData<Self>, r: &'a T) -> &'b T {
} }
type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>;
//~^ ERROR reference has a longer lifetime than the data it references
// Even _defining_use with an explicit `'a: 'b` compiles fine, too. // Even _defining_use with an explicit `'a: 'b` compiles fine, too.
fn _defining_use<'a, 'b>(x: &'b &'a ()) -> Converter<'a, 'b> { fn _defining_use<'a, 'b>(x: &'b &'a ()) -> Converter<'a, 'b> {
x x
//~^ ERROR reference has a longer lifetime than the data it references
} }
fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T { fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T {

View File

@ -1,8 +1,8 @@
error[E0491]: in type `&'b &'a ()`, reference has a longer lifetime than the data it references error[E0491]: in type `&'b &'a ()`, reference has a longer lifetime than the data it references
--> $DIR/underconstrained_lifetime.rs:15:26 --> $DIR/underconstrained_lifetime.rs:19:5
| |
LL | type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; LL | x
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^
| |
note: the pointer is valid for the lifetime `'b` as defined here note: the pointer is valid for the lifetime `'b` as defined here
--> $DIR/underconstrained_lifetime.rs:15:20 --> $DIR/underconstrained_lifetime.rs:15:20

View File

@ -1,10 +1,11 @@
error[E0309]: the parameter type `T` may not live long enough error[E0309]: the parameter type `T` may not live long enough
--> $DIR/wf-in-associated-type.rs:38:23 --> $DIR/wf-in-associated-type.rs:40:13
| |
LL | impl<'a, T> Trait<'a, T> for () { LL | impl<'a, T> Trait<'a, T> for () {
| -- the parameter type `T` must be valid for the lifetime `'a` as defined here... | -- the parameter type `T` must be valid for the lifetime `'a` as defined here...
LL | type Opaque = impl Sized + 'a; ...
| ^^^^^^^^^^^^^^^ ...so that the type `&'a T` will meet its required lifetime bounds LL | req
| ^^^ ...so that the type `&'a T` will meet its required lifetime bounds
| |
help: consider adding an explicit lifetime bound help: consider adding an explicit lifetime bound
| |
@ -12,12 +13,13 @@ LL | impl<'a, T: 'a> Trait<'a, T> for () {
| ++++ | ++++
error[E0309]: the parameter type `T` may not live long enough error[E0309]: the parameter type `T` may not live long enough
--> $DIR/wf-in-associated-type.rs:38:23 --> $DIR/wf-in-associated-type.rs:40:13
| |
LL | impl<'a, T> Trait<'a, T> for () { LL | impl<'a, T> Trait<'a, T> for () {
| -- the parameter type `T` must be valid for the lifetime `'a` as defined here... | -- the parameter type `T` must be valid for the lifetime `'a` as defined here...
LL | type Opaque = impl Sized + 'a; ...
| ^^^^^^^^^^^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at LL | req
| ^^^ ...so that the reference type `&'a T` does not outlive the data it points at
| |
help: consider adding an explicit lifetime bound help: consider adding an explicit lifetime bound
| |

View File

@ -36,10 +36,10 @@ trait Trait<'a, T> {
impl<'a, T> Trait<'a, T> for () { impl<'a, T> Trait<'a, T> for () {
type Opaque = impl Sized + 'a; type Opaque = impl Sized + 'a;
//[fail]~^ ERROR the parameter type `T` may not live long enough
//[fail]~| ERROR the parameter type `T` may not live long enough
fn constrain_opaque(req: &'a T) -> Self::Opaque { fn constrain_opaque(req: &'a T) -> Self::Opaque {
req req
//[fail]~^ ERROR the parameter type `T` may not live long enough
//[fail]~| ERROR the parameter type `T` may not live long enough
} }
} }
} }