Increase accuracy of lifetime bound on trait object impl suggestion
This commit is contained in:
parent
6513148c14
commit
4e08bab87d
18 changed files with 321 additions and 114 deletions
|
@ -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,
|
||||
|
|
|
@ -36,12 +36,13 @@ use crate::traits::{Obligation, PredicateObligations};
|
|||
|
||||
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 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||
};
|
||||
|
||||
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 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
|||
|
||||
// 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(
|
||||
|
|
|
@ -2010,7 +2010,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
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))
|
||||
|
|
|
@ -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 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
) 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 @@ 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);
|
||||
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
|
||||
/// `'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<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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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 @@ 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,20 +7,18 @@ use rustc_hir::def_id::LocalDefId;
|
|||
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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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 @@ impl<'tcx> SubregionOrigin<'tcx> {
|
|||
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`"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -300,6 +300,8 @@ pub enum ObligationCauseCode<'tcx> {
|
|||
/// Method receiver
|
||||
MethodReceiver,
|
||||
|
||||
UnifyReceiver(Rc<ty::AssocItem>),
|
||||
|
||||
/// `return` with no expression
|
||||
ReturnNoExpression,
|
||||
|
||||
|
|
|
@ -213,6 +213,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
|
|||
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),
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ pub struct ResolverOutputs {
|
|||
pub extern_prelude: FxHashMap<Symbol, bool>,
|
||||
}
|
||||
|
||||
#[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 @@ 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 {
|
||||
/// Visible everywhere (including in other crates).
|
||||
Public,
|
||||
|
|
|
@ -1706,6 +1706,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
| ObligationCauseCode::IntrinsicType
|
||||
| ObligationCauseCode::MethodReceiver
|
||||
| ObligationCauseCode::ReturnNoExpression
|
||||
| ObligationCauseCode::UnifyReceiver(_)
|
||||
| ObligationCauseCode::MiscObligation => {}
|
||||
ObligationCauseCode::SliceOrArrayElem => {
|
||||
err.note("slice and array elements must have `Sized` type");
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::hir::def_id::DefId;
|
|||
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_span::Span;
|
|||
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 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||
// 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 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||
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 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||
)
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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() {}
|
|
@ -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`.
|
|
@ -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<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() {}
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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<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() {}
|
||||
|
|
|
@ -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<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`.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue