about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_middle/src/middle/resolve_lifetime.rs5
-rw-r--r--compiler/rustc_middle/src/query/mod.rs23
-rw-r--r--compiler/rustc_middle/src/ty/context.rs4
-rw-r--r--compiler/rustc_resolve/src/late/lifetimes.rs483
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs14
-rw-r--r--src/test/ui/error-codes/E0106.stderr22
-rw-r--r--src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr168
-rw-r--r--src/test/ui/generic-associated-types/shadowing.stderr16
-rw-r--r--src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr22
-rw-r--r--src/test/ui/generics/wrong-number-of-args.stderr66
-rw-r--r--src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.rs2
-rw-r--r--src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr18
-rw-r--r--src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr20
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-unresolved.rs2
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-unresolved.stderr17
-rw-r--r--src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs2
-rw-r--r--src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr18
-rw-r--r--src/test/ui/regions/regions-name-undeclared.stderr40
-rw-r--r--src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr87
-rw-r--r--src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs7
-rw-r--r--src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr107
-rw-r--r--src/test/ui/suggestions/missing-lifetime-specifier.stderr48
22 files changed, 581 insertions, 610 deletions
diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_lifetime.rs
index 1b7d0e620a4..32615f6c410 100644
--- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs
+++ b/compiler/rustc_middle/src/middle/resolve_lifetime.rs
@@ -78,9 +78,4 @@ pub struct ResolveLifetimes {
     /// be late-bound if (a) it does NOT appear in a where-clause and
     /// (b) it DOES appear in the arguments.
     pub late_bound: FxHashMap<LocalDefId, FxHashSet<ItemLocalId>>,
-
-    /// For each type and trait definition, maps type parameters
-    /// to the trait object lifetime defaults computed from them.
-    pub object_lifetime_defaults:
-        FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Vec<ObjectLifetimeDefault>>>,
 }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 5ba3864e351..fbd5af9d0a9 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1258,8 +1258,19 @@ rustc_queries! {
         desc { "looking up link arguments for a crate" }
     }
 
