about summary refs log tree commit diff
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2022-07-08 10:59:35 +0200
committerlcnr <rust@lcnr.de>2022-07-15 16:53:20 +0200
commit5bd8c960f5f7b07128ebdb12e7f788b1ba0a1902 (patch)
treec718862fc57fb9262a09d1593022fe580ba8cddd
parentb955fa7dd013d04b2a781785d95f76ce1d6d80ee (diff)
downloadrust-5bd8c960f5f7b07128ebdb12e7f788b1ba0a1902.tar.gz
rust-5bd8c960f5f7b07128ebdb12e7f788b1ba0a1902.zip
provide `generic_param_scope` for region errors
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs84
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs8
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs38
-rw-r--r--compiler/rustc_typeck/src/check/check.rs5
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs18
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs2
-rw-r--r--compiler/rustc_typeck/src/coherence/builtin.rs4
-rw-r--r--compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs2
-rw-r--r--src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr8
-rw-r--r--src/test/ui/fn/implied-bounds-unnorm-associated-type-3.stderr8
-rw-r--r--src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr40
-rw-r--r--src/test/ui/regions/regions-normalize-in-where-clause-list.rs1
-rw-r--r--src/test/ui/regions/regions-normalize-in-where-clause-list.stderr34
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr8
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr24
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr16
-rw-r--r--src/test/ui/wf/wf-impl-associated-type-region.stderr8
-rw-r--r--src/test/ui/wf/wf-in-fn-type-static.stderr16
-rw-r--r--src/test/ui/wf/wf-in-obj-type-static.stderr8
-rw-r--r--src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr16
22 files changed, 179 insertions, 175 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 5d3997289bb..6508c0da75f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -181,11 +181,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                         let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx);
                         let origin = RelateParamBound(type_test_span, generic_ty, None);
                         self.buffer_error(self.infcx.construct_generic_bound_failure(
+                            self.body.source.def_id().expect_local(),
                             type_test_span,
                             Some(origin),
                             type_test.generic_kind,
                             lower_bound_region,
-                            self.body.source.def_id().as_local(),
                         ));
                     } else {
                         // FIXME. We should handle this case better. It
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 4f59215c70b..d7505717bf3 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -63,7 +63,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, Mul
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::lang_items::LangItem;
-use rustc_hir::{Item, ItemKind, Node};
+use rustc_hir::Node;
 use rustc_middle::dep_graph::DepContext;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{
@@ -348,7 +348,11 @@ pub fn same_type_modulo_infer<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
 }
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    pub fn report_region_errors(&self, errors: &[RegionResolutionError<'tcx>]) {
+    pub fn report_region_errors(
+        &self,
+        generic_param_scope: LocalDefId,
+        errors: &[RegionResolutionError<'tcx>],
+    ) {
         debug!("report_region_errors(): {} errors to start", errors.len());
 
         // try to pre-process the errors, which will group some of them
@@ -379,6 +383,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
                     RegionResolutionError::GenericBoundFailure(origin, param_ty, sub) => {
                         self.report_generic_bound_failure(
+                            generic_param_scope,
                             origin.span(),
                             Some(origin),
                             param_ty,
@@ -2269,56 +2274,30 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
     pub fn report_generic_bound_failure(
         &self,
+        generic_param_scope: LocalDefId,
         span: Span,
         origin: Option<SubregionOrigin<'tcx>>,
         bound_kind: GenericKind<'tcx>,
         sub: Region<'tcx>,
     ) {
-        let owner =
-            self.in_progress_typeck_results.map(|typeck_results| typeck_results.borrow().hir_owner);
-        self.construct_generic_bound_failure(span, origin, bound_kind, sub, owner).emit();
+        self.construct_generic_bound_failure(generic_param_scope, span, origin, bound_kind, sub)
+            .emit();
     }
 
     pub fn construct_generic_bound_failure(
         &self,
+        generic_param_scope: LocalDefId,
         span: Span,
         origin: Option<SubregionOrigin<'tcx>>,
         bound_kind: GenericKind<'tcx>,
         sub: Region<'tcx>,
-        owner: Option<LocalDefId>,
     ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
-        let hir = self.tcx.hir();
         // Attempt to obtain the span of the parameter so we can
         // suggest adding an explicit lifetime bound to it.
-        let generics = owner.map(|owner| {
-            let hir_id = hir.local_def_id_to_hir_id(owner);
-            let parent_id = hir.get_parent_item(hir_id);
-            (
-                // Parent item could be a `mod`, so we check the HIR before calling:
-                if let Some(Node::Item(Item {
-                    kind: ItemKind::Trait(..) | ItemKind::Impl { .. },
-                    ..
-                })) = hir.find_by_def_id(parent_id)
-                {
-                    Some(self.tcx.generics_of(parent_id))
-                } else {
-                    None
-                },
-                self.tcx.generics_of(owner.to_def_id()),
-                hir.span(hir_id),
-            )
-        });
-
-        let span = match generics {
-            // This is to get around the trait identity obligation, that has a `DUMMY_SP` as signal
-            // for other diagnostics, so we need to recover it here.
-            Some((_, _, node)) if span.is_dummy() => node,
-            _ => span,
-        };
-
+        let generics = self.tcx.generics_of(generic_param_scope);
         // type_param_span is (span, has_bounds)
-        let type_param_span = match (generics, bound_kind) {
-            (Some((_, ref generics, _)), GenericKind::Param(ref param)) => {
+        let type_param_span = match bound_kind {
+            GenericKind::Param(ref param) => {
                 // Account for the case where `param` corresponds to `Self`,
                 // which doesn't have the expected type argument.
                 if !(generics.has_self && param.index == 0) {
@@ -2346,30 +2325,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             }
             _ => None,
         };
-        let new_lt = generics
-            .as_ref()
-            .and_then(|(parent_g, g, _)| {
-                let mut possible = (b'a'..=b'z').map(|c| format!("'{}", c as char));
-                let mut lts_names = g
-                    .params
-                    .iter()
+
+        let new_lt = {
+            let mut possible = (b'a'..=b'z').map(|c| format!("'{}", c as char));
+            let lts_names =
+                iter::successors(Some(generics), |g| g.parent.map(|p| self.tcx.generics_of(p)))
+                    .flat_map(|g| &g.params)
                     .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
                     .map(|p| p.name.as_str())
                     .collect::<Vec<_>>();
-                if let Some(g) = parent_g {
-                    lts_names.extend(
-                        g.params
-                            .iter()
-                            .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
-                            .map(|p| p.name.as_str()),
-                    );
-                }
-                possible.find(|candidate| !lts_names.contains(&&candidate[..]))
-            })
-            .unwrap_or("'lt".to_string());
+            possible
+                .find(|candidate| !lts_names.contains(&&candidate[..]))
+                .unwrap_or("'lt".to_string())
+        };
+
         let add_lt_sugg = generics
-            .as_ref()
-            .and_then(|(_, g, _)| g.params.first())
+            .params
+            .first()
             .and_then(|param| param.def_id.as_local())
             .map(|def_id| (self.tcx.def_span(def_id).shrink_to_lo(), format!("{}, ", new_lt)));
 
@@ -2571,7 +2543,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 );
                 if let Some(infer::RelateParamBound(_, t, _)) = origin {
                     let return_impl_trait =
-                        owner.and_then(|owner| self.tcx.return_type_impl_trait(owner)).is_some();
+                        self.tcx.return_type_impl_trait(generic_param_scope).is_some();
                     let t = self.resolve_vars_if_possible(t);
                     match t.kind() {
                         // We've got:
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 881682678db..c5a342c1ba2 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1301,7 +1301,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     /// result. After this, no more unification operations should be
     /// done -- or the compiler will panic -- but it is legal to use
     /// `resolve_vars_if_possible` as well as `fully_resolve`.
-    pub fn resolve_regions_and_report_errors(&self, outlives_env: &OutlivesEnvironment<'tcx>) {
+    pub fn resolve_regions_and_report_errors(
+        &self,
+        generic_param_scope: LocalDefId,
+        outlives_env: &OutlivesEnvironment<'tcx>,
+    ) {
         let errors = self.resolve_regions(outlives_env);
 
         if !self.is_tainted_by_errors() {
@@ -1310,7 +1314,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             // this infcx was in use.  This is totally hokey but
             // otherwise we have a hard time separating legit region
             // errors from silly ones.
-            self.report_region_errors(&errors);
+            self.report_region_errors(generic_param_scope, &errors);
         }
     }
 
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index 59cf39abe64..a57971bfb69 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -68,6 +68,7 @@ use crate::infer::{
 };
 use crate::traits::{ObligationCause, ObligationCauseCode};
 use rustc_data_structures::undo_log::UndoLogs;
+use rustc_hir::def_id::LocalDefId;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeVisitable};
 use smallvec::smallvec;
@@ -163,6 +164,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
 
     pub fn check_region_obligations_and_report_errors(
         &self,
+        generic_param_scope: LocalDefId,
         outlives_env: &OutlivesEnvironment<'tcx>,
     ) {
         self.process_registered_region_obligations(
@@ -170,7 +172,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
             outlives_env.param_env,
         );
 
-        self.resolve_regions_and_report_errors(outlives_env)
+        self.resolve_regions_and_report_errors(generic_param_scope, outlives_env)
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 559f0a05507..a14bf72242b 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -237,29 +237,37 @@ fn do_normalize_predicates<'tcx>(
         // cares about declarations like `'a: 'b`.
         let outlives_env = OutlivesEnvironment::new(elaborated_env);
 
-        infcx.resolve_regions_and_report_errors(&outlives_env);
+        // FIXME: It's very weird that we ignore region obligations but apparently
+        // still need to use `resolve_regions` as we need the resolved regions in
+        // the normalized predicates.
+        let errors = infcx.resolve_regions(&outlives_env);
+        if !errors.is_empty() {
+            tcx.sess.delay_span_bug(
+                span,
+                format!(
+                    "failed region resolution while normalizing {elaborated_env:?}: {errors:?}"
+                ),
+            );
+        }
 
-        let predicates = match infcx.fully_resolve(predicates) {
-            Ok(predicates) => predicates,
+        match infcx.fully_resolve(predicates) {
+            Ok(predicates) => Ok(predicates),
             Err(fixup_err) => {
                 // If we encounter a fixup error, it means that some type
                 // variable wound up unconstrained. I actually don't know
                 // if this can happen, and I certainly don't expect it to
                 // happen often, but if it did happen it probably
                 // represents a legitimate failure due to some kind of
-                // unconstrained variable, and it seems better not to ICE,
-                // all things considered.
-                let reported = tcx.sess.span_err(span, &fixup_err.to_string());
-                return Err(reported);
+                // unconstrained variable.
+                //
+                // @lcnr: Let's still ICE here for now. I want a test case
+                // for that.
+                span_bug!(
+                    span,
+                    "inference variables in normalized parameter environment: {}",
+                    fixup_err
+                );
             }
-        };
-        if predicates.needs_infer() {
-            let reported = tcx
-                .sess
-                .delay_span_bug(span, "encountered inference variables after `fully_resolve`");
-            Err(reported)
-        } else {
-            Ok(predicates)
         }
     })
 }
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 51ddec62d78..69f3f03cfa9 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -767,7 +767,10 @@ fn check_opaque_meets_bounds<'tcx>(
             // Can have different predicates to their defining use
             hir::OpaqueTyOrigin::TyAlias => {
                 let outlives_environment = OutlivesEnvironment::new(param_env);
-                infcx.check_region_obligations_and_report_errors(&outlives_environment);
+                infcx.check_region_obligations_and_report_errors(
+                    defining_use_anchor,
+                    &outlives_environment,
+                );
             }
         }
 
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index 529d53a19bf..1f921ca8358 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -394,7 +394,10 @@ fn compare_predicate_entailment<'tcx>(
         // lifetime parameters.
         let mut outlives_environment = OutlivesEnvironment::new(param_env);
         outlives_environment.add_implied_bounds(infcx, wf_tys, impl_m_hir_id);
-        infcx.check_region_obligations_and_report_errors(&outlives_environment);
+        infcx.check_region_obligations_and_report_errors(
+            impl_m.def_id.expect_local(),
+            &outlives_environment,
+        );
 
         Ok(())
     })
@@ -1145,7 +1148,8 @@ pub(crate) fn compare_const_impl<'tcx>(
         }
 
         let outlives_environment = OutlivesEnvironment::new(param_env);
-        infcx.resolve_regions_and_report_errors(&outlives_environment);
+        infcx
+            .resolve_regions_and_report_errors(impl_c.def_id.expect_local(), &outlives_environment);
     });
 }
 
@@ -1262,7 +1266,10 @@ fn compare_type_predicate_entailment<'tcx>(
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
         let outlives_environment = OutlivesEnvironment::new(param_env);
-        infcx.check_region_obligations_and_report_errors(&outlives_environment);
+        infcx.check_region_obligations_and_report_errors(
+            impl_ty.def_id.expect_local(),
+            &outlives_environment,
+        );
 
         Ok(())
     })
@@ -1493,7 +1500,10 @@ pub fn check_type_bounds<'tcx>(
         };
         let mut outlives_environment = OutlivesEnvironment::new(param_env);
         outlives_environment.add_implied_bounds(&infcx, implied_bounds, impl_ty_hir_id);
-        infcx.check_region_obligations_and_report_errors(&outlives_environment);
+        infcx.check_region_obligations_and_report_errors(
+            impl_ty.def_id.expect_local(),
+            &outlives_environment,
+        );
 
         Ok(())
     })
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 149e4254a20..6df59ea1096 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -107,7 +107,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
 
         let mut outlives_environment = OutlivesEnvironment::new(param_env);
         outlives_environment.add_implied_bounds(infcx, wf_tys, body_id);
