about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2020-06-28 15:26:12 -0700
committerEsteban Küber <esteban@kuber.com.ar>2020-07-22 12:25:54 -0700
commit4e08bab87dbddea55247013bab9735fa2148ec84 (patch)
tree968799d399f34371f60995ff790a10607ca16dfa /src
parent6513148c146c36b0d1649cdb65a3a4737599252f (diff)
downloadrust-4e08bab87dbddea55247013bab9735fa2148ec84.tar.gz
rust-4e08bab87dbddea55247013bab9735fa2148ec84.zip
Increase accuracy of lifetime bound on trait object impl suggestion
Diffstat (limited to 'src')
-rw-r--r--src/librustc_hir/hir.rs12
-rw-r--r--src/librustc_infer/infer/combine.rs10
-rw-r--r--src/librustc_infer/infer/error_reporting/mod.rs2
-rw-r--r--src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs184
-rw-r--r--src/librustc_infer/infer/error_reporting/nice_region_error/util.rs14
-rw-r--r--src/librustc_infer/infer/mod.rs18
-rw-r--r--src/librustc_infer/lib.rs1
-rw-r--r--src/librustc_middle/traits/mod.rs2
-rw-r--r--src/librustc_middle/traits/structural_impls.rs1
-rw-r--r--src/librustc_middle/ty/mod.rs8
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/suggestions.rs1
-rw-r--r--src/librustc_typeck/check/method/confirm.rs24
-rw-r--r--src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs14
-rw-r--r--src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.stderr18
-rw-r--r--src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed36
-rw-r--r--src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr22
-rw-r--r--src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs36
-rw-r--r--src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr32
18 files changed, 321 insertions, 114 deletions
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 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(
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 @@ 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))
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 @@ 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);
+    }
+}
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_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,
 }
 
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 @@ 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`"),
         }
     }
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<ty::AssocItem>),
+
     /// `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 @@ 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),
         }
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<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,
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 @@ 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");
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::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);
             }
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<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() {}
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 @@ 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() {}
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<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`.