-    /// Lifetime resolution. See `middle::resolve_lifetimes`.
-    query resolve_lifetimes(_: CrateNum) -> ResolveLifetimes {
+    /// Does lifetime resolution, but does not descend into trait items. This
+    /// should only be used for resolving lifetimes of on trait definitions,
+    /// and is used to avoid cycles. Importantly, `resolve_lifetimes` still visits
+    /// the same lifetimes and is responsible for diagnostics.
+    /// See `rustc_resolve::late::lifetimes for details.
+    query resolve_lifetimes_trait_definition(_: LocalDefId) -> ResolveLifetimes {
+        storage(ArenaCacheSelector<'tcx>)
+        desc { "resolving lifetimes for a trait definition" }
+    }
+    /// Does lifetime resolution on items. Importantly, we can't resolve
+    /// lifetimes directly on things like trait methods, because of trait params.
+    /// See `rustc_resolve::late::lifetimes for details.
+    query resolve_lifetimes(_: LocalDefId) -> ResolveLifetimes {
         storage(ArenaCacheSelector<'tcx>)
         desc { "resolving lifetimes" }
     }
@@ -1271,9 +1282,13 @@ rustc_queries! {
         Option<(LocalDefId, &'tcx FxHashSet<ItemLocalId>)> {
         desc { "testing if a region is late bound" }
     }
+    /// For a given item (like a struct), gets the default lifetimes to be used
+    /// for each paramter if a trait object were to be passed for that parameter.
+    /// For example, for `struct Foo<'a, T, U>`, this would be `['static, 'static]`.
+    /// For `struct Foo<'a, T: 'a, U>`, this would instead be `['a, 'static]`.
     query object_lifetime_defaults_map(_: LocalDefId)
-        -> Option<&'tcx FxHashMap<ItemLocalId, Vec<ObjectLifetimeDefault>>> {
-        desc { "looking up lifetime defaults for a region" }
+        -> Option<Vec<ObjectLifetimeDefault>> {
+        desc { "looking up lifetime defaults for a region on an item" }
     }
 
     query visibility(def_id: DefId) -> ty::Visibility {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 56c38baa2df..57225b7abf7 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -2641,6 +2641,7 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     pub fn named_region(self, id: HirId) -> Option<resolve_lifetime::Region> {
+        debug!(?id, "named_region");
         self.named_region_map(id.owner).and_then(|map| map.get(&id.local_id).cloned())
     }
 
@@ -2649,9 +2650,8 @@ impl<'tcx> TyCtxt<'tcx> {
             .map_or(false, |(owner, set)| owner == id.owner && set.contains(&id.local_id))
     }
 
-    pub fn object_lifetime_defaults(self, id: HirId) -> Option<&'tcx [ObjectLifetimeDefault]> {
+    pub fn object_lifetime_defaults(self, id: HirId) -> Option<Vec<ObjectLifetimeDefault>> {
         self.object_lifetime_defaults_map(id.owner)
-            .and_then(|map| map.get(&id.local_id).map(|v| &**v))
     }
 }
 
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index 744945c5b0f..698e5048f7b 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -1,3 +1,4 @@
+// ignore-tidy-filelength
 //! Name resolution for lifetimes.
 //!
 //! Name resolution for lifetimes follows *much* simpler rules than the
@@ -11,7 +12,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefIdMap, LOCAL_CRATE};
+use rustc_hir::def_id::DefIdMap;
 use rustc_hir::hir_id::ItemLocalId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node, ParamName, QPath};
@@ -26,6 +27,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
 use std::borrow::Cow;
 use std::cell::Cell;
+use std::fmt;
 use std::mem::take;
 
 use tracing::debug;
@@ -135,7 +137,7 @@ impl RegionExt for Region {
 /// FIXME. This struct gets converted to a `ResolveLifetimes` for
 /// actual use. It has the same data, but indexed by `LocalDefId`.  This
 /// is silly.
-#[derive(Default)]
+#[derive(Debug, Default)]
 struct NamedRegionMap {
     // maps from every use of a named (not anonymous) lifetime to a
     // `Region` describing how that region is bound
@@ -145,10 +147,6 @@ struct NamedRegionMap {
     // be late-bound if (a) it does NOT appear in a where-clause and
     // (b) it DOES appear in the arguments.
     late_bound: HirIdSet,
-
-    // For each type and trait definition, maps type parameters
-    // to the trait object lifetime defaults computed from them.
-    object_lifetime_defaults: HirIdMap<Vec<ObjectLifetimeDefault>>,
 }
 
 crate struct LifetimeContext<'a, 'tcx> {
@@ -176,6 +174,11 @@ crate struct LifetimeContext<'a, 'tcx> {
 
     is_in_const_generic: bool,
 
+    /// Indicates that we only care about the definition of a trait. This should
+    /// be false if the `Item` we are resolving lifetimes for is not a trait or
+    /// we eventually need lifetimes resolve for trait items.
+    trait_definition_only: bool,
+
     /// List of labels in the function/method currently under analysis.
     labels_in_fn: Vec<Ident>,
 
@@ -252,6 +255,42 @@ enum Scope<'a> {
     Root,
 }
 
+// A helper struct for debugging scopes without printing parent scopes
+struct TruncatedScopeDebug<'a>(&'a Scope<'a>);
+
+impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self.0 {
+            Scope::Binder {
+                lifetimes,
+                next_early_index,
+                track_lifetime_uses,
+                opaque_type_parent,
+                s: _,
+            } => f
+                .debug_struct("Binder")
+                .field("lifetimes", lifetimes)
+                .field("next_early_index", next_early_index)
+                .field("track_lifetime_uses", track_lifetime_uses)
+                .field("opaque_type_parent", opaque_type_parent)
+                .field("s", &"..")
+                .finish(),
+            Scope::Body { id, s: _ } => {
+                f.debug_struct("Body").field("id", id).field("s", &"..").finish()
+            }
+            Scope::Elision { elide, s: _ } => {
+                f.debug_struct("Elision").field("elide", elide).field("s", &"..").finish()
+            }
+            Scope::ObjectLifetimeDefault { lifetime, s: _ } => f
+                .debug_struct("ObjectLifetimeDefault")
+                .field("lifetime", lifetime)
+                .field("s", &"..")
+                .finish(),
+            Scope::Root => f.debug_struct("Root").finish(),
+        }
+    }
+}
+
 #[derive(Clone, Debug)]
 enum Elide {
     /// Use a fresh anonymous late-bound lifetime each time, by
@@ -283,26 +322,91 @@ const ROOT_SCOPE: ScopeRef<'static> = &Scope::Root;
 
 pub fn provide(providers: &mut ty::query::Providers) {
     *providers = ty::query::Providers {
+        resolve_lifetimes_trait_definition,
         resolve_lifetimes,
 
-        named_region_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id),
+        named_region_map: |tcx, id| resolve_lifetimes_for(tcx, id).defs.get(&id),
         is_late_bound_map,
         object_lifetime_defaults_map: |tcx, id| {
-            tcx.resolve_lifetimes(LOCAL_CRATE).object_lifetime_defaults.get(&id)
+            let hir_id = tcx.hir().local_def_id_to_hir_id(id);
+            match tcx.hir().find(hir_id) {
+                Some(Node::Item(item)) => compute_object_lifetime_defaults(tcx, item),
+                _ => None,
+            }
         },
 
         ..*providers
     };
 }
 
-/// Computes the `ResolveLifetimes` map that contains data for the
-/// entire crate. You should not read the result of this query
-/// directly, but rather use `named_region_map`, `is_late_bound_map`,
-/// etc.
-fn resolve_lifetimes(tcx: TyCtxt<'_>, for_krate: CrateNum) -> ResolveLifetimes {
-    assert_eq!(for_krate, LOCAL_CRATE);
+/// Like `resolve_lifetimes`, but does not resolve lifetimes for trait items.
+/// Also does not generate any diagnostics.
+///
+/// This is ultimately a subset of the `resolve_lifetimes` work. It effectively
+/// resolves lifetimes only within the trait "header" -- that is, the trait
+/// and supertrait list. In contrast, `resolve_lifetimes` resolves all the
+/// lifetimes within the trait and its items. There is room to refactor this,
+/// for example to resolve lifetimes for each trait item in separate queries,
+/// but it's convenient to do the entire trait at once because the lifetimes
+/// from the trait definition are in scope within the trait items as well.
+///
+/// The reason for this separate call is to resolve what would otherwise
+/// be a cycle. Consider this example:
+///
+/// ```rust
+/// trait Base<'a> {
+///     type BaseItem;
+/// }
+/// trait Sub<'b>: for<'a> Base<'a> {
+///    type SubItem: Sub<BaseItem = &'b u32>;
+/// }
+/// ```
+///
+/// When we resolve `Sub` and all its items, we also have to resolve `Sub<BaseItem = &'b u32>`.
+/// To figure out the index of `'b`, we have to know about the supertraits
+/// of `Sub` so that we can determine that the `for<'a>` will be in scope.
+/// (This is because we -- currently at least -- flatten all the late-bound
+/// lifetimes into a single binder.) This requires us to resolve the
+/// *trait definition* of `Sub`; basically just enough lifetime information
+/// to look at the supertraits.
+#[tracing::instrument(level = "debug", skip(tcx))]
+fn resolve_lifetimes_trait_definition(
+    tcx: TyCtxt<'_>,
+    local_def_id: LocalDefId,
+) -> ResolveLifetimes {
+    do_resolve(tcx, local_def_id, true)
+}
 
-    let named_region_map = krate(tcx);
+/// Computes the `ResolveLifetimes` map that contains data for an entire `Item`.
+/// You should not read the result of this query directly, but rather use
+/// `named_region_map`, `is_late_bound_map`, etc.
+#[tracing::instrument(level = "debug", skip(tcx))]
+fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifetimes {
+    do_resolve(tcx, local_def_id, false)
+}
+
+fn do_resolve(
+    tcx: TyCtxt<'_>,
+    local_def_id: LocalDefId,
+    trait_definition_only: bool,
+) -> ResolveLifetimes {
+    let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(local_def_id));
+    let mut named_region_map =
+        NamedRegionMap { defs: Default::default(), late_bound: Default::default() };
+    let mut visitor = LifetimeContext {
+        tcx,
+        map: &mut named_region_map,
+        scope: ROOT_SCOPE,
+        trait_ref_hack: false,
+        is_in_fn_syntax: false,
+        is_in_const_generic: false,
+        trait_definition_only,
+        labels_in_fn: vec![],
+        xcrate_object_lifetime_defaults: Default::default(),
+        lifetime_uses: &mut Default::default(),
+        missing_named_lifetime_spots: vec![],
+    };
+    visitor.visit_item(item);
 
     let mut rl = ResolveLifetimes::default();
 
@@ -314,14 +418,58 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, for_krate: CrateNum) -> ResolveLifetimes {
         let map = rl.late_bound.entry(hir_id.owner).or_default();
         map.insert(hir_id.local_id);
     }
-    for (hir_id, v) in named_region_map.object_lifetime_defaults {
-        let map = rl.object_lifetime_defaults.entry(hir_id.owner).or_default();
-        map.insert(hir_id.local_id, v);
-    }
 
+    debug!(?rl.defs);
     rl
 }
 
+/// Given `any` owner (structs, traits, trait methods, etc.), does lifetime resolution.
+/// There are two important things this does.
+/// First, we have to resolve lifetimes for
+/// the entire *`Item`* that contains this owner, because that's the largest "scope"
+/// where we can have relevant lifetimes.
+/// Second, if we are asking for lifetimes in a trait *definition*, we use `resolve_lifetimes_trait_definition`
+/// instead of `resolve_lifetimes`, which does not descend into the trait items and does not emit diagnostics.
+/// This allows us to avoid cycles. Importantly, if we ask for lifetimes for lifetimes that have an owner
+/// other than the trait itself (like the trait methods or associated types), then we just use the regular
+/// `resolve_lifetimes`.
+fn resolve_lifetimes_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx ResolveLifetimes {
+    let item_id = item_for(tcx, def_id);
+    if item_id == def_id {
+        let item = tcx.hir().item(hir::ItemId { def_id: item_id });
+        match item.kind {
+            hir::ItemKind::Trait(..) => tcx.resolve_lifetimes_trait_definition(item_id),
+            _ => tcx.resolve_lifetimes(item_id),
+        }
+    } else {
+        tcx.resolve_lifetimes(item_id)
+    }
+}
+
+/// Finds the `Item` that contains the given `LocalDefId`
+fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId {
+    let hir_id = tcx.hir().local_def_id_to_hir_id(local_def_id);
+    match tcx.hir().find(hir_id) {
+        Some(Node::Item(item)) => {
+            return item.def_id;
+        }
+        _ => {}
+    }
+    let item = {
+        let hir = tcx.hir();
+        let mut parent_iter = hir.parent_iter(hir_id);
+        loop {
+            let node = parent_iter.next().map(|n| n.1);
+            match node {
+                Some(hir::Node::Item(item)) => break item.def_id,
+                Some(hir::Node::Crate(_)) | None => bug!("Called `item_for` on an Item."),
+                _ => {}
+            }
+        }
+    };
+    item
+}
+
 fn is_late_bound_map<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
@@ -344,37 +492,10 @@ fn is_late_bound_map<'tcx>(
 
             tcx.is_late_bound_map(def_id.expect_local())
         }
-        _ => tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&def_id).map(|lt| (def_id, lt)),
+        _ => resolve_lifetimes_for(tcx, def_id).late_bound.get(&def_id).map(|lt| (def_id, lt)),
     }
 }
 