-        infcx.check_region_obligations_and_report_errors(&outlives_environment);
+        infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
     })
 }
 
diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs
index d532050d050..a92c37ff143 100644
--- a/compiler/rustc_typeck/src/coherence/builtin.rs
+++ b/compiler/rustc_typeck/src/coherence/builtin.rs
@@ -349,7 +349,7 @@ fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did:
 
                     // Finally, resolve all regions.
                     let outlives_env = OutlivesEnvironment::new(param_env);
-                    infcx.resolve_regions_and_report_errors(&outlives_env);
+                    infcx.resolve_regions_and_report_errors(impl_did, &outlives_env);
                 }
             }
             _ => {
@@ -606,7 +606,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
 
         // Finally, resolve all regions.
         let outlives_env = OutlivesEnvironment::new(param_env);
-        infcx.resolve_regions_and_report_errors(&outlives_env);
+        infcx.resolve_regions_and_report_errors(impl_did, &outlives_env);
 
         CoerceUnsizedInfo { custom_kind: kind }
     })
diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
index c46b825f457..6ece955de64 100644
--- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
@@ -150,7 +150,7 @@ fn get_impl_substs<'tcx>(
 
     // Conservatively use an empty `ParamEnv`.
     let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty());
-    infcx.resolve_regions_and_report_errors(&outlives_env);
+    infcx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
     let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
         let span = tcx.def_span(impl1_def_id);
         tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr
