diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 2aa535da0e54c..2b10348513049 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -62,11 +62,15 @@ use crate::infer::outlives::components::{push_outlives_components, Component}; use crate::infer::outlives::env::RegionBoundPairs; use crate::infer::outlives::verify::VerifyBoundCx; +use crate::infer::traits::{Obligation, PredicateObligation}; +use crate::infer::LateBoundRegionConversionTime; use crate::infer::{ self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, UndoLog, VerifyBound, }; use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::subst::GenericArgKind; +use rustc_middle::ty::subst::InternalSubsts; +use rustc_middle::ty::ToPredicate; use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeFoldable}; use rustc_data_structures::fx::FxHashMap; @@ -186,6 +190,173 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { } } } + + fn compute_nested_outlives_obligations( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + region: ty::Region<'tcx>, + obligations: &mut Vec>, + ) { + let nested = |ty, obligations: &mut _| { + self.compute_nested_outlives_obligations(cause, param_env, ty, region, obligations) + }; + let to_obligation = |pred: ty::Binder<'tcx, ty::PredicateKind<'tcx>>| { + Obligation::new(cause.clone(), param_env, pred.to_predicate(self.tcx)) + }; + let ty_outlives = |ty| { + to_obligation(ty::Binder::dummy(ty::PredicateKind::TypeOutlives( + ty::OutlivesPredicate(ty, region), + ))) + }; + let reg_outlives = |reg| { + to_obligation(ty::Binder::dummy(ty::PredicateKind::RegionOutlives( + ty::OutlivesPredicate(reg, region), + ))) + }; + + match ty.kind() { + // Trivial types + ty::Bool + | ty::Char + | ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::Never + | ty::Str + | ty::Foreign(..) => (), + + // For `&'a T` to be well formed, we require `T: 'a`. + // + // `&'a T: 'b` holds if both `'a: 'b` and `T: 'b` holds. + // `T: 'b` is implied by `'a: 'b`, so we don't have to recurse + // the type. + &ty::Ref(re, _, _) => obligations.push(reg_outlives(re)), + + &ty::RawPtr(ty::TypeAndMut { ty, mutbl: _ }) | &ty::Slice(ty) | &ty::Array(ty, _) => { + nested(ty, obligations) + } + + &ty::Adt(_, substs) | &ty::Opaque(_, substs) => { + for arg in substs { + match arg.unpack() { + GenericArgKind::Lifetime(re) => obligations.push(reg_outlives(re)), + GenericArgKind::Type(ty) => nested(ty, obligations), + GenericArgKind::Const(_) => (), + } + } + } + + ty::Infer(..) => obligations.push(ty_outlives(ty)), + + &ty::FnDef(_, substs) => { + for arg in substs { + match arg.unpack() { + GenericArgKind::Type(ty) => nested(ty, obligations), + // HACK(eddyb) ignore lifetimes found shallowly in `substs`. + // This is inconsistent with `ty::Adt` (including all substs) + // and with `ty::Closure` (ignoring all substs other than + // upvars, of which a `ty::FnDef` doesn't have any), but + // consistent with previous (accidental) behavior. + // See https://github.com/rust-lang/rust/issues/70917 + // for further background and discussion. + GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => {} + } + } + } + + // FIXME: Add comment on why we can ignore the signature. + ty::Closure(_, substs) => { + let tupled_ty = substs.as_closure().tupled_upvars_ty(); + nested(tupled_ty, obligations) + } + + // FIXME: Add comment on why we can ignore the signature. + ty::Generator(_, substs, _) => { + let tupled_ty = substs.as_generator().tupled_upvars_ty(); + nested(tupled_ty, obligations) + } + + // All regions are bound inside a witness + ty::GeneratorWitness(..) => {} + + // FIXME: These two should ideally happen eagerly here, but + // require some kind of `Any` bound which we don't have yet. + ty::Param(_) | ty::Projection(_) => { + self.register_region_obligation_with_cause(ty, region, cause) + } + + &ty::Tuple(fields) => { + for field in fields { + nested(field, obligations) + } + } + + &ty::FnPtr(data) => { + let (data, _) = self.replace_bound_vars_with_fresh_vars( + cause.span, + LateBoundRegionConversionTime::HigherRankedType, + data, + ); + for ty in data.inputs_and_output { + nested(ty, obligations) + } + } + + &ty::Dynamic(traits, region) => { + obligations.push(reg_outlives(region)); + let traits_iter = traits.iter().flat_map(|predicate| { + let (predicate, _) = self.replace_bound_vars_with_fresh_vars( + cause.span, + LateBoundRegionConversionTime::HigherRankedType, + predicate, + ); + let (substs, opt_ty) = match predicate { + ty::ExistentialPredicate::Trait(tr) => (tr.substs, None), + ty::ExistentialPredicate::Projection(p) => (p.substs, Some(p.term)), + ty::ExistentialPredicate::AutoTrait(_) => (InternalSubsts::empty(), None), + }; + + substs.iter().rev().chain(opt_ty.and_then(|term| match term { + ty::Term::Ty(ty) => Some(ty.into()), + ty::Term::Const(_) => None, + })) + }); + for arg in traits_iter { + match arg.unpack() { + GenericArgKind::Lifetime(re) => obligations.push(reg_outlives(re)), + GenericArgKind::Type(ty) => nested(ty, obligations), + GenericArgKind::Const(_) => (), + } + } + } + + // FIXME: The way we deal with placeholders is wrong for now. + // + // Have to check for bounds in the `param_env`. + ty::Placeholder(..) => {} + + ty::Bound(..) => bug!("unexpected type: {:?}", ty), + + ty::Error(_) => {} + } + } + + pub fn nested_outlives_obligations( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + region: ty::Region<'tcx>, + ) -> Vec> { + // Directly using this for inference variables would cause + // the trait solver to be stuck. + assert!(!ty.is_ty_infer()); + let mut obligations = Vec::new(); + self.compute_nested_outlives_obligations(cause, param_env, ty, region, &mut obligations); + obligations + } } /// The `TypeOutlives` struct has the job of "lowering" a `T: 'a` diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 255b52584edc6..d9f633710b0d0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2162,10 +2162,24 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { } } + ty::PredicateKind::TypeOutlives(outlives) => { + if self.tcx.sess.has_errors().is_some() || self.is_tainted_by_errors() { + return; + } + self.emit_inference_failure_err( + body_id, + span, + outlives.0.into(), + vec![], + ErrorCode::E0284, + ) + } + _ => { if self.tcx.sess.has_errors().is_some() || self.is_tainted_by_errors() { return; } + let mut err = struct_span_err!( self.tcx.sess, span, diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 053e871c14f6e..6d1247cb6ad3f 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -434,13 +434,26 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(t_a, r_b)) => { if self.register_region_obligations { - self.selcx.infcx().register_region_obligation_with_cause( - t_a, - r_b, - &obligation.cause, - ); + if t_a.is_ty_infer() { + pending_obligation.stalled_on = + vec![TyOrConstInferVar::maybe_from_ty(t_a).unwrap()]; + ProcessResult::Unchanged + } else { + if self.register_region_obligations { + let obligations = infcx.nested_outlives_obligations( + &obligation.cause, + obligation.param_env, + t_a, + r_b, + ); + ProcessResult::Changed(mk_pending(obligations)) + } else { + ProcessResult::Changed(vec![]) + } + } + } else { + ProcessResult::Changed(vec![]) } - ProcessResult::Changed(vec![]) } ty::PredicateKind::Projection(ref data) => { diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 34dc81b14d29e..cc3f31c23c8f4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -10,7 +10,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::GrowableBitSet; use rustc_infer::infer::InferOk; -use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; +use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::{self, EarlyBinder, GenericParamDefKind, Ty, TyCtxt}; use rustc_middle::ty::{ToPolyTraitRef, ToPredicate}; @@ -425,7 +425,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .infcx .replace_bound_vars_with_fresh_vars( obligation.cause.span, - HigherRankedType, + LateBoundRegionConversionTime::HigherRankedType, object_trait_ref, ) .0; diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type-3.stderr b/src/test/ui/fn/implied-bounds-unnorm-associated-type-3.stderr index 26eecf6a21d3d..c420f58f6a6fc 100644 --- a/src/test/ui/fn/implied-bounds-unnorm-associated-type-3.stderr +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type-3.stderr @@ -5,7 +5,7 @@ LL | fn zero_copy_from<'b>(cart: &'b [T]) -> &'b [T] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `T: 'static`... - = note: ...so that the type `[T]` will meet its required lifetime bounds + = note: ...so that the type `T` will meet its required lifetime bounds error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr index fbf1c8f95feca..0c2b858b616ea 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr @@ -1,10 +1,15 @@ -error[E0477]: the type `<() as Yay<&'a ()>>::InnerStream<'s>` does not fulfill the required lifetime +error[E0478]: lifetime bound not satisfied --> $DIR/issue-86218.rs:23:28 | LL | type InnerStream<'s> = impl Stream + 's; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: type must outlive the lifetime `'s` as defined here as required by this binding +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/issue-86218.rs:22:6 + | +LL | impl<'a> Yay<&'a ()> for () { + | ^^ +note: but lifetime parameter must outlive the lifetime `'s` as defined here --> $DIR/issue-86218.rs:23:22 | LL | type InnerStream<'s> = impl Stream + 's; @@ -20,4 +25,4 @@ LL | type InnerStream<'s> = impl Stream + 's; error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0477`. +For more information about this error, try `rustc --explain E0478`. diff --git a/src/test/ui/generic-associated-types/issue-90014.rs b/src/test/ui/generic-associated-types/issue-90014.rs index f110b069383d3..a507771e0b3ca 100644 --- a/src/test/ui/generic-associated-types/issue-90014.rs +++ b/src/test/ui/generic-associated-types/issue-90014.rs @@ -12,7 +12,7 @@ trait MakeFut { impl MakeFut for &'_ mut () { type Fut<'a> = impl Future; - //~^ ERROR: the type `&mut ()` does not fulfill the required lifetime + //~^ ERROR: lifetime bound not satisfied fn make_fut<'a>(&'a self) -> Self::Fut<'a> { async { () } diff --git a/src/test/ui/generic-associated-types/issue-90014.stderr b/src/test/ui/generic-associated-types/issue-90014.stderr index 51fe3360c7eb2..d390e0fa58527 100644 --- a/src/test/ui/generic-associated-types/issue-90014.stderr +++ b/src/test/ui/generic-associated-types/issue-90014.stderr @@ -1,4 +1,4 @@ -error[E0477]: the type `&mut ()` does not fulfill the required lifetime +error[E0478]: lifetime bound not satisfied --> $DIR/issue-90014.rs:14:20 | LL | type Fut<'a> where Self: 'a; @@ -7,7 +7,12 @@ LL | type Fut<'a> where Self: 'a; LL | type Fut<'a> = impl Future; | ^^^^^^^^^^^^^^^^^^^^^^^^- help: try copying this clause from the trait: `where Self: 'a` | -note: type must outlive the lifetime `'a` as defined here +note: lifetime parameter instantiated with the anonymous lifetime as defined here + --> $DIR/issue-90014.rs:13:19 + | +LL | impl MakeFut for &'_ mut () { + | ^^ +note: but lifetime parameter must outlive the lifetime `'a` as defined here --> $DIR/issue-90014.rs:14:14 | LL | type Fut<'a> = impl Future; @@ -15,4 +20,4 @@ LL | type Fut<'a> = impl Future; error: aborting due to previous error -For more information about this error, try `rustc --explain E0477`. +For more information about this error, try `rustc --explain E0478`. diff --git a/src/test/ui/generic-associated-types/issue-92033.rs b/src/test/ui/generic-associated-types/issue-92033.rs index 1d5f7d5c0099e..e5c16615ea44b 100644 --- a/src/test/ui/generic-associated-types/issue-92033.rs +++ b/src/test/ui/generic-associated-types/issue-92033.rs @@ -20,7 +20,7 @@ trait Swapchain { impl<'s> Surface for &'s Texture { type TextureIter<'a> = std::option::IntoIter<&'a Texture>; - //~^ ERROR the type + //~^ ERROR lifetime bound not satisfied fn get_texture(&self) -> Self::TextureIter<'_> { let option: Option<&Texture> = Some(self); diff --git a/src/test/ui/generic-associated-types/issue-92033.stderr b/src/test/ui/generic-associated-types/issue-92033.stderr index 5b90199b8091f..7ed50f9ee0f27 100644 --- a/src/test/ui/generic-associated-types/issue-92033.stderr +++ b/src/test/ui/generic-associated-types/issue-92033.stderr @@ -1,4 +1,4 @@ -error[E0477]: the type `&'s Texture` does not fulfill the required lifetime +error[E0478]: lifetime bound not satisfied --> $DIR/issue-92033.rs:22:28 | LL | / type TextureIter<'a>: Iterator @@ -9,7 +9,12 @@ LL | | Self: 'a; LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try copying this clause from the trait: `where Self: 'a` | -note: type must outlive the lifetime `'a` as defined here +note: lifetime parameter instantiated with the lifetime `'s` as defined here + --> $DIR/issue-92033.rs:21:6 + | +LL | impl<'s> Surface for &'s Texture { + | ^^ +note: but lifetime parameter must outlive the lifetime `'a` as defined here --> $DIR/issue-92033.rs:22:22 | LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; @@ -17,4 +22,4 @@ LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; error: aborting due to previous error -For more information about this error, try `rustc --explain E0477`. +For more information about this error, try `rustc --explain E0478`. diff --git a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs index 6466bf98dfc8f..d404f30ad2c98 100644 --- a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs +++ b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs @@ -6,7 +6,7 @@ trait ATy { impl<'b> ATy for &'b () { type Item<'a> = &'b (); - //~^ ERROR the type `&'b ()` does not fulfill the required lifetime + //~^ ERROR lifetime bound not satisfied } trait StaticTy { @@ -15,7 +15,7 @@ trait StaticTy { impl StaticTy for () { type Item<'a> = &'a (); - //~^ ERROR the type `&'a ()` does not fulfill the required lifetime + //~^ ERROR lifetime bound not satisfied } fn main() {} diff --git a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr index 7ec9386cabead..0614ef47ca91a 100644 --- a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr +++ b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr @@ -1,27 +1,33 @@ -error[E0477]: the type `&'b ()` does not fulfill the required lifetime +error[E0478]: lifetime bound not satisfied --> $DIR/unsatisfied-outlives-bound.rs:8:21 | LL | type Item<'a> = &'b (); | ^^^^^^ | -note: type must outlive the lifetime `'a` as defined here as required by this binding +note: lifetime parameter instantiated with the lifetime `'b` as defined here + --> $DIR/unsatisfied-outlives-bound.rs:7:6 + | +LL | impl<'b> ATy for &'b () { + | ^^ +note: but lifetime parameter must outlive the lifetime `'a` as defined here --> $DIR/unsatisfied-outlives-bound.rs:8:15 | LL | type Item<'a> = &'b (); | ^^ -error[E0477]: the type `&'a ()` does not fulfill the required lifetime +error[E0478]: lifetime bound not satisfied --> $DIR/unsatisfied-outlives-bound.rs:17:21 | LL | type Item<'a> = &'a (); | ^^^^^^ | -note: type must satisfy the static lifetime as required by this binding - --> $DIR/unsatisfied-outlives-bound.rs:13:20 +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/unsatisfied-outlives-bound.rs:17:15 | -LL | type Item<'a>: 'static; - | ^^^^^^^ +LL | type Item<'a> = &'a (); + | ^^ + = note: but lifetime parameter must outlive the static lifetime error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0477`. +For more information about this error, try `rustc --explain E0478`. diff --git a/src/test/ui/issues/issue-24013.stderr b/src/test/ui/issues/issue-24013.stderr index 4e3cb88297d3b..18cd4277dbb74 100644 --- a/src/test/ui/issues/issue-24013.stderr +++ b/src/test/ui/issues/issue-24013.stderr @@ -1,9 +1,11 @@ -error[E0282]: type annotations needed +error[E0284]: type annotations needed --> $DIR/issue-24013.rs:5:20 | LL | unsafe {swap::<&mut _>(transmute(&a), transmute(&b))}; | ^^^^^^ cannot infer type + | + = note: required so that reference `&mut _` does not outlive its referent error: aborting due to previous error -For more information about this error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0284`. diff --git a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs index 575dfafe15efc..76f15626bd7e5 100644 --- a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs +++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs @@ -13,12 +13,12 @@ impl<'a> Foo<'a> for &'a i16 { impl<'a> Foo<'static> for &'a i32 { type Value = &'a i32; - //~^ ERROR the type `&'a i32` does not fulfill the required lifetime + //~^ ERROR lifetime bound not satisfied } impl<'a, 'b> Foo<'b> for &'a i64 { type Value = &'a i32; - //~^ ERROR the type `&'a i32` does not fulfill the required lifetime + //~^ ERROR lifetime bound not satisfied } fn main() {} diff --git a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr index ac6154139e269..619ba82d044a6 100644 --- a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr +++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr @@ -1,22 +1,28 @@ -error[E0477]: the type `&'a i32` does not fulfill the required lifetime +error[E0478]: lifetime bound not satisfied --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:15:18 | LL | type Value = &'a i32; | ^^^^^^^ | -note: type must satisfy the static lifetime as required by this binding - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:5:17 +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:6 | -LL | type Value: 'a; - | ^^ +LL | impl<'a> Foo<'static> for &'a i32 { + | ^^ + = note: but lifetime parameter must outlive the static lifetime -error[E0477]: the type `&'a i32` does not fulfill the required lifetime +error[E0478]: lifetime bound not satisfied --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:20:18 | LL | type Value = &'a i32; | ^^^^^^^ | -note: type must outlive the lifetime `'b` as defined here as required by this binding +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:6 + | +LL | impl<'a, 'b> Foo<'b> for &'a i64 { + | ^^ +note: but lifetime parameter must outlive the lifetime `'b` as defined here --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:10 | LL | impl<'a, 'b> Foo<'b> for &'a i64 { @@ -24,4 +30,4 @@ LL | impl<'a, 'b> Foo<'b> for &'a i64 { error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0477`. +For more information about this error, try `rustc --explain E0478`. diff --git a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs index 00100e0e9ea75..308644669bd3d 100644 --- a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs +++ b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs @@ -8,7 +8,7 @@ trait Foo { impl<'a> Foo for &'a i32 { type Value = &'a i32; - //~^ ERROR the type `&'a i32` does not fulfill the required lifetime + //~^ ERROR lifetime bound not satisfied } impl<'a> Foo for i32 { diff --git a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr index a96f5612fa23d..ed8a19340d477 100644 --- a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr +++ b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr @@ -1,15 +1,16 @@ -error[E0477]: the type `&'a i32` does not fulfill the required lifetime +error[E0478]: lifetime bound not satisfied --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:10:18 | LL | type Value = &'a i32; | ^^^^^^^ | -note: type must satisfy the static lifetime as required by this binding - --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:5:17 +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:6 | -LL | type Value: 'static; - | ^^^^^^^ +LL | impl<'a> Foo for &'a i32 { + | ^^ + = note: but lifetime parameter must outlive the static lifetime error: aborting due to previous error -For more information about this error, try `rustc --explain E0477`. +For more information about this error, try `rustc --explain E0478`.