-fn krate(tcx: TyCtxt<'_>) -> NamedRegionMap {
-    let krate = tcx.hir().krate();
-    let mut map = NamedRegionMap {
-        defs: Default::default(),
-        late_bound: Default::default(),
-        object_lifetime_defaults: compute_object_lifetime_defaults(tcx),
-    };
-    {
-        let mut visitor = LifetimeContext {
-            tcx,
-            map: &mut map,
-            scope: ROOT_SCOPE,
-            trait_ref_hack: false,
-            is_in_fn_syntax: false,
-            is_in_const_generic: false,
-            labels_in_fn: vec![],
-            xcrate_object_lifetime_defaults: Default::default(),
-            lifetime_uses: &mut Default::default(),
-            missing_named_lifetime_spots: vec![],
-        };
-        for item in krate.items.values() {
-            visitor.visit_item(item);
-        }
-    }
-    map
-}
-
 /// In traits, there is an implicit `Self` type parameter which comes before the generics.
 /// We have to account for this when computing the index of the other generic parameters.
 /// This function returns whether there is such an implicit parameter defined on the given item.
@@ -392,6 +513,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
     // We want to nest trait/impl items in their parent, but nothing else.
     fn visit_nested_item(&mut self, _: hir::ItemId) {}
 
+    fn visit_trait_item_ref(&mut self, ii: &'tcx hir::TraitItemRef) {
+        if !self.trait_definition_only {
+            intravisit::walk_trait_item_ref(self, ii)
+        }
+    }
+
     fn visit_nested_body(&mut self, body: hir::BodyId) {
         // Each body has their own set of labels, save labels.
         let saved = take(&mut self.labels_in_fn);
@@ -430,6 +557,37 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 // Opaque types are visited when we visit the
                 // `TyKind::OpaqueDef`, so that they have the lifetimes from
                 // their parent opaque_ty in scope.
+                //
+                // The core idea here is that since OpaqueTys are generated with the impl Trait as
+                // their owner, we can keep going until we find the Item that owns that. We then
+                // conservatively add all resolved lifetimes. Otherwise we run into problems in
+                // cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`.
+                for (_hir_id, node) in
+                    self.tcx.hir().parent_iter(self.tcx.hir().local_def_id_to_hir_id(item.def_id))
+                {
+                    match node {
+                        hir::Node::Item(parent_item) => {
+                            let resolved_lifetimes: &ResolveLifetimes =
+                                self.tcx.resolve_lifetimes(item_for(self.tcx, parent_item.def_id));
+                            // We need to add *all* deps, since opaque tys may want them from *us*
+                            for (&owner, defs) in resolved_lifetimes.defs.iter() {
+                                defs.iter().for_each(|(&local_id, region)| {
+                                    self.map
+                                        .defs
+                                        .insert(hir::HirId { owner, local_id }, region.clone());
+                                });
+                            }
+                            for (&owner, late_bound) in resolved_lifetimes.late_bound.iter() {
+                                late_bound.iter().for_each(|&local_id| {
+                                    self.map.late_bound.insert(hir::HirId { owner, local_id });
+                                });
+                            }
+                            break;
+                        }
+                        hir::Node::Crate(_) => bug!("No Item about an OpaqueTy"),
+                        _ => {}
+                    }
+                }
             }
             hir::ItemKind::TyAlias(_, ref generics)
             | hir::ItemKind::Enum(_, ref generics)
@@ -495,9 +653,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         }
     }
 
+    #[tracing::instrument(level = "debug", skip(self))]
     fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
-        debug!("visit_ty: id={:?} ty={:?}", ty.hir_id, ty);
-        debug!("visit_ty: ty.kind={:?}", ty.kind);
         match ty.kind {
             hir::TyKind::BareFn(ref c) => {
                 let next_early_index = self.next_early_index();
@@ -541,7 +698,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 self.is_in_fn_syntax = was_in_fn_syntax;
             }
             hir::TyKind::TraitObject(bounds, ref lifetime, _) => {
-                debug!("visit_ty: TraitObject(bounds={:?}, lifetime={:?})", bounds, lifetime);
+                debug!(?bounds, ?lifetime, "TraitObject");
                 for bound in bounds {
                     self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
                 }
@@ -652,14 +809,16 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                                 };
 
                                 if !parent_is_item {
-                                    struct_span_err!(
-                                        self.tcx.sess,
-                                        lifetime.span,
-                                        E0657,
-                                        "`impl Trait` can only capture lifetimes \
-                                             bound at the fn or impl level"
-                                    )
-                                    .emit();
+                                    if !self.trait_definition_only {
+                                        struct_span_err!(
+                                            self.tcx.sess,
+                                            lifetime.span,
+                                            E0657,
+                                            "`impl Trait` can only capture lifetimes \
+                                                bound at the fn or impl level"
+                                        )
+                                        .emit();
+                                    }
                                     self.uninsert_lifetime_on_error(lifetime, def.unwrap());
                                 }
                             }
@@ -670,7 +829,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 // We want to start our early-bound indices at the end of the parent scope,
                 // not including any parent `impl Trait`s.
                 let mut index = self.next_early_index_for_opaque_type();
-                debug!("visit_ty: index = {}", index);
+                debug!(?index);
 
                 let mut elision = None;
                 let mut lifetimes = FxHashMap::default();
@@ -862,8 +1021,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         }
     }
 
+    #[tracing::instrument(level = "debug", skip(self))]
     fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
-        debug!("visit_lifetime(lifetime_ref={:?})", lifetime_ref);
         if lifetime_ref.is_elided() {
             self.resolve_elided_lifetimes(vec![lifetime_ref]);
             return;
@@ -897,7 +1056,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
     }
 
     fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
-        check_mixed_explicit_and_in_band_defs(self.tcx, &generics.params);
+        if !self.trait_definition_only {
+            check_mixed_explicit_and_in_band_defs(self.tcx, &generics.params);
+        }
         for param in generics.params {
             match param.kind {
                 GenericParamKind::Lifetime { .. } => {}
@@ -1224,56 +1385,53 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body<'_>) {
     }
 }
 