index 1a600affb31..e2b177b951c 100644
--- a/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr
+++ b/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr
@@ -2,15 +2,17 @@ error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/builtin-superkinds-self-type.rs:10:16
    |
 LL | impl <T: Sync> Foo for T { }
-   |                ^^^
+   |                ^^^ ...so that the type `T` will meet its required lifetime bounds...
    |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
-   = note: ...so that the type `T` will meet its required lifetime bounds...
 note: ...that is required by this bound
   --> $DIR/builtin-superkinds-self-type.rs:6:24
    |
 LL | trait Foo : Sized+Sync+'static {
    |                        ^^^^^^^
+help: consider adding an explicit lifetime bound...
+   |
+LL | impl <T: Sync + 'static> Foo for T { }
+   |               +++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type-3.stderr b/src/test/ui/fn/implied-bounds-unnorm-associated-type-3.stderr
index 26eecf6a21d..95cf4fb168f 100644
--- a/src/test/ui/fn/implied-bounds-unnorm-associated-type-3.stderr
+++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type-3.stderr
@@ -2,10 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/implied-bounds-unnorm-associated-type-3.rs:19:5
    |
 LL |     fn zero_copy_from<'b>(cart: &'b [T]) -> &'b [T] {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `[T]` will meet its required lifetime bounds
    |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
