1
Fork 0

Increase accuracy of lifetime bound on trait object impl suggestion

This commit is contained in:
Esteban Küber 2020-06-28 15:26:12 -07:00
parent 6513148c14
commit 4e08bab87d
18 changed files with 321 additions and 114 deletions

View file

@ -2198,7 +2198,17 @@ pub enum IsAsync {
NotAsync, NotAsync,
} }
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] #[derive(
Copy,
Clone,
PartialEq,
RustcEncodable,
RustcDecodable,
Debug,
HashStable_Generic,
Eq,
Hash
)]
pub enum Defaultness { pub enum Defaultness {
Default { has_value: bool }, Default { has_value: bool },
Final, Final,

View file

@ -36,12 +36,13 @@ use crate::traits::{Obligation, PredicateObligations};
use rustc_ast::ast; use rustc_ast::ast;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::error::TypeError; use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::{IntType, UintType}; use rustc_middle::ty::{IntType, UintType};
use rustc_span::{Span, DUMMY_SP}; use rustc_span::DUMMY_SP;
#[derive(Clone)] #[derive(Clone)]
pub struct CombineFields<'infcx, 'tcx> { pub struct CombineFields<'infcx, 'tcx> {
@ -367,10 +368,11 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
}; };
debug!("generalize: for_universe = {:?}", for_universe); debug!("generalize: for_universe = {:?}", for_universe);
debug!("generalize: trace = {:?}", self.trace);
let mut generalize = Generalizer { let mut generalize = Generalizer {
infcx: self.infcx, 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_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
for_universe, for_universe,
ambient_variance, ambient_variance,
@ -414,7 +416,7 @@ struct Generalizer<'cx, 'tcx> {
infcx: &'cx InferCtxt<'cx, 'tcx>, infcx: &'cx InferCtxt<'cx, 'tcx>,
/// The span, used when creating new type variables and things. /// 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 /// The vid of the type variable that is in the process of being
/// instantiated; if we find this within the type we are folding, /// instantiated; if we find this within the type we are folding,
@ -639,7 +641,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
// FIXME: This is non-ideal because we don't give a // FIXME: This is non-ideal because we don't give a
// very descriptive origin for this region variable. // 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( fn consts(

View file

@ -2010,7 +2010,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
infer::MiscVariable(_) => String::new(), infer::MiscVariable(_) => String::new(),
infer::PatternRegion(_) => " for pattern".to_string(), infer::PatternRegion(_) => " for pattern".to_string(),
infer::AddrOfRegion(_) => " for borrow expression".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::Coercion(_) => " for automatic coercion".to_string(),
infer::LateBoundRegion(_, br, infer::FnCall) => { infer::LateBoundRegion(_, br, infer::FnCall) => {
format!(" for lifetime parameter {}in function call", br_string(br)) format!(" for lifetime parameter {}in function call", br_string(br))

View file

@ -2,14 +2,14 @@
use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use crate::infer::lexical_region_resolve::RegionResolutionError; 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_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::{ use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor};
GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, Path, PolyTraitRef, TraitRef, use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind};
TyKind, use rustc_middle::ty::{self, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor};
}; use rustc_span::Span;
use rustc_middle::ty::{self, RegionKind, Ty, TypeFoldable, TypeVisitor};
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { 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.
@ -27,6 +27,39 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
) if **sub_r == RegionKind::ReStatic => { ) if **sub_r == RegionKind::ReStatic => {
(var_origin, sub_origin, sub_r, sup_origin, sup_r) (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, _ => return None,
}; };
debug!( debug!(
@ -96,7 +129,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
); );
} }
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); 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); debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
@ -222,63 +259,86 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
/// When we call a method coming from an `impl Foo for dyn Bar`, `dyn Bar` introduces a default /// 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. 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 tcx = self.tcx();
let mut suggested = false;
// Find the trait object types in the argument. // Find the trait object types in the argument.
let mut v = TraitObjectVisitor(vec![]); let mut v = TraitObjectVisitor(vec![]);
v.visit_ty(ty); 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. let container_id = match container {
// FIXME: this doesn't find `impl dyn Trait { /**/ }`. // 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 let impl_self_tys = tcx
.all_traits(LOCAL_CRATE) .all_traits(LOCAL_CRATE)
.iter() .iter()
.flat_map(|trait_did| tcx.hir().trait_impls(*trait_did)) .flat_map(|trait_did| tcx.hir().trait_impls(*trait_did))
.filter_map(|impl_node| { .filter_map(|impl_node| {
let impl_did = tcx.hir().local_def_id(*impl_node); let impl_did = tcx.hir().local_def_id(*impl_node);
if let Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) = match tcx.hir().get_if_local(impl_did.to_def_id()) {
tcx.hir().get_if_local(impl_did.to_def_id()) Some(Node::Item(Item {
{ kind: ItemKind::Impl { self_ty, of_trait: Some(of_trait), .. },
Some(self_ty) ..
} else { })) if of_trait.trait_def_id() == Some(*container_id) => Some(self_ty),
None _ => 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 { for self_ty in impl_self_tys {
if let TyKind::TraitObject( for found_did in &v.0 {
poly_trait_refs, let mut hir_v = HirTraitObjectVisitor(vec![], *found_did);
Lifetime { name: LifetimeName::ImplicitObjectLifetimeDefault, .. }, hir_v.visit_ty(self_ty);
) = self_ty.kind if let [span] = &hir_v.0[..] {
{ err.span_suggestion_verbose(
for p in poly_trait_refs { span.shrink_to_hi(),
if let PolyTraitRef { "this `impl` introduces an implicit `'static` requirement, \
trait_ref: consider changing it",
TraitRef { path: Path { res: Res::Def(DefKind::Trait, did), .. }, .. }, " + '_".to_string(),
.. Applicability::MaybeIncorrect,
} = p );
{ suggested = true;
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<dyn Bar> {}`.
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;
}
}
}
} }
err.emit();
return Some(ErrorReported);
} }
} }
suggested suggested
@ -301,3 +361,31 @@ impl TypeVisitor<'_> for TraitObjectVisitor {
} }
} }
} }
/// Collect all `hir::Ty<'_>` `Span`s for trait objects with an implicit lifetime.
struct HirTraitObjectVisitor(Vec<Span>, DefId);
impl<'tcx> Visitor<'tcx> for HirTraitObjectVisitor {
type Map = ErasedMap<'tcx>;
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
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);
}
}

View file

@ -7,20 +7,18 @@ use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::{self, DefIdTree, Region, Ty}; use rustc_middle::ty::{self, DefIdTree, Region, Ty};
use rustc_span::Span; use rustc_span::Span;
// The struct contains the information about the anonymous region /// Information about the anonymous region we are searching for.
// we are searching for.
#[derive(Debug)] #[derive(Debug)]
pub(super) struct AnonymousParamInfo<'tcx> { 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>, 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>, 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, pub bound_region: ty::BoundRegion,
// param_ty_span contains span of parameter type /// The `Span` of the parameter type.
pub param_ty_span: Span, pub param_ty_span: Span,
// corresponds to id the argument is the first parameter /// Signals that the argument is the first parameter in the declaration.
// in the declaration
pub is_first: bool, pub is_first: bool,
} }

View file

@ -463,7 +463,7 @@ pub enum RegionVariableOrigin {
AddrOfRegion(Span), AddrOfRegion(Span),
/// Regions created as part of an autoref of a method receiver /// 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 /// Regions created as part of an automatic coercion
Coercion(Span), Coercion(Span),
@ -1800,15 +1800,15 @@ impl<'tcx> SubregionOrigin<'tcx> {
impl RegionVariableOrigin { impl RegionVariableOrigin {
pub fn span(&self) -> Span { pub fn span(&self) -> Span {
match *self { match *self {
MiscVariable(a) => a, MiscVariable(a)
PatternRegion(a) => a, | PatternRegion(a)
AddrOfRegion(a) => a, | AddrOfRegion(a)
Autoref(a) => a, | Autoref(a, _)
Coercion(a) => a, | Coercion(a)
EarlyBoundRegion(a, ..) => a, | EarlyBoundRegion(a, ..)
LateBoundRegion(a, ..) => a, | LateBoundRegion(a, ..)
| UpvarRegion(_, a) => a,
BoundRegionInCoherence(_) => rustc_span::DUMMY_SP, BoundRegionInCoherence(_) => rustc_span::DUMMY_SP,
UpvarRegion(_, a) => a,
NLL(..) => bug!("NLL variable used with `span`"), NLL(..) => bug!("NLL variable used with `span`"),
} }
} }

View file

@ -13,6 +13,7 @@
//! This API is completely unstable and subject to change. //! This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(bindings_after_at)]
#![feature(bool_to_option)] #![feature(bool_to_option)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(box_syntax)] #![feature(box_syntax)]

View file

@ -300,6 +300,8 @@ pub enum ObligationCauseCode<'tcx> {
/// Method receiver /// Method receiver
MethodReceiver, MethodReceiver,
UnifyReceiver(Rc<ty::AssocItem>),
/// `return` with no expression /// `return` with no expression
ReturnNoExpression, ReturnNoExpression,

View file

@ -213,6 +213,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
super::StartFunctionType => Some(super::StartFunctionType), super::StartFunctionType => Some(super::StartFunctionType),
super::IntrinsicType => Some(super::IntrinsicType), super::IntrinsicType => Some(super::IntrinsicType),
super::MethodReceiver => Some(super::MethodReceiver), super::MethodReceiver => Some(super::MethodReceiver),
super::UnifyReceiver(ref assoc) => Some(super::UnifyReceiver(assoc.clone())),
super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)), super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
super::TrivialBound => Some(super::TrivialBound), super::TrivialBound => Some(super::TrivialBound),
} }

View file

@ -136,7 +136,7 @@ pub struct ResolverOutputs {
pub extern_prelude: FxHashMap<Symbol, bool>, pub extern_prelude: FxHashMap<Symbol, bool>,
} }
#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)] #[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash)]
pub enum AssocItemContainer { pub enum AssocItemContainer {
TraitContainer(DefId), TraitContainer(DefId),
ImplContainer(DefId), ImplContainer(DefId),
@ -184,7 +184,7 @@ pub enum ImplPolarity {
Reservation, Reservation,
} }
#[derive(Copy, Clone, Debug, PartialEq, HashStable)] #[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash)]
pub struct AssocItem { pub struct AssocItem {
pub def_id: DefId, pub def_id: DefId,
#[stable_hasher(project(name))] #[stable_hasher(project(name))]
@ -199,7 +199,7 @@ pub struct AssocItem {
pub fn_has_self_parameter: bool, pub fn_has_self_parameter: bool,
} }
#[derive(Copy, Clone, PartialEq, Debug, HashStable)] #[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash)]
pub enum AssocKind { pub enum AssocKind {
Const, Const,
Fn, Fn,
@ -316,7 +316,7 @@ impl<'tcx> AssociatedItems<'tcx> {
} }
} }
#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable)] #[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable, Hash)]
pub enum Visibility { pub enum Visibility {
/// Visible everywhere (including in other crates). /// Visible everywhere (including in other crates).
Public, Public,

View file

@ -1706,6 +1706,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
| ObligationCauseCode::IntrinsicType | ObligationCauseCode::IntrinsicType
| ObligationCauseCode::MethodReceiver | ObligationCauseCode::MethodReceiver
| ObligationCauseCode::ReturnNoExpression | ObligationCauseCode::ReturnNoExpression
| ObligationCauseCode::UnifyReceiver(_)
| ObligationCauseCode::MiscObligation => {} | ObligationCauseCode::MiscObligation => {}
ObligationCauseCode::SliceOrArrayElem => { ObligationCauseCode::SliceOrArrayElem => {
err.note("slice and array elements must have `Sized` type"); err.note("slice and array elements must have `Sized` type");

View file

@ -6,6 +6,7 @@ use crate::hir::def_id::DefId;
use crate::hir::GenericArg; use crate::hir::GenericArg;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_infer::infer::{self, InferOk}; use rustc_infer::infer::{self, InferOk};
use rustc_middle::traits::ObligationCauseCode;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::fold::TypeFoldable;
@ -15,6 +16,7 @@ use rustc_span::Span;
use rustc_trait_selection::traits; use rustc_trait_selection::traits;
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc;
struct ConfirmContext<'a, 'tcx> { struct ConfirmContext<'a, 'tcx> {
fcx: &'a FnCtxt<'a, 'tcx>, fcx: &'a FnCtxt<'a, 'tcx>,
@ -91,7 +93,11 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
// signature (which is also done during probing). // signature (which is also done during probing).
let method_sig_rcvr = let method_sig_rcvr =
self.normalize_associated_types_in(self.span, &method_sig.inputs()[0]); 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) = let (method_sig, method_predicates) =
self.normalize_associated_types_in(self.span, &(method_sig, method_predicates)); self.normalize_associated_types_in(self.span, &(method_sig, method_predicates));
@ -150,7 +156,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
if let Some(mutbl) = pick.autoref { 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 }); target = self.tcx.mk_ref(region, ty::TypeAndMut { mutbl, ty: target });
let mutbl = match mutbl { let mutbl = match mutbl {
hir::Mutability::Not => AutoBorrowMutability::Not, hir::Mutability::Not => AutoBorrowMutability::Not,
@ -334,8 +340,18 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
) )
} }
fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) { fn unify_receivers(
match self.at(&self.misc(self.span), self.param_env).sup(method_self_ty, self_ty) { &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: () }) => { Ok(InferOk { obligations, value: () }) => {
self.register_predicates(obligations); self.register_predicates(obligations);
} }

View file

@ -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() {}

View file

@ -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`.

View file

@ -9,10 +9,12 @@ mod foo {
trait MyTrait { trait MyTrait {
fn use_self(&self) -> &(); fn use_self(&self) -> &();
} }
trait Irrelevant {}
impl MyTrait for dyn ObjectTrait + '_ { impl MyTrait for dyn ObjectTrait + '_ {
fn use_self(&self) -> &() { panic!() } fn use_self(&self) -> &() { panic!() }
} }
impl Irrelevant for dyn ObjectTrait {}
fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
val.use_self() //~ ERROR cannot infer an appropriate lifetime val.use_self() //~ ERROR cannot infer an appropriate lifetime
@ -24,14 +26,48 @@ mod bar {
trait MyTrait { trait MyTrait {
fn use_self(&self) -> &(); fn use_self(&self) -> &();
} }
trait Irrelevant {}
impl MyTrait for dyn ObjectTrait + '_ { impl MyTrait for dyn ObjectTrait + '_ {
fn use_self(&self) -> &() { panic!() } fn use_self(&self) -> &() { panic!() }
} }
impl Irrelevant for dyn ObjectTrait {}
fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
val.use_self() //~ ERROR cannot infer an appropriate lifetime 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<dyn ObjectTrait + '_> {
fn use_self(&self) -> &() { panic!() }
}
impl Irrelevant for Box<dyn ObjectTrait> {}
fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'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() {} fn main() {}

View file

@ -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

View file

@ -9,10 +9,12 @@ mod foo {
trait MyTrait { trait MyTrait {
fn use_self(&self) -> &(); fn use_self(&self) -> &();
} }
trait Irrelevant {}
impl MyTrait for dyn ObjectTrait { impl MyTrait for dyn ObjectTrait {
fn use_self(&self) -> &() { panic!() } fn use_self(&self) -> &() { panic!() }
} }
impl Irrelevant for dyn ObjectTrait {}
fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
val.use_self() //~ ERROR cannot infer an appropriate lifetime val.use_self() //~ ERROR cannot infer an appropriate lifetime
@ -24,14 +26,48 @@ mod bar {
trait MyTrait { trait MyTrait {
fn use_self(&self) -> &(); fn use_self(&self) -> &();
} }
trait Irrelevant {}
impl MyTrait for dyn ObjectTrait { impl MyTrait for dyn ObjectTrait {
fn use_self(&self) -> &() { panic!() } fn use_self(&self) -> &() { panic!() }
} }
impl Irrelevant for dyn ObjectTrait {}
fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
val.use_self() //~ ERROR cannot infer an appropriate lifetime 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<dyn ObjectTrait> {
fn use_self(&self) -> &() { panic!() }
}
impl Irrelevant for Box<dyn ObjectTrait> {}
fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'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() {} fn main() {}

View file

@ -1,5 +1,5 @@
error[E0759]: cannot infer an appropriate lifetime 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 { LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
| ------------------- this data with lifetime `'a`... | ------------------- this data with lifetime `'a`...
@ -12,7 +12,20 @@ LL | impl MyTrait for dyn ObjectTrait + '_ {
| ^^^^ | ^^^^
error[E0759]: cannot infer an appropriate lifetime 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 () { LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
| ------------------- this data with lifetime `'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 + '_ { 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<dyn ObjectTrait + '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 MyTrait for Box<dyn ObjectTrait + '_> {
| ^^^^
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0759`. For more information about this error, try `rustc --explain E0759`.