-fn compute_object_lifetime_defaults(tcx: TyCtxt<'_>) -> HirIdMap<Vec<ObjectLifetimeDefault>> {
-    let mut map = HirIdMap::default();
-    for item in tcx.hir().krate().items.values() {
-        match item.kind {
-            hir::ItemKind::Struct(_, ref generics)
-            | hir::ItemKind::Union(_, ref generics)
-            | hir::ItemKind::Enum(_, ref generics)
-            | hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                ref generics, impl_trait_fn: None, ..
-            })
-            | hir::ItemKind::TyAlias(_, ref generics)
-            | hir::ItemKind::Trait(_, _, ref generics, ..) => {
-                let result = object_lifetime_defaults_for_item(tcx, generics);
-
-                // Debugging aid.
-                let attrs = tcx.hir().attrs(item.hir_id());
-                if tcx.sess.contains_name(attrs, sym::rustc_object_lifetime_default) {
-                    let object_lifetime_default_reprs: String = result
-                        .iter()
-                        .map(|set| match *set {
-                            Set1::Empty => "BaseDefault".into(),
-                            Set1::One(Region::Static) => "'static".into(),
-                            Set1::One(Region::EarlyBound(mut i, _, _)) => generics
-                                .params
-                                .iter()
-                                .find_map(|param| match param.kind {
-                                    GenericParamKind::Lifetime { .. } => {
-                                        if i == 0 {
-                                            return Some(param.name.ident().to_string().into());
-                                        }
-                                        i -= 1;
-                                        None
+fn compute_object_lifetime_defaults(
+    tcx: TyCtxt<'_>,
+    item: &hir::Item<'_>,
+) -> Option<Vec<ObjectLifetimeDefault>> {
+    match item.kind {
+        hir::ItemKind::Struct(_, ref generics)
+        | hir::ItemKind::Union(_, ref generics)
+        | hir::ItemKind::Enum(_, ref generics)
+        | hir::ItemKind::OpaqueTy(hir::OpaqueTy { ref generics, impl_trait_fn: None, .. })
+        | hir::ItemKind::TyAlias(_, ref generics)
+        | hir::ItemKind::Trait(_, _, ref generics, ..) => {
+            let result = object_lifetime_defaults_for_item(tcx, generics);
+
+            // Debugging aid.
+            let attrs = tcx.hir().attrs(item.hir_id());
+            if tcx.sess.contains_name(attrs, sym::rustc_object_lifetime_default) {
+                let object_lifetime_default_reprs: String = result
+                    .iter()
+                    .map(|set| match *set {
+                        Set1::Empty => "BaseDefault".into(),
+                        Set1::One(Region::Static) => "'static".into(),
+                        Set1::One(Region::EarlyBound(mut i, _, _)) => generics
+                            .params
+                            .iter()
+                            .find_map(|param| match param.kind {
+                                GenericParamKind::Lifetime { .. } => {
+                                    if i == 0 {
+                                        return Some(param.name.ident().to_string().into());
                                     }
-                                    _ => None,
-                                })
-                                .unwrap(),
-                            Set1::One(_) => bug!(),
-                            Set1::Many => "Ambiguous".into(),
-                        })
-                        .collect::<Vec<Cow<'static, str>>>()
-                        .join(",");
-                    tcx.sess.span_err(item.span, &object_lifetime_default_reprs);
-                }
-
-                map.insert(item.hir_id(), result);
+                                    i -= 1;
+                                    None
+                                }
+                                _ => None,
+                            })
+                            .unwrap(),
+                        Set1::One(_) => bug!(),
+                        Set1::Many => "Ambiguous".into(),
+                    })
+                    .collect::<Vec<Cow<'static, str>>>()
+                    .join(",");
+                tcx.sess.span_err(item.span, &object_lifetime_default_reprs);
             }
-            _ => {}
+
+            Some(result)
         }
+        _ => None,
     }
-    map
 }
 
 /// Scan the bounds and where-clauses on parameters to extract bounds
@@ -1392,15 +1550,20 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             trait_ref_hack: self.trait_ref_hack,
             is_in_fn_syntax: self.is_in_fn_syntax,
             is_in_const_generic: self.is_in_const_generic,
+            trait_definition_only: self.trait_definition_only,
             labels_in_fn,
             xcrate_object_lifetime_defaults,
             lifetime_uses,
             missing_named_lifetime_spots,
         };
-        debug!("entering scope {:?}", this.scope);
-        f(self.scope, &mut this);
-        this.check_uses_for_lifetimes_defined_by_scope();
-        debug!("exiting scope {:?}", this.scope);
+        let span = tracing::debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope));
+        {
+            let _enter = span.enter();
+            f(self.scope, &mut this);
+            if !self.trait_definition_only {
+                this.check_uses_for_lifetimes_defined_by_scope();
+            }
+        }
         self.labels_in_fn = this.labels_in_fn;
         self.xcrate_object_lifetime_defaults = this.xcrate_object_lifetime_defaults;
         self.missing_named_lifetime_spots = this.missing_named_lifetime_spots;
@@ -1859,7 +2022,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             }
 
             // Check for fn-syntax conflicts with in-band lifetime definitions
-            if self.is_in_fn_syntax {
+            if !self.trait_definition_only && self.is_in_fn_syntax {
                 match def {
                     Region::EarlyBound(_, _, LifetimeDefOrigin::InBand)
                     | Region::LateBound(_, _, LifetimeDefOrigin::InBand) => {
@@ -1991,47 +2154,47 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             };
 
             let map = &self.map;
-            let unsubst = if let Some(def_id) = def_id.as_local() {
+            let set_to_region = |set: &ObjectLifetimeDefault| match *set {
+                Set1::Empty => {
+                    if in_body {
+                        None
+                    } else {
+                        Some(Region::Static)
+                    }
+                }
+                Set1::One(r) => {
+                    let lifetimes = generic_args.args.iter().filter_map(|arg| match arg {
+                        GenericArg::Lifetime(lt) => Some(lt),
+                        _ => None,
+                    });
+                    r.subst(lifetimes, map)
+                }
+                Set1::Many => None,
+            };
+            if let Some(def_id) = def_id.as_local() {
                 let id = self.tcx.hir().local_def_id_to_hir_id(def_id);
-                &map.object_lifetime_defaults[&id]
+                self.tcx.object_lifetime_defaults(id).unwrap().iter().map(set_to_region).collect()
             } else {
                 let tcx = self.tcx;
-                self.xcrate_object_lifetime_defaults.entry(def_id).or_insert_with(|| {
-                    tcx.generics_of(def_id)
-                        .params
-                        .iter()
-                        .filter_map(|param| match param.kind {
-                            GenericParamDefKind::Type { object_lifetime_default, .. } => {
-                                Some(object_lifetime_default)
-                            }
-                            GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => {
-                                None
-                            }
-                        })
-                        .collect()
-                })
-            };
-            debug!("visit_segment_args: unsubst={:?}", unsubst);
-            unsubst
-                .iter()
-                .map(|set| match *set {
-                    Set1::Empty => {
-                        if in_body {
-                            None
-                        } else {
-                            Some(Region::Static)
-                        }
-                    }
-                    Set1::One(r) => {
-                        let lifetimes = generic_args.args.iter().filter_map(|arg| match arg {
-                            GenericArg::Lifetime(lt) => Some(lt),
-                            _ => None,
-                        });
-                        r.subst(lifetimes, map)
-                    }
-                    Set1::Many => None,
-                })
-                .collect()
+                self.xcrate_object_lifetime_defaults
+                    .entry(def_id)
+                    .or_insert_with(|| {
+                        tcx.generics_of(def_id)
+                            .params
+                            .iter()
+                            .filter_map(|param| match param.kind {
+                                GenericParamDefKind::Type { object_lifetime_default, .. } => {
+                                    Some(object_lifetime_default)
+                                }
+                                GenericParamDefKind::Lifetime
+                                | GenericParamDefKind::Const { .. } => None,
+                            })
+                            .collect()
+                    })
+                    .iter()
+                    .map(set_to_region)
+                    .collect()
+            }
         });
 
         debug!("visit_segment_args: object_lifetime_defaults={:?}", object_lifetime_defaults);
@@ -2092,12 +2255,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         }
     }
 
+    #[tracing::instrument(level = "debug", skip(self))]
     fn visit_fn_like_elision(
         &mut self,
         inputs: &'tcx [hir::Ty<'tcx>],
         output: Option<&'tcx hir::Ty<'tcx>>,
     ) {
-        debug!("visit_fn_like_elision: enter");
         let arg_scope = Scope::Elision { elide: Elide::FreshLateAnon(Cell::new(0)), s: self.scope };
         self.with(arg_scope, |_, this| {
             for input in inputs {
@@ -2110,7 +2273,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             None => return,
         };
 
-        debug!("visit_fn_like_elision: determine output");
+        debug!("determine output");
 
         // Figure out if there's a body we can get argument names from,
         // and whether there's a `self` argument (treated specially).
@@ -2276,11 +2439,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             Elide::Error(arg_lifetimes)
         };
 
-        debug!("visit_fn_like_elision: elide={:?}", elide);
+        debug!(?elide);
 
         let scope = Scope::Elision { elide, s: self.scope };
         self.with(scope, |_, this| this.visit_ty(output));
-        debug!("visit_fn_like_elision: exit");
 
         struct GatherLifetimes<'a> {
             map: &'a NamedRegionMap,
@@ -2743,12 +2905,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         }
     }
 
