From f80743712eea6e90c4fd73b596bf45c43d9c9e58 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Esteban=20K=C3=BCber?= Date: Tue, 30 Jun 2020 17:41:15 -0700 Subject: [PATCH] Use `ty::Instance::resolve` to identify `'static` bound source --- .../nice_region_error/static_impl_trait.rs | 221 ++++++++---------- src/librustc_middle/traits/mod.rs | 9 +- .../traits/structural_impls.rs | 15 +- .../traits/codegen/mod.rs | 13 ++ .../traits/error_reporting/suggestions.rs | 2 +- src/librustc_typeck/check/method/confirm.rs | 15 +- ...dyn-trait-with-implicit-static-bound.fixed | 23 +- ...rait-with-implicit-static-bound.nll.stderr | 10 +- ...on-dyn-trait-with-implicit-static-bound.rs | 23 +- ...yn-trait-with-implicit-static-bound.stderr | 47 ++-- 10 files changed, 196 insertions(+), 182 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 9fa905cb5ab..9c2e02968f6 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -3,18 +3,20 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::{SubregionOrigin, TypeTrace}; -use crate::traits::ObligationCauseCode; +use crate::traits::{ObligationCauseCode, UnifyReceiverContext}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported}; -use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor}; -use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind}; -use rustc_middle::ty::{ - self, AssocItem, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor, +use rustc_hir::{ + self as hir, GenericBound, ImplItem, Item, ItemKind, Lifetime, LifetimeName, Node, TraitItem, + TyKind, }; +use rustc_middle::ty::{self, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor}; use rustc_span::{MultiSpan, Span}; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { - /// Print the error message for lifetime errors when the return type is a static impl Trait. + /// Print the error message for lifetime errors when the return type is a static `impl Trait`, + /// `dyn Trait` or if a method call on a trait object introduces a static requirement. pub(super) fn try_report_static_impl_trait(&self) -> Option { debug!("try_report_static_impl_trait(error={:?})", self.error); let tcx = self.tcx(); @@ -34,8 +36,8 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option { sub_r, sup_r, ) if **sub_r == RegionKind::ReStatic => { - // This is for the implicit `'static` requirement coming from `impl dyn Trait {}`. - if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code { + // This is for an implicit `'static` requirement coming from `impl dyn Trait {}`. + if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code { let param = self.find_param_with_region(sup_r, sub_r)?; let lifetime = if sup_r.has_name() { format!("lifetime `{}`", sup_r) @@ -55,7 +57,7 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option { .map(|s| format!("`{}`", s)) .unwrap_or_else(|| "`fn` parameter".to_string()), lifetime, - assoc.ident, + ctxt.assoc_item.ident, ); err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime)); err.span_label( @@ -63,7 +65,7 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option { &format!( "...is captured and required to live as long as `'static` here \ because of an implicit lifetime bound on the {}", - match assoc.container { + match ctxt.assoc_item.container { AssocItemContainer::TraitContainer(id) => format!("`impl` of `{}`", tcx.def_path_str(id)), AssocItemContainer::ImplContainer(_) => @@ -71,7 +73,7 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option { }, ), ); - if self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc) { + if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) { err.emit(); return Some(ErrorReported); } else { @@ -117,25 +119,26 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option { let mut postfix = String::new(); if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin { - if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code { - if self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc) + if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code { + if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) && fn_returns.is_empty() { err.code(rustc_errors::error_code!(E0767)); err.set_primary_message(&format!( "{} has {} but calling `{}` introduces an implicit `'static` lifetime \ requirement", - param_name, lifetime, assoc.ident, + param_name, lifetime, ctxt.assoc_item.ident, )); postfix = format!( " because of an implicit lifetime on the {}", - match assoc.container { + match ctxt.assoc_item.container { AssocItemContainer::TraitContainer(id) => format!("`impl` of `{}`", tcx.def_path_str(id)), AssocItemContainer::ImplContainer(_) => "inherent `impl`".to_string(), }, ); } + // } } } @@ -316,128 +319,104 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option { } /// When we call a method coming from an `impl Foo for dyn Bar`, `dyn Bar` introduces a default - /// `'static` obligation. Find `impl` blocks that are implemented + /// `'static` obligation. Suggest relaxing that implicit bound. fn find_impl_on_dyn_trait( &self, err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>, - assoc: &AssocItem, + ctxt: &UnifyReceiverContext<'tcx>, ) -> bool { let tcx = self.tcx(); let mut suggested = false; - // Find the trait object types in the argument. - let mut v = TraitObjectVisitor(vec![]); - v.visit_ty(ty); - - let container_id = match assoc.container { - // When the obligation comes from an `impl Foo for dyn Bar {}`, we - // have the `DefId` of the `trait` itself, not the relevant `impl` - // block. Because of this, we have to look at all the `trait`s - // available, and filter out all that are not of `Foo` (this `def_id`) - // and not of `Bar` (the `filter_map` later in this method). - AssocItemContainer::TraitContainer(def_id) => def_id, + // Find the method being called. + let instance = match ty::Instance::resolve( + tcx, + ctxt.param_env, + ctxt.assoc_item.def_id, + self.infcx.resolve_vars_if_possible(&ctxt.substs), + ) { + Ok(Some(instance)) => instance, + _ => return false, + }; - // When the obligation comes from an `impl dyn Trait {}`, we already - // have the `DefId` of the relevant `Item`, so we use it directly. - AssocItemContainer::ImplContainer(def_id) => { - if let Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) = - tcx.hir().get_if_local(def_id) - { - for found_did in &v.0 { - let mut hir_v = HirTraitObjectVisitor(vec![], *found_did); - hir_v.visit_ty(self_ty); - if let [span] = &hir_v.0[..] { - let mut multi_span: MultiSpan = vec![*span].into(); - multi_span.push_span_label( - *span, - "this has an implicit `'static` lifetime requirement".to_string(), - ); - multi_span.push_span_label( - assoc.ident.span, - "`'static` requirement is introduced when calling this method" - .to_string(), - ); - err.span_note( - multi_span, - &format!( - "`{}`'s inherent `impl` has a `'static` requirement", - tcx.def_path_str(*found_did), - ), - ); - err.span_suggestion_verbose( - span.shrink_to_hi(), - "consider relaxing the implicit `'static` requirement", - " + '_".to_string(), - Applicability::MaybeIncorrect, - ); - suggested = true; - } + // Get the `Ident` of the method being called and the corresponding `impl` (to point at + // `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called). + let (ident, self_ty) = match tcx.hir().get_if_local(instance.def_id()) { + Some(Node::ImplItem(ImplItem { ident, hir_id, .. })) => { + match tcx.hir().find(tcx.hir().get_parent_item(*hir_id)) { + Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) => { + (ident, self_ty) } + _ => return false, } - return suggested; } - }; - - // Find all the `impl`s in the local scope that can be called on the type parameter. And - // retain all that are `impl`s of the trait that originated the `'static` obligation. - // This doesn't find `impl dyn Trait { /**/ }`, but that case is handled above. - let impl_self_tys = tcx - .all_traits(LOCAL_CRATE) - .iter() - .flat_map(|trait_did| tcx.hir().trait_impls(*trait_did)) - .filter_map(|impl_node| { - let impl_did = tcx.hir().local_def_id(*impl_node); - match tcx.hir().get_if_local(impl_did.to_def_id()) { - Some(Node::Item(Item { - kind: ItemKind::Impl { self_ty, of_trait: Some(of_trait), items, .. }, - .. - })) if of_trait.trait_def_id() == Some(container_id) => Some(( - self_ty, - // Get the ident of the method, in order to use its `Span`. - items + Some(Node::TraitItem(TraitItem { ident, hir_id, .. })) => { + let parent_id = tcx.hir().get_parent_item(*hir_id); + match tcx.hir().find(parent_id) { + Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => { + // The method being called is defined in the `trait`, but the `'static` + // obligation comes from the `impl`. Find that `impl` so that we can point + // at it in the suggestion. + let trait_did = tcx.hir().local_def_id(parent_id).to_def_id(); + match tcx.hir().trait_impls(trait_did) .iter() - .filter(|item| item.ident == assoc.ident) - .map(|item| item.ident) + .filter_map(|impl_node| { + let impl_did = tcx.hir().local_def_id(*impl_node); + match tcx.hir().get_if_local(impl_did.to_def_id()) { + Some(Node::Item(Item { + kind: ItemKind::Impl { self_ty, of_trait: Some(of_trait), .. }, + .. + })) if of_trait.trait_def_id() == Some(trait_did) => Some(self_ty), + _ => None, + } + }) .next() - .unwrap_or(assoc.ident), - )), - _ => None, + { + Some(self_ty) => (ident, self_ty), + _ => return false, + } + } + _ => return false, } - }); + } + _ => return false, + }; - // Given all the `impl`s of the relevant `trait`, look for those that are implemented for - // the trait object in the `fn` parameter type. - for (self_ty, method) in impl_self_tys { - for found_did in &v.0 { - let mut hir_v = HirTraitObjectVisitor(vec![], *found_did); - hir_v.visit_ty(self_ty); - if let [span] = &hir_v.0[..] { - let mut multi_span: MultiSpan = vec![*span].into(); - multi_span.push_span_label( - *span, - "this has an implicit `'static` lifetime requirement".to_string(), - ); - multi_span.push_span_label( - method.span, - "`'static` requirement is introduced when calling this method".to_string(), - ); - err.span_note( - multi_span, - &format!( - "`{}`'s `impl` of `{}` has an implicit `'static` requirement", - tcx.def_path_str(*found_did), - tcx.def_path_str(container_id), - ), - ); - err.span_suggestion_verbose( - span.shrink_to_hi(), - "consider relaxing the implicit `'static` requirement", - " + '_".to_string(), - Applicability::MaybeIncorrect, - ); - suggested = true; - } + // Find the trait object types in the argument, so we point at *only* the trait object. + let mut v = TraitObjectVisitor(vec![]); + v.visit_ty(ty); + for found_did in &v.0 { + let mut hir_v = HirTraitObjectVisitor(vec![], *found_did); + hir_v.visit_ty(self_ty); + for span in &hir_v.0 { + let mut multi_span: MultiSpan = vec![*span].into(); + multi_span.push_span_label( + *span, + "this has an implicit `'static` lifetime requirement".to_string(), + ); + multi_span.push_span_label( + ident.span, + "calling this method introduces the `impl`'s 'static` requirement".to_string(), + ); + err.span_note( + multi_span, + &format!( + "{} has a `'static` requirement", + match ctxt.assoc_item.container { + AssocItemContainer::TraitContainer(id) => + format!("`impl` of `{}`", tcx.def_path_str(id)), + AssocItemContainer::ImplContainer(_) => "inherent `impl`".to_string(), + }, + ), + ); + err.span_suggestion_verbose( + span.shrink_to_hi(), + "consider relaxing the implicit `'static` requirement", + " + '_".to_string(), + Applicability::MaybeIncorrect, + ); + suggested = true; } } suggested diff --git a/src/librustc_middle/traits/mod.rs b/src/librustc_middle/traits/mod.rs index c066ea831b2..d2747e5fc65 100644 --- a/src/librustc_middle/traits/mod.rs +++ b/src/librustc_middle/traits/mod.rs @@ -169,6 +169,13 @@ pub fn span(&self, tcx: TyCtxt<'tcx>) -> Span { } } +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct UnifyReceiverContext<'tcx> { + pub assoc_item: ty::AssocItem, + pub param_env: ty::ParamEnv<'tcx>, + pub substs: SubstsRef<'tcx>, +} + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum ObligationCauseCode<'tcx> { /// Not well classified or should be obvious from the span. @@ -300,7 +307,7 @@ pub enum ObligationCauseCode<'tcx> { /// Method receiver MethodReceiver, - UnifyReceiver(Rc), + UnifyReceiver(Box>), /// `return` with no expression ReturnNoExpression, diff --git a/src/librustc_middle/traits/structural_impls.rs b/src/librustc_middle/traits/structural_impls.rs index 61ef0821733..18b4371053a 100644 --- a/src/librustc_middle/traits/structural_impls.rs +++ b/src/librustc_middle/traits/structural_impls.rs @@ -213,13 +213,26 @@ fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option { super::StartFunctionType => Some(super::StartFunctionType), super::IntrinsicType => Some(super::IntrinsicType), super::MethodReceiver => Some(super::MethodReceiver), - super::UnifyReceiver(ref assoc) => Some(super::UnifyReceiver(assoc.clone())), + super::UnifyReceiver(ref ctxt) => tcx.lift(ctxt).map(|ctxt| super::UnifyReceiver(ctxt)), super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)), super::TrivialBound => Some(super::TrivialBound), } } } +impl<'a, 'tcx> Lift<'tcx> for traits::UnifyReceiverContext<'a> { + type Lifted = traits::UnifyReceiverContext<'tcx>; + fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option { + tcx.lift(&self.param_env).and_then(|param_env| { + tcx.lift(&self.substs).map(|substs| traits::UnifyReceiverContext { + assoc_item: self.assoc_item, + param_env, + substs, + }) + }) + } +} + impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> { type Lifted = traits::DerivedObligationCause<'tcx>; fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option { diff --git a/src/librustc_trait_selection/traits/codegen/mod.rs b/src/librustc_trait_selection/traits/codegen/mod.rs index cf575d3eca9..dd7ea55cc10 100644 --- a/src/librustc_trait_selection/traits/codegen/mod.rs +++ b/src/librustc_trait_selection/traits/codegen/mod.rs @@ -6,6 +6,7 @@ use crate::infer::{InferCtxt, TyCtxtInferExt}; use crate::traits::{ FulfillmentContext, ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, + Unimplemented, }; use rustc_errors::ErrorReported; use rustc_middle::ty::fold::TypeFoldable; @@ -58,6 +59,18 @@ pub fn codegen_fulfill_obligation<'tcx>( ); return Err(ErrorReported); } + Err(Unimplemented) => { + // This can trigger when we probe for the source of a `'static` lifetime requirement + // on a trait object: `impl Foo for dyn Trait {}` has an implicit `'static` bound. + infcx.tcx.sess.delay_span_bug( + rustc_span::DUMMY_SP, + &format!( + "Encountered error `Unimplemented` selecting `{:?}` during codegen", + trait_ref + ), + ); + return Err(ErrorReported); + } Err(e) => { bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref) } diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index e94b44d8795..0632ce2319a 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1706,7 +1706,7 @@ fn note_obligation_cause_code( | ObligationCauseCode::IntrinsicType | ObligationCauseCode::MethodReceiver | ObligationCauseCode::ReturnNoExpression - | ObligationCauseCode::UnifyReceiver(_) + | ObligationCauseCode::UnifyReceiver(..) | ObligationCauseCode::MiscObligation => {} ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 58cbe8b2479..ed84095ae6b 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -6,7 +6,7 @@ use crate::hir::GenericArg; use rustc_hir as hir; use rustc_infer::infer::{self, InferOk}; -use rustc_middle::traits::ObligationCauseCode; +use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::fold::TypeFoldable; @@ -16,7 +16,6 @@ use rustc_trait_selection::traits; use std::ops::Deref; -use std::rc::Rc; struct ConfirmContext<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, @@ -97,7 +96,7 @@ fn confirm( "confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}", self_ty, method_sig_rcvr, method_sig, method_predicates ); - self.unify_receivers(self_ty, method_sig_rcvr, &pick); + self.unify_receivers(self_ty, method_sig_rcvr, &pick, all_substs); let (method_sig, method_predicates) = self.normalize_associated_types_in(self.span, &(method_sig, method_predicates)); @@ -345,12 +344,20 @@ fn unify_receivers( self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>, + substs: SubstsRef<'tcx>, ) { debug!( "unify_receivers: self_ty={:?} method_self_ty={:?} span={:?} pick={:?}", self_ty, method_self_ty, self.span, pick ); - let cause = self.cause(self.span, ObligationCauseCode::UnifyReceiver(Rc::new(pick.item))); + let cause = self.cause( + self.span, + ObligationCauseCode::UnifyReceiver(Box::new(UnifyReceiverContext { + assoc_item: pick.item, + param_env: self.param_env, + substs, + })), + ); match self.at(&cause, self.param_env).sup(method_self_ty, self_ty) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed index 832b185e619..45e6cfdb821 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed @@ -5,19 +5,19 @@ mod foo { trait OtherTrait<'a> {} impl<'a> OtherTrait<'a> for &'a () {} - trait ObjectTrait {} - trait MyTrait { - fn use_self(&self) -> &(); + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); } trait Irrelevant {} - impl MyTrait for dyn ObjectTrait + '_ { - fn use_self(&self) -> &() { panic!() } + impl MyTrait for dyn ObjectTrait + '_ { + fn use_self(&self) -> &() { panic!() } } - impl Irrelevant for dyn ObjectTrait {} + impl Irrelevant for dyn ObjectTrait {} - fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - val.use_self() //~ ERROR E0759 + fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self::() //~ ERROR E0759 } } @@ -76,13 +76,11 @@ mod ban { trait ObjectTrait {} trait MyTrait { - fn use_self(&self) -> &(); + fn use_self(&self) -> &() { panic!() } } trait Irrelevant {} - impl MyTrait for dyn ObjectTrait + '_ { - fn use_self(&self) -> &() { panic!() } - } + impl MyTrait for dyn ObjectTrait + '_ {} impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { @@ -90,5 +88,4 @@ mod ban { } } - fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr index 8765591c4a1..fb6e62e76da 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr @@ -1,10 +1,10 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:9 | -LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - | --- `val` is a reference that is only valid in the function body -LL | val.use_self() - | ^^^^^^^^^^^^^^ `val` escapes the function body here +LL | fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | --- `val` is a reference that is only valid in the function body +LL | val.use_self::() + | ^^^^^^^^^^^^^^^^^^^ `val` escapes the function body here | = help: consider replacing `'a` with `'static` @@ -19,7 +19,7 @@ LL | val.use_self() = help: consider replacing `'a` with `'static` error[E0521]: borrowed data escapes outside of function - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:89:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:87:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { | --- `val` is a reference that is only valid in the function body diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs index ba26c2d67df..7de11f4f8fc 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs @@ -5,19 +5,19 @@ mod foo { trait OtherTrait<'a> {} impl<'a> OtherTrait<'a> for &'a () {} - trait ObjectTrait {} - trait MyTrait { - fn use_self(&self) -> &(); + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); } trait Irrelevant {} - impl MyTrait for dyn ObjectTrait { - fn use_self(&self) -> &() { panic!() } + impl MyTrait for dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } } - impl Irrelevant for dyn ObjectTrait {} + impl Irrelevant for dyn ObjectTrait {} - fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - val.use_self() //~ ERROR E0759 + fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self::() //~ ERROR E0759 } } @@ -76,13 +76,11 @@ impl<'a> OtherTrait<'a> for &'a () {} trait ObjectTrait {} trait MyTrait { - fn use_self(&self) -> &(); + fn use_self(&self) -> &() { panic!() } } trait Irrelevant {} - impl MyTrait for dyn ObjectTrait { - fn use_self(&self) -> &() { panic!() } - } + impl MyTrait for dyn ObjectTrait {} impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { @@ -90,5 +88,4 @@ fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { } } - fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr index 425159edbcd..1375ac8db8d 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -1,22 +1,22 @@ error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:13 | -LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - | ------------------- this data with lifetime `'a`... -LL | val.use_self() +LL | fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | ---------------------- this data with lifetime `'a`... +LL | val.use_self::() | ^^^^^^^^ ...is captured and required to live as long as `'static` here | -note: `foo::ObjectTrait`'s `impl` of `foo::MyTrait` has an implicit `'static` requirement - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:14:26 +note: `impl` of `foo::MyTrait` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:14:32 | -LL | impl MyTrait for dyn ObjectTrait { - | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement -LL | fn use_self(&self) -> &() { panic!() } - | -------- `'static` requirement is introduced when calling this method +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 | -LL | impl MyTrait for dyn ObjectTrait + '_ { - | ^^^^ +LL | impl MyTrait for dyn ObjectTrait + '_ { + | ^^^^ error[E0767]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:13 @@ -26,36 +26,37 @@ LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { LL | val.use_self() | ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime bound on the inherent `impl` | -note: `bat::ObjectTrait`'s inherent `impl` has a `'static` requirement +note: inherent `impl` has a `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:64:14 | LL | impl dyn ObjectTrait { | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } - | -------- `'static` requirement is introduced when calling this method + | -------- calling this method introduces the `impl`'s 'static` requirement help: consider relaxing the implicit `'static` requirement | LL | impl dyn ObjectTrait + '_ { | ^^^^ error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:89:13 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:87:13 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { | ------------------- this data with lifetime `'a`... LL | val.use_self() | ^^^^^^^^ ...is captured and required to live as long as `'static` here | -note: `ban::ObjectTrait`'s `impl` of `ban::MyTrait` has an implicit `'static` requirement +note: `impl` of `ban::MyTrait` has a `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:83:26 | -LL | impl MyTrait for dyn ObjectTrait { - | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } - | -------- `'static` requirement is introduced when calling this method + | -------- calling this method introduces the `impl`'s 'static` requirement +... +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 + '_ { +LL | impl MyTrait for dyn ObjectTrait + '_ {} | ^^^^ help: to declare that the `impl Trait` captures data from argument `val`, you can add an explicit `'a` lifetime bound | @@ -70,13 +71,13 @@ LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { LL | val.use_self() | ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime on the `impl` of `bar::MyTrait` | -note: `bar::ObjectTrait`'s `impl` of `bar::MyTrait` has an implicit `'static` requirement +note: `impl` of `bar::MyTrait` has a `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:31:26 | LL | impl MyTrait for dyn ObjectTrait { | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } - | -------- `'static` requirement is introduced when calling this method + | -------- calling this method introduces the `impl`'s 'static` requirement help: consider relaxing the implicit `'static` requirement | LL | impl MyTrait for dyn ObjectTrait + '_ { @@ -90,13 +91,13 @@ LL | fn use_it<'a>(val: &'a Box) -> &'a () { LL | val.use_self() | ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime on the `impl` of `baz::MyTrait` | -note: `baz::ObjectTrait`'s `impl` of `baz::MyTrait` has an implicit `'static` requirement +note: `impl` of `baz::MyTrait` has a `'static` requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:48:30 | LL | impl MyTrait for Box { | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } - | -------- `'static` requirement is introduced when calling this method + | -------- calling this method introduces the `impl`'s 'static` requirement help: consider relaxing the implicit `'static` requirement | LL | impl MyTrait for Box { -- 2.44.0