From 4e08bab87dbddea55247013bab9735fa2148ec84 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Esteban=20K=C3=BCber?= Date: Sun, 28 Jun 2020 15:26:12 -0700 Subject: [PATCH] Increase accuracy of lifetime bound on trait object impl suggestion --- src/librustc_hir/hir.rs | 12 +- src/librustc_infer/infer/combine.rs | 10 +- .../infer/error_reporting/mod.rs | 2 +- .../nice_region_error/static_impl_trait.rs | 184 +++++++++++++----- .../error_reporting/nice_region_error/util.rs | 14 +- src/librustc_infer/infer/mod.rs | 18 +- src/librustc_infer/lib.rs | 1 + src/librustc_middle/traits/mod.rs | 2 + .../traits/structural_impls.rs | 1 + src/librustc_middle/ty/mod.rs | 8 +- .../traits/error_reporting/suggestions.rs | 1 + src/librustc_typeck/check/method/confirm.rs | 24 ++- ...mplicit-static-bound-without-suggestion.rs | 14 -- ...cit-static-bound-without-suggestion.stderr | 18 -- ...dyn-trait-with-implicit-static-bound.fixed | 36 ++++ ...rait-with-implicit-static-bound.nll.stderr | 22 +++ ...on-dyn-trait-with-implicit-static-bound.rs | 36 ++++ ...yn-trait-with-implicit-static-bound.stderr | 32 ++- 18 files changed, 321 insertions(+), 114 deletions(-) delete mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs delete mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr create mode 100644 src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index f56522406b0..6474dc318d3 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -2198,7 +2198,17 @@ pub enum IsAsync { NotAsync, } -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] +#[derive( + Copy, + Clone, + PartialEq, + RustcEncodable, + RustcDecodable, + Debug, + HashStable_Generic, + Eq, + Hash +)] pub enum Defaultness { Default { has_value: bool }, Final, diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs index 3b564e03d9a..c63464e5bae 100644 --- a/src/librustc_infer/infer/combine.rs +++ b/src/librustc_infer/infer/combine.rs @@ -36,12 +36,13 @@ use rustc_ast::ast; use rustc_hir::def_id::DefId; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{IntType, UintType}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::DUMMY_SP; #[derive(Clone)] pub struct CombineFields<'infcx, 'tcx> { @@ -367,10 +368,11 @@ fn generalize( }; debug!("generalize: for_universe = {:?}", for_universe); + debug!("generalize: trace = {:?}", self.trace); let mut generalize = Generalizer { infcx: self.infcx, - span: self.trace.cause.span, + cause: &self.trace.cause, for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid), for_universe, ambient_variance, @@ -414,7 +416,7 @@ struct Generalizer<'cx, 'tcx> { infcx: &'cx InferCtxt<'cx, 'tcx>, /// The span, used when creating new type variables and things. - span: Span, + cause: &'cx ObligationCause<'tcx>, /// The vid of the type variable that is in the process of being /// instantiated; if we find this within the type we are folding, @@ -639,7 +641,7 @@ fn regions( // FIXME: This is non-ideal because we don't give a // very descriptive origin for this region variable. - Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.span), self.for_universe)) + Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.cause.span), self.for_universe)) } fn consts( diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index 633589db270..ff905faa95a 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -2010,7 +2010,7 @@ fn report_inference_failure( infer::MiscVariable(_) => String::new(), infer::PatternRegion(_) => " for pattern".to_string(), infer::AddrOfRegion(_) => " for borrow expression".to_string(), - infer::Autoref(_) => " for autoref".to_string(), + infer::Autoref(_, _) => " for autoref".to_string(), infer::Coercion(_) => " for automatic coercion".to_string(), infer::LateBoundRegion(_, br, infer::FnCall) => { format!(" for lifetime parameter {}in function call", br_string(br)) 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 da776f269d5..0aa1d65612e 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 @@ -2,14 +2,14 @@ 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 rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported}; -use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_hir::{ - GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, Path, PolyTraitRef, TraitRef, - TyKind, -}; -use rustc_middle::ty::{self, RegionKind, Ty, TypeFoldable, TypeVisitor}; +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, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor}; +use rustc_span::Span; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when the return type is a static impl Trait. @@ -27,6 +27,39 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option { ) if **sub_r == RegionKind::ReStatic => { (var_origin, sub_origin, sub_r, sup_origin, sup_r) } + RegionResolutionError::ConcreteFailure( + SubregionOrigin::Subtype(box TypeTrace { cause, .. }), + 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 { + let param = self.find_param_with_region(sup_r, sub_r)?; + let lifetime = if sup_r.has_name() { + format!("lifetime `{}`", sup_r) + } else { + "an anonymous lifetime `'_`".to_string() + }; + let mut err = struct_span_err!( + tcx.sess, + cause.span, + E0759, + "cannot infer an appropriate lifetime" + ); + err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime)); + err.span_label( + cause.span, + "...is captured and required to live as long as `'static` here", + ); + if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &assoc.container) { + err.emit(); + return Some(ErrorReported); + } else { + err.cancel(); + } + } + return None; + } _ => return None, }; debug!( @@ -96,7 +129,11 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option { ); } - self.find_impl_on_dyn_trait(&mut err, param.param_ty); + if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin { + if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code { + self.find_impl_on_dyn_trait(&mut err, param.param_ty, &assoc.container); + } + } let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id); debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns); @@ -222,63 +259,86 @@ 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 - fn find_impl_on_dyn_trait(&self, err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>) -> bool { + fn find_impl_on_dyn_trait( + &self, + err: &mut DiagnosticBuilder<'_>, + ty: Ty<'_>, + container: &AssocItemContainer, + ) -> 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); - debug!("TraitObjectVisitor {:?}", v.0); - // Find all the `impl`s in the local scope that can be called on the type parameter. - // FIXME: this doesn't find `impl dyn Trait { /**/ }`. + let container_id = match 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, + + // 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[..] { + err.span_suggestion_verbose( + span.shrink_to_hi(), + "this `impl` introduces an implicit `'static` requirement, \ + consider changing it", + " + '_".to_string(), + Applicability::MaybeIncorrect, + ); + suggested = true; + } + } + } + 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); - if let Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) = - tcx.hir().get_if_local(impl_did.to_def_id()) - { - Some(self_ty) - } else { - None + 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(*container_id) => Some(self_ty), + _ => None, } }); - let mut suggested = 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 in impl_self_tys { - if let TyKind::TraitObject( - poly_trait_refs, - Lifetime { name: LifetimeName::ImplicitObjectLifetimeDefault, .. }, - ) = self_ty.kind - { - for p in poly_trait_refs { - if let PolyTraitRef { - trait_ref: - TraitRef { path: Path { res: Res::Def(DefKind::Trait, did), .. }, .. }, - .. - } = p - { - for found_did in &v.0 { - if did == found_did { - // We've found an `impl Foo for dyn Bar {}`. - // FIXME: we should change this so it also works for - // `impl Foo for Box {}`. - err.span_suggestion_verbose( - self_ty.span.shrink_to_hi(), - "this `impl` introduces an implicit `'static` requirement, \ - consider changing it", - " + '_".to_string(), - Applicability::MaybeIncorrect, - ); - suggested = true; - } - } - } + 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[..] { + err.span_suggestion_verbose( + span.shrink_to_hi(), + "this `impl` introduces an implicit `'static` requirement, \ + consider changing it", + " + '_".to_string(), + Applicability::MaybeIncorrect, + ); + suggested = true; } - err.emit(); - return Some(ErrorReported); } } suggested @@ -301,3 +361,31 @@ fn visit_ty(&mut self, t: Ty<'_>) -> bool { } } } + +/// Collect all `hir::Ty<'_>` `Span`s for trait objects with an implicit lifetime. +struct HirTraitObjectVisitor(Vec, DefId); + +impl<'tcx> Visitor<'tcx> for HirTraitObjectVisitor { + type Map = ErasedMap<'tcx>; + + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::None + } + + fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) { + match t.kind { + TyKind::TraitObject( + poly_trait_refs, + Lifetime { name: LifetimeName::ImplicitObjectLifetimeDefault, .. }, + ) => { + for ptr in poly_trait_refs { + if Some(self.1) == ptr.trait_ref.trait_def_id() { + self.0.push(ptr.span); + } + } + } + _ => {} + } + walk_ty(self, t); + } +} diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs index fa999abb1a8..28e9dd90cfd 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs @@ -7,20 +7,18 @@ use rustc_middle::ty::{self, DefIdTree, Region, Ty}; use rustc_span::Span; -// The struct contains the information about the anonymous region -// we are searching for. +/// Information about the anonymous region we are searching for. #[derive(Debug)] pub(super) struct AnonymousParamInfo<'tcx> { - // the parameter corresponding to the anonymous region + /// The parameter corresponding to the anonymous region. pub param: &'tcx hir::Param<'tcx>, - // the type corresponding to the anonymopus region parameter + /// The type corresponding to the anonymous region parameter. pub param_ty: Ty<'tcx>, - // the ty::BoundRegion corresponding to the anonymous region + /// The ty::BoundRegion corresponding to the anonymous region. pub bound_region: ty::BoundRegion, - // param_ty_span contains span of parameter type + /// The `Span` of the parameter type. pub param_ty_span: Span, - // corresponds to id the argument is the first parameter - // in the declaration + /// Signals that the argument is the first parameter in the declaration. pub is_first: bool, } diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index 37883fcb074..3744ad5d032 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -463,7 +463,7 @@ pub enum RegionVariableOrigin { AddrOfRegion(Span), /// Regions created as part of an autoref of a method receiver - Autoref(Span), + Autoref(Span, ty::AssocItem), /// Regions created as part of an automatic coercion Coercion(Span), @@ -1800,15 +1800,15 @@ pub fn from_obligation_cause(cause: &traits::ObligationCause<'tcx>, default: impl RegionVariableOrigin { pub fn span(&self) -> Span { match *self { - MiscVariable(a) => a, - PatternRegion(a) => a, - AddrOfRegion(a) => a, - Autoref(a) => a, - Coercion(a) => a, - EarlyBoundRegion(a, ..) => a, - LateBoundRegion(a, ..) => a, + MiscVariable(a) + | PatternRegion(a) + | AddrOfRegion(a) + | Autoref(a, _) + | Coercion(a) + | EarlyBoundRegion(a, ..) + | LateBoundRegion(a, ..) + | UpvarRegion(_, a) => a, BoundRegionInCoherence(_) => rustc_span::DUMMY_SP, - UpvarRegion(_, a) => a, NLL(..) => bug!("NLL variable used with `span`"), } } diff --git a/src/librustc_infer/lib.rs b/src/librustc_infer/lib.rs index 0cd6585163c..bacb7fa153e 100644 --- a/src/librustc_infer/lib.rs +++ b/src/librustc_infer/lib.rs @@ -13,6 +13,7 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] +#![feature(bindings_after_at)] #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] diff --git a/src/librustc_middle/traits/mod.rs b/src/librustc_middle/traits/mod.rs index c15c31a53f0..c066ea831b2 100644 --- a/src/librustc_middle/traits/mod.rs +++ b/src/librustc_middle/traits/mod.rs @@ -300,6 +300,8 @@ pub enum ObligationCauseCode<'tcx> { /// Method receiver MethodReceiver, + UnifyReceiver(Rc), + /// `return` with no expression ReturnNoExpression, diff --git a/src/librustc_middle/traits/structural_impls.rs b/src/librustc_middle/traits/structural_impls.rs index 334462790ed..61ef0821733 100644 --- a/src/librustc_middle/traits/structural_impls.rs +++ b/src/librustc_middle/traits/structural_impls.rs @@ -213,6 +213,7 @@ 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::BlockTailExpression(id) => Some(super::BlockTailExpression(id)), super::TrivialBound => Some(super::TrivialBound), } diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 51a353c0132..9007bd99d7e 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -136,7 +136,7 @@ pub struct ResolverOutputs { pub extern_prelude: FxHashMap, } -#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash)] pub enum AssocItemContainer { TraitContainer(DefId), ImplContainer(DefId), @@ -184,7 +184,7 @@ pub enum ImplPolarity { Reservation, } -#[derive(Copy, Clone, Debug, PartialEq, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash)] pub struct AssocItem { pub def_id: DefId, #[stable_hasher(project(name))] @@ -199,7 +199,7 @@ pub struct AssocItem { pub fn_has_self_parameter: bool, } -#[derive(Copy, Clone, PartialEq, Debug, HashStable)] +#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash)] pub enum AssocKind { Const, Fn, @@ -316,7 +316,7 @@ pub fn find_by_name_and_namespace( } } -#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable, Hash)] pub enum Visibility { /// Visible everywhere (including in other crates). Public, diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 0a6fb72ca51..e94b44d8795 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1706,6 +1706,7 @@ fn note_obligation_cause_code( | ObligationCauseCode::IntrinsicType | ObligationCauseCode::MethodReceiver | ObligationCauseCode::ReturnNoExpression + | 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 96248e18aaf..58cbe8b2479 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -6,6 +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::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::fold::TypeFoldable; @@ -15,6 +16,7 @@ use rustc_trait_selection::traits; use std::ops::Deref; +use std::rc::Rc; struct ConfirmContext<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, @@ -91,7 +93,11 @@ fn confirm( // signature (which is also done during probing). let method_sig_rcvr = self.normalize_associated_types_in(self.span, &method_sig.inputs()[0]); - self.unify_receivers(self_ty, method_sig_rcvr); + debug!( + "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); let (method_sig, method_predicates) = self.normalize_associated_types_in(self.span, &(method_sig, method_predicates)); @@ -150,7 +156,7 @@ fn adjust_self_ty( self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); if let Some(mutbl) = pick.autoref { - let region = self.next_region_var(infer::Autoref(self.span)); + let region = self.next_region_var(infer::Autoref(self.span, pick.item)); target = self.tcx.mk_ref(region, ty::TypeAndMut { mutbl, ty: target }); let mutbl = match mutbl { hir::Mutability::Not => AutoBorrowMutability::Not, @@ -334,8 +340,18 @@ fn instantiate_method_substs( ) } - fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) { - match self.at(&self.misc(self.span), self.param_env).sup(method_self_ty, self_ty) { + fn unify_receivers( + &mut self, + self_ty: Ty<'tcx>, + method_self_ty: Ty<'tcx>, + pick: &probe::Pick<'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))); + 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-without-suggestion.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs deleted file mode 100644 index dd53ee06ff5..00000000000 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs +++ /dev/null @@ -1,14 +0,0 @@ -trait OtherTrait<'a> {} -impl<'a> OtherTrait<'a> for &'a () {} - -trait ObjectTrait {} - -impl dyn ObjectTrait { - fn use_self(&self) -> &() { panic!() } -} - -fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - val.use_self() //~ ERROR mismatched types -} - -fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr deleted file mode 100644 index 4618b540c70..00000000000 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs:11:9 - | -LL | val.use_self() - | ^^^^^^^^ lifetime mismatch - | - = note: expected reference `&(dyn ObjectTrait + 'static)` - found reference `&(dyn ObjectTrait + 'a)` -note: the lifetime `'a` as defined on the function body at 10:11... - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs:10:11 - | -LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - | ^^ - = note: ...does not necessarily outlive the static lifetime - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. 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 dfe475d3c06..62cf9b989bb 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 @@ -9,10 +9,12 @@ mod foo { trait MyTrait { fn use_self(&self) -> &(); } + trait Irrelevant {} impl MyTrait for dyn ObjectTrait + '_ { fn use_self(&self) -> &() { panic!() } } + impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { val.use_self() //~ ERROR cannot infer an appropriate lifetime @@ -24,14 +26,48 @@ mod bar { trait MyTrait { fn use_self(&self) -> &(); } + trait Irrelevant {} impl MyTrait for dyn ObjectTrait + '_ { fn use_self(&self) -> &() { panic!() } } + impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { val.use_self() //~ ERROR cannot infer an appropriate lifetime } } +mod baz { + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for Box { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for Box {} + + fn use_it<'a>(val: &'a Box) -> &'a () { + val.use_self() //~ ERROR cannot infer an appropriate lifetime + } +} + +mod bat { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + + impl dyn ObjectTrait + '_ { + fn use_self(&self) -> &() { panic!() } + } + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR cannot infer an appropriate lifetime + } +} + 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 new file mode 100644 index 00000000000..00f65a23489 --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr @@ -0,0 +1,22 @@ +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 + | + = help: consider replacing `'a` with `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69: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 + | + = help: consider replacing `'a` with `'static` + +error: aborting due to 2 previous errors + 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 85e6c2993b9..28a599d12bf 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 @@ -9,10 +9,12 @@ trait ObjectTrait {} trait MyTrait { fn use_self(&self) -> &(); } + trait Irrelevant {} impl MyTrait for dyn ObjectTrait { fn use_self(&self) -> &() { panic!() } } + impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { val.use_self() //~ ERROR cannot infer an appropriate lifetime @@ -24,14 +26,48 @@ trait ObjectTrait {} trait MyTrait { fn use_self(&self) -> &(); } + trait Irrelevant {} impl MyTrait for dyn ObjectTrait { fn use_self(&self) -> &() { panic!() } } + impl Irrelevant for dyn ObjectTrait {} fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { val.use_self() //~ ERROR cannot infer an appropriate lifetime } } +mod baz { + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for Box { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for Box {} + + fn use_it<'a>(val: &'a Box) -> &'a () { + val.use_self() //~ ERROR cannot infer an appropriate lifetime + } +} + +mod bat { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + + impl dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } + } + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR cannot infer an appropriate lifetime + } +} + 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 6780459adbe..1a03590febe 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,5 +1,5 @@ error[E0759]: cannot infer an appropriate lifetime - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:18:13 + --> $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`... @@ -12,7 +12,20 @@ LL | impl MyTrait for dyn ObjectTrait + '_ { | ^^^^ error[E0759]: cannot infer an appropriate lifetime - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:33:13 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:13 + | +LL | fn use_it<'a>(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 + | +help: this `impl` introduces an implicit `'static` requirement, consider changing it + | +LL | impl dyn ObjectTrait + '_ { + | ^^^^ + +error[E0759]: cannot infer an appropriate lifetime + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:37:13 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { | ------------------- this data with lifetime `'a`... @@ -24,6 +37,19 @@ help: this `impl` introduces an implicit `'static` requirement, consider changin LL | impl MyTrait for dyn ObjectTrait + '_ { | ^^^^ -error: aborting due to 2 previous errors +error[E0759]: cannot infer an appropriate lifetime + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:54:13 + | +LL | fn use_it<'a>(val: &'a Box) -> &'a () { + | ----------------------------- this data with lifetime `'a`... +LL | val.use_self() + | ^^^^^^^^ ...is captured and required to live as long as `'static` here + | +help: this `impl` introduces an implicit `'static` requirement, consider changing it + | +LL | impl MyTrait for Box { + | ^^^^ + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0759`. -- 2.44.0