+    #[tracing::instrument(level = "debug", skip(self))]
     fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: Region) {
         debug!(
-            "insert_lifetime: {} resolved to {:?} span={:?}",
-            self.tcx.hir().node_to_string(lifetime_ref.hir_id),
-            def,
-            self.tcx.sess.source_map().span_to_string(lifetime_ref.span)
+            node = ?self.tcx.hir().node_to_string(lifetime_ref.hir_id),
+            span = ?self.tcx.sess.source_map().span_to_string(lifetime_ref.span)
         );
         self.map.defs.insert(lifetime_ref.hir_id, def);
 
@@ -2762,12 +2923,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             | Region::EarlyBound(_, def_id, _) => {
                 // A lifetime declared by the user.
                 let track_lifetime_uses = self.track_lifetime_uses();
-                debug!("insert_lifetime: track_lifetime_uses={}", track_lifetime_uses);
+                debug!(?track_lifetime_uses);
                 if track_lifetime_uses && !self.lifetime_uses.contains_key(&def_id) {
-                    debug!("insert_lifetime: first use of {:?}", def_id);
+                    debug!("first use of {:?}", def_id);
                     self.lifetime_uses.insert(def_id, LifetimeUseSet::One(lifetime_ref));
                 } else {
-                    debug!("insert_lifetime: many uses of {:?}", def_id);
+                    debug!("many uses of {:?}", def_id);
                     self.lifetime_uses.insert(def_id, LifetimeUseSet::Many);
                 }
             }
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 8076aa7102c..dbc518da8c8 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -198,6 +198,7 @@ pub trait CreateSubstsForGenericArgsCtxt<'a, 'tcx> {
 }
 
 impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
+    #[tracing::instrument(level = "debug", skip(self))]
     pub fn ast_region_to_region(
         &self,
         lifetime: &hir::Lifetime,
@@ -237,6 +238,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
             None => {
                 self.re_infer(def, lifetime.span).unwrap_or_else(|| {
+                    debug!(?lifetime, "unelided lifetime in signature");
+
                     // This indicates an illegal lifetime
                     // elision. `resolve_lifetime` should have
                     // reported an error in this case -- but if
@@ -2173,9 +2176,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
     /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait
     /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors.
+    #[tracing::instrument(level = "debug", skip(self))]
     fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool) -> Ty<'tcx> {
-        debug!("ast_ty_to_ty(id={:?}, ast_ty={:?} ty_ty={:?})", ast_ty.hir_id, ast_ty, ast_ty.kind);
-
         let tcx = self.tcx();
 
         let result_ty = match ast_ty.kind {
@@ -2185,7 +2187,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
             hir::TyKind::Rptr(ref region, ref mt) => {
                 let r = self.ast_region_to_region(region, None);
-                debug!("ast_ty_to_ty: r={:?}", r);
+                debug!(?r);
                 let t = self.ast_ty_to_ty_inner(&mt.ty, true);
                 tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl })
             }
@@ -2209,7 +2211,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed)
             }
             hir::TyKind::Path(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
-                debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
+                debug!(?maybe_qself, ?path);
                 let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself));
                 self.res_to_ty(opt_self_ty, path, false)
             }
@@ -2225,7 +2227,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 }
             }
             hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
-                debug!("ast_ty_to_ty: qself={:?} segment={:?}", qself, segment);
+                debug!(?qself, ?segment);
                 let ty = self.ast_ty_to_ty(qself);
 
                 let res = if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = qself.kind {
@@ -2270,7 +2272,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             hir::TyKind::Err => tcx.ty_error(),
         };
 
-        debug!("ast_ty_to_ty: result_ty={:?}", result_ty);
+        debug!(?result_ty);
 
         self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span);
         result_ty
diff --git a/src/test/ui/error-codes/E0106.stderr b/src/test/ui/error-codes/E0106.stderr
index ac70e887626..b961fc8aeeb 100644
--- a/src/test/ui/error-codes/E0106.stderr
+++ b/src/test/ui/error-codes/E0106.stderr
@@ -24,17 +24,6 @@ LL |     B(&'a bool),
    |
 
 error[E0106]: missing lifetime specifier
-  --> $DIR/E0106.rs:10:14
-   |
-LL | type MyStr = &str;
-   |              ^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL | type MyStr<'a> = &'a str;
-   |           ^^^^   ^^^
-
-error[E0106]: missing lifetime specifier
   --> $DIR/E0106.rs:17:10
    |
 LL |     baz: Baz,
@@ -61,6 +50,17 @@ LL |
 LL |     buzz: Buzz<'a, 'a>,
    |
 
+error[E0106]: missing lifetime specifier
+  --> $DIR/E0106.rs:10:14
+   |
+LL | type MyStr = &str;
+   |              ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | type MyStr<'a> = &'a str;
+   |           ^^^^   ^^^
+
 error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr b/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr
index 0f0406b8e17..497b8a429e0 100644
--- a/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr
+++ b/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr
@@ -1,3 +1,87 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:50:14
+   |
+LL | impl MyTrait<'a> for Y<&'a u8> {
+   |     -        ^^ undeclared lifetime
+   |     |
+   |     help: consider introducing lifetime `'a` here: `<'a>`
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:50:25
+   |
+LL | impl MyTrait<'a> for Y<&'a u8> {
+   |     -                   ^^ undeclared lifetime
+   |     |
+   |     help: consider introducing lifetime `'a` here: `<'a>`
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:53:31
+   |
+LL |     fn my_lifetime(&self) -> &'a u8 { self.0 }
+   |                               ^^ undeclared lifetime
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+help: consider introducing lifetime `'a` here
+   |
+LL | impl<'a> MyTrait<'a> for Y<&'a u8> {
+   |     ^^^^
+help: consider introducing lifetime `'a` here
+   |
+LL |     fn my_lifetime<'a>(&self) -> &'a u8 { self.0 }
+   |                   ^^^^
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:55:27
+   |
+LL |     fn any_lifetime() -> &'b u8 { &0 }
+   |                           ^^ undeclared lifetime
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+help: consider introducing lifetime `'b` here
+   |
+LL | impl<'b> MyTrait<'a> for Y<&'a u8> {
+   |     ^^^^
+help: consider introducing lifetime `'b` here
+   |
+LL |     fn any_lifetime<'b>() -> &'b u8 { &0 }
+   |                    ^^^^
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:57:27
+   |
+LL |     fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
+   |                           ^^ undeclared lifetime
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+help: consider introducing lifetime `'b` here
+   |
+LL | impl<'b> MyTrait<'a> for Y<&'a u8> {
+   |     ^^^^
+help: consider introducing lifetime `'b` here
+   |
+LL |     fn borrowed_lifetime<'b>(&'b self) -> &'b u8 { &*self.0 }
+   |                         ^^^^
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:57:40
+   |
+LL |     fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
+   |                                        ^^ undeclared lifetime
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+help: consider introducing lifetime `'b` here
+   |
+LL | impl<'b> MyTrait<'a> for Y<&'a u8> {
+   |     ^^^^
+help: consider introducing lifetime `'b` here
+   |
+LL |     fn borrowed_lifetime<'b>(&'b self) -> &'b u8 { &*self.0 }
+   |                         ^^^^
+
 error[E0261]: use of undeclared lifetime name `'x`
   --> $DIR/feature-gate-in_band_lifetimes.rs:3:12
    |
@@ -142,90 +226,6 @@ help: consider introducing lifetime `'b` here
 LL |     fn borrowed_lifetime<'b>(&'b self) -> &'b u8;
    |                         ^^^^
 
