diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml index 714f46270f92c..53744626c8f7f 100644 --- a/compiler/rustc_borrowck/Cargo.toml +++ b/compiler/rustc_borrowck/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" either = "1.5.0" itertools = "0.11" polonius-engine = "0.13.0" +rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index e8effd5c1633a..81480450b8f96 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1,5 +1,6 @@ //! Error reporting machinery for lifetime errors. +use rustc_ast::TraitObjectSyntax::Dyn; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, MultiSpan}; use rustc_hir as hir; @@ -16,14 +17,12 @@ use rustc_infer::infer::{ HirTraitObjectVisitor, NiceRegionError, TraitObjectVisitor, }, error_reporting::unexpected_hidden_region_diagnostic, - NllRegionVariableOrigin, RelateParamBound, + BoundRegionConversionTime, NllRegionVariableOrigin, RelateParamBound, }; use rustc_middle::hir::place::PlaceBase; use rustc_middle::mir::{ConstraintCategory, ReturnConstraint}; -use rustc_middle::ty::GenericArgs; -use rustc_middle::ty::TypeVisitor; -use rustc_middle::ty::{self, RegionVid, Ty}; -use rustc_middle::ty::{Region, TyCtxt}; +use rustc_middle::traits::ObligationCauseCode; +use rustc_middle::ty::{self, GenericArgs, Region, RegionVid, Ty, TyCtxt, TypeVisitor}; use rustc_span::symbol::{kw, Ident}; use rustc_span::Span; @@ -490,19 +489,21 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } }; + self.explain_impl_static_obligation(&mut diag, cause.code(), outlived_fr); + match variance_info { ty::VarianceDiagInfo::None => {} ty::VarianceDiagInfo::Invariant { ty, param_index } => { let (desc, note) = match ty.kind() { ty::RawPtr(ty_mut) => { - assert_eq!(ty_mut.mutbl, rustc_hir::Mutability::Mut); + assert_eq!(ty_mut.mutbl, hir::Mutability::Mut); ( format!("a mutable pointer to `{}`", ty_mut.ty), "mutable pointers are invariant over their type parameter".to_string(), ) } ty::Ref(_, inner_ty, mutbl) => { - assert_eq!(*mutbl, rustc_hir::Mutability::Mut); + assert_eq!(*mutbl, hir::Mutability::Mut); ( format!("a mutable reference to `{inner_ty}`"), "mutable references are invariant over their type parameter" @@ -518,10 +519,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let adt_desc = adt.descr(); let desc = format!( - "the type `{ty}`, which makes the generic argument `{generic_arg}` invariant" + "the type `{ty}`, which makes the generic argument `{generic_arg}` \ + invariant" ); let note = format!( - "the {adt_desc} `{base_ty}` is invariant over the parameter `{base_generic_arg}`" + "the {adt_desc} `{base_ty}` is invariant over the parameter \ + `{base_generic_arg}`" ); (desc, note) } @@ -539,14 +542,21 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; diag.note(format!("requirement occurs because of {desc}",)); diag.note(note); - diag.help("see for more information about variance"); + diag.help( + "see for more \ + information about variance", + ); } } for extra in extra_info { match extra { ExtraConstraintInfo::PlaceholderFromPredicate(span) => { - diag.span_note(span, "due to current limitations in the borrow checker, this implies a `'static` lifetime"); + diag.span_note( + span, + "due to current limitations in the borrow checker, this implies a \ + `'static` lifetime", + ); } } } @@ -554,6 +564,212 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { self.buffer_error(diag); } + /// Report a specialized error when a `'static` obligation comes from an `impl dyn Trait` + /// + /// ```text + /// error: lifetime may not live long enough + /// --> $DIR/static-impl-obligation.rs:8:27 + /// | + /// LL | fn bar<'a>(x: &'a &'a u32) { + /// | -- lifetime `'a` defined here + /// LL | let y: &dyn Foo = x; + /// | ^ cast requires that `'a` must outlive `'static` + /// LL | y.hello(); + /// | --------- calling this method introduces a `'static` lifetime requirement + /// | + /// note: the `impl` on `(dyn a::Foo + 'static)` has a `'static` lifetime requirement + /// --> $DIR/static-impl-obligation.rs:4:10 + /// | + /// LL | impl dyn Foo { + /// | ^^^^^^^ + /// help: relax the implicit `'static` bound on the impl + /// | + /// LL | impl dyn Foo + '_ { + /// | ++++ + /// ``` + /// ```text + /// error: lifetime may not live long enough + /// --> $DIR/static-impl-obligation.rs:173:27 + /// | + /// LL | fn bar<'a>(x: &'a &'a u32) { + /// | -- lifetime `'a` defined here + /// LL | let y: &dyn Foo = x; + /// | ^ cast requires that `'a` must outlive `'static` + /// LL | y.hello(); + /// | --------- calling this method introduces a `'static` lifetime requirement + /// | + /// note: the `impl` on `(dyn p::Foo + 'static)` has `'static` lifetime requirements + /// --> $DIR/static-impl-obligation.rs:169:20 + /// | + /// LL | impl dyn Foo + 'static where Self: 'static { + /// | ^^^^^^^ ^^^^^^^ + /// LL | fn hello(&self) where Self: 'static {} + /// | ^^^^^^^ + /// ``` + fn explain_impl_static_obligation( + &self, + diag: &mut DiagnosticBuilder<'_>, + code: &ObligationCauseCode<'tcx>, + outlived_fr: RegionVid, + ) { + let tcx = self.infcx.tcx; + let ObligationCauseCode::MethodCallConstraint(ty, call_span) = code else { + return; + }; + let ty::FnDef(def_id, args) = ty.kind() else { + return; + }; + let Ok(Some(instance)) = ty::Instance::resolve( + tcx, + self.param_env, + *def_id, + self.infcx.resolve_vars_if_possible(args), + ) else { + return; + }; + let def_id = instance.def_id(); + let parent = tcx.parent(def_id); + let hir::def::DefKind::Impl { .. } = tcx.def_kind(parent) else { + return; + }; + let ty = tcx.type_of(parent).instantiate(tcx, instance.args); + if self.to_error_region(outlived_fr) != Some(tcx.lifetimes.re_static) { + return; + } + // FIXME: there's a case that's yet to be handled: `impl dyn Trait + '_ where Self: '_` + // causes *two* errors to be produded, one about `where Self: '_` not being allowed, + // and the regular error with no additional information about "lifetime may not live + // long enough for `'static`" without mentioning where it came from. This is because + // our error recovery fallback is indeed `ReStatic`. We should at some point introduce + // a `ReError` instead to avoid this and other similar issues. + + // Look for `'static` bounds in the generics of the method and the `impl`. + // ``` + // impl dyn Trait where Self: 'static { + // fn foo(&self) where Self: 'static {} + // } + // ``` + let mut predicates: Vec = tcx + .predicates_of(def_id) + .predicates + .iter() + .chain(tcx.predicates_of(parent).predicates.iter()) + .filter_map(|(pred, pred_span)| { + if let Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(pred_ty, r))) = + pred.kind().no_bound_vars() + // Look for `'static` bounds + && r.kind() == ty::ReStatic + // We only want bounds on `Self` + && self.infcx.can_eq(self.param_env, ty, pred_ty) + { + Some(*pred_span) + } else { + None + } + }) + .collect(); + + // Look at the receiver for `&'static self`, which introduces a `'static` obligation. + // ``` + // impl dyn Trait { + // fn foo(&'static self) {} + // } + // ``` + if let ty::Ref(region, _, _) = self + .infcx + .instantiate_binder_with_fresh_vars( + *call_span, + BoundRegionConversionTime::FnCall, + tcx.fn_sig(def_id).instantiate_identity().inputs().map_bound(|inputs| inputs[0]), + ) + .kind() + && *region == tcx.lifetimes.re_static + && let Some(assoc) = tcx.opt_associated_item(def_id) + && assoc.fn_has_self_parameter + { + // We have a `&'static self` receiver. + if let Some(def_id) = def_id.as_local() + && let owner = tcx.expect_hir_owner_node(def_id) + && let Some(decl) = owner.fn_decl() + && let Some(ty) = decl.inputs.get(0) + { + // Point at the `&'static self` receiver. + predicates.push(ty.span); + } else { + // The method is not defined on the local crate, point at the signature + // instead of just the receiver as an approximation. + predicates.push(tcx.def_span(def_id)) + } + } + + // When we have the HIR `Node` at hand, see if we can identify an + // implicit `'static` bound in an `impl dyn Trait {}` and if that's + // the only restriction, suggest relaxing it. + if let Some(hir::Node::Item(hir::Item { + kind: + hir::ItemKind::Impl(hir::Impl { + self_ty: hir::Ty { kind: hir::TyKind::TraitObject(_, lt, _), span, .. }, + .. + }), + .. + })) = tcx.hir().get_if_local(parent) + && let Some(hir::Node::ImplItem(hir::ImplItem { .. })) = tcx.hir().get_if_local(def_id) + { + let suggestion = match lt.res { + hir::LifetimeName::ImplicitObjectLifetimeDefault if predicates.is_empty() => { + // `impl dyn Trait {}` + Some(( + span.shrink_to_hi(), + "consider relaxing the implicit `'static` requirement on the impl", + " + '_", + )) + } + hir::LifetimeName::Static if predicates.is_empty() => { + // `impl dyn Trait + 'static {}` + Some((lt.ident.span, "consider replacing this `'static` requirement", "'_")) + } + _ => None, + }; + if let Some((span, msg, sugg)) = suggestion { + // We only emit the suggestion to write `impl dyn Trait + '_ {}` if that's the only + // thing needed. + diag.span_suggestion_verbose(span, msg, sugg, Applicability::MachineApplicable); + // This is redundant but needed because we won't enter the section with the + // additional note, so we point at the method call here too. + diag.span_label( + *call_span, + "calling this method introduces a `'static` lifetime requirement", + ); + } else if let hir::LifetimeName::ImplicitObjectLifetimeDefault + | hir::LifetimeName::Static = lt.res + { + // Otherwise, we add the right span for the note pointing at all the places where + // a `'static` requirement is introduced when invoking the method on this `impl`. + predicates.push(lt.ident.span); + } + } else if let ty::Dynamic(_, region, ty::Dyn) = ty.kind() + && *region == tcx.lifetimes.re_static + { + // The `self_ty` has a `'static` bound on a `dyn Trait`, either implicit or explicit, + // but we don't have access to the HIR to identify which one nor to provide a targetted + // enough `Span`, so instead we fall back to pointing at the `impl` header instead. + predicates.push(tcx.def_span(parent)); + } + if !predicates.is_empty() { + diag.span_label( + *call_span, + "calling this method introduces a `'static` lifetime requirement", + ); + let a_static_lt = if predicates.len() == 1 { + "a `'static` lifetime requirement" + } else { + "`'static` lifetime requirements" + }; + let span: MultiSpan = predicates.into(); + diag.span_note(span, format!("the `impl` on `{ty}` has {a_static_lt}")); + } + } + /// Report a specialized error when `FnMut` closures return a reference to a captured variable. /// This function expects `fr` to be local and `outlived_fr` to not be local. /// @@ -793,7 +1009,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { self.add_static_impl_trait_suggestion(&mut diag, *fr, fr_name, *outlived_fr); self.suggest_adding_lifetime_params(&mut diag, *fr, *outlived_fr); self.suggest_move_on_borrowing_closure(&mut diag); - diag } @@ -908,37 +1123,32 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let tcx = self.infcx.tcx; - let instance = if let ConstraintCategory::CallArgument(Some(func_ty)) = category { - let (fn_did, args) = match func_ty.kind() { - ty::FnDef(fn_did, args) => (fn_did, args), - _ => return, - }; - debug!(?fn_did, ?args); + let ConstraintCategory::CallArgument(Some(func_ty)) = category else { + return; + }; + let ty::FnDef(fn_did, args) = func_ty.kind() else { + return; + }; + debug!(?fn_did, ?args); - // Only suggest this on function calls, not closures - let ty = tcx.type_of(fn_did).instantiate_identity(); - debug!("ty: {:?}, ty.kind: {:?}", ty, ty.kind()); - if let ty::Closure(_, _) = ty.kind() { - return; - } + // Only suggest this on function calls, not closures + let ty = tcx.type_of(fn_did).instantiate_identity(); + debug!("ty: {:?}, ty.kind: {:?}", ty, ty.kind()); + if let ty::Closure(_, _) = ty.kind() { + return; + } - if let Ok(Some(instance)) = ty::Instance::resolve( - tcx, - self.param_env, - *fn_did, - self.infcx.resolve_vars_if_possible(args), - ) { - instance - } else { - return; - } - } else { + let Ok(Some(instance)) = ty::Instance::resolve( + tcx, + self.param_env, + *fn_did, + self.infcx.resolve_vars_if_possible(args), + ) else { return; }; - let param = match find_param_with_region(tcx, f, o) { - Some(param) => param, - None => return, + let Some(param) = find_param_with_region(tcx, f, o) else { + return; }; debug!(?param); @@ -980,12 +1190,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { "calling this method introduces the `impl`'s `'static` requirement", ); err.subdiagnostic(self.dcx(), RequireStaticErr::UsedImpl { multi_span }); - err.span_suggestion_verbose( - span.shrink_to_hi(), - "consider relaxing the implicit `'static` requirement", - " + '_", - Applicability::MaybeIncorrect, - ); + if let hir::TyKind::TraitObject(traits, lt, Dyn) = self_ty.kind + && lt.res == hir::LifetimeName::ImplicitObjectLifetimeDefault + && traits.iter().any(|t| t.span == *span) + { + // We already handle the case where `self_ty` has an implicit 'static` + // requirement specifically in `explain_impl_static_obligation`. + } else { + err.span_suggestion_verbose( + span.shrink_to_hi(), + "consider relaxing the implicit `'static` requirement", + " + '_", + Applicability::MaybeIncorrect, + ); + } suggested = true; } } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 34d60fc8f6e17..dfbee8a66aad4 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -2051,6 +2051,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { CRATE_DEF_ID.to_def_id(), predicate_span, )) + } else if let ConstraintCategory::CallArgument(Some(fn_def)) = constraint.category { + Some(ObligationCauseCode::MethodCallConstraint(fn_def, constraint.span)) } else { None } diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index fc600af1b76f0..e5ebf97cfc4ee 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -100,7 +100,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { locations: Locations, ) { for (predicate, span) in instantiated_predicates { - debug!(?predicate); + debug!(?span, ?predicate); let category = ConstraintCategory::Predicate(span); let predicate = self.normalize_with_category(predicate, locations, category); self.prove_predicate(predicate, locations, category); diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index c97e31701669c..de75a9857f8b5 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -8,7 +8,7 @@ use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Const use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::Span; use rustc_trait_selection::solve::deeply_normalize; use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; @@ -183,7 +183,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { // we don't actually use this for anything, but // the `TypeOutlives` code needs an origin. - let origin = infer::RelateParamBound(DUMMY_SP, t1, None); + let origin = infer::RelateParamBound(self.span, t1, None); TypeOutlives::new( &mut *self, diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 2e0caf4481902..356f0024c071e 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -10,7 +10,7 @@ use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::query::OutlivesBound; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt}; -use rustc_span::{ErrorGuaranteed, DUMMY_SP}; +use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::solve::deeply_normalize; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; @@ -269,7 +269,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { debug!("build: input_or_output={:?}", ty); // We add implied bounds from both the unnormalized and normalized ty. // See issue #87748 - let constraints_unnorm = self.add_implied_bounds(ty); + let constraints_unnorm = self.add_implied_bounds(ty, span); if let Some(c) = constraints_unnorm { constraints.push(c) } @@ -299,7 +299,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { // ``` // Both &Self::Bar and &() are WF if ty != norm_ty { - let constraints_norm = self.add_implied_bounds(norm_ty); + let constraints_norm = self.add_implied_bounds(norm_ty, span); if let Some(c) = constraints_norm { constraints.push(c) } @@ -323,7 +323,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { // We currently add implied bounds from the normalized ty only. // This is more conservative and matches wfcheck behavior. - let c = self.add_implied_bounds(norm_ty); + let c = self.add_implied_bounds(norm_ty, span); constraints.extend(c); } } @@ -361,11 +361,15 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { /// the same time, compute and add any implied bounds that come /// from this local. #[instrument(level = "debug", skip(self))] - fn add_implied_bounds(&mut self, ty: Ty<'tcx>) -> Option<&'tcx QueryRegionConstraints<'tcx>> { + fn add_implied_bounds( + &mut self, + ty: Ty<'tcx>, + span: Span, + ) -> Option<&'tcx QueryRegionConstraints<'tcx>> { let TypeOpOutput { output: bounds, constraints, .. } = self .param_env .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty }) - .fully_perform(self.infcx, DUMMY_SP) + .fully_perform(self.infcx, span) .map_err(|_: ErrorGuaranteed| debug!("failed to compute implied bounds {:?}", ty)) .ok()?; debug!(?bounds, ?constraints); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 64469727d0dbe..f96c2cbd8c05b 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -37,7 +37,7 @@ use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::Span; use rustc_target::abi::{FieldIdx, FIRST_VARIANT}; use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints; use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; @@ -1014,7 +1014,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ) -> Self { let mut checker = Self { infcx, - last_span: DUMMY_SP, + last_span: body.span, body, user_type_annotations: &body.user_type_annotations, param_env, @@ -2766,7 +2766,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.param_env, self.known_type_outlives_obligations, locations, - DUMMY_SP, // irrelevant; will be overridden. + self.body.span, // irrelevant; will be overridden. ConstraintCategory::Boring, // same as above. self.borrowck_context.constraints, ) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index a5ef1490bce97..cffb88a1365b2 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1630,7 +1630,7 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx: 'a>( #[instrument(level = "debug", skip(tcx))] fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { let mut result = tcx.explicit_predicates_of(def_id); - debug!("predicates_defined_on: explicit_predicates_of({:?}) = {:?}", def_id, result,); + debug!("predicates_defined_on: explicit_predicates_of({:?}) = {:?}", def_id, result); let inferred_outlives = tcx.inferred_outlives_of(def_id); if !inferred_outlives.is_empty() { debug!( diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 56a45586c9d2e..6d1abc33ae757 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -405,7 +405,7 @@ impl<'tcx> InferCtxt<'tcx> { /// will instantiate fresh inference variables for each canonical /// variable instead. Therefore, the result of this method must be /// properly unified - #[instrument(level = "debug", skip(self, cause, param_env))] + #[instrument(level = "debug", skip(self, param_env))] fn query_response_instantiation_guess( &self, cause: &ObligationCause<'tcx>, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 119e0a49acf1f..8605421a89a28 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -451,6 +451,9 @@ pub enum ObligationCauseCode<'tcx> { /// Obligations emitted during the normalization of a weak type alias. TypeAlias(InternedObligationCauseCode<'tcx>, Span, DefId), + + /// During borrowck we've found a method call that could have introduced a lifetime requirement. + MethodCallConstraint(Ty<'tcx>, Span), } /// Whether a value can be extracted into a const. diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 2d85f84f480dc..47e60943238d7 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2683,6 +2683,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { | ObligationCauseCode::MethodReceiver | ObligationCauseCode::ReturnNoExpression | ObligationCauseCode::UnifyReceiver(..) + | ObligationCauseCode::MethodCallConstraint(..) | ObligationCauseCode::MiscObligation | ObligationCauseCode::WellFormed(..) | ObligationCauseCode::MatchImpl(..) diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index 6825dd4ac713d..8b2e8b54aee64 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -62,9 +62,10 @@ fn implied_outlives_bounds<'a, 'tcx>( }; let mut constraints = QueryRegionConstraints::default(); + let span = infcx.tcx.def_span(body_id); let Ok(InferOk { value: mut bounds, obligations }) = infcx .instantiate_nll_query_response_and_region_obligations( - &ObligationCause::dummy(), + &ObligationCause::dummy_with_span(span), param_env, &canonical_var_values, canonical_result, @@ -80,8 +81,6 @@ fn implied_outlives_bounds<'a, 'tcx>( bounds.retain(|bound| !bound.has_placeholders()); if !constraints.is_empty() { - let span = infcx.tcx.def_span(body_id); - debug!(?constraints); if !constraints.member_constraints.is_empty() { span_bug!(span, "{:#?}", constraints.member_constraints); diff --git a/tests/ui/inference/issue-80409.no-compat.stderr b/tests/ui/inference/issue-80409.no-compat.stderr index 7bb4786db3a91..c332a5ec03572 100644 --- a/tests/ui/inference/issue-80409.no-compat.stderr +++ b/tests/ui/inference/issue-80409.no-compat.stderr @@ -1,6 +1,16 @@ error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ImpliedOutlivesBounds { ty: &'?2 mut StateContext<'?3, usize> } } + --> $DIR/issue-80409.rs:48:30 | - = query stack during panic: +LL | builder.state().on_entry(|_| {}); + | ^^^ + | +note: delayed at /home/gh-estebank/rust/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs:164:29 - disabled backtrace + --> $DIR/issue-80409.rs:48:30 + | +LL | builder.state().on_entry(|_| {}); + | ^^^ + +query stack during panic: end of query stack error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/static-impl-obligation.rs b/tests/ui/lifetimes/static-impl-obligation.rs new file mode 100644 index 0000000000000..7c06a78b4b359 --- /dev/null +++ b/tests/ui/lifetimes/static-impl-obligation.rs @@ -0,0 +1,195 @@ +mod a { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo { //~ HELP consider relaxing the implicit `'static` requirement + fn hello(&self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; //~ ERROR lifetime may not live long enough + y.hello(); + } +} +mod b { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo { + fn hello(&'static self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; //~ ERROR lifetime may not live long enough + y.hello(); + } +} +mod c { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo { + fn hello(&'static self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; //~ ERROR lifetime may not live long enough + y.hello(); + } +} +mod d { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo { + fn hello(&self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; //~ ERROR lifetime may not live long enough + y.hello(); + } +} +mod e { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static { //~ HELP consider replacing this `'static` requirement + fn hello(&self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; //~ ERROR lifetime may not live long enough + y.hello(); + } +} +mod f { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static { + fn hello(&'static self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; //~ ERROR lifetime may not live long enough + y.hello(); + } +} +mod g { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static { + fn hello(&'static self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; //~ ERROR lifetime may not live long enough + y.hello(); + } +} +mod h { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static { + fn hello(&self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; //~ ERROR lifetime may not live long enough + y.hello(); + } +} +mod i { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo where Self: 'static { + fn hello(&self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; //~ ERROR lifetime may not live long enough + y.hello(); + } +} +mod j { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo where Self: 'static { + fn hello(&'static self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; //~ ERROR lifetime may not live long enough + y.hello(); + } +} +mod k { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo where Self: 'static { + fn hello(&'static self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; //~ ERROR lifetime may not live long enough + y.hello(); + } +} +mod l { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo where Self: 'static { + fn hello(&self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; //~ ERROR lifetime may not live long enough + y.hello(); + } +} +mod m { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static where Self: 'static { + fn hello(&self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; //~ ERROR lifetime may not live long enough + y.hello(); + } +} +mod n { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static where Self: 'static { + fn hello(&'static self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; //~ ERROR lifetime may not live long enough + y.hello(); + } +} +mod o { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static where Self: 'static { + fn hello(&'static self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; //~ ERROR lifetime may not live long enough + y.hello(); + } +} +mod p { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static where Self: 'static { + fn hello(&self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; //~ ERROR lifetime may not live long enough + y.hello(); + } +} +mod q { + struct Foo {} + impl Foo { + fn hello(&'static self) {} + } + fn bar<'a>(x: &'a &'a Foo) { + x.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod r { + struct Foo {} + impl Foo { + fn hello(&'static self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a Foo) { + x.hello(); //~ ERROR borrowed data escapes outside of function + } +} +fn main() {} \ No newline at end of file diff --git a/tests/ui/lifetimes/static-impl-obligation.stderr b/tests/ui/lifetimes/static-impl-obligation.stderr new file mode 100644 index 0000000000000..2530db5f2b6e1 --- /dev/null +++ b/tests/ui/lifetimes/static-impl-obligation.stderr @@ -0,0 +1,321 @@ +error: lifetime may not live long enough + --> $DIR/static-impl-obligation.rs:8:27 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- lifetime `'a` defined here +LL | let y: &dyn Foo = x; + | ^ cast requires that `'a` must outlive `'static` +LL | y.hello(); + | --------- calling this method introduces a `'static` lifetime requirement + | +help: consider relaxing the implicit `'static` requirement on the impl + | +LL | impl dyn Foo + '_ { + | ++++ + +error: lifetime may not live long enough + --> $DIR/static-impl-obligation.rs:19:27 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- lifetime `'a` defined here +LL | let y: &dyn Foo = x; + | ^ cast requires that `'a` must outlive `'static` +LL | y.hello(); + | --------- calling this method introduces a `'static` lifetime requirement + | +note: the `impl` on `(dyn b::Foo + 'static)` has `'static` lifetime requirements + --> $DIR/static-impl-obligation.rs:15:10 + | +LL | impl dyn Foo { + | ^^^^^^^ +LL | fn hello(&'static self) {} + | ^^^^^^^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/static-impl-obligation.rs:30:27 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- lifetime `'a` defined here +LL | let y: &dyn Foo = x; + | ^ cast requires that `'a` must outlive `'static` +LL | y.hello(); + | --------- calling this method introduces a `'static` lifetime requirement + | +note: the `impl` on `(dyn c::Foo + 'static)` has `'static` lifetime requirements + --> $DIR/static-impl-obligation.rs:26:10 + | +LL | impl dyn Foo { + | ^^^^^^^ +LL | fn hello(&'static self) where Self: 'static {} + | ^^^^^^^^^^^^^ ^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/static-impl-obligation.rs:41:27 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- lifetime `'a` defined here +LL | let y: &dyn Foo = x; + | ^ cast requires that `'a` must outlive `'static` +LL | y.hello(); + | --------- calling this method introduces a `'static` lifetime requirement + | +note: the `impl` on `(dyn d::Foo + 'static)` has `'static` lifetime requirements + --> $DIR/static-impl-obligation.rs:37:10 + | +LL | impl dyn Foo { + | ^^^^^^^ +LL | fn hello(&self) where Self: 'static {} + | ^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/static-impl-obligation.rs:52:27 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- lifetime `'a` defined here +LL | let y: &dyn Foo = x; + | ^ cast requires that `'a` must outlive `'static` +LL | y.hello(); + | --------- calling this method introduces a `'static` lifetime requirement + | +help: consider replacing this `'static` requirement + | +LL | impl dyn Foo + '_ { + | ~~ + +error: lifetime may not live long enough + --> $DIR/static-impl-obligation.rs:63:27 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- lifetime `'a` defined here +LL | let y: &dyn Foo = x; + | ^ cast requires that `'a` must outlive `'static` +LL | y.hello(); + | --------- calling this method introduces a `'static` lifetime requirement + | +note: the `impl` on `(dyn f::Foo + 'static)` has `'static` lifetime requirements + --> $DIR/static-impl-obligation.rs:59:20 + | +LL | impl dyn Foo + 'static { + | ^^^^^^^ +LL | fn hello(&'static self) {} + | ^^^^^^^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/static-impl-obligation.rs:74:27 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- lifetime `'a` defined here +LL | let y: &dyn Foo = x; + | ^ cast requires that `'a` must outlive `'static` +LL | y.hello(); + | --------- calling this method introduces a `'static` lifetime requirement + | +note: the `impl` on `(dyn g::Foo + 'static)` has `'static` lifetime requirements + --> $DIR/static-impl-obligation.rs:70:20 + | +LL | impl dyn Foo + 'static { + | ^^^^^^^ +LL | fn hello(&'static self) where Self: 'static {} + | ^^^^^^^^^^^^^ ^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/static-impl-obligation.rs:85:27 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- lifetime `'a` defined here +LL | let y: &dyn Foo = x; + | ^ cast requires that `'a` must outlive `'static` +LL | y.hello(); + | --------- calling this method introduces a `'static` lifetime requirement + | +note: the `impl` on `(dyn h::Foo + 'static)` has `'static` lifetime requirements + --> $DIR/static-impl-obligation.rs:81:20 + | +LL | impl dyn Foo + 'static { + | ^^^^^^^ +LL | fn hello(&self) where Self: 'static {} + | ^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/static-impl-obligation.rs:96:27 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- lifetime `'a` defined here +LL | let y: &dyn Foo = x; + | ^ cast requires that `'a` must outlive `'static` +LL | y.hello(); + | --------- calling this method introduces a `'static` lifetime requirement + | +note: the `impl` on `(dyn i::Foo + 'static)` has `'static` lifetime requirements + --> $DIR/static-impl-obligation.rs:92:10 + | +LL | impl dyn Foo where Self: 'static { + | ^^^^^^^ ^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/static-impl-obligation.rs:107:27 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- lifetime `'a` defined here +LL | let y: &dyn Foo = x; + | ^ cast requires that `'a` must outlive `'static` +LL | y.hello(); + | --------- calling this method introduces a `'static` lifetime requirement + | +note: the `impl` on `(dyn j::Foo + 'static)` has `'static` lifetime requirements + --> $DIR/static-impl-obligation.rs:103:10 + | +LL | impl dyn Foo where Self: 'static { + | ^^^^^^^ ^^^^^^^ +LL | fn hello(&'static self) {} + | ^^^^^^^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/static-impl-obligation.rs:118:27 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- lifetime `'a` defined here +LL | let y: &dyn Foo = x; + | ^ cast requires that `'a` must outlive `'static` +LL | y.hello(); + | --------- calling this method introduces a `'static` lifetime requirement + | +note: the `impl` on `(dyn k::Foo + 'static)` has `'static` lifetime requirements + --> $DIR/static-impl-obligation.rs:114:10 + | +LL | impl dyn Foo where Self: 'static { + | ^^^^^^^ ^^^^^^^ +LL | fn hello(&'static self) where Self: 'static {} + | ^^^^^^^^^^^^^ ^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/static-impl-obligation.rs:129:27 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- lifetime `'a` defined here +LL | let y: &dyn Foo = x; + | ^ cast requires that `'a` must outlive `'static` +LL | y.hello(); + | --------- calling this method introduces a `'static` lifetime requirement + | +note: the `impl` on `(dyn l::Foo + 'static)` has `'static` lifetime requirements + --> $DIR/static-impl-obligation.rs:125:10 + | +LL | impl dyn Foo where Self: 'static { + | ^^^^^^^ ^^^^^^^ +LL | fn hello(&self) where Self: 'static {} + | ^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/static-impl-obligation.rs:140:27 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- lifetime `'a` defined here +LL | let y: &dyn Foo = x; + | ^ cast requires that `'a` must outlive `'static` +LL | y.hello(); + | --------- calling this method introduces a `'static` lifetime requirement + | +note: the `impl` on `(dyn m::Foo + 'static)` has `'static` lifetime requirements + --> $DIR/static-impl-obligation.rs:136:20 + | +LL | impl dyn Foo + 'static where Self: 'static { + | ^^^^^^^ ^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/static-impl-obligation.rs:151:27 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- lifetime `'a` defined here +LL | let y: &dyn Foo = x; + | ^ cast requires that `'a` must outlive `'static` +LL | y.hello(); + | --------- calling this method introduces a `'static` lifetime requirement + | +note: the `impl` on `(dyn n::Foo + 'static)` has `'static` lifetime requirements + --> $DIR/static-impl-obligation.rs:147:20 + | +LL | impl dyn Foo + 'static where Self: 'static { + | ^^^^^^^ ^^^^^^^ +LL | fn hello(&'static self) {} + | ^^^^^^^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/static-impl-obligation.rs:162:27 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- lifetime `'a` defined here +LL | let y: &dyn Foo = x; + | ^ cast requires that `'a` must outlive `'static` +LL | y.hello(); + | --------- calling this method introduces a `'static` lifetime requirement + | +note: the `impl` on `(dyn o::Foo + 'static)` has `'static` lifetime requirements + --> $DIR/static-impl-obligation.rs:158:20 + | +LL | impl dyn Foo + 'static where Self: 'static { + | ^^^^^^^ ^^^^^^^ +LL | fn hello(&'static self) where Self: 'static {} + | ^^^^^^^^^^^^^ ^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/static-impl-obligation.rs:173:27 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- lifetime `'a` defined here +LL | let y: &dyn Foo = x; + | ^ cast requires that `'a` must outlive `'static` +LL | y.hello(); + | --------- calling this method introduces a `'static` lifetime requirement + | +note: the `impl` on `(dyn p::Foo + 'static)` has `'static` lifetime requirements + --> $DIR/static-impl-obligation.rs:169:20 + | +LL | impl dyn Foo + 'static where Self: 'static { + | ^^^^^^^ ^^^^^^^ +LL | fn hello(&self) where Self: 'static {} + | ^^^^^^^ + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:183:9 + | +LL | fn bar<'a>(x: &'a &'a Foo) { + | -- - `x` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | x.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | calling this method introduces a `'static` lifetime requirement + | +note: the `impl` on `q::Foo` has a `'static` lifetime requirement + --> $DIR/static-impl-obligation.rs:180:18 + | +LL | fn hello(&'static self) {} + | ^^^^^^^^^^^^^ + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:192:9 + | +LL | fn bar<'a>(x: &'a &'a Foo) { + | -- - `x` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | x.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | calling this method introduces a `'static` lifetime requirement + | +note: the `impl` on `r::Foo` has `'static` lifetime requirements + --> $DIR/static-impl-obligation.rs:189:18 + | +LL | fn hello(&'static self) where Self: 'static {} + | ^^^^^^^^^^^^^ ^^^^^^^ + +error: aborting due to 18 previous errors + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/regions/issue-78262.base.stderr b/tests/ui/regions/issue-78262.base.stderr index 113c84c656287..bf915ef35e9a3 100644 --- a/tests/ui/regions/issue-78262.base.stderr +++ b/tests/ui/regions/issue-78262.base.stderr @@ -6,8 +6,14 @@ LL | let f = |x: &dyn TT| x.func(); | | | | | | | `x` escapes the closure body here | | | argument requires that `'1` must outlive `'static` + | | | calling this method introduces a `'static` lifetime requirement | | let's call the lifetime of this reference `'1` | `x` is a reference that is only valid in the closure body + | +help: consider relaxing the implicit `'static` requirement on the impl + | +LL | impl dyn TT + '_ { + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/regions/issue-78262.polonius.stderr b/tests/ui/regions/issue-78262.polonius.stderr index 113c84c656287..bf915ef35e9a3 100644 --- a/tests/ui/regions/issue-78262.polonius.stderr +++ b/tests/ui/regions/issue-78262.polonius.stderr @@ -6,8 +6,14 @@ LL | let f = |x: &dyn TT| x.func(); | | | | | | | `x` escapes the closure body here | | | argument requires that `'1` must outlive `'static` + | | | calling this method introduces a `'static` lifetime requirement | | let's call the lifetime of this reference `'1` | `x` is a reference that is only valid in the closure body + | +help: consider relaxing the implicit `'static` requirement on the impl + | +LL | impl dyn TT + '_ { + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr index 6effaf61099ec..7b918d8ee01f6 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -10,6 +10,7 @@ LL | val.use_self::() | | | `val` escapes the function body here | argument requires that `'a` must outlive `'static` + | calling this method introduces a `'static` lifetime requirement | note: the used `impl` has a `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:15:32 @@ -18,7 +19,7 @@ LL | impl MyTrait for dyn ObjectTrait { | ^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement -help: consider relaxing the implicit `'static` requirement +help: consider relaxing the implicit `'static` requirement on the impl | LL | impl MyTrait for dyn ObjectTrait + '_ { | ++++ @@ -35,6 +36,7 @@ LL | val.use_self() | | | `val` escapes the function body here | argument requires that `'a` must outlive `'static` + | calling this method introduces a `'static` lifetime requirement | note: the used `impl` has a `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:67:14 @@ -43,7 +45,7 @@ LL | impl dyn ObjectTrait { | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement -help: consider relaxing the implicit `'static` requirement +help: consider relaxing the implicit `'static` requirement on the impl | LL | impl dyn ObjectTrait + '_ { | ++++ @@ -69,10 +71,6 @@ LL | fn use_self(&self) -> &() { panic!() } ... LL | impl MyTrait for dyn ObjectTrait {} | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement -help: consider relaxing the implicit `'static` requirement - | -LL | impl MyTrait for dyn ObjectTrait + '_ {} - | ++++ error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:112:9 @@ -95,10 +93,6 @@ LL | fn use_self(&self) -> &() { panic!() } ... LL | impl MyTrait for dyn ObjectTrait {} | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement -help: consider relaxing the implicit `'static` requirement - | -LL | impl MyTrait for dyn ObjectTrait + '_ {} - | ++++ error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:38:9 @@ -112,6 +106,7 @@ LL | val.use_self() | | | `val` escapes the function body here | argument requires that `'a` must outlive `'static` + | calling this method introduces a `'static` lifetime requirement | note: the used `impl` has a `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:32:26 @@ -120,7 +115,7 @@ LL | impl MyTrait for dyn ObjectTrait { | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement -help: consider relaxing the implicit `'static` requirement +help: consider relaxing the implicit `'static` requirement on the impl | LL | impl MyTrait for dyn ObjectTrait + '_ { | ++++