-   = note: ...so that the type `[T]` will meet its required lifetime bounds
+help: consider adding an explicit lifetime bound...
+   |
+LL | impl<T: 'static> ZeroCopyFrom<[T]> for &'static [T] {
+   |       +++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr
index 3db0a96960f..affb4e8d044 100644
--- a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr
+++ b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr
@@ -2,37 +2,45 @@ error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/lifetime-doesnt-live-long-enough.rs:19:10
    |
 LL |     foo: &'static T
-   |          ^^^^^^^^^^
+   |          ^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at
    |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
-   = note: ...so that the reference type `&'static T` does not outlive the data it points at
+help: consider adding an explicit lifetime bound...
+   |
+LL | struct Foo<T: 'static> {
+   |             +++++++++
 
 error[E0309]: the parameter type `K` may not live long enough
   --> $DIR/lifetime-doesnt-live-long-enough.rs:41:33
    |
 LL |     fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
-   |                                 ^^^^^^^^^^^^^^^^
+   |                                 ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound...
    |
-   = help: consider adding an explicit lifetime bound `K: 'a`...
-   = note: ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
+LL | impl<K: 'a> Nested<K> {
+   |       ++++
 
 error[E0309]: the parameter type `M` may not live long enough
   --> $DIR/lifetime-doesnt-live-long-enough.rs:44:36
    |
 LL |     fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
-   |                                    ^^^^^^^^^^^^^^^^
+   |                                    ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<M>` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound...
    |
-   = help: consider adding an explicit lifetime bound `M: 'a`...
-   = note: ...so that the reference type `&'a Nested<M>` does not outlive the data it points at
+LL |     fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b + 'a>() {
+   |                                                            ++++
 
 error[E0309]: the parameter type `K` may not live long enough
   --> $DIR/lifetime-doesnt-live-long-enough.rs:24:19
    |
 LL |     fn foo<'a, L: X<&'a Nested<K>>>();
-   |                   ^^^^^^^^^^^^^^^^
+   |                   ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
    |
-   = help: consider adding an explicit lifetime bound `K: 'a`...
-   = note: ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
+help: consider adding an explicit lifetime bound...
+   |
+LL | trait X<K: 'a>: Sized {
+   |          ++++
 
 error[E0309]: the parameter type `Self` may not live long enough
   --> $DIR/lifetime-doesnt-live-long-enough.rs:28:19
@@ -47,10 +55,12 @@ error[E0309]: the parameter type `L` may not live long enough
   --> $DIR/lifetime-doesnt-live-long-enough.rs:32:22
    |
 LL |     fn baz<'a, L, M: X<&'a Nested<L>>>() {
-   |                      ^^^^^^^^^^^^^^^^
+   |                      ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<L>` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound...
    |
-   = help: consider adding an explicit lifetime bound `L: 'a`...
-   = note: ...so that the reference type `&'a Nested<L>` does not outlive the data it points at
+LL |     fn baz<'a, L: 'a, M: X<&'a Nested<L>>>() {
+   |                 ++++
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.rs b/src/test/ui/regions/regions-normalize-in-where-clause-list.rs
index 9912e88c2ec..389f82e794b 100644
--- a/src/test/ui/regions/regions-normalize-in-where-clause-list.rs
+++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.rs
@@ -23,7 +23,6 @@ where
 // Here we get an error: we need `'a: 'b`.
 fn bar<'a, 'b>()
 //~^ ERROR cannot infer
-//~| ERROR cannot infer
 where
     <() as Project<'a, 'b>>::Item: Eq,
 {
diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
index 2bb58b5ec2d..5672837290c 100644
--- a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
+++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
@@ -1,36 +1,4 @@
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
-  --> $DIR/regions-normalize-in-where-clause-list.rs:24:1
-   |
-LL | / fn bar<'a, 'b>()
-LL | |
-LL | |
-LL | | where
-LL | |     <() as Project<'a, 'b>>::Item: Eq,
-   | |______________________________________^
-   |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
-  --> $DIR/regions-normalize-in-where-clause-list.rs:24:8
-   |
-LL | fn bar<'a, 'b>()
-   |        ^^
-note: ...but the lifetime must also be valid for the lifetime `'b` as defined here...
-  --> $DIR/regions-normalize-in-where-clause-list.rs:24:12
-   |
-LL | fn bar<'a, 'b>()
-   |            ^^
-note: ...so that the types are compatible
-  --> $DIR/regions-normalize-in-where-clause-list.rs:24:1
-   |
-LL | / fn bar<'a, 'b>()
-LL | |
-LL | |
-LL | | where
-LL | |     <() as Project<'a, 'b>>::Item: Eq,
-   | |______________________________________^
-   = note: expected `Project<'a, 'b>`
-              found `Project<'_, '_>`
-
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
   --> $DIR/regions-normalize-in-where-clause-list.rs:24:4
    |
 LL | fn bar<'a, 'b>()
@@ -54,6 +22,6 @@ LL | fn bar<'a, 'b>()
    = note: expected `Project<'a, 'b>`
               found `Project<'_, '_>`
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr
index 8ace0087710..0c388f5fe41 100644
--- a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr
+++ b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr
@@ -2,15 +2,17 @@ error[E0310]: the parameter type `U` may not live long enough
   --> $DIR/dont-infer-static.rs:6:10
    |
 LL |     bar: Bar<U>
-   |          ^^^^^^
+   |          ^^^^^^ ...so that the type `U` will meet its required lifetime bounds...
    |
-   = help: consider adding an explicit lifetime bound `U: 'static`...
-   = note: ...so that the type `U` will meet its required lifetime bounds...
 note: ...that is required by this bound
   --> $DIR/dont-infer-static.rs:8:15
    |
 LL | struct Bar<T: 'static> {
    |               ^^^^^^^
+help: consider adding an explicit lifetime bound...
+   |
+LL | struct Foo<U: 'static> {
+   |             +++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr
index 2444046a16d..2c660b28500 100644
--- a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr
@@ -2,28 +2,34 @@ error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/regions-enum-not-wf.rs:17:18
    |
 LL |     Ref1Variant1(RequireOutlives<'a, T>),
-   |                  ^^^^^^^^^^^^^^^^^^^^^^
+   |                  ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
-   = note: ...so that the type `T` will meet its required lifetime bounds
+help: consider adding an explicit lifetime bound...
+   |
+LL | enum Ref1<'a, T: 'a> {
+   |                ++++
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/regions-enum-not-wf.rs:22:25
    |
 LL |     Ref2Variant2(isize, RequireOutlives<'a, T>),
-   |                         ^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound...
    |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
-   = note: ...so that the type `T` will meet its required lifetime bounds
+LL | enum Ref2<'a, T: 'a> {
+   |                ++++
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/regions-enum-not-wf.rs:35:23
    |
 LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>),
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound...
    |
-   = help: consider adding an explicit lifetime bound `T: 'b`...
-   = note: ...so that the type `T` will meet its required lifetime bounds
+LL | enum RefDouble<'a, 'b, T: 'b> {
+   |                         ++++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr
index 674bfa9633e..34ff1362cf3 100644
--- a/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr
@@ -2,24 +2,28 @@ error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/regions-struct-not-wf.rs:13:16
    |
 LL |     type Out = &'a T;
-   |                ^^^^^
+   |                ^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
    |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
-   = note: ...so that the reference type `&'a T` does not outlive the data it points at
+help: consider adding an explicit lifetime bound...
+   |
+LL | impl<'a, T: 'a> Trait<'a, T> for usize {
+   |           ++++
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/regions-struct-not-wf.rs:21:16
    |
 LL |     type Out = RefOk<'a, T>;
-   |                ^^^^^^^^^^^^
+   |                ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
    |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
-   = note: ...so that the type `T` will meet its required lifetime bounds...
 note: ...that is required by this bound
   --> $DIR/regions-struct-not-wf.rs:16:20
    |
 LL | struct RefOk<'a, T:'a> {
    |                    ^^
+help: consider adding an explicit lifetime bound...
+   |
+LL | impl<'a, T: 'a> Trait<'a, T> for u32 {
+   |           ++++
 
 error[E0491]: in type `&'a &'b T`, reference has a longer lifetime than the data it references
   --> $DIR/regions-struct-not-wf.rs:25:16
diff --git a/src/test/ui/wf/wf-impl-associated-type-region.stderr b/src/test/ui/wf/wf-impl-associated-type-region.stderr
index 1ae4bfbffa0..b9d4857a3ef 100644
--- a/src/test/ui/wf/wf-impl-associated-type-region.stderr
+++ b/src/test/ui/wf/wf-impl-associated-type-region.stderr
@@ -2,10 +2,12 @@ error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/wf-impl-associated-type-region.rs:10:16
    |
 LL |     type Bar = &'a T;
-   |                ^^^^^
+   |                ^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
    |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
-   = note: ...so that the reference type `&'a T` does not outlive the data it points at
+help: consider adding an explicit lifetime bound...
+   |
+LL | impl<'a, T: 'a> Foo<'a> for T {
+   |           ++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-in-fn-type-static.stderr b/src/test/ui/wf/wf-in-fn-type-static.stderr
index 67fd639ee4a..73fbb9ca670 100644
--- a/src/test/ui/wf/wf-in-fn-type-static.stderr
+++ b/src/test/ui/wf/wf-in-fn-type-static.stderr
@@ -2,19 +2,23 @@ error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/wf-in-fn-type-static.rs:13:8
    |
 LL |     x: fn() -> &'static T
-   |        ^^^^^^^^^^^^^^^^^^
+   |        ^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at
    |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
-   = note: ...so that the reference type `&'static T` does not outlive the data it points at
+help: consider adding an explicit lifetime bound...
+   |
+LL | struct Foo<T: 'static> {
+   |             +++++++++
 
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/wf-in-fn-type-static.rs:18:8
    |
 LL |     x: fn(&'static T)
-   |        ^^^^^^^^^^^^^^
+   |        ^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound...
    |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
-   = note: ...so that the reference type `&'static T` does not outlive the data it points at
+LL | struct Bar<T: 'static> {
+   |             +++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/wf/wf-in-obj-type-static.stderr b/src/test/ui/wf/wf-in-obj-type-static.stderr
index 8eb443ae2b7..c3ad42dd5d5 100644
--- a/src/test/ui/wf/wf-in-obj-type-static.stderr
+++ b/src/test/ui/wf/wf-in-obj-type-static.stderr
@@ -2,10 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/wf-in-obj-type-static.rs:14:8
    |
 LL |     x: dyn Object<&'static T>
-   |        ^^^^^^^^^^^^^^^^^^^^^^
+   |        ^^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at
    |
-   = help: consider adding an explicit lifetime bound `T: 'static`...
-   = note: ...so that the reference type `&'static T` does not outlive the data it points at
+help: consider adding an explicit lifetime bound...
+   |
+LL | struct Foo<T: 'static> {
+   |             +++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr b/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr
index 535e0c6489a..4d4d8b2ab4d 100644
--- a/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr
+++ b/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr
@@ -2,19 +2,23 @@ error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:9:16
    |
 LL |     type Out = &'a fn(T);
-   |                ^^^^^^^^^
+   |                ^^^^^^^^^ ...so that the reference type `&'a fn(T)` does not outlive the data it points at
    |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
-   = note: ...so that the reference type `&'a fn(T)` does not outlive the data it points at
+help: consider adding an explicit lifetime bound...
+   |
+LL | impl<'a, T: 'a> Trait<'a, T> for usize {
+   |           ++++
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:16
    |
 LL |     type Out = &'a dyn Baz<T>;
-   |                ^^^^^^^^^^^^^^
+   |                ^^^^^^^^^^^^^^ ...so that the reference type `&'a (dyn Baz<T> + 'a)` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound...
    |
-   = help: consider adding an explicit lifetime bound `T: 'a`...
-   = note: ...so that the reference type `&'a (dyn Baz<T> + 'a)` does not outlive the data it points at
+LL | impl<'a, T: 'a> Trait<'a, T> for u32 {
+   |           ++++
 
 error: aborting due to 2 previous errors