-error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/feature-gate-in_band_lifetimes.rs:50:14
-   |
-LL | impl MyTrait<'a> for Y<&'a u8> {
-   |     -        ^^ undeclared lifetime
-   |     |
-   |     help: consider introducing lifetime `'a` here: `<'a>`
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-
-error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/feature-gate-in_band_lifetimes.rs:50:25
-   |
-LL | impl MyTrait<'a> for Y<&'a u8> {
-   |     -                   ^^ undeclared lifetime
-   |     |
-   |     help: consider introducing lifetime `'a` here: `<'a>`
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-
-error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/feature-gate-in_band_lifetimes.rs:53:31
-   |
-LL |     fn my_lifetime(&self) -> &'a u8 { self.0 }
-   |                               ^^ undeclared lifetime
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-help: consider introducing lifetime `'a` here
-   |
-LL | impl<'a> MyTrait<'a> for Y<&'a u8> {
-   |     ^^^^
-help: consider introducing lifetime `'a` here
-   |
-LL |     fn my_lifetime<'a>(&self) -> &'a u8 { self.0 }
-   |                   ^^^^
-
-error[E0261]: use of undeclared lifetime name `'b`
-  --> $DIR/feature-gate-in_band_lifetimes.rs:55:27
-   |
-LL |     fn any_lifetime() -> &'b u8 { &0 }
-   |                           ^^ undeclared lifetime
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-help: consider introducing lifetime `'b` here
-   |
-LL | impl<'b> MyTrait<'a> for Y<&'a u8> {
-   |     ^^^^
-help: consider introducing lifetime `'b` here
-   |
-LL |     fn any_lifetime<'b>() -> &'b u8 { &0 }
-   |                    ^^^^
-
-error[E0261]: use of undeclared lifetime name `'b`
-  --> $DIR/feature-gate-in_band_lifetimes.rs:57:27
-   |
-LL |     fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
-   |                           ^^ undeclared lifetime
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-help: consider introducing lifetime `'b` here
-   |
-LL | impl<'b> MyTrait<'a> for Y<&'a u8> {
-   |     ^^^^
-help: consider introducing lifetime `'b` here
-   |
-LL |     fn borrowed_lifetime<'b>(&'b self) -> &'b u8 { &*self.0 }
-   |                         ^^^^
-
-error[E0261]: use of undeclared lifetime name `'b`
-  --> $DIR/feature-gate-in_band_lifetimes.rs:57:40
-   |
-LL |     fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
-   |                                        ^^ undeclared lifetime
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-help: consider introducing lifetime `'b` here
-   |
-LL | impl<'b> MyTrait<'a> for Y<&'a u8> {
-   |     ^^^^
-help: consider introducing lifetime `'b` here
-   |
-LL |     fn borrowed_lifetime<'b>(&'b self) -> &'b u8 { &*self.0 }
-   |                         ^^^^
-
 error: aborting due to 17 previous errors
 
 For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/generic-associated-types/shadowing.stderr b/src/test/ui/generic-associated-types/shadowing.stderr
index 95cebbb8681..d45ef83873a 100644
--- a/src/test/ui/generic-associated-types/shadowing.stderr
+++ b/src/test/ui/generic-associated-types/shadowing.stderr
@@ -15,14 +15,6 @@ LL |     type Bar<T> = i32;
    |              ^ already used
 
 error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
-  --> $DIR/shadowing.rs:5:14
-   |
-LL | trait Shadow<'a> {
-   |              -- first declared here
-LL |     type Bar<'a>;
-   |              ^^ lifetime `'a` already in scope
-
-error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
   --> $DIR/shadowing.rs:14:14
    |
 LL | impl<'a> NoShadow<'a> for &'a u32 {
@@ -30,6 +22,14 @@ LL | impl<'a> NoShadow<'a> for &'a u32 {
 LL |     type Bar<'a> = i32;
    |              ^^ lifetime `'a` already in scope
 
+error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
+  --> $DIR/shadowing.rs:5:14
+   |
+LL | trait Shadow<'a> {
+   |              -- first declared here
+LL |     type Bar<'a>;
+   |              ^^ lifetime `'a` already in scope
+
 error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0403, E0496.
diff --git a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
index 1106a067822..ce853d4d36d 100644
--- a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
+++ b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
@@ -5,6 +5,17 @@ LL | fn should_error<T>() where T : Into<&u32> {}
    |                                     ^ explicit lifetime name needed here
 
 error[E0106]: missing lifetime specifier
+  --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:13:17
+   |
+LL | fn bar<'b, L: X<&'b Nested<i32>>>(){}
+   |                 ^ expected named lifetime parameter
+   |
+help: consider using the `'b` lifetime
+   |
+LL | fn bar<'b, L: X<'b, &'b Nested<i32>>>(){}
+   |                 ^^^
+
+error[E0106]: missing lifetime specifier
   --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:21
    |
 LL |     fn foo<'b, L: X<&'b Nested<K>>>();
@@ -22,17 +33,6 @@ help: consider using one of the available lifetimes here
 LL |     fn foo<'b, L: X<'lifetime, &'b Nested<K>>>();
    |                     ^^^^^^^^^^
 
-error[E0106]: missing lifetime specifier
-  --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:13:17
-   |
-LL | fn bar<'b, L: X<&'b Nested<i32>>>(){}
-   |                 ^ expected named lifetime parameter
-   |
-help: consider using the `'b` lifetime
-   |
-LL | fn bar<'b, L: X<'b, &'b Nested<i32>>>(){}
-   |                 ^^^
-
 error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0106, E0637.
diff --git a/src/test/ui/generics/wrong-number-of-args.stderr b/src/test/ui/generics/wrong-number-of-args.stderr
index 73bd76aa5fa..94fdd355d48 100644
--- a/src/test/ui/generics/wrong-number-of-args.stderr
+++ b/src/test/ui/generics/wrong-number-of-args.stderr
@@ -1,36 +1,3 @@
-error[E0106]: missing lifetime specifier
-  --> $DIR/wrong-number-of-args.rs:44:14
-   |
-LL |     type A = Ty;
-   |              ^^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL |     type A<'a> = Ty<'a>;
-   |           ^^^^   ^^^^^^
-
-error[E0106]: missing lifetime specifier
-  --> $DIR/wrong-number-of-args.rs:54:17
-   |
-LL |     type C = Ty<usize>;
-   |                 ^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL |     type C<'a> = Ty<'a, usize>;
-   |           ^^^^      ^^^
-
-error[E0106]: missing lifetime specifier
-  --> $DIR/wrong-number-of-args.rs:100:22
-   |
-LL |     type B = Box<dyn GenericLifetime>;
-   |                      ^^^^^^^^^^^^^^^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL |     type B<'a> = Box<dyn GenericLifetime<'a>>;
-   |           ^^^^           ^^^^^^^^^^^^^^^^^^^
-
 error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
   --> $DIR/wrong-number-of-args.rs:6:14
    |
@@ -165,6 +132,17 @@ help: use angle brackets to add missing type argument
 LL |     type A = Ty<T>;
    |                ^^^
 
+error[E0106]: missing lifetime specifier
+  --> $DIR/wrong-number-of-args.rs:44:14
+   |
+LL |     type A = Ty;
+   |              ^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |     type A<'a> = Ty<'a>;
+   |           ^^^^   ^^^^^^
+
 error[E0107]: this struct takes 1 type argument but 0 type arguments were supplied
   --> $DIR/wrong-number-of-args.rs:50:14
    |
@@ -181,6 +159,17 @@ help: add missing type argument
 LL |     type B = Ty<'static, T>;
    |                        ^^^
 
+error[E0106]: missing lifetime specifier
+  --> $DIR/wrong-number-of-args.rs:54:17
+   |
+LL |     type C = Ty<usize>;
+   |                 ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |     type C<'a> = Ty<'a, usize>;
+   |           ^^^^      ^^^
+
 error[E0107]: missing generics for struct `type_and_type_and_type::Ty`
   --> $DIR/wrong-number-of-args.rs:64:14
    |
@@ -243,6 +232,17 @@ note: trait defined here, with 0 type parameters
 LL |     trait NonGeneric {
    |           ^^^^^^^^^^
 
+error[E0106]: missing lifetime specifier
+  --> $DIR/wrong-number-of-args.rs:100:22
+   |
+LL |     type B = Box<dyn GenericLifetime>;
+   |                      ^^^^^^^^^^^^^^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |     type B<'a> = Box<dyn GenericLifetime<'a>>;
+   |           ^^^^           ^^^^^^^^^^^^^^^^^^^
+
 error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
   --> $DIR/wrong-number-of-args.rs:104:22
    |
diff --git a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.rs b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.rs
index c1c40afdbab..3b407871e37 100644
--- a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.rs
+++ b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.rs
@@ -7,7 +7,7 @@ fn foo(x: &u32) {
 
 fn foo2(x: &u32) {}
 fn bar() {
-    let y: fn(&'test u32) = foo2; //~ ERROR use of undeclared lifetime
+    let y: fn(&'test u32) = foo2;
 }
 
 fn main() {}
diff --git a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr
index a43b49041ec..7ecb6ff0c9d 100644
--- a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr
+++ b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr
@@ -6,22 +6,6 @@ LL | fn foo(x: &u32) {
 LL |     let y: &'test u32 = x;
    |             ^^^^^ undeclared lifetime
 
-error[E0261]: use of undeclared lifetime name `'test`
-  --> $DIR/no_introducing_in_band_in_locals.rs:10:16
-   |
-LL |     let y: fn(&'test u32) = foo2;
-   |                ^^^^^ undeclared lifetime
-   |
-   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
-help: consider introducing lifetime `'test` here
-   |
-LL | fn bar<'test>() {
-   |       ^^^^^^^
-help: consider making the type lifetime-generic with a new `'test` lifetime
-   |
-LL |     let y: for<'test> fn(&'test u32) = foo2;
-   |            ^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr b/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr
index 30142e24cd5..16333a7ca38 100644
--- a/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr
+++ b/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr
@@ -1,4 +1,14 @@
 error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9
+   |
+LL | struct Test {
+   |            - help: consider introducing lifetime `'b` here: `<'b>`
+LL |     a: &'b str,
+   |         ^^ undeclared lifetime
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+
+error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:13:13
    |
 LL |     fn foo(&'b self) {}
@@ -17,16 +27,6 @@ LL |     fn foo<'b>(&'b self) {}
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9
    |
-LL | struct Test {
-   |            - help: consider introducing lifetime `'b` here: `<'b>`
-LL |     a: &'b str,
-   |         ^^ undeclared lifetime
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-
-error[E0261]: use of undeclared lifetime name `'b`
-  --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9
-   |
 LL | #[derive(Eq, PartialEq)]
    |          -- lifetime `'b` is missing in item created through this procedural macro
 LL | struct Test {
diff --git a/src/test/ui/methods/method-call-lifetime-args-unresolved.rs b/src/test/ui/methods/method-call-lifetime-args-unresolved.rs
index d16ba3df47b..d7760985ec6 100644
--- a/src/test/ui/methods/method-call-lifetime-args-unresolved.rs
+++ b/src/test/ui/methods/method-call-lifetime-args-unresolved.rs
@@ -1,3 +1,5 @@
 fn main() {
     0.clone::<'a>(); //~ ERROR use of undeclared lifetime name `'a`
+    //~^ WARNING cannot specify lifetime arguments
+    //~| WARNING this was previously accepted
 }
diff --git a/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr b/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
index 93c0384fcc2..5a958bc4b9c 100644
--- a/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
+++ b/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
@@ -1,3 +1,18 @@
+warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/method-call-lifetime-args-unresolved.rs:2:15
+   |
+LL |     0.clone::<'a>();
+   |               ^^
+   | 
+  ::: $SRC_DIR/core/src/clone.rs:LL:COL
+   |
+LL |     fn clone(&self) -> Self;
+   |              - the late bound lifetime parameter is introduced here
+   |
+   = note: `#[warn(late_bound_lifetime_arguments)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/method-call-lifetime-args-unresolved.rs:2:15
    |
@@ -8,6 +23,6 @@ LL |     0.clone::<'a>();
    |
    = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs
index 0e3ea4bc8c9..6aa34354a7a 100644
--- a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs
+++ b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs
@@ -8,7 +8,7 @@ struct ChunkingIterator<T, S: 'static + Iterator<Item = T>> {
 impl<T, S: Iterator<Item = T>> Iterator for ChunkingIterator<T, S> {
     type Item = IteratorChunk<T, S>; //~ ERROR missing lifetime
 
-    fn next(&mut self) -> Option<IteratorChunk<T, S>> { //~ ERROR `impl`
+    fn next(&mut self) -> Option<IteratorChunk<T, S>> {
         todo!()
     }
 }
diff --git a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr
index 5df35fa571c..1e035ff99d0 100644
--- a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr
+++ b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr
@@ -9,22 +9,6 @@ help: consider introducing a named lifetime parameter
 LL |     type Item<'a> = IteratorChunk<'a, T, S>;
    |              ^^^^                 ^^^
 
-error: `impl` item signature doesn't match `trait` item signature
-  --> $DIR/issue-74918-missing-lifetime.rs:11:5
-   |
-LL |     fn next(&mut self) -> Option<IteratorChunk<T, S>> {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'_, T, S>>`
-   | 
-  ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn next(&mut self) -> Option<Self::Item>;
-   |     ----------------------------------------- expected `fn(&mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, _, _>>`
-   |
-   = note: expected `fn(&mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, _, _>>`
-              found `fn(&mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'_, _, _>>`
-   = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
-   = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/regions/regions-name-undeclared.stderr b/src/test/ui/regions/regions-name-undeclared.stderr
index ad0e7bd5afb..5f6ff280e65 100644
--- a/src/test/ui/regions/regions-name-undeclared.stderr
+++ b/src/test/ui/regions/regions-name-undeclared.stderr
@@ -1,3 +1,23 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/regions-name-undeclared.rs:28:13
+   |
+LL |     enum E {
+   |           - help: consider introducing lifetime `'a` here: `<'a>`
+LL |         E1(&'a isize)
+   |             ^^ undeclared lifetime
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/regions-name-undeclared.rs:31:13
+   |
+LL |     struct S {
+   |             - help: consider introducing lifetime `'a` here: `<'a>`
+LL |         f: &'a isize
+   |             ^^ undeclared lifetime
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/regions-name-undeclared.rs:16:24
    |
@@ -57,26 +77,6 @@ LL |     type X = Option<&'a isize>;
    = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
 
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/regions-name-undeclared.rs:28:13
-   |
-LL |     enum E {
-   |           - help: consider introducing lifetime `'a` here: `<'a>`
-LL |         E1(&'a isize)
-   |             ^^ undeclared lifetime
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-
-error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/regions-name-undeclared.rs:31:13
-   |
-LL |     struct S {
-   |             - help: consider introducing lifetime `'a` here: `<'a>`
-LL |         f: &'a isize
-   |             ^^ undeclared lifetime
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-
-error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/regions-name-undeclared.rs:33:14
    |
 LL |     fn f(a: &'a isize) { }
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr
index b509610b89e..916a6c2bf12 100644
--- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr
+++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr
@@ -1,92 +1,11 @@
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/missing-lifetimes-in-signature.rs:37:11
+  --> $DIR/missing-lifetimes-in-signature.rs:36:11
    |
 LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
    |        -  ^^ undeclared lifetime
    |        |
    |        help: consider introducing lifetime `'a` here: `'a,`
 
-error: lifetime may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:15:37
-   |
-LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
-   |                          -          ^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static`
-   |                          |
-   |                          let's call the lifetime of this reference `'1`
-   |
-help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
-   |
-LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                     ^^^^^^^^^^^^^^^^^^
-
-error[E0311]: the parameter type `G` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:25:37
-   |
-LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                     ^^^^^^^^^^^^^^^^^^
-   |
-note: the parameter type `G` must be valid for the anonymous lifetime defined on the function body at 25:26...
-  --> $DIR/missing-lifetimes-in-signature.rs:25:26
-   |
-LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                          ^^^^^^
-
-error[E0311]: the parameter type `G` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:47:45
-   |
-LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                             ^^^^^^^^^^^^^^^^^^
-   |
-note: the parameter type `G` must be valid for the anonymous lifetime defined on the function body at 47:34...
-  --> $DIR/missing-lifetimes-in-signature.rs:47:34
-   |
-LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                  ^^^^^^
-
-error[E0311]: the parameter type `G` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:59:58
-   |
-LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
-   |                                                          ^^^^^^^^^^^^^^^^^^
-   |
-note: the parameter type `G` must be valid for the anonymous lifetime defined on the method body at 59:47...
-  --> $DIR/missing-lifetimes-in-signature.rs:59:47
-   |
-LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
-   |                                               ^^^^^^
-
-error[E0311]: the parameter type `G` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:68:45
-   |
-LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
-   |                                             ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: the parameter type `G` must be valid for the anonymous lifetime defined on the function body at 68:34...
-  --> $DIR/missing-lifetimes-in-signature.rs:68:34
-   |
-LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
-   |                                  ^^^^^^
-
-error[E0621]: explicit lifetime required in the type of `dest`
-  --> $DIR/missing-lifetimes-in-signature.rs:73:5
-   |
-LL |   fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
-   |                                    ------ help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
-...
-LL | /     move || {
-LL | |         *dest = g.get();
-LL | |     }
-   | |_____^ lifetime `'a` required
-
-error[E0309]: the parameter type `G` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:79:44
-   |
-LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
-   |                                            ^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `G: 'a`...
-
-error: aborting due to 8 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0261, E0309, E0621.
-For more information about an error, try `rustc --explain E0261`.
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs
index 94dd826a15c..dd434ea5318 100644
--- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs
+++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs
@@ -16,14 +16,13 @@ fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
 where
     G: Get<T>
 {
-    move || { //~ ERROR `dest`
+    move || {
         *dest = g.get();
     }
 }
 
 // After applying suggestion for `foo`:
 fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-//~^ ERROR the parameter type `G` may not live long enough
 where
     G: Get<T>
 {
@@ -45,7 +44,6 @@ where
 
 // After applying suggestion for `baz`:
 fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-//~^ ERROR the parameter type `G` may not live long enough
 where
     G: Get<T>
 {
@@ -57,7 +55,6 @@ where
 // Same as above, but show that we pay attention to lifetime names from parent item
 impl<'a> Foo {
     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
-        //~^ ERROR the parameter type `G` may not live long enough
         move || {
             *dest = g.get();
         }
@@ -66,7 +63,6 @@ impl<'a> Foo {
 
 // After applying suggestion for `qux`:
 fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
-//~^ ERROR explicit lifetime required in the type of `dest`
 where
     G: Get<T>
 {
@@ -77,7 +73,6 @@ where
 
 // Potential incorrect attempt:
 fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
-//~^ ERROR the parameter type `G` may not live long enough
 where
     G: Get<T>
 {
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
index 789fff7acc2..916a6c2bf12 100644
--- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
+++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
@@ -1,112 +1,11 @@
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/missing-lifetimes-in-signature.rs:37:11
+  --> $DIR/missing-lifetimes-in-signature.rs:36:11
    |
 LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
    |        -  ^^ undeclared lifetime
    |        |
    |        help: consider introducing lifetime `'a` here: `'a,`
 
-error[E0759]: `dest` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
-  --> $DIR/missing-lifetimes-in-signature.rs:19:5
-   |
-LL |   fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
-   |                            ------ this data with an anonymous lifetime `'_`...
-...
-LL | /     move || {
-LL | |         *dest = g.get();
-LL | |     }
-   | |_____^ ...is captured here...
-   |
-note: ...and is required to live as long as `'static` here
-  --> $DIR/missing-lifetimes-in-signature.rs:15:37
-   |
-LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
-   |                                     ^^^^^^^^^^^^^
-help: to declare that the `impl Trait` captures data from argument `dest`, you can add an explicit `'_` lifetime bound
-   |
-LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                                   ^^^^
-
-error[E0311]: the parameter type `G` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:25:37
-   |
-LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                     ^^^^^^^^^^^^^^^^^^
-   |
-note: the parameter type `G` must be valid for the anonymous lifetime defined on the function body at 25:26...
-  --> $DIR/missing-lifetimes-in-signature.rs:25:26
-   |
-LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                          ^^^^^^
-note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:30:5: 32:6]` will meet its required lifetime bounds
-  --> $DIR/missing-lifetimes-in-signature.rs:25:37
-   |
-LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                     ^^^^^^^^^^^^^^^^^^
-help: consider introducing an explicit lifetime bound
-   |
-LL | fn bar<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
-   |        ^^^^^                                                   ^^^^
-
-error[E0311]: the parameter type `G` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:47:45
-   |
-LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                             ^^^^^^^^^^^^^^^^^^
-   |
-note: the parameter type `G` must be valid for the anonymous lifetime defined on the function body at 47:34...
-  --> $DIR/missing-lifetimes-in-signature.rs:47:34
-   |
-LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                  ^^^^^^
-note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:52:5: 54:6]` will meet its required lifetime bounds
-  --> $DIR/missing-lifetimes-in-signature.rs:47:45
-   |
-LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |                                             ^^^^^^^^^^^^^^^^^^
-help: consider introducing an explicit lifetime bound
-   |
-LL | fn qux<'b, 'a, G: 'b + 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'b
-   |        ^^^     ^^^^^^^                                                  ^^^^
-
-error[E0311]: the parameter type `G` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:59:58
-   |
-LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
-   |                                                          ^^^^^^^^^^^^^^^^^^
-   |
-note: the parameter type `G` must be valid for the anonymous lifetime defined on the method body at 59:47...
-  --> $DIR/missing-lifetimes-in-signature.rs:59:47
-   |
-LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
-   |                                               ^^^^^^
-note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:61:9: 63:10]` will meet its required lifetime bounds
-  --> $DIR/missing-lifetimes-in-signature.rs:59:58
-   |
-LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
-   |                                                          ^^^^^^^^^^^^^^^^^^
-help: consider introducing an explicit lifetime bound
-   |
-LL |     fn qux<'c, 'b, G: 'c + Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'c {
-   |            ^^^     ^^^^^^^                                                           ^^^^
-
-error[E0621]: explicit lifetime required in the type of `dest`
-  --> $DIR/missing-lifetimes-in-signature.rs:68:45
-   |
-LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
-   |                                  ------     ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required
-   |                                  |
-   |                                  help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
-
-error[E0309]: the parameter type `G` may not live long enough
-  --> $DIR/missing-lifetimes-in-signature.rs:79:44
-   |
-LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
-   |            -                               ^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:84:5: 86:6]` will meet its required lifetime bounds
-   |            |
-   |            help: consider adding an explicit lifetime bound...: `G: 'a`
-
-error: aborting due to 7 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0261, E0309, E0621, E0759.
-For more information about an error, try `rustc --explain E0261`.
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.stderr b/src/test/ui/suggestions/missing-lifetime-specifier.stderr
index e6cec5cbd45..489926ea78a 100644
--- a/src/test/ui/suggestions/missing-lifetime-specifier.stderr
+++ b/src/test/ui/suggestions/missing-lifetime-specifier.stderr
@@ -142,30 +142,6 @@ help: consider using the `'static` lifetime
 LL |     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                                 ^^^^^^^^^^^^^^^^^
 
-error[E0106]: missing lifetime specifier
-  --> $DIR/missing-lifetime-specifier.rs:50:44
-   |
-LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ^ expected named lifetime parameter
-   |
-   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-help: consider using the `'static` lifetime
-   |
-LL |     static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ^^^^^^^^
-
-error[E0106]: missing lifetime specifier
-  --> $DIR/missing-lifetime-specifier.rs:50:44
-   |
-LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ^ expected named lifetime parameter
-   |
-   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-help: consider using the `'static` lifetime
-   |
-LL |     static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                            ^^^^^^^^
-
 error[E0107]: this union takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:43:44
    |
@@ -256,6 +232,18 @@ help: add missing lifetime argument
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
    |                                                        ^^^^
 
+error[E0106]: missing lifetime specifier
+  --> $DIR/missing-lifetime-specifier.rs:50:44
+   |
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
+   |                                            ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+   |
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
+   |                                            ^^^^^^^^
+
 error[E0107]: this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:50:45
    |
@@ -274,6 +262,18 @@ help: add missing lifetime argument
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
    |                                                        ^^^^
 
+error[E0106]: missing lifetime specifier
+  --> $DIR/missing-lifetime-specifier.rs:50:44
+   |
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
+   |                                            ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+   |
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
+   |                                            ^^^^^^^^
+
 error[E0107]: this trait takes 2 lifetime arguments but only 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:50:45
    |