about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libcore/fmt/builders.rs56
-rw-r--r--src/libcore/tests/fmt/builders.rs85
-rw-r--r--src/libcore/tests/lib.rs1
-rw-r--r--src/librustc/mir/interpret/error.rs2
-rw-r--r--src/librustc/mir/interpret/mod.rs4
-rw-r--r--src/librustc/traits/error_reporting.rs2991
-rw-r--r--src/librustc/traits/error_reporting/mod.rs1412
-rw-r--r--src/librustc/traits/error_reporting/on_unimplemented.rs199
-rw-r--r--src/librustc/traits/error_reporting/suggestions.rs1718
-rw-r--r--src/librustc/traits/mod.rs15
-rw-r--r--src/librustc/ty/error.rs4
-rw-r--r--src/librustc_error_codes/error_codes.rs1
-rw-r--r--src/librustc_error_codes/error_codes/E0746.md138
-rw-r--r--src/librustc_hir/hir.rs7
-rw-r--r--src/librustc_mir/interpret/memory.rs7
-rw-r--r--src/librustc_mir/interpret/operand.rs18
-rw-r--r--src/librustc_mir/interpret/place.rs11
-rw-r--r--src/librustc_mir/interpret/validity.rs12
-rw-r--r--src/librustc_resolve/diagnostics.rs162
-rw-r--r--src/librustc_resolve/imports.rs6
-rw-r--r--src/librustc_resolve/lib.rs162
-rw-r--r--src/librustc_typeck/check/coercion.rs109
-rw-r--r--src/librustc_typeck/check/mod.rs87
-rw-r--r--src/test/ui/async-await/issue-64130-4-async-move.stderr13
-rw-r--r--src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr14
-rw-r--r--src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.stderr15
-rw-r--r--src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr21
-rw-r--r--src/test/ui/destructure-trait-ref.rs2
-rw-r--r--src/test/ui/destructure-trait-ref.stderr10
-rw-r--r--src/test/ui/dst/dst-bad-assign-3.rs2
-rw-r--r--src/test/ui/dst/dst-bad-assign-3.stderr2
-rw-r--r--src/test/ui/dst/dst-bad-assign.rs2
-rw-r--r--src/test/ui/dst/dst-bad-assign.stderr2
-rw-r--r--src/test/ui/error-codes/E0603.stderr8
-rw-r--r--src/test/ui/error-codes/E0746.fixed18
-rw-r--r--src/test/ui/error-codes/E0746.rs18
-rw-r--r--src/test/ui/error-codes/E0746.stderr27
-rw-r--r--src/test/ui/error-festival.stderr8
-rw-r--r--src/test/ui/export-import.stderr8
-rw-r--r--src/test/ui/export-tag-variant.stderr8
-rw-r--r--src/test/ui/export.stderr8
-rw-r--r--src/test/ui/extern/extern-crate-visibility.rs4
-rw-r--r--src/test/ui/extern/extern-crate-visibility.stderr20
-rw-r--r--src/test/ui/generic-associated-types/impl_bounds.stderr2
-rw-r--r--src/test/ui/hygiene/privacy.stderr8
-rw-r--r--src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs34
-rw-r--r--src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr113
-rw-r--r--src/test/ui/impl-trait/equality.stderr6
-rw-r--r--src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs35
-rw-r--r--src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr21
-rw-r--r--src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs46
-rw-r--r--src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr39
-rw-r--r--src/test/ui/import.stderr10
-rw-r--r--src/test/ui/imports/issue-55884-2.rs2
-rw-r--r--src/test/ui/imports/issue-55884-2.stderr10
-rw-r--r--src/test/ui/imports/reexports.stderr20
-rw-r--r--src/test/ui/imports/unresolved-imports-used.stderr8
-rw-r--r--src/test/ui/issues/issue-10545.stderr8
-rw-r--r--src/test/ui/issues/issue-11593.stderr8
-rw-r--r--src/test/ui/issues/issue-11680.stderr16
-rw-r--r--src/test/ui/issues/issue-13407.stderr8
-rw-r--r--src/test/ui/issues/issue-13641.stderr16
-rw-r--r--src/test/ui/issues/issue-16725.stderr8
-rw-r--r--src/test/ui/issues/issue-17718-const-privacy.stderr16
-rw-r--r--src/test/ui/issues/issue-28388-2.stderr8
-rw-r--r--src/test/ui/issues/issue-29161.stderr8
-rw-r--r--src/test/ui/issues/issue-38857.rs5
-rw-r--r--src/test/ui/issues/issue-38857.stderr12
-rw-r--r--src/test/ui/issues/issue-3993.stderr8
-rw-r--r--src/test/ui/issues/issue-58344.stderr6
-rw-r--r--src/test/ui/issues/issue-5883.stderr3
-rw-r--r--src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr3
-rw-r--r--src/test/ui/macros/macro-local-data-key-priv.stderr9
-rw-r--r--src/test/ui/never_type/feature-gate-never_type_fallback.stderr4
-rw-r--r--src/test/ui/parser/macro/pub-item-macro.stderr11
-rw-r--r--src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr36
-rw-r--r--src/test/ui/privacy/decl-macro.stderr8
-rw-r--r--src/test/ui/privacy/privacy-in-paths.stderr24
-rw-r--r--src/test/ui/privacy/privacy-ns2.stderr24
-rw-r--r--src/test/ui/privacy/privacy-ufcs.stderr8
-rw-r--r--src/test/ui/privacy/privacy1.stderr104
-rw-r--r--src/test/ui/privacy/privacy2.stderr10
-rw-r--r--src/test/ui/privacy/privacy4.stderr8
-rw-r--r--src/test/ui/privacy/privacy5.stderr384
-rw-r--r--src/test/ui/privacy/private-item-simple.stderr8
-rw-r--r--src/test/ui/privacy/restricted/test.stderr16
-rw-r--r--src/test/ui/proc-macro/disappearing-resolution.rs2
-rw-r--r--src/test/ui/proc-macro/disappearing-resolution.stderr10
-rw-r--r--src/test/ui/reachable/unreachable-variant.stderr8
-rw-r--r--src/test/ui/repr/repr-packed-contains-align.rs16
-rw-r--r--src/test/ui/repr/repr-packed-contains-align.stderr112
-rw-r--r--src/test/ui/resolve/privacy-enum-ctor.stderr32
-rw-r--r--src/test/ui/resolve/privacy-struct-ctor.stderr48
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/struct.stderr16
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/variant.stderr40
-rw-r--r--src/test/ui/shadowed/shadowed-use-visibility.rs4
-rw-r--r--src/test/ui/shadowed/shadowed-use-visibility.stderr20
-rw-r--r--src/test/ui/stability-in-private-module.rs5
-rw-r--r--src/test/ui/stability-in-private-module.stderr10
-rw-r--r--src/test/ui/static/static-priv-by-default2.stderr16
-rw-r--r--src/test/ui/structs/struct-variant-privacy-xc.stderr16
-rw-r--r--src/test/ui/structs/struct-variant-privacy.stderr16
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr4
-rw-r--r--src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr2
-rw-r--r--src/test/ui/use/use-from-trait-xc.stderr16
-rw-r--r--src/test/ui/use/use-mod/use-mod-3.stderr16
-rw-r--r--src/test/ui/xcrate/xcrate-private-by-default.stderr80
m---------src/tools/clippy16
108 files changed, 5636 insertions, 3427 deletions
diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs
index 626eb1e862d..dd0f3ccb158 100644
--- a/src/libcore/fmt/builders.rs
+++ b/src/libcore/fmt/builders.rs
@@ -159,6 +159,62 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
         self
     }
 
+    /// Marks the struct as non-exhaustive, indicating to the reader that there are some other
+    /// fields that are not shown in the debug representation.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(debug_non_exhaustive)]
+    /// use std::fmt;
+    ///
+    /// struct Bar {
+    ///     bar: i32,
+    ///     hidden: f32,
+    /// }
+    ///
+    /// impl fmt::Debug for Bar {
+    ///     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+    ///         fmt.debug_struct("Bar")
+    ///            .field("bar", &self.bar)
+    ///            .finish_non_exhaustive() // Show that some other field(s) exist.
+    ///     }
+    /// }
+    ///
+    /// assert_eq!(
+    ///     format!("{:?}", Bar { bar: 10, hidden: 1.0 }),
+    ///     "Bar { bar: 10, .. }",
+    /// );
+    /// ```
+    #[unstable(feature = "debug_non_exhaustive", issue = "67364")]
+    pub fn finish_non_exhaustive(&mut self) -> fmt::Result {
+        self.result = self.result.and_then(|_| {
+            // Draw non-exhaustive dots (`..`), and open brace if necessary (no fields).
+            if self.is_pretty() {
+                if !self.has_fields {
+                    self.fmt.write_str(" {\n")?;
+                }
+                let mut slot = None;
+                let mut state = Default::default();
+                let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut state);
+                writer.write_str("..\n")?;
+            } else {
+                if self.has_fields {
+                    self.fmt.write_str(", ..")?;
+                } else {
+                    self.fmt.write_str(" { ..")?;
+                }
+            }
+            if self.is_pretty() {
+                self.fmt.write_str("}")?
+            } else {
+                self.fmt.write_str(" }")?;
+            }
+            Ok(())
+        });
+        self.result
+    }
+
     /// Finishes output and returns any error encountered.
     ///
     /// # Examples
diff --git a/src/libcore/tests/fmt/builders.rs b/src/libcore/tests/fmt/builders.rs
index 90a9bccda15..129c121e8ce 100644
--- a/src/libcore/tests/fmt/builders.rs
+++ b/src/libcore/tests/fmt/builders.rs
@@ -93,6 +93,91 @@ mod debug_struct {
             format!("{:#?}", Bar)
         );
     }
+
+    #[test]
+    fn test_only_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_struct("Foo").finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!("Foo { .. }", format!("{:?}", Foo));
+        assert_eq!(
+            "Foo {
+    ..
+}",
+            format!("{:#?}", Foo)
+        );
+    }
+
+    #[test]
+    fn test_multiple_and_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_struct("Foo")
+                    .field("bar", &true)
+                    .field("baz", &format_args!("{}/{}", 10, 20))
+                    .finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!("Foo { bar: true, baz: 10/20, .. }", format!("{:?}", Foo));
+        assert_eq!(
+            "Foo {
+    bar: true,
+    baz: 10/20,
+    ..
+}",
+            format!("{:#?}", Foo)
+        );
+    }
+
+    #[test]
+    fn test_nested_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_struct("Foo")
+                    .field("bar", &true)
+                    .field("baz", &format_args!("{}/{}", 10, 20))
+                    .finish_non_exhaustive()
+            }
+        }
+
+        struct Bar;
+
+        impl fmt::Debug for Bar {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_struct("Bar")
+                    .field("foo", &Foo)
+                    .field("hello", &"world")
+                    .finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!(
+            "Bar { foo: Foo { bar: true, baz: 10/20, .. }, hello: \"world\", .. }",
+            format!("{:?}", Bar)
+        );
+        assert_eq!(
+            "Bar {
+    foo: Foo {
+        bar: true,
+        baz: 10/20,
+        ..
+    },
+    hello: \"world\",
+    ..
+}",
+            format!("{:#?}", Bar)
+        );
+    }
 }
 
 mod debug_tuple {
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 86cf6fc104c..8c034938c2b 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -5,6 +5,7 @@
 #![feature(core_private_bignum)]
 #![feature(core_private_diy_float)]
 #![feature(debug_map_key_value)]
+#![feature(debug_non_exhaustive)]
 #![feature(dec2flt)]
 #![feature(exact_size_is_empty)]
 #![feature(fixed_size_array)]
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index 8643bd63d8c..42d896af801 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -33,7 +33,7 @@ impl ErrorHandled {
             ErrorHandled::Reported => {}
             ErrorHandled::TooGeneric => bug!(
                 "MIR interpretation failed without reporting an error \
-                                              even though it was fully monomorphized"
+                 even though it was fully monomorphized"
             ),
         }
     }
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs
index 47f067590b9..e554b280ef7 100644
--- a/src/librustc/mir/interpret/mod.rs
+++ b/src/librustc/mir/interpret/mod.rs
@@ -403,8 +403,8 @@ impl<'tcx> AllocMap<'tcx> {
         let next = self.next_id;
         self.next_id.0 = self.next_id.0.checked_add(1).expect(
             "You overflowed a u64 by incrementing by 1... \
-                     You've just earned yourself a free drink if we ever meet. \
-                     Seriously, how did you do that?!",
+             You've just earned yourself a free drink if we ever meet. \
+             Seriously, how did you do that?!",
         );
         next
     }
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
deleted file mode 100644
index 7f151af7abe..00000000000
--- a/src/librustc/traits/error_reporting.rs
+++ /dev/null
@@ -1,2991 +0,0 @@
-use super::{
-    ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode,
-    MismatchedProjectionTypes, ObjectSafetyViolation, Obligation, ObligationCause,
-    ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote,
-    OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionContext, SelectionError,
-    TraitNotObjectSafe,
-};
-
-use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
-use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use crate::infer::{self, InferCtxt};
-use crate::mir::interpret::ErrorHandled;
-use crate::session::DiagnosticMessageId;
-use crate::traits::object_safety_violations;
-use crate::ty::error::ExpectedFound;
-use crate::ty::fast_reject;
-use crate::ty::fold::TypeFolder;
-use crate::ty::subst::Subst;
-use crate::ty::GenericParamDefKind;
-use crate::ty::SubtypePredicate;
-use crate::ty::TypeckTables;
-use crate::ty::{self, AdtKind, DefIdTree, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
-
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style};
-use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_hir::Node;
-use rustc_span::source_map::SourceMap;
-use rustc_span::symbol::{kw, sym};
-use rustc_span::{ExpnKind, MultiSpan, Span, DUMMY_SP};
-use std::fmt;
-use syntax::ast;
-
-use rustc_error_codes::*;
-
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    pub fn report_fulfillment_errors(
-        &self,
-        errors: &[FulfillmentError<'tcx>],
-        body_id: Option<hir::BodyId>,
-        fallback_has_occurred: bool,
-    ) {
-        #[derive(Debug)]
-        struct ErrorDescriptor<'tcx> {
-            predicate: ty::Predicate<'tcx>,
-            index: Option<usize>, // None if this is an old error
-        }
-
-        let mut error_map: FxHashMap<_, Vec<_>> = self
-            .reported_trait_errors
-            .borrow()
-            .iter()
-            .map(|(&span, predicates)| {
-                (
-                    span,
-                    predicates
-                        .iter()
-                        .map(|predicate| ErrorDescriptor {
-                            predicate: predicate.clone(),
-                            index: None,
-                        })
-                        .collect(),
-                )
-            })
-            .collect();
-
-        for (index, error) in errors.iter().enumerate() {
-            // We want to ignore desugarings here: spans are equivalent even
-            // if one is the result of a desugaring and the other is not.
-            let mut span = error.obligation.cause.span;
-            let expn_data = span.ctxt().outer_expn_data();
-            if let ExpnKind::Desugaring(_) = expn_data.kind {
-                span = expn_data.call_site;
-            }
-
-            error_map.entry(span).or_default().push(ErrorDescriptor {
-                predicate: error.obligation.predicate.clone(),
-                index: Some(index),
-            });
-
-            self.reported_trait_errors
-                .borrow_mut()
-                .entry(span)
-                .or_default()
-                .push(error.obligation.predicate.clone());
-        }
-
-        // We do this in 2 passes because we want to display errors in order, though
-        // maybe it *is* better to sort errors by span or something.
-        let mut is_suppressed = vec![false; errors.len()];
-        for (_, error_set) in error_map.iter() {
-            // We want to suppress "duplicate" errors with the same span.
-            for error in error_set {
-                if let Some(index) = error.index {
-                    // Suppress errors that are either:
-                    // 1) strictly implied by another error.
-                    // 2) implied by an error with a smaller index.
-                    for error2 in error_set {
-                        if error2.index.map_or(false, |index2| is_suppressed[index2]) {
-                            // Avoid errors being suppressed by already-suppressed
-                            // errors, to prevent all errors from being suppressed
-                            // at once.
-                            continue;
-                        }
-
-                        if self.error_implies(&error2.predicate, &error.predicate)
-                            && !(error2.index >= error.index
-                                && self.error_implies(&error.predicate, &error2.predicate))
-                        {
-                            info!("skipping {:?} (implied by {:?})", error, error2);
-                            is_suppressed[index] = true;
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-
-        for (error, suppressed) in errors.iter().zip(is_suppressed) {
-            if !suppressed {
-                self.report_fulfillment_error(error, body_id, fallback_has_occurred);
-            }
-        }
-    }
-
-    // returns if `cond` not occurring implies that `error` does not occur - i.e., that
-    // `error` occurring implies that `cond` occurs.
-    fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool {
-        if cond == error {
-            return true;
-        }
-
-        let (cond, error) = match (cond, error) {
-            (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error)) => (cond, error),
-            _ => {
-                // FIXME: make this work in other cases too.
-                return false;
-            }
-        };
-
-        for implication in super::elaborate_predicates(self.tcx, vec![cond.clone()]) {
-            if let ty::Predicate::Trait(implication) = implication {
-                let error = error.to_poly_trait_ref();
-                let implication = implication.to_poly_trait_ref();
-                // FIXME: I'm just not taking associated types at all here.
-                // Eventually I'll need to implement param-env-aware
-                // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
-                let param_env = ty::ParamEnv::empty();
-                if self.can_sub(param_env, error, implication).is_ok() {
-                    debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
-                    return true;
-                }
-            }
-        }
-
-        false
-    }
-
-    fn report_fulfillment_error(
-        &self,
-        error: &FulfillmentError<'tcx>,
-        body_id: Option<hir::BodyId>,
-        fallback_has_occurred: bool,
-    ) {
-        debug!("report_fulfillment_error({:?})", error);
-        match error.code {
-            FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
-                self.report_selection_error(
-                    &error.obligation,
-                    selection_error,
-                    fallback_has_occurred,
-                    error.points_at_arg_span,
-                );
-            }
-            FulfillmentErrorCode::CodeProjectionError(ref e) => {
-                self.report_projection_error(&error.obligation, e);
-            }
-            FulfillmentErrorCode::CodeAmbiguity => {
-                self.maybe_report_ambiguity(&error.obligation, body_id);
-            }
-            FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
-                self.report_mismatched_types(
-                    &error.obligation.cause,
-                    expected_found.expected,
-                    expected_found.found,
-                    err.clone(),
-                )
-                .emit();
-            }
-        }
-    }
-
-    fn report_projection_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        error: &MismatchedProjectionTypes<'tcx>,
-    ) {
-        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-
-        if predicate.references_error() {
-            return;
-        }
-
-        self.probe(|_| {
-            let err_buf;
-            let mut err = &error.err;
-            let mut values = None;
-
-            // try to find the mismatched types to report the error with.
-            //
-            // this can fail if the problem was higher-ranked, in which
-            // cause I have no idea for a good error message.
-            if let ty::Predicate::Projection(ref data) = predicate {
-                let mut selcx = SelectionContext::new(self);
-                let (data, _) = self.replace_bound_vars_with_fresh_vars(
-                    obligation.cause.span,
-                    infer::LateBoundRegionConversionTime::HigherRankedType,
-                    data,
-                );
-                let mut obligations = vec![];
-                let normalized_ty = super::normalize_projection_type(
-                    &mut selcx,
-                    obligation.param_env,
-                    data.projection_ty,
-                    obligation.cause.clone(),
-                    0,
-                    &mut obligations,
-                );
-
-                debug!(
-                    "report_projection_error obligation.cause={:?} obligation.param_env={:?}",
-                    obligation.cause, obligation.param_env
-                );
-
-                debug!(
-                    "report_projection_error normalized_ty={:?} data.ty={:?}",
-                    normalized_ty, data.ty
-                );
-
-                let is_normalized_ty_expected = match &obligation.cause.code {
-                    ObligationCauseCode::ItemObligation(_)
-                    | ObligationCauseCode::BindingObligation(_, _)
-                    | ObligationCauseCode::ObjectCastObligation(_) => false,
-                    _ => true,
-                };
-
-                if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(
-                    is_normalized_ty_expected,
-                    normalized_ty,
-                    data.ty,
-                ) {
-                    values = Some(infer::ValuePairs::Types(ExpectedFound::new(
-                        is_normalized_ty_expected,
-                        normalized_ty,
-                        data.ty,
-                    )));
-
-                    err_buf = error;
-                    err = &err_buf;
-                }
-            }
-
-            let msg = format!("type mismatch resolving `{}`", predicate);
-            let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg);
-            let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
-            if fresh {
-                let mut diag = struct_span_err!(
-                    self.tcx.sess,
-                    obligation.cause.span,
-                    E0271,
-                    "type mismatch resolving `{}`",
-                    predicate
-                );
-                self.note_type_err(&mut diag, &obligation.cause, None, values, err);
-                self.note_obligation_cause(&mut diag, obligation);
-                diag.emit();
-            }
-        });
-    }
-
-    fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
-        /// returns the fuzzy category of a given type, or None
-        /// if the type can be equated to any type.
-        fn type_category(t: Ty<'_>) -> Option<u32> {
-            match t.kind {
-                ty::Bool => Some(0),
-                ty::Char => Some(1),
-                ty::Str => Some(2),
-                ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3),
-                ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4),
-                ty::Ref(..) | ty::RawPtr(..) => Some(5),
-                ty::Array(..) | ty::Slice(..) => Some(6),
-                ty::FnDef(..) | ty::FnPtr(..) => Some(7),
-                ty::Dynamic(..) => Some(8),
-                ty::Closure(..) => Some(9),
-                ty::Tuple(..) => Some(10),
-                ty::Projection(..) => Some(11),
-                ty::Param(..) => Some(12),
-                ty::Opaque(..) => Some(13),
-                ty::Never => Some(14),
-                ty::Adt(adt, ..) => match adt.adt_kind() {
-                    AdtKind::Struct => Some(15),
-                    AdtKind::Union => Some(16),
-                    AdtKind::Enum => Some(17),
-                },
-                ty::Generator(..) => Some(18),
-                ty::Foreign(..) => Some(19),
-                ty::GeneratorWitness(..) => Some(20),
-                ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None,
-                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
-            }
-        }
-
-        match (type_category(a), type_category(b)) {
-            (Some(cat_a), Some(cat_b)) => match (&a.kind, &b.kind) {
-                (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b,
-                _ => cat_a == cat_b,
-            },
-            // infer and error can be equated to all types
-            _ => true,
-        }
-    }
-
-    fn impl_similar_to(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> Option<DefId> {
-        let tcx = self.tcx;
-        let param_env = obligation.param_env;
-        let trait_ref = tcx.erase_late_bound_regions(&trait_ref);
-        let trait_self_ty = trait_ref.self_ty();
-
-        let mut self_match_impls = vec![];
-        let mut fuzzy_match_impls = vec![];
-
-        self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| {
-            let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id);
-            let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().subst(tcx, impl_substs);
-
-            let impl_self_ty = impl_trait_ref.self_ty();
-
-            if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) {
-                self_match_impls.push(def_id);
-
-                if trait_ref
-                    .substs
-                    .types()
-                    .skip(1)
-                    .zip(impl_trait_ref.substs.types().skip(1))
-                    .all(|(u, v)| self.fuzzy_match_tys(u, v))
-                {
-                    fuzzy_match_impls.push(def_id);
-                }
-            }
-        });
-
-        let impl_def_id = if self_match_impls.len() == 1 {
-            self_match_impls[0]
-        } else if fuzzy_match_impls.len() == 1 {
-            fuzzy_match_impls[0]
-        } else {
-            return None;
-        };
-
-        tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented).then_some(impl_def_id)
-    }
-
-    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
-        self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind {
-            hir::GeneratorKind::Gen => "a generator",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure",
-        })
-    }
-
-    /// Used to set on_unimplemented's `ItemContext`
-    /// to be the enclosing (async) block/function/closure
-    fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> {
-        let hir = &self.tcx.hir();
-        let node = hir.find(hir_id)?;
-        if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) = &node {
-            self.describe_generator(*body_id).or_else(|| {
-                Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
-                    "an async function"
-                } else {
-                    "a function"
-                })
-            })
-        } else if let hir::Node::Expr(hir::Expr {
-            kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability),
-            ..
-        }) = &node
-        {
-            self.describe_generator(*body_id).or_else(|| {
-                Some(if gen_movability.is_some() { "an async closure" } else { "a closure" })
-            })
-        } else if let hir::Node::Expr(hir::Expr { .. }) = &node {
-            let parent_hid = hir.get_parent_node(hir_id);
-            if parent_hid != hir_id {
-                return self.describe_enclosure(parent_hid);
-            } else {
-                None
-            }
-        } else {
-            None
-        }
-    }
-
-    fn on_unimplemented_note(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> OnUnimplementedNote {
-        let def_id =
-            self.impl_similar_to(trait_ref, obligation).unwrap_or_else(|| trait_ref.def_id());
-        let trait_ref = *trait_ref.skip_binder();
-
-        let mut flags = vec![];
-        flags.push((
-            sym::item_context,
-            self.describe_enclosure(obligation.cause.body_id).map(|s| s.to_owned()),
-        ));
-
-        match obligation.cause.code {
-            ObligationCauseCode::BuiltinDerivedObligation(..)
-            | ObligationCauseCode::ImplDerivedObligation(..) => {}
-            _ => {
-                // this is a "direct", user-specified, rather than derived,
-                // obligation.
-                flags.push((sym::direct, None));
-            }
-        }
-
-        if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code {
-            // FIXME: maybe also have some way of handling methods
-            // from other traits? That would require name resolution,
-            // which we might want to be some sort of hygienic.
-            //
-            // Currently I'm leaving it for what I need for `try`.
-            if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
-                let method = self.tcx.item_name(item);
-                flags.push((sym::from_method, None));
-                flags.push((sym::from_method, Some(method.to_string())));
-            }
-        }
-        if let Some((t, _)) = self.get_parent_trait_ref(&obligation.cause.code) {
-            flags.push((sym::parent_trait, Some(t)));
-        }
-
-        if let Some(k) = obligation.cause.span.desugaring_kind() {
-            flags.push((sym::from_desugaring, None));
-            flags.push((sym::from_desugaring, Some(format!("{:?}", k))));
-        }
-        let generics = self.tcx.generics_of(def_id);
-        let self_ty = trait_ref.self_ty();
-        // This is also included through the generics list as `Self`,
-        // but the parser won't allow you to use it
-        flags.push((sym::_Self, Some(self_ty.to_string())));
-        if let Some(def) = self_ty.ty_adt_def() {
-            // We also want to be able to select self's original
-            // signature with no type arguments resolved
-            flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string())));
-        }
-
-        for param in generics.params.iter() {
-            let value = match param.kind {
-                GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
-                    trait_ref.substs[param.index as usize].to_string()
-                }
-                GenericParamDefKind::Lifetime => continue,
-            };
-            let name = param.name;
-            flags.push((name, Some(value)));
-        }
-
-        if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) {
-            flags.push((sym::crate_local, None));
-        }
-
-        // Allow targeting all integers using `{integral}`, even if the exact type was resolved
-        if self_ty.is_integral() {
-            flags.push((sym::_Self, Some("{integral}".to_owned())));
-        }
-
-        if let ty::Array(aty, len) = self_ty.kind {
-            flags.push((sym::_Self, Some("[]".to_owned())));
-            flags.push((sym::_Self, Some(format!("[{}]", aty))));
-            if let Some(def) = aty.ty_adt_def() {
-                // We also want to be able to select the array's type's original
-                // signature with no type arguments resolved
-                flags.push((
-                    sym::_Self,
-                    Some(format!("[{}]", self.tcx.type_of(def.did).to_string())),
-                ));
-                let tcx = self.tcx;
-                if let Some(len) = len.try_eval_usize(tcx, ty::ParamEnv::empty()) {
-                    flags.push((
-                        sym::_Self,
-                        Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)),
-                    ));
-                } else {
-                    flags.push((
-                        sym::_Self,
-                        Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())),
-                    ));
-                }
-            }
-        }
-
-        if let Ok(Some(command)) =
-            OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id)
-        {
-            command.evaluate(self.tcx, trait_ref, &flags[..])
-        } else {
-            OnUnimplementedNote::default()
-        }
-    }
-
-    fn find_similar_impl_candidates(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Vec<ty::TraitRef<'tcx>> {
-        let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true);
-        let all_impls = self.tcx.all_impls(trait_ref.def_id());
-
-        match simp {
-            Some(simp) => all_impls
-                .iter()
-                .filter_map(|&def_id| {
-                    let imp = self.tcx.impl_trait_ref(def_id).unwrap();
-                    let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true);
-                    if let Some(imp_simp) = imp_simp {
-                        if simp != imp_simp {
-                            return None;
-                        }
-                    }
-
-                    Some(imp)
-                })
-                .collect(),
-            None => {
-                all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect()
-            }
-        }
-    }
-
-    fn report_similar_impl_candidates(
-        &self,
-        impl_candidates: Vec<ty::TraitRef<'tcx>>,
-        err: &mut DiagnosticBuilder<'_>,
-    ) {
-        if impl_candidates.is_empty() {
-            return;
-        }
-
-        let len = impl_candidates.len();
-        let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { 4 };
-
-        let normalize = |candidate| {
-            self.tcx.infer_ctxt().enter(|ref infcx| {
-                let normalized = infcx
-                    .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
-                    .normalize(candidate)
-                    .ok();
-                match normalized {
-                    Some(normalized) => format!("\n  {:?}", normalized.value),
-                    None => format!("\n  {:?}", candidate),
-                }
-            })
-        };
-
-        // Sort impl candidates so that ordering is consistent for UI tests.
-        let mut normalized_impl_candidates =
-            impl_candidates.iter().map(normalize).collect::<Vec<String>>();
-
-        // Sort before taking the `..end` range,
-        // because the ordering of `impl_candidates` may not be deterministic:
-        // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
-        normalized_impl_candidates.sort();
-
-        err.help(&format!(
-            "the following implementations were found:{}{}",
-            normalized_impl_candidates[..end].join(""),
-            if len > 5 { format!("\nand {} others", len - 4) } else { String::new() }
-        ));
-    }
-
-    /// Reports that an overflow has occurred and halts compilation. We
-    /// halt compilation unconditionally because it is important that
-    /// overflows never be masked -- they basically represent computations
-    /// whose result could not be truly determined and thus we can't say
-    /// if the program type checks or not -- and they are unusual
-    /// occurrences in any case.
-    pub fn report_overflow_error<T>(
-        &self,
-        obligation: &Obligation<'tcx, T>,
-        suggest_increasing_limit: bool,
-    ) -> !
-    where
-        T: fmt::Display + TypeFoldable<'tcx>,
-    {
-        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            obligation.cause.span,
-            E0275,
-            "overflow evaluating the requirement `{}`",
-            predicate
-        );
-
-        if suggest_increasing_limit {
-            self.suggest_new_overflow_limit(&mut err);
-        }
-
-        self.note_obligation_cause_code(
-            &mut err,
-            &obligation.predicate,
-            &obligation.cause.code,
-            &mut vec![],
-        );
-
-        err.emit();
-        self.tcx.sess.abort_if_errors();
-        bug!();
-    }
-
-    /// Reports that a cycle was detected which led to overflow and halts
-    /// compilation. This is equivalent to `report_overflow_error` except
-    /// that we can give a more helpful error message (and, in particular,
-    /// we do not suggest increasing the overflow limit, which is not
-    /// going to help).
-    pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
-        let cycle = self.resolve_vars_if_possible(&cycle.to_owned());
-        assert!(cycle.len() > 0);
-
-        debug!("report_overflow_error_cycle: cycle={:?}", cycle);
-
-        self.report_overflow_error(&cycle[0], false);
-    }
-
-    pub fn report_extra_impl_obligation(
-        &self,
-        error_span: Span,
-        item_name: ast::Name,
-        _impl_item_def_id: DefId,
-        trait_item_def_id: DefId,
-        requirement: &dyn fmt::Display,
-    ) -> DiagnosticBuilder<'tcx> {
-        let msg = "impl has stricter requirements than trait";
-        let sp = self.tcx.sess.source_map().def_span(error_span);
-
-        let mut err = struct_span_err!(self.tcx.sess, sp, E0276, "{}", msg);
-
-        if let Some(trait_item_span) = self.tcx.hir().span_if_local(trait_item_def_id) {
-            let span = self.tcx.sess.source_map().def_span(trait_item_span);
-            err.span_label(span, format!("definition of `{}` from trait", item_name));
-        }
-
-        err.span_label(sp, format!("impl has extra requirement {}", requirement));
-
-        err
-    }
-
-    /// Gets the parent trait chain start
-    fn get_parent_trait_ref(
-        &self,
-        code: &ObligationCauseCode<'tcx>,
-    ) -> Option<(String, Option<Span>)> {
-        match code {
-            &ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
-                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-                match self.get_parent_trait_ref(&data.parent_code) {
-                    Some(t) => Some(t),
-                    None => {
-                        let ty = parent_trait_ref.skip_binder().self_ty();
-                        let span =
-                            TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id));
-                        Some((ty.to_string(), span))
-                    }
-                }
-            }
-            _ => None,
-        }
-    }
-
-    pub fn report_selection_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        error: &SelectionError<'tcx>,
-        fallback_has_occurred: bool,
-        points_at_arg: bool,
-    ) {
-        let tcx = self.tcx;
-        let span = obligation.cause.span;
-
-        let mut err = match *error {
-            SelectionError::Unimplemented => {
-                if let ObligationCauseCode::CompareImplMethodObligation {
-                    item_name,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                }
-                | ObligationCauseCode::CompareImplTypeObligation {
-                    item_name,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                } = obligation.cause.code
-                {
-                    self.report_extra_impl_obligation(
-                        span,
-                        item_name,
-                        impl_item_def_id,
-                        trait_item_def_id,
-                        &format!("`{}`", obligation.predicate),
-                    )
-                    .emit();
-                    return;
-                }
-                match obligation.predicate {
-                    ty::Predicate::Trait(ref trait_predicate) => {
-                        let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
-
-                        if self.tcx.sess.has_errors() && trait_predicate.references_error() {
-                            return;
-                        }
-                        let trait_ref = trait_predicate.to_poly_trait_ref();
-                        let (post_message, pre_message, type_def) = self
-                            .get_parent_trait_ref(&obligation.cause.code)
-                            .map(|(t, s)| {
-                                (
-                                    format!(" in `{}`", t),
-                                    format!("within `{}`, ", t),
-                                    s.map(|s| (format!("within this `{}`", t), s)),
-                                )
-                            })
-                            .unwrap_or_default();
-
-                        let OnUnimplementedNote { message, label, note, enclosing_scope } =
-                            self.on_unimplemented_note(trait_ref, obligation);
-                        let have_alt_message = message.is_some() || label.is_some();
-                        let is_try = self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .span_to_snippet(span)
-                            .map(|s| &s == "?")
-                            .unwrap_or(false);
-                        let is_from = format!("{}", trait_ref.print_only_trait_path())
-                            .starts_with("std::convert::From<");
-                        let (message, note) = if is_try && is_from {
-                            (
-                                Some(format!(
-                                    "`?` couldn't convert the error to `{}`",
-                                    trait_ref.self_ty(),
-                                )),
-                                Some(
-                                    "the question mark operation (`?`) implicitly performs a \
-                                 conversion on the error value using the `From` trait"
-                                        .to_owned(),
-                                ),
-                            )
-                        } else {
-                            (message, note)
-                        };
-
-                        let mut err = struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0277,
-                            "{}",
-                            message.unwrap_or_else(|| format!(
-                                "the trait bound `{}` is not satisfied{}",
-                                trait_ref.to_predicate(),
-                                post_message,
-                            ))
-                        );
-
-                        let explanation =
-                            if obligation.cause.code == ObligationCauseCode::MainFunctionType {
-                                "consider using `()`, or a `Result`".to_owned()
-                            } else {
-                                format!(
-                                    "{}the trait `{}` is not implemented for `{}`",
-                                    pre_message,
-                                    trait_ref.print_only_trait_path(),
-                                    trait_ref.self_ty(),
-                                )
-                            };
-
-                        if self.suggest_add_reference_to_arg(
-                            &obligation,
-                            &mut err,
-                            &trait_ref,
-                            points_at_arg,
-                            have_alt_message,
-                        ) {
-                            self.note_obligation_cause(&mut err, obligation);
-                            err.emit();
-                            return;
-                        }
-                        if let Some(ref s) = label {
-                            // If it has a custom `#[rustc_on_unimplemented]`
-                            // error message, let's display it as the label!
-                            err.span_label(span, s.as_str());
-                            err.help(&explanation);
-                        } else {
-                            err.span_label(span, explanation);
-                        }
-                        if let Some((msg, span)) = type_def {
-                            err.span_label(span, &msg);
-                        }
-                        if let Some(ref s) = note {
-                            // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
-                            err.note(s.as_str());
-                        }
-                        if let Some(ref s) = enclosing_scope {
-                            let enclosing_scope_span = tcx.def_span(
-                                tcx.hir()
-                                    .opt_local_def_id(obligation.cause.body_id)
-                                    .unwrap_or_else(|| {
-                                        tcx.hir().body_owner_def_id(hir::BodyId {
-                                            hir_id: obligation.cause.body_id,
-                                        })
-                                    }),
-                            );
-
-                            err.span_label(enclosing_scope_span, s.as_str());
-                        }
-
-                        self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
-                        self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg);
-                        self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
-                        self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
-                        self.note_version_mismatch(&mut err, &trait_ref);
-
-                        // Try to report a help message
-                        if !trait_ref.has_infer_types()
-                            && self.predicate_can_apply(obligation.param_env, trait_ref)
-                        {
-                            // If a where-clause may be useful, remind the
-                            // user that they can add it.
-                            //
-                            // don't display an on-unimplemented note, as
-                            // these notes will often be of the form
-                            //     "the type `T` can't be frobnicated"
-                            // which is somewhat confusing.
-                            self.suggest_restricting_param_bound(
-                                &mut err,
-                                &trait_ref,
-                                obligation.cause.body_id,
-                            );
-                        } else {
-                            if !have_alt_message {
-                                // Can't show anything else useful, try to find similar impls.
-                                let impl_candidates = self.find_similar_impl_candidates(trait_ref);
-                                self.report_similar_impl_candidates(impl_candidates, &mut err);
-                            }
-                            self.suggest_change_mut(
-                                &obligation,
-                                &mut err,
-                                &trait_ref,
-                                points_at_arg,
-                            );
-                        }
-
-                        // If this error is due to `!: Trait` not implemented but `(): Trait` is
-                        // implemented, and fallback has occurred, then it could be due to a
-                        // variable that used to fallback to `()` now falling back to `!`. Issue a
-                        // note informing about the change in behaviour.
-                        if trait_predicate.skip_binder().self_ty().is_never()
-                            && fallback_has_occurred
-                        {
-                            let predicate = trait_predicate.map_bound(|mut trait_pred| {
-                                trait_pred.trait_ref.substs = self.tcx.mk_substs_trait(
-                                    self.tcx.mk_unit(),
-                                    &trait_pred.trait_ref.substs[1..],
-                                );
-                                trait_pred
-                            });
-                            let unit_obligation = Obligation {
-                                predicate: ty::Predicate::Trait(predicate),
-                                ..obligation.clone()
-                            };
-                            if self.predicate_may_hold(&unit_obligation) {
-                                err.note(
-                                    "the trait is implemented for `()`. \
-                                         Possibly this error has been caused by changes to \
-                                         Rust's type-inference algorithm \
-                                         (see: https://github.com/rust-lang/rust/issues/48950 \
-                                         for more info). Consider whether you meant to use the \
-                                         type `()` here instead.",
-                                );
-                            }
-                        }
-
-                        err
-                    }
-
-                    ty::Predicate::Subtype(ref predicate) => {
-                        // Errors for Subtype predicates show up as
-                        // `FulfillmentErrorCode::CodeSubtypeError`,
-                        // not selection error.
-                        span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
-                    }
-
-                    ty::Predicate::RegionOutlives(ref predicate) => {
-                        let predicate = self.resolve_vars_if_possible(predicate);
-                        let err = self
-                            .region_outlives_predicate(&obligation.cause, &predicate)
-                            .err()
-                            .unwrap();
-                        struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0279,
-                            "the requirement `{}` is not satisfied (`{}`)",
-                            predicate,
-                            err,
-                        )
-                    }
-
-                    ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
-                        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-                        struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0280,
-                            "the requirement `{}` is not satisfied",
-                            predicate
-                        )
-                    }
-
-                    ty::Predicate::ObjectSafe(trait_def_id) => {
-                        let violations = object_safety_violations(self.tcx, trait_def_id);
-                        report_object_safety_error(self.tcx, span, trait_def_id, violations)
-                    }
-
-                    ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
-                        let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap();
-                        let closure_span = self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .def_span(self.tcx.hir().span_if_local(closure_def_id).unwrap());
-                        let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id).unwrap();
-                        let mut err = struct_span_err!(
-                            self.tcx.sess,
-                            closure_span,
-                            E0525,
-                            "expected a closure that implements the `{}` trait, \
-                             but this closure only implements `{}`",
-                            kind,
-                            found_kind
-                        );
-
-                        err.span_label(
-                            closure_span,
-                            format!("this closure implements `{}`, not `{}`", found_kind, kind),
-                        );
-                        err.span_label(
-                            obligation.cause.span,
-                            format!("the requirement to implement `{}` derives from here", kind),
-                        );
-
-                        // Additional context information explaining why the closure only implements
-                        // a particular trait.
-                        if let Some(tables) = self.in_progress_tables {
-                            let tables = tables.borrow();
-                            match (found_kind, tables.closure_kind_origins().get(hir_id)) {
-                                (ty::ClosureKind::FnOnce, Some((span, name))) => {
-                                    err.span_label(
-                                        *span,
-                                        format!(
-                                            "closure is `FnOnce` because it moves the \
-                                         variable `{}` out of its environment",
-                                            name
-                                        ),
-                                    );
-                                }
-                                (ty::ClosureKind::FnMut, Some((span, name))) => {
-                                    err.span_label(
-                                        *span,
-                                        format!(
-                                            "closure is `FnMut` because it mutates the \
-                                         variable `{}` here",
-                                            name
-                                        ),
-                                    );
-                                }
-                                _ => {}
-                            }
-                        }
-
-                        err.emit();
-                        return;
-                    }
-
-                    ty::Predicate::WellFormed(ty) => {
-                        if !self.tcx.sess.opts.debugging_opts.chalk {
-                            // WF predicates cannot themselves make
-                            // errors. They can only block due to
-                            // ambiguity; otherwise, they always
-                            // degenerate into other obligations
-                            // (which may fail).
-                            span_bug!(span, "WF predicate not satisfied for {:?}", ty);
-                        } else {
-                            // FIXME: we'll need a better message which takes into account
-                            // which bounds actually failed to hold.
-                            self.tcx.sess.struct_span_err(
-                                span,
-                                &format!("the type `{}` is not well-formed (chalk)", ty),
-                            )
-                        }
-                    }
-
-                    ty::Predicate::ConstEvaluatable(..) => {
-                        // Errors for `ConstEvaluatable` predicates show up as
-                        // `SelectionError::ConstEvalFailure`,
-                        // not `Unimplemented`.
-                        span_bug!(
-                            span,
-                            "const-evaluatable requirement gave wrong error: `{:?}`",
-                            obligation
-                        )
-                    }
-                }
-            }
-
-            OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => {
-                let found_trait_ref = self.resolve_vars_if_possible(&*found_trait_ref);
-                let expected_trait_ref = self.resolve_vars_if_possible(&*expected_trait_ref);
-
-                if expected_trait_ref.self_ty().references_error() {
-                    return;
-                }
-
-                let found_trait_ty = found_trait_ref.self_ty();
-
-                let found_did = match found_trait_ty.kind {
-                    ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did),
-                    ty::Adt(def, _) => Some(def.did),
-                    _ => None,
-                };
-
-                let found_span = found_did
-                    .and_then(|did| self.tcx.hir().span_if_local(did))
-                    .map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def
-
-                if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
-                    // We check closures twice, with obligations flowing in different directions,
-                    // but we want to complain about them only once.
-                    return;
-                }
-
-                self.reported_closure_mismatch.borrow_mut().insert((span, found_span));
-
-                let found = match found_trait_ref.skip_binder().substs.type_at(1).kind {
-                    ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()],
-                    _ => vec![ArgKind::empty()],
-                };
-
-                let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1);
-                let expected = match expected_ty.kind {
-                    ty::Tuple(ref tys) => tys
-                        .iter()
-                        .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span)))
-                        .collect(),
-                    _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())],
-                };
-
-                if found.len() == expected.len() {
-                    self.report_closure_arg_mismatch(
-                        span,
-                        found_span,
-                        found_trait_ref,
-                        expected_trait_ref,
-                    )
-                } else {
-                    let (closure_span, found) = found_did
-                        .and_then(|did| self.tcx.hir().get_if_local(did))
-                        .map(|node| {
-                            let (found_span, found) = self.get_fn_like_arguments(node);
-                            (Some(found_span), found)
-                        })
-                        .unwrap_or((found_span, found));
-
-                    self.report_arg_count_mismatch(
-                        span,
-                        closure_span,
-                        expected,
-                        found,
-                        found_trait_ty.is_closure(),
-                    )
-                }
-            }
-
-            TraitNotObjectSafe(did) => {
-                let violations = object_safety_violations(self.tcx, did);
-                report_object_safety_error(self.tcx, span, did, violations)
-            }
-
-            // already reported in the query
-            ConstEvalFailure(err) => {
-                if let ErrorHandled::TooGeneric = err {
-                    // Silence this error, as it can be produced during intermediate steps
-                    // when a constant is not yet able to be evaluated (but will be later).
-                    return;
-                }
-                self.tcx.sess.delay_span_bug(
-                    span,
-                    &format!("constant in type had an ignored error: {:?}", err),
-                );
-                return;
-            }
-
-            Overflow => {
-                bug!("overflow should be handled before the `report_selection_error` path");
-            }
-        };
-
-        self.note_obligation_cause(&mut err, obligation);
-
-        err.emit();
-    }
-
-    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
-    /// with the same path as `trait_ref`, a help message about
-    /// a probable version mismatch is added to `err`
-    fn note_version_mismatch(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        trait_ref: &ty::PolyTraitRef<'tcx>,
-    ) {
-        let get_trait_impl = |trait_def_id| {
-            let mut trait_impl = None;
-            self.tcx.for_each_relevant_impl(trait_def_id, trait_ref.self_ty(), |impl_def_id| {
-                if trait_impl.is_none() {
-                    trait_impl = Some(impl_def_id);
-                }
-            });
-            trait_impl
-        };
-        let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
-        let all_traits = self.tcx.all_traits(LOCAL_CRATE);
-        let traits_with_same_path: std::collections::BTreeSet<_> = all_traits
-            .iter()
-            .filter(|trait_def_id| **trait_def_id != trait_ref.def_id())
-            .filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path)
-            .collect();
-        for trait_with_same_path in traits_with_same_path {
-            if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) {
-                let impl_span = self.tcx.def_span(impl_def_id);
-                err.span_help(impl_span, "trait impl with same name found");
-                let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
-                let crate_msg = format!(
-                    "perhaps two different versions of crate `{}` are being used?",
-                    trait_crate
-                );
-                err.note(&crate_msg);
-            }
-        }
-    }
-    fn suggest_restricting_param_bound(
-        &self,
-        mut err: &mut DiagnosticBuilder<'_>,
-        trait_ref: &ty::PolyTraitRef<'_>,
-        body_id: hir::HirId,
-    ) {
-        let self_ty = trait_ref.self_ty();
-        let (param_ty, projection) = match &self_ty.kind {
-            ty::Param(_) => (true, None),
-            ty::Projection(projection) => (false, Some(projection)),
-            _ => return,
-        };
-
-        let suggest_restriction =
-            |generics: &hir::Generics<'_>, msg, err: &mut DiagnosticBuilder<'_>| {
-                let span = generics.where_clause.span_for_predicates_or_empty_place();
-                if !span.from_expansion() && span.desugaring_kind().is_none() {
-                    err.span_suggestion(
-                        generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(),
-                        &format!("consider further restricting {}", msg),
-                        format!(
-                            "{} {} ",
-                            if !generics.where_clause.predicates.is_empty() {
-                                ","
-                            } else {
-                                " where"
-                            },
-                            trait_ref.to_predicate(),
-                        ),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            };
-
-        // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
-        //        don't suggest `T: Sized + ?Sized`.
-        let mut hir_id = body_id;
-        while let Some(node) = self.tcx.hir().find(hir_id) {
-            match node {
-                hir::Node::TraitItem(hir::TraitItem {
-                    generics,
-                    kind: hir::TraitItemKind::Method(..),
-                    ..
-                }) if param_ty && self_ty == self.tcx.types.self_param => {
-                    // Restricting `Self` for a single method.
-                    suggest_restriction(&generics, "`Self`", err);
-                    return;
-                }
-
-                hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
-                | hir::Node::TraitItem(hir::TraitItem {
-                    generics,
-                    kind: hir::TraitItemKind::Method(..),
-                    ..
-                })
-                | hir::Node::ImplItem(hir::ImplItem {
-                    generics,
-                    kind: hir::ImplItemKind::Method(..),
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Trait(_, _, generics, _, _),
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Impl(_, _, _, generics, ..),
-                    ..
-                }) if projection.is_some() => {
-                    // Missing associated type bound.
-                    suggest_restriction(&generics, "the associated type", err);
-                    return;
-                }
-
-                hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Struct(_, generics),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Enum(_, generics), span, ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Union(_, generics),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Trait(_, _, generics, ..),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Impl(_, _, _, generics, ..),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Fn(_, generics, _),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::TyAlias(_, generics),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::TraitAlias(generics, _),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }),
-                    span,
-                    ..
-                })
-                | hir::Node::TraitItem(hir::TraitItem { generics, span, .. })
-                | hir::Node::ImplItem(hir::ImplItem { generics, span, .. })
-                    if param_ty =>
-                {
-                    // Missing generic type parameter bound.
-                    let param_name = self_ty.to_string();
-                    let constraint = trait_ref.print_only_trait_path().to_string();
-                    if suggest_constraining_type_param(
-                        generics,
-                        &mut err,
-                        &param_name,
-                        &constraint,
-                        self.tcx.sess.source_map(),
-                        *span,
-                    ) {
-                        return;
-                    }
-                }
-
-                hir::Node::Crate => return,
-
-                _ => {}
-            }
-
-            hir_id = self.tcx.hir().get_parent_item(hir_id);
-        }
-    }
-
-    /// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a
-    /// suggestion to borrow the initializer in order to use have a slice instead.
-    fn suggest_borrow_on_unsized_slice(
-        &self,
-        code: &ObligationCauseCode<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-    ) {
-        if let &ObligationCauseCode::VariableType(hir_id) = code {
-            let parent_node = self.tcx.hir().get_parent_node(hir_id);
-            if let Some(Node::Local(ref local)) = self.tcx.hir().find(parent_node) {
-                if let Some(ref expr) = local.init {
-                    if let hir::ExprKind::Index(_, _) = expr.kind {
-                        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
-                            err.span_suggestion(
-                                expr.span,
-                                "consider borrowing here",
-                                format!("&{}", snippet),
-                                Applicability::MachineApplicable,
-                            );
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    fn mk_obligation_for_def_id(
-        &self,
-        def_id: DefId,
-        output_ty: Ty<'tcx>,
-        cause: ObligationCause<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> PredicateObligation<'tcx> {
-        let new_trait_ref =
-            ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
-        Obligation::new(cause, param_env, new_trait_ref.to_predicate())
-    }
-
-    /// Given a closure's `DefId`, return the given name of the closure.
-    ///
-    /// This doesn't account for reassignments, but it's only used for suggestions.
-    fn get_closure_name(
-        &self,
-        def_id: DefId,
-        err: &mut DiagnosticBuilder<'_>,
-        msg: &str,
-    ) -> Option<String> {
-        let get_name =
-            |err: &mut DiagnosticBuilder<'_>, kind: &hir::PatKind<'_>| -> Option<String> {
-                // Get the local name of this closure. This can be inaccurate because
-                // of the possibility of reassignment, but this should be good enough.
-                match &kind {
-                    hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => {
-                        Some(format!("{}", name))
-                    }
-                    _ => {
-                        err.note(&msg);
-                        None
-                    }
-                }
-            };
-
-        let hir = self.tcx.hir();
-        let hir_id = hir.as_local_hir_id(def_id)?;
-        let parent_node = hir.get_parent_node(hir_id);
-        match hir.find(parent_node) {
-            Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. })) => {
-                get_name(err, &local.pat.kind)
-            }
-            // Different to previous arm because one is `&hir::Local` and the other
-            // is `P<hir::Local>`.
-            Some(hir::Node::Local(local)) => get_name(err, &local.pat.kind),
-            _ => return None,
-        }
-    }
-
-    /// We tried to apply the bound to an `fn` or closure. Check whether calling it would
-    /// evaluate to a type that *would* satisfy the trait binding. If it would, suggest calling
-    /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
-    fn suggest_fn_call(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'_>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
-    ) {
-        let self_ty = trait_ref.self_ty();
-        let (def_id, output_ty, callable) = match self_ty.kind {
-            ty::Closure(def_id, substs) => {
-                (def_id, self.closure_sig(def_id, substs).output(), "closure")
-            }
-            ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"),
-            _ => return,
-        };
-        let msg = format!("use parentheses to call the {}", callable);
-
-        let obligation = self.mk_obligation_for_def_id(
-            trait_ref.def_id(),
-            output_ty.skip_binder(),
-            obligation.cause.clone(),
-            obligation.param_env,
-        );
-
-        match self.evaluate_obligation(&obligation) {
-            Ok(EvaluationResult::EvaluatedToOk)
-            | Ok(EvaluationResult::EvaluatedToOkModuloRegions)
-            | Ok(EvaluationResult::EvaluatedToAmbig) => {}
-            _ => return,
-        }
-        let hir = self.tcx.hir();
-        // Get the name of the callable and the arguments to be used in the suggestion.
-        let snippet = match hir.get_if_local(def_id) {
-            Some(hir::Node::Expr(hir::Expr {
-                kind: hir::ExprKind::Closure(_, decl, _, span, ..),
-                ..
-            })) => {
-                err.span_label(*span, "consider calling this closure");
-                let name = match self.get_closure_name(def_id, err, &msg) {
-                    Some(name) => name,
-                    None => return,
-                };
-                let args = decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
-                format!("{}({})", name, args)
-            }
-            Some(hir::Node::Item(hir::Item {
-                ident,
-                kind: hir::ItemKind::Fn(.., body_id),
-                ..
-            })) => {
-                err.span_label(ident.span, "consider calling this function");
-                let body = hir.body(*body_id);
-                let args = body
-                    .params
-                    .iter()
-                    .map(|arg| match &arg.pat.kind {
-                        hir::PatKind::Binding(_, _, ident, None)
-                        // FIXME: provide a better suggestion when encountering `SelfLower`, it
-                        // should suggest a method call.
-                        if ident.name != kw::SelfLower => ident.to_string(),
-                        _ => "_".to_string(),
-                    })
-                    .collect::<Vec<_>>()
-                    .join(", ");
-                format!("{}({})", ident, args)
-            }
-            _ => return,
-        };
-        if points_at_arg {
-            // When the obligation error has been ensured to have been caused by
-            // an argument, the `obligation.cause.span` points at the expression
-            // of the argument, so we can provide a suggestion. This is signaled
-            // by `points_at_arg`. Otherwise, we give a more general note.
-            err.span_suggestion(
-                obligation.cause.span,
-                &msg,
-                snippet,
-                Applicability::HasPlaceholders,
-            );
-        } else {
-            err.help(&format!("{}: `{}`", msg, snippet));
-        }
-    }
-
-    fn suggest_add_reference_to_arg(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
-        has_custom_message: bool,
-    ) -> bool {
-        if !points_at_arg {
-            return false;
-        }
-
-        let span = obligation.cause.span;
-        let param_env = obligation.param_env;
-        let trait_ref = trait_ref.skip_binder();
-
-        if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code {
-            // Try to apply the original trait binding obligation by borrowing.
-            let self_ty = trait_ref.self_ty();
-            let found = self_ty.to_string();
-            let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
-            let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
-            let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
-            let new_obligation =
-                Obligation::new(ObligationCause::dummy(), param_env, new_trait_ref.to_predicate());
-            if self.predicate_must_hold_modulo_regions(&new_obligation) {
-                if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-                    // We have a very specific type of error, where just borrowing this argument
-                    // might solve the problem. In cases like this, the important part is the
-                    // original type obligation, not the last one that failed, which is arbitrary.
-                    // Because of this, we modify the error to refer to the original obligation and
-                    // return early in the caller.
-                    let msg = format!(
-                        "the trait bound `{}: {}` is not satisfied",
-                        found,
-                        obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
-                    );
-                    if has_custom_message {
-                        err.note(&msg);
-                    } else {
-                        err.message = vec![(msg, Style::NoStyle)];
-                    }
-                    if snippet.starts_with('&') {
-                        // This is already a literal borrow and the obligation is failing
-                        // somewhere else in the obligation chain. Do not suggest non-sense.
-                        return false;
-                    }
-                    err.span_label(
-                        span,
-                        &format!(
-                            "expected an implementor of trait `{}`",
-                            obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
-                        ),
-                    );
-                    err.span_suggestion(
-                        span,
-                        "consider borrowing here",
-                        format!("&{}", snippet),
-                        Applicability::MaybeIncorrect,
-                    );
-                    return true;
-                }
-            }
-        }
-        false
-    }
-
-    /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
-    /// suggest removing these references until we reach a type that implements the trait.
-    fn suggest_remove_reference(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-    ) {
-        let trait_ref = trait_ref.skip_binder();
-        let span = obligation.cause.span;
-
-        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-            let refs_number =
-                snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
-            if let Some('\'') =
-                snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next()
-            {
-                // Do not suggest removal of borrow from type arguments.
-                return;
-            }
-
-            let mut trait_type = trait_ref.self_ty();
-
-            for refs_remaining in 0..refs_number {
-                if let ty::Ref(_, t_type, _) = trait_type.kind {
-                    trait_type = t_type;
-
-                    let new_obligation = self.mk_obligation_for_def_id(
-                        trait_ref.def_id,
-                        trait_type,
-                        ObligationCause::dummy(),
-                        obligation.param_env,
-                    );
-
-                    if self.predicate_may_hold(&new_obligation) {
-                        let sp = self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .span_take_while(span, |c| c.is_whitespace() || *c == '&');
-
-                        let remove_refs = refs_remaining + 1;
-                        let format_str =
-                            format!("consider removing {} leading `&`-references", remove_refs);
-
-                        err.span_suggestion_short(
-                            sp,
-                            &format_str,
-                            String::new(),
-                            Applicability::MachineApplicable,
-                        );
-                        break;
-                    }
-                } else {
-                    break;
-                }
-            }
-        }
-    }
-
-    /// Check if the trait bound is implemented for a different mutability and note it in the
-    /// final error.
-    fn suggest_change_mut(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
-    ) {
-        let span = obligation.cause.span;
-        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-            let refs_number =
-                snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
-            if let Some('\'') =
-                snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next()
-            {
-                // Do not suggest removal of borrow from type arguments.
-                return;
-            }
-            let trait_ref = self.resolve_vars_if_possible(trait_ref);
-            if trait_ref.has_infer_types() {
-                // Do not ICE while trying to find if a reborrow would succeed on a trait with
-                // unresolved bindings.
-                return;
-            }
-
-            if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind {
-                let trait_type = match mutability {
-                    hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type),
-                    hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type),
-                };
-
-                let new_obligation = self.mk_obligation_for_def_id(
-                    trait_ref.skip_binder().def_id,
-                    trait_type,
-                    ObligationCause::dummy(),
-                    obligation.param_env,
-                );
-
-                if self.evaluate_obligation_no_overflow(&new_obligation).must_apply_modulo_regions()
-                {
-                    let sp = self
-                        .tcx
-                        .sess
-                        .source_map()
-                        .span_take_while(span, |c| c.is_whitespace() || *c == '&');
-                    if points_at_arg && mutability == hir::Mutability::Not && refs_number > 0 {
-                        err.span_suggestion(
-                            sp,
-                            "consider changing this borrow's mutability",
-                            "&mut ".to_string(),
-                            Applicability::MachineApplicable,
-                        );
-                    } else {
-                        err.note(&format!(
-                            "`{}` is implemented for `{:?}`, but not for `{:?}`",
-                            trait_ref.print_only_trait_path(),
-                            trait_type,
-                            trait_ref.skip_binder().self_ty(),
-                        ));
-                    }
-                }
-            }
-        }
-    }
-
-    fn suggest_semicolon_removal(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        span: Span,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-    ) {
-        let hir = self.tcx.hir();
-        let parent_node = hir.get_parent_node(obligation.cause.body_id);
-        let node = hir.find(parent_node);
-        if let Some(hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::Fn(sig, _, body_id), ..
-        })) = node
-        {
-            let body = hir.body(*body_id);
-            if let hir::ExprKind::Block(blk, _) = &body.value.kind {
-                if sig.decl.output.span().overlaps(span)
-                    && blk.expr.is_none()
-                    && "()" == &trait_ref.self_ty().to_string()
-                {
-                    // FIXME(estebank): When encountering a method with a trait
-                    // bound not satisfied in the return type with a body that has
-                    // no return, suggest removal of semicolon on last statement.
-                    // Once that is added, close #54771.
-                    if let Some(ref stmt) = blk.stmts.last() {
-                        let sp = self.tcx.sess.source_map().end_point(stmt.span);
-                        err.span_label(sp, "consider removing this semicolon");
-                    }
-                }
-            }
-        }
-    }
-
-    /// Given some node representing a fn-like thing in the HIR map,
-    /// returns a span and `ArgKind` information that describes the
-    /// arguments it expects. This can be supplied to
-    /// `report_arg_count_mismatch`.
-    pub fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>) {
-        match node {
-            Node::Expr(&hir::Expr {
-                kind: hir::ExprKind::Closure(_, ref _decl, id, span, _),
-                ..
-            }) => (
-                self.tcx.sess.source_map().def_span(span),
-                self.tcx
-                    .hir()
-                    .body(id)
-                    .params
-                    .iter()
-                    .map(|arg| {
-                        if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
-                            *arg.pat
-                        {
-                            ArgKind::Tuple(
-                                Some(span),
-                                args.iter()
-                                    .map(|pat| {
-                                        let snippet = self
-                                            .tcx
-                                            .sess
-                                            .source_map()
-                                            .span_to_snippet(pat.span)
-                                            .unwrap();
-                                        (snippet, "_".to_owned())
-                                    })
-                                    .collect::<Vec<_>>(),
-                            )
-                        } else {
-                            let name =
-                                self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap();
-                            ArgKind::Arg(name, "_".to_owned())
-                        }
-                    })
-                    .collect::<Vec<ArgKind>>(),
-            ),
-            Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. })
-            | Node::ImplItem(&hir::ImplItem {
-                span,
-                kind: hir::ImplItemKind::Method(ref sig, _),
-                ..
-            })
-            | Node::TraitItem(&hir::TraitItem {
-                span,
-                kind: hir::TraitItemKind::Method(ref sig, _),
-                ..
-            }) => (
-                self.tcx.sess.source_map().def_span(span),
-                sig.decl
-                    .inputs
-                    .iter()
-                    .map(|arg| match arg.clone().kind {
-                        hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
-                            Some(arg.span),
-                            vec![("_".to_owned(), "_".to_owned()); tys.len()],
-                        ),
-                        _ => ArgKind::empty(),
-                    })
-                    .collect::<Vec<ArgKind>>(),
-            ),
-            Node::Ctor(ref variant_data) => {
-                let span = variant_data
-                    .ctor_hir_id()
-                    .map(|hir_id| self.tcx.hir().span(hir_id))
-                    .unwrap_or(DUMMY_SP);
-                let span = self.tcx.sess.source_map().def_span(span);
-
-                (span, vec![ArgKind::empty(); variant_data.fields().len()])
-            }
-            _ => panic!("non-FnLike node found: {:?}", node),
-        }
-    }
-
-    /// Reports an error when the number of arguments needed by a
-    /// trait match doesn't match the number that the expression
-    /// provides.
-    pub fn report_arg_count_mismatch(
-        &self,
-        span: Span,
-        found_span: Option<Span>,
-        expected_args: Vec<ArgKind>,
-        found_args: Vec<ArgKind>,
-        is_closure: bool,
-    ) -> DiagnosticBuilder<'tcx> {
-        let kind = if is_closure { "closure" } else { "function" };
-
-        let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
-            let arg_length = arguments.len();
-            let distinct = match &other[..] {
-                &[ArgKind::Tuple(..)] => true,
-                _ => false,
-            };
-            match (arg_length, arguments.get(0)) {
-                (1, Some(&ArgKind::Tuple(_, ref fields))) => {
-                    format!("a single {}-tuple as argument", fields.len())
-                }
-                _ => format!(
-                    "{} {}argument{}",
-                    arg_length,
-                    if distinct && arg_length > 1 { "distinct " } else { "" },
-                    pluralize!(arg_length)
-                ),
-            }
-        };
-
-        let expected_str = args_str(&expected_args, &found_args);
-        let found_str = args_str(&found_args, &expected_args);
-
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            span,
-            E0593,
-            "{} is expected to take {}, but it takes {}",
-            kind,
-            expected_str,
-            found_str,
-        );
-
-        err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
-
-        if let Some(found_span) = found_span {
-            err.span_label(found_span, format!("takes {}", found_str));
-
-            // move |_| { ... }
-            // ^^^^^^^^-- def_span
-            //
-            // move |_| { ... }
-            // ^^^^^-- prefix
-            let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
-            // move |_| { ... }
-            //      ^^^-- pipe_span
-            let pipe_span =
-                if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span };
-
-            // Suggest to take and ignore the arguments with expected_args_length `_`s if
-            // found arguments is empty (assume the user just wants to ignore args in this case).
-            // For example, if `expected_args_length` is 2, suggest `|_, _|`.
-            if found_args.is_empty() && is_closure {
-                let underscores = vec!["_"; expected_args.len()].join(", ");
-                err.span_suggestion(
-                    pipe_span,
-                    &format!(
-                        "consider changing the closure to take and ignore the expected argument{}",
-                        if expected_args.len() < 2 { "" } else { "s" }
-                    ),
-                    format!("|{}|", underscores),
-                    Applicability::MachineApplicable,
-                );
-            }
-
-            if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
-                if fields.len() == expected_args.len() {
-                    let sugg = fields
-                        .iter()
-                        .map(|(name, _)| name.to_owned())
-                        .collect::<Vec<String>>()
-                        .join(", ");
-                    err.span_suggestion(
-                        found_span,
-                        "change the closure to take multiple arguments instead of a single tuple",
-                        format!("|{}|", sugg),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
-                if fields.len() == found_args.len() && is_closure {
-                    let sugg = format!(
-                        "|({}){}|",
-                        found_args
-                            .iter()
-                            .map(|arg| match arg {
-                                ArgKind::Arg(name, _) => name.to_owned(),
-                                _ => "_".to_owned(),
-                            })
-                            .collect::<Vec<String>>()
-                            .join(", "),
-                        // add type annotations if available
-                        if found_args.iter().any(|arg| match arg {
-                            ArgKind::Arg(_, ty) => ty != "_",
-                            _ => false,
-                        }) {
-                            format!(
-                                ": ({})",
-                                fields
-                                    .iter()
-                                    .map(|(_, ty)| ty.to_owned())
-                                    .collect::<Vec<String>>()
-                                    .join(", ")
-                            )
-                        } else {
-                            String::new()
-                        },
-                    );
-                    err.span_suggestion(
-                        found_span,
-                        "change the closure to accept a tuple instead of individual arguments",
-                        sugg,
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-        }
-
-        err
-    }
-
-    fn report_closure_arg_mismatch(
-        &self,
-        span: Span,
-        found_span: Option<Span>,
-        expected_ref: ty::PolyTraitRef<'tcx>,
-        found: ty::PolyTraitRef<'tcx>,
-    ) -> DiagnosticBuilder<'tcx> {
-        fn build_fn_sig_string<'tcx>(tcx: TyCtxt<'tcx>, trait_ref: &ty::TraitRef<'tcx>) -> String {
-            let inputs = trait_ref.substs.type_at(1);
-            let sig = if let ty::Tuple(inputs) = inputs.kind {
-                tcx.mk_fn_sig(
-                    inputs.iter().map(|k| k.expect_ty()),
-                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
-                    false,
-                    hir::Unsafety::Normal,
-                    ::rustc_target::spec::abi::Abi::Rust,
-                )
-            } else {
-                tcx.mk_fn_sig(
-                    ::std::iter::once(inputs),
-                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
-                    false,
-                    hir::Unsafety::Normal,
-                    ::rustc_target::spec::abi::Abi::Rust,
-                )
-            };
-            ty::Binder::bind(sig).to_string()
-        }
-
-        let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            span,
-            E0631,
-            "type mismatch in {} arguments",
-            if argument_is_closure { "closure" } else { "function" }
-        );
-
-        let found_str = format!(
-            "expected signature of `{}`",
-            build_fn_sig_string(self.tcx, found.skip_binder())
-        );
-        err.span_label(span, found_str);
-
-        let found_span = found_span.unwrap_or(span);
-        let expected_str = format!(
-            "found signature of `{}`",
-            build_fn_sig_string(self.tcx, expected_ref.skip_binder())
-        );
-        err.span_label(found_span, expected_str);
-
-        err
-    }
-}
-
-pub fn recursive_type_with_infinite_size_error(
-    tcx: TyCtxt<'tcx>,
-    type_def_id: DefId,
-) -> DiagnosticBuilder<'tcx> {
-    assert!(type_def_id.is_local());
-    let span = tcx.hir().span_if_local(type_def_id).unwrap();
-    let span = tcx.sess.source_map().def_span(span);
-    let mut err = struct_span_err!(
-        tcx.sess,
-        span,
-        E0072,
-        "recursive type `{}` has infinite size",
-        tcx.def_path_str(type_def_id)
-    );
-    err.span_label(span, "recursive type has infinite size");
-    err.help(&format!(
-        "insert indirection (e.g., a `Box`, `Rc`, or `&`) \
-                           at some point to make `{}` representable",
-        tcx.def_path_str(type_def_id)
-    ));
-    err
-}
-
-pub fn report_object_safety_error(
-    tcx: TyCtxt<'tcx>,
-    span: Span,
-    trait_def_id: DefId,
-    violations: Vec<ObjectSafetyViolation>,
-) -> DiagnosticBuilder<'tcx> {
-    let trait_str = tcx.def_path_str(trait_def_id);
-    let span = tcx.sess.source_map().def_span(span);
-    let mut err = struct_span_err!(
-        tcx.sess,
-        span,
-        E0038,
-        "the trait `{}` cannot be made into an object",
-        trait_str
-    );
-    err.span_label(span, format!("the trait `{}` cannot be made into an object", trait_str));
-
-    let mut reported_violations = FxHashSet::default();
-    for violation in violations {
-        if reported_violations.insert(violation.clone()) {
-            match violation.span() {
-                Some(span) => err.span_label(span, violation.error_msg()),
-                None => err.note(&violation.error_msg()),
-            };
-        }
-    }
-
-    if tcx.sess.trait_methods_not_found.borrow().contains(&span) {
-        // Avoid emitting error caused by non-existing method (#58734)
-        err.cancel();
-    }
-
-    err
-}
-
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    fn maybe_report_ambiguity(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        body_id: Option<hir::BodyId>,
-    ) {
-        // Unable to successfully determine, probably means
-        // insufficient type information, but could mean
-        // ambiguous impls. The latter *ought* to be a
-        // coherence violation, so we don't report it here.
-
-        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-        let span = obligation.cause.span;
-
-        debug!(
-            "maybe_report_ambiguity(predicate={:?}, obligation={:?} body_id={:?}, code={:?})",
-            predicate, obligation, body_id, obligation.cause.code,
-        );
-
-        // Ambiguity errors are often caused as fallout from earlier
-        // errors. So just ignore them if this infcx is tainted.
-        if self.is_tainted_by_errors() {
-            return;
-        }
-
-        let mut err = match predicate {
-            ty::Predicate::Trait(ref data) => {
-                let trait_ref = data.to_poly_trait_ref();
-                let self_ty = trait_ref.self_ty();
-                debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref);
-
-                if predicate.references_error() {
-                    return;
-                }
-                // Typically, this ambiguity should only happen if
-                // there are unresolved type inference variables
-                // (otherwise it would suggest a coherence
-                // failure). But given #21974 that is not necessarily
-                // the case -- we can have multiple where clauses that
-                // are only distinguished by a region, which results
-                // in an ambiguity even when all types are fully
-                // known, since we don't dispatch based on region
-                // relationships.
-
-                // This is kind of a hack: it frequently happens that some earlier
-                // error prevents types from being fully inferred, and then we get
-                // a bunch of uninteresting errors saying something like "<generic
-                // #0> doesn't implement Sized".  It may even be true that we
-                // could just skip over all checks where the self-ty is an
-                // inference variable, but I was afraid that there might be an
-                // inference variable created, registered as an obligation, and
-                // then never forced by writeback, and hence by skipping here we'd
-                // be ignoring the fact that we don't KNOW the type works
-                // out. Though even that would probably be harmless, given that
-                // we're only talking about builtin traits, which are known to be
-                // inhabited. We used to check for `self.tcx.sess.has_errors()` to
-                // avoid inundating the user with unnecessary errors, but we now
-                // check upstream for type errors and dont add the obligations to
-                // begin with in those cases.
-                if self
-                    .tcx
-                    .lang_items()
-                    .sized_trait()
-                    .map_or(false, |sized_id| sized_id == trait_ref.def_id())
-                {
-                    self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
-                    return;
-                }
-                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283);
-                err.note(&format!("cannot resolve `{}`", predicate));
-                if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
-                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
-                } else if let (
-                    Ok(ref snippet),
-                    ObligationCauseCode::BindingObligation(ref def_id, _),
-                ) =
-                    (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code)
-                {
-                    let generics = self.tcx.generics_of(*def_id);
-                    if !generics.params.is_empty() && !snippet.ends_with('>') {
-                        // FIXME: To avoid spurious suggestions in functions where type arguments
-                        // where already supplied, we check the snippet to make sure it doesn't
-                        // end with a turbofish. Ideally we would have access to a `PathSegment`
-                        // instead. Otherwise we would produce the following output:
-                        //
-                        // error[E0283]: type annotations needed
-                        //   --> $DIR/issue-54954.rs:3:24
-                        //    |
-                        // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
-                        //    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
-                        //    |                        |
-                        //    |                        cannot infer type
-                        //    |                        help: consider specifying the type argument
-                        //    |                        in the function call:
-                        //    |                        `Tt::const_val::<[i8; 123]>::<T>`
-                        // ...
-                        // LL |     const fn const_val<T: Sized>() -> usize {
-                        //    |              --------- - required by this bound in `Tt::const_val`
-                        //    |
-                        //    = note: cannot resolve `_: Tt`
-
-                        err.span_suggestion(
-                            span,
-                            &format!(
-                                "consider specifying the type argument{} in the function call",
-                                if generics.params.len() > 1 { "s" } else { "" },
-                            ),
-                            format!(
-                                "{}::<{}>",
-                                snippet,
-                                generics
-                                    .params
-                                    .iter()
-                                    .map(|p| p.name.to_string())
-                                    .collect::<Vec<String>>()
-                                    .join(", ")
-                            ),
-                            Applicability::HasPlaceholders,
-                        );
-                    }
-                }
-                err
-            }
-
-            ty::Predicate::WellFormed(ty) => {
-                // Same hacky approach as above to avoid deluging user
-                // with error messages.
-                if ty.references_error() || self.tcx.sess.has_errors() {
-                    return;
-                }
-                self.need_type_info_err(body_id, span, ty, ErrorCode::E0282)
-            }
-
-            ty::Predicate::Subtype(ref data) => {
-                if data.references_error() || self.tcx.sess.has_errors() {
-                    // no need to overload user in such cases
-                    return;
-                }
-                let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
-                // both must be type variables, or the other would've been instantiated
-                assert!(a.is_ty_var() && b.is_ty_var());
-                self.need_type_info_err(body_id, span, a, ErrorCode::E0282)
-            }
-            ty::Predicate::Projection(ref data) => {
-                let trait_ref = data.to_poly_trait_ref(self.tcx);
-                let self_ty = trait_ref.self_ty();
-                if predicate.references_error() {
-                    return;
-                }
-                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284);
-                err.note(&format!("cannot resolve `{}`", predicate));
-                err
-            }
-
-            _ => {
-                if self.tcx.sess.has_errors() {
-                    return;
-                }
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0284,
-                    "type annotations needed: cannot resolve `{}`",
-                    predicate,
-                );
-                err.span_label(span, &format!("cannot resolve `{}`", predicate));
-                err
-            }
-        };
-        self.note_obligation_cause(&mut err, obligation);
-        err.emit();
-    }
-
-    fn suggest_fully_qualified_path(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        def_id: DefId,
-        span: Span,
-        trait_ref: DefId,
-    ) {
-        if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) {
-            if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind {
-                err.note(&format!(
-                    "{}s cannot be accessed directly on a `trait`, they can only be \
-                        accessed through a specific `impl`",
-                    assoc_item.kind.suggestion_descr(),
-                ));
-                err.span_suggestion(
-                    span,
-                    "use the fully qualified path to an implementation",
-                    format!("<Type as {}>::{}", self.tcx.def_path_str(trait_ref), assoc_item.ident),
-                    Applicability::HasPlaceholders,
-                );
-            }
-        }
-    }
-
-    /// Returns `true` if the trait predicate may apply for *some* assignment
-    /// to the type parameters.
-    fn predicate_can_apply(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        pred: ty::PolyTraitRef<'tcx>,
-    ) -> bool {
-        struct ParamToVarFolder<'a, 'tcx> {
-            infcx: &'a InferCtxt<'a, 'tcx>,
-            var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
-        }
-
-        impl<'a, 'tcx> TypeFolder<'tcx> for ParamToVarFolder<'a, 'tcx> {
-            fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
-                self.infcx.tcx
-            }
-
-            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-                if let ty::Param(ty::ParamTy { name, .. }) = ty.kind {
-                    let infcx = self.infcx;
-                    self.var_map.entry(ty).or_insert_with(|| {
-                        infcx.next_ty_var(TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
-                            span: DUMMY_SP,
-                        })
-                    })
-                } else {
-                    ty.super_fold_with(self)
-                }
-            }
-        }
-
-        self.probe(|_| {
-            let mut selcx = SelectionContext::new(self);
-
-            let cleaned_pred =
-                pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() });
-
-            let cleaned_pred = super::project::normalize(
-                &mut selcx,
-                param_env,
-                ObligationCause::dummy(),
-                &cleaned_pred,
-            )
-            .value;
-
-            let obligation =
-                Obligation::new(ObligationCause::dummy(), param_env, cleaned_pred.to_predicate());
-
-            self.predicate_may_hold(&obligation)
-        })
-    }
-
-    fn note_obligation_cause(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        obligation: &PredicateObligation<'tcx>,
-    ) {
-        // First, attempt to add note to this error with an async-await-specific
-        // message, and fall back to regular note otherwise.
-        if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
-            self.note_obligation_cause_code(
-                err,
-                &obligation.predicate,
-                &obligation.cause.code,
-                &mut vec![],
-            );
-        }
-    }
-
-    /// Adds an async-await specific note to the diagnostic when the future does not implement
-    /// an auto trait because of a captured type.
-    ///
-    /// ```ignore (diagnostic)
-    /// note: future does not implement `Qux` as this value is used across an await
-    ///   --> $DIR/issue-64130-3-other.rs:17:5
-    ///    |
-    /// LL |     let x = Foo;
-    ///    |         - has type `Foo`
-    /// LL |     baz().await;
-    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
-    /// LL | }
-    ///    | - `x` is later dropped here
-    /// ```
-    ///
-    /// When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
-    /// is "replaced" with a different message and a more specific error.
-    ///
-    /// ```ignore (diagnostic)
-    /// error: future cannot be sent between threads safely
-    ///   --> $DIR/issue-64130-2-send.rs:21:5
-    ///    |
-    /// LL | fn is_send<T: Send>(t: T) { }
-    ///    |    -------    ---- required by this bound in `is_send`
-    /// ...
-    /// LL |     is_send(bar());
-    ///    |     ^^^^^^^ future returned by `bar` is not send
-    ///    |
-    ///    = help: within `impl std::future::Future`, the trait `std::marker::Send` is not
-    ///            implemented for `Foo`
-    /// note: future is not send as this value is used across an await
-    ///   --> $DIR/issue-64130-2-send.rs:15:5
-    ///    |
-    /// LL |     let x = Foo;
-    ///    |         - has type `Foo`
-    /// LL |     baz().await;
-    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
-    /// LL | }
-    ///    | - `x` is later dropped here
-    /// ```
-    ///
-    /// Returns `true` if an async-await specific note was added to the diagnostic.
-    fn maybe_note_obligation_cause_for_async_await(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> bool {
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: obligation.predicate={:?} \
-                obligation.cause.span={:?}",
-            obligation.predicate, obligation.cause.span
-        );
-        let source_map = self.tcx.sess.source_map();
-
-        // Attempt to detect an async-await error by looking at the obligation causes, looking
-        // for a generator to be present.
-        //
-        // When a future does not implement a trait because of a captured type in one of the
-        // generators somewhere in the call stack, then the result is a chain of obligations.
-        //
-        // Given a `async fn` A that calls a `async fn` B which captures a non-send type and that
-        // future is passed as an argument to a function C which requires a `Send` type, then the
-        // chain looks something like this:
-        //
-        // - `BuiltinDerivedObligation` with a generator witness (B)
-        // - `BuiltinDerivedObligation` with a generator (B)
-        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (B)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
-        // - `BuiltinDerivedObligation` with a generator witness (A)
-        // - `BuiltinDerivedObligation` with a generator (A)
-        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (A)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
-        // - `BindingObligation` with `impl_send (Send requirement)
-        //
-        // The first obligation in the chain is the most useful and has the generator that captured
-        // the type. The last generator has information about where the bound was introduced. At
-        // least one generator should be present for this diagnostic to be modified.
-        let (mut trait_ref, mut target_ty) = match obligation.predicate {
-            ty::Predicate::Trait(p) => {
-                (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty()))
-            }
-            _ => (None, None),
-        };
-        let mut generator = None;
-        let mut last_generator = None;
-        let mut next_code = Some(&obligation.cause.code);
-        while let Some(code) = next_code {
-            debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
-            match code {
-                ObligationCauseCode::BuiltinDerivedObligation(derived_obligation)
-                | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => {
-                    let ty = derived_obligation.parent_trait_ref.self_ty();
-                    debug!(
-                        "maybe_note_obligation_cause_for_async_await: \
-                            parent_trait_ref={:?} self_ty.kind={:?}",
-                        derived_obligation.parent_trait_ref, ty.kind
-                    );
-
-                    match ty.kind {
-                        ty::Generator(did, ..) => {
-                            generator = generator.or(Some(did));
-                            last_generator = Some(did);
-                        }
-                        ty::GeneratorWitness(..) => {}
-                        _ if generator.is_none() => {
-                            trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder());
-                            target_ty = Some(ty);
-                        }
-                        _ => {}
-                    }
-
-                    next_code = Some(derived_obligation.parent_code.as_ref());
-                }
-                _ => break,
-            }
-        }
-
-        // Only continue if a generator was found.
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \
-                target_ty={:?}",
-            generator, trait_ref, target_ty
-        );
-        let (generator_did, trait_ref, target_ty) = match (generator, trait_ref, target_ty) {
-            (Some(generator_did), Some(trait_ref), Some(target_ty)) => {
-                (generator_did, trait_ref, target_ty)
-            }
-            _ => return false,
-        };
-
-        let span = self.tcx.def_span(generator_did);
-
-        // Do not ICE on closure typeck (#66868).
-        if self.tcx.hir().as_local_hir_id(generator_did).is_none() {
-            return false;
-        }
-
-        // Get the tables from the infcx if the generator is the function we are
-        // currently type-checking; otherwise, get them by performing a query.
-        // This is needed to avoid cycles.
-        let in_progress_tables = self.in_progress_tables.map(|t| t.borrow());
-        let generator_did_root = self.tcx.closure_base_def_id(generator_did);
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: generator_did={:?} \
-             generator_did_root={:?} in_progress_tables.local_id_root={:?} span={:?}",
-            generator_did,
-            generator_did_root,
-            in_progress_tables.as_ref().map(|t| t.local_id_root),
-            span
-        );
-        let query_tables;
-        let tables: &TypeckTables<'tcx> = match &in_progress_tables {
-            Some(t) if t.local_id_root == Some(generator_did_root) => t,
-            _ => {
-                query_tables = self.tcx.typeck_tables_of(generator_did);
-                &query_tables
-            }
-        };
-
-        // Look for a type inside the generator interior that matches the target type to get
-        // a span.
-        let target_ty_erased = self.tcx.erase_regions(&target_ty);
-        let target_span = tables
-            .generator_interior_types
-            .iter()
-            .find(|ty::GeneratorInteriorTypeCause { ty, .. }| {
-                // Careful: the regions for types that appear in the
-                // generator interior are not generally known, so we
-                // want to erase them when comparing (and anyway,
-                // `Send` and other bounds are generally unaffected by
-                // the choice of region).  When erasing regions, we
-                // also have to erase late-bound regions. This is
-                // because the types that appear in the generator
-                // interior generally contain "bound regions" to
-                // represent regions that are part of the suspended
-                // generator frame. Bound regions are preserved by
-                // `erase_regions` and so we must also call
-                // `erase_late_bound_regions`.
-                let ty_erased = self.tcx.erase_late_bound_regions(&ty::Binder::bind(*ty));
-                let ty_erased = self.tcx.erase_regions(&ty_erased);
-                let eq = ty::TyS::same_type(ty_erased, target_ty_erased);
-                debug!(
-                    "maybe_note_obligation_cause_for_async_await: ty_erased={:?} \
-                        target_ty_erased={:?} eq={:?}",
-                    ty_erased, target_ty_erased, eq
-                );
-                eq
-            })
-            .map(|ty::GeneratorInteriorTypeCause { span, scope_span, expr, .. }| {
-                (span, source_map.span_to_snippet(*span), scope_span, expr)
-            });
-
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: target_ty={:?} \
-                generator_interior_types={:?} target_span={:?}",
-            target_ty, tables.generator_interior_types, target_span
-        );
-        if let Some((target_span, Ok(snippet), scope_span, expr)) = target_span {
-            self.note_obligation_cause_for_async_await(
-                err,
-                *target_span,
-                scope_span,
-                *expr,
-                snippet,
-                generator_did,
-                last_generator,
-                trait_ref,
-                target_ty,
-                tables,
-                obligation,
-                next_code,
-            );
-            true
-        } else {
-            false
-        }
-    }
-
-    /// Unconditionally adds the diagnostic note described in
-    /// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
-    fn note_obligation_cause_for_async_await(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        target_span: Span,
-        scope_span: &Option<Span>,
-        expr: Option<hir::HirId>,
-        snippet: String,
-        first_generator: DefId,
-        last_generator: Option<DefId>,
-        trait_ref: ty::TraitRef<'_>,
-        target_ty: Ty<'tcx>,
-        tables: &ty::TypeckTables<'_>,
-        obligation: &PredicateObligation<'tcx>,
-        next_code: Option<&ObligationCauseCode<'tcx>>,
-    ) {
-        let source_map = self.tcx.sess.source_map();
-
-        let is_async_fn = self
-            .tcx
-            .parent(first_generator)
-            .map(|parent_did| self.tcx.asyncness(parent_did))
-            .map(|parent_asyncness| parent_asyncness == hir::IsAsync::Async)
-            .unwrap_or(false);
-        let is_async_move = self
-            .tcx
-            .hir()
-            .as_local_hir_id(first_generator)
-            .and_then(|hir_id| self.tcx.hir().maybe_body_owned_by(hir_id))
-            .map(|body_id| self.tcx.hir().body(body_id))
-            .and_then(|body| body.generator_kind())
-            .map(|generator_kind| match generator_kind {
-                hir::GeneratorKind::Async(..) => true,
-                _ => false,
-            })
-            .unwrap_or(false);
-        let await_or_yield = if is_async_fn || is_async_move { "await" } else { "yield" };
-
-        // Special case the primary error message when send or sync is the trait that was
-        // not implemented.
-        let is_send = self.tcx.is_diagnostic_item(sym::send_trait, trait_ref.def_id);
-        let is_sync = self.tcx.is_diagnostic_item(sym::sync_trait, trait_ref.def_id);
-        let hir = self.tcx.hir();
-        let trait_explanation = if is_send || is_sync {
-            let (trait_name, trait_verb) =
-                if is_send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
-
-            err.clear_code();
-            err.set_primary_message(format!(
-                "future cannot be {} between threads safely",
-                trait_verb
-            ));
-
-            let original_span = err.span.primary_span().unwrap();
-            let mut span = MultiSpan::from_span(original_span);
-
-            let message = if let Some(name) = last_generator
-                .and_then(|generator_did| self.tcx.parent(generator_did))
-                .and_then(|parent_did| hir.as_local_hir_id(parent_did))
-                .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
-            {
-                format!("future returned by `{}` is not {}", name, trait_name)
-            } else {
-                format!("future is not {}", trait_name)
-            };
-
-            span.push_span_label(original_span, message);
-            err.set_span(span);
-
-            format!("is not {}", trait_name)
-        } else {
-            format!("does not implement `{}`", trait_ref.print_only_trait_path())
-        };
-
-        // Look at the last interior type to get a span for the `.await`.
-        let await_span = tables.generator_interior_types.iter().map(|t| t.span).last().unwrap();
-        let mut span = MultiSpan::from_span(await_span);
-        span.push_span_label(
-            await_span,
-            format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet),
-        );
-
-        span.push_span_label(target_span, format!("has type `{}`", target_ty));
-
-        // If available, use the scope span to annotate the drop location.
-        if let Some(scope_span) = scope_span {
-            span.push_span_label(
-                source_map.end_point(*scope_span),
-                format!("`{}` is later dropped here", snippet),
-            );
-        }
-
-        err.span_note(
-            span,
-            &format!(
-                "future {} as this value is used across an {}",
-                trait_explanation, await_or_yield,
-            ),
-        );
-
-        if let Some(expr_id) = expr {
-            let expr = hir.expect_expr(expr_id);
-            let is_ref = tables.expr_adjustments(expr).iter().any(|adj| adj.is_region_borrow());
-            let parent = hir.get_parent_node(expr_id);
-            if let Some(hir::Node::Expr(e)) = hir.find(parent) {
-                let method_span = hir.span(parent);
-                if tables.is_method_call(e) && is_ref {
-                    err.span_help(
-                        method_span,
-                        "consider moving this method call into a `let` \
-                        binding to create a shorter lived borrow",
-                    );
-                }
-            }
-        }
-
-        // Add a note for the item obligation that remains - normally a note pointing to the
-        // bound that introduced the obligation (e.g. `T: Send`).
-        debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code);
-        self.note_obligation_cause_code(
-            err,
-            &obligation.predicate,
-            next_code.unwrap(),
-            &mut Vec::new(),
-        );
-    }
-
-    fn note_obligation_cause_code<T>(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        predicate: &T,
-        cause_code: &ObligationCauseCode<'tcx>,
-        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
-    ) where
-        T: fmt::Display,
-    {
-        let tcx = self.tcx;
-        match *cause_code {
-            ObligationCauseCode::ExprAssignable
-            | ObligationCauseCode::MatchExpressionArm { .. }
-            | ObligationCauseCode::Pattern { .. }
-            | ObligationCauseCode::IfExpression { .. }
-            | ObligationCauseCode::IfExpressionWithNoElse
-            | ObligationCauseCode::MainFunctionType
-            | ObligationCauseCode::StartFunctionType
-            | ObligationCauseCode::IntrinsicType
-            | ObligationCauseCode::MethodReceiver
-            | ObligationCauseCode::ReturnNoExpression
-            | ObligationCauseCode::MiscObligation => {}
-            ObligationCauseCode::SliceOrArrayElem => {
-                err.note("slice and array elements must have `Sized` type");
-            }
-            ObligationCauseCode::TupleElem => {
-                err.note("only the last element of a tuple may have a dynamically sized type");
-            }
-            ObligationCauseCode::ProjectionWf(data) => {
-                err.note(&format!("required so that the projection `{}` is well-formed", data,));
-            }
-            ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
-                err.note(&format!(
-                    "required so that reference `{}` does not outlive its referent",
-                    ref_ty,
-                ));
-            }
-            ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
-                err.note(&format!(
-                    "required so that the lifetime bound of `{}` for `{}` is satisfied",
-                    region, object_ty,
-                ));
-            }
-            ObligationCauseCode::ItemObligation(item_def_id) => {
-                let item_name = tcx.def_path_str(item_def_id);
-                let msg = format!("required by `{}`", item_name);
-
-                if let Some(sp) = tcx.hir().span_if_local(item_def_id) {
-                    let sp = tcx.sess.source_map().def_span(sp);
-                    err.span_label(sp, &msg);
-                } else {
-                    err.note(&msg);
-                }
-            }
-            ObligationCauseCode::BindingObligation(item_def_id, span) => {
-                let item_name = tcx.def_path_str(item_def_id);
-                let msg = format!("required by this bound in `{}`", item_name);
-                if let Some(ident) = tcx.opt_item_name(item_def_id) {
-                    err.span_label(ident.span, "");
-                }
-                if span != DUMMY_SP {
-                    err.span_label(span, &msg);
-                } else {
-                    err.note(&msg);
-                }
-            }
-            ObligationCauseCode::ObjectCastObligation(object_ty) => {
-                err.note(&format!(
-                    "required for the cast to the object type `{}`",
-                    self.ty_to_string(object_ty)
-                ));
-            }
-            ObligationCauseCode::Coercion { source: _, target } => {
-                err.note(&format!("required by cast to type `{}`", self.ty_to_string(target)));
-            }
-            ObligationCauseCode::RepeatVec(suggest_const_in_array_repeat_expressions) => {
-                err.note(
-                    "the `Copy` trait is required because the \
-                          repeated element will be copied",
-                );
-                if suggest_const_in_array_repeat_expressions {
-                    err.note(
-                        "this array initializer can be evaluated at compile-time, for more \
-                              information, see issue \
-                              https://github.com/rust-lang/rust/issues/49147",
-                    );
-                    if tcx.sess.opts.unstable_features.is_nightly_build() {
-                        err.help(
-                            "add `#![feature(const_in_array_repeat_expressions)]` to the \
-                                  crate attributes to enable",
-                        );
-                    }
-                }
-            }
-            ObligationCauseCode::VariableType(_) => {
-                err.note("all local variables must have a statically known size");
-                if !self.tcx.features().unsized_locals {
-                    err.help("unsized locals are gated as an unstable feature");
-                }
-            }
-            ObligationCauseCode::SizedArgumentType => {
-                err.note("all function arguments must have a statically known size");
-                if !self.tcx.features().unsized_locals {
-                    err.help("unsized locals are gated as an unstable feature");
-                }
-            }
-            ObligationCauseCode::SizedReturnType => {
-                err.note(
-                    "the return type of a function must have a \
-                          statically known size",
-                );
-            }
-            ObligationCauseCode::SizedYieldType => {
-                err.note(
-                    "the yield type of a generator must have a \
-                          statically known size",
-                );
-            }
-            ObligationCauseCode::AssignmentLhsSized => {
-                err.note("the left-hand-side of an assignment must have a statically known size");
-            }
-            ObligationCauseCode::TupleInitializerSized => {
-                err.note("tuples must have a statically known size to be initialized");
-            }
-            ObligationCauseCode::StructInitializerSized => {
-                err.note("structs must have a statically known size to be initialized");
-            }
-            ObligationCauseCode::FieldSized { adt_kind: ref item, last } => match *item {
-                AdtKind::Struct => {
-                    if last {
-                        err.note(
-                            "the last field of a packed struct may only have a \
-                                      dynamically sized type if it does not need drop to be run",
-                        );
-                    } else {
-                        err.note(
-                            "only the last field of a struct may have a dynamically \
-                                      sized type",
-                        );
-                    }
-                }
-                AdtKind::Union => {
-                    err.note("no field of a union may have a dynamically sized type");
-                }
-                AdtKind::Enum => {
-                    err.note("no field of an enum variant may have a dynamically sized type");
-                }
-            },
-            ObligationCauseCode::ConstSized => {
-                err.note("constant expressions must have a statically known size");
-            }
-            ObligationCauseCode::ConstPatternStructural => {
-                err.note("constants used for pattern-matching must derive `PartialEq` and `Eq`");
-            }
-            ObligationCauseCode::SharedStatic => {
-                err.note("shared static variables must have a type that implements `Sync`");
-            }
-            ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
-                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-                let ty = parent_trait_ref.skip_binder().self_ty();
-                err.note(&format!("required because it appears within the type `{}`", ty));
-                obligated_types.push(ty);
-
-                let parent_predicate = parent_trait_ref.to_predicate();
-                if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
-                    self.note_obligation_cause_code(
-                        err,
-                        &parent_predicate,
-                        &data.parent_code,
-                        obligated_types,
-                    );
-                }
-            }
-            ObligationCauseCode::ImplDerivedObligation(ref data) => {
-                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-                err.note(&format!(
-                    "required because of the requirements on the impl of `{}` for `{}`",
-                    parent_trait_ref.print_only_trait_path(),
-                    parent_trait_ref.skip_binder().self_ty()
-                ));
-                let parent_predicate = parent_trait_ref.to_predicate();
-                self.note_obligation_cause_code(
-                    err,
-                    &parent_predicate,
-                    &data.parent_code,
-                    obligated_types,
-                );
-            }
-            ObligationCauseCode::CompareImplMethodObligation { .. } => {
-                err.note(&format!(
-                    "the requirement `{}` appears on the impl method \
-                              but not on the corresponding trait method",
-                    predicate
-                ));
-            }
-            ObligationCauseCode::CompareImplTypeObligation { .. } => {
-                err.note(&format!(
-                    "the requirement `{}` appears on the associated impl type\
-                     but not on the corresponding associated trait type",
-                    predicate
-                ));
-            }
-            ObligationCauseCode::ReturnType
-            | ObligationCauseCode::ReturnValue(_)
-            | ObligationCauseCode::BlockTailExpression(_) => (),
-            ObligationCauseCode::TrivialBound => {
-                err.help("see issue #48214");
-                if tcx.sess.opts.unstable_features.is_nightly_build() {
-                    err.help(
-                        "add `#![feature(trivial_bounds)]` to the \
-                              crate attributes to enable",
-                    );
-                }
-            }
-            ObligationCauseCode::AssocTypeBound(ref data) => {
-                err.span_label(data.original, "associated type defined here");
-                if let Some(sp) = data.impl_span {
-                    err.span_label(sp, "in this `impl` item");
-                }
-                for sp in &data.bounds {
-                    err.span_label(*sp, "restricted in this bound");
-                }
-            }
-        }
-    }
-
-    fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
-        let current_limit = self.tcx.sess.recursion_limit.get();
-        let suggested_limit = current_limit * 2;
-        err.help(&format!(
-            "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
-            suggested_limit
-        ));
-    }
-
-    fn is_recursive_obligation(
-        &self,
-        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
-        cause_code: &ObligationCauseCode<'tcx>,
-    ) -> bool {
-        if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
-            let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-
-            if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) {
-                return true;
-            }
-        }
-        false
-    }
-}
-
-/// Summarizes information
-#[derive(Clone)]
-pub enum ArgKind {
-    /// An argument of non-tuple type. Parameters are (name, ty)
-    Arg(String, String),
-
-    /// An argument of tuple type. For a "found" argument, the span is
-    /// the locationo in the source of the pattern. For a "expected"
-    /// argument, it will be None. The vector is a list of (name, ty)
-    /// strings for the components of the tuple.
-    Tuple(Option<Span>, Vec<(String, String)>),
-}
-
-impl ArgKind {
-    fn empty() -> ArgKind {
-        ArgKind::Arg("_".to_owned(), "_".to_owned())
-    }
-
-    /// Creates an `ArgKind` from the expected type of an
-    /// argument. It has no name (`_`) and an optional source span.
-    pub fn from_expected_ty(t: Ty<'_>, span: Option<Span>) -> ArgKind {
-        match t.kind {
-            ty::Tuple(ref tys) => ArgKind::Tuple(
-                span,
-                tys.iter().map(|ty| ("_".to_owned(), ty.to_string())).collect::<Vec<_>>(),
-            ),
-            _ => ArgKind::Arg("_".to_owned(), t.to_string()),
-        }
-    }
-}
-
-/// Suggest restricting a type param with a new bound.
-pub fn suggest_constraining_type_param(
-    generics: &hir::Generics<'_>,
-    err: &mut DiagnosticBuilder<'_>,
-    param_name: &str,
-    constraint: &str,
-    source_map: &SourceMap,
-    span: Span,
-) -> bool {
-    let restrict_msg = "consider further restricting this bound";
-    if let Some(param) =
-        generics.params.iter().filter(|p| p.name.ident().as_str() == param_name).next()
-    {
-        if param_name.starts_with("impl ") {
-            // `impl Trait` in argument:
-            // `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
-            err.span_suggestion(
-                param.span,
-                restrict_msg,
-                // `impl CurrentTrait + MissingTrait`
-                format!("{} + {}", param_name, constraint),
-                Applicability::MachineApplicable,
-            );
-        } else if generics.where_clause.predicates.is_empty() && param.bounds.is_empty() {
-            // If there are no bounds whatsoever, suggest adding a constraint
-            // to the type parameter:
-            // `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
-            err.span_suggestion(
-                param.span,
-                "consider restricting this bound",
-                format!("{}: {}", param_name, constraint),
-                Applicability::MachineApplicable,
-            );
-        } else if !generics.where_clause.predicates.is_empty() {
-            // There is a `where` clause, so suggest expanding it:
-            // `fn foo<T>(t: T) where T: Debug {}` →
-            // `fn foo<T>(t: T) where T: Debug, T: Trait {}`
-            err.span_suggestion(
-                generics.where_clause.span().unwrap().shrink_to_hi(),
-                &format!("consider further restricting type parameter `{}`", param_name),
-                format!(", {}: {}", param_name, constraint),
-                Applicability::MachineApplicable,
-            );
-        } else {
-            // If there is no `where` clause lean towards constraining to the
-            // type parameter:
-            // `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
-            // `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
-            let sp = param.span.with_hi(span.hi());
-            let span = source_map.span_through_char(sp, ':');
-            if sp != param.span && sp != span {
-                // Only suggest if we have high certainty that the span
-                // covers the colon in `foo<T: Trait>`.
-                err.span_suggestion(
-                    span,
-                    restrict_msg,
-                    format!("{}: {} + ", param_name, constraint),
-                    Applicability::MachineApplicable,
-                );
-            } else {
-                err.span_label(
-                    param.span,
-                    &format!("consider adding a `where {}: {}` bound", param_name, constraint),
-                );
-            }
-        }
-        return true;
-    }
-    false
-}
diff --git a/src/librustc/traits/error_reporting/mod.rs b/src/librustc/traits/error_reporting/mod.rs
new file mode 100644
index 00000000000..db3173989ac
--- /dev/null
+++ b/src/librustc/traits/error_reporting/mod.rs
@@ -0,0 +1,1412 @@
+pub mod on_unimplemented;
+pub mod suggestions;
+
+use super::{
+    ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode,
+    MismatchedProjectionTypes, ObjectSafetyViolation, Obligation, ObligationCause,
+    ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote,
+    OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionContext, SelectionError,
+    TraitNotObjectSafe,
+};
+
+use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
+use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::infer::{self, InferCtxt};
+use crate::mir::interpret::ErrorHandled;
+use crate::session::DiagnosticMessageId;
+use crate::traits::object_safety_violations;
+use crate::ty::error::ExpectedFound;
+use crate::ty::fast_reject;
+use crate::ty::fold::TypeFolder;
+use crate::ty::SubtypePredicate;
+use crate::ty::{self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
+
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_span::source_map::SourceMap;
+use rustc_span::{ExpnKind, Span, DUMMY_SP};
+use std::fmt;
+use syntax::ast;
+
+use rustc_error_codes::*;
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+    pub fn report_fulfillment_errors(
+        &self,
+        errors: &[FulfillmentError<'tcx>],
+        body_id: Option<hir::BodyId>,
+        fallback_has_occurred: bool,
+    ) {
+        #[derive(Debug)]
+        struct ErrorDescriptor<'tcx> {
+            predicate: ty::Predicate<'tcx>,
+            index: Option<usize>, // None if this is an old error
+        }
+
+        let mut error_map: FxHashMap<_, Vec<_>> = self
+            .reported_trait_errors
+            .borrow()
+            .iter()
+            .map(|(&span, predicates)| {
+                (
+                    span,
+                    predicates
+                        .iter()
+                        .map(|predicate| ErrorDescriptor {
+                            predicate: predicate.clone(),
+                            index: None,
+                        })
+                        .collect(),
+                )
+            })
+            .collect();
+
+        for (index, error) in errors.iter().enumerate() {
+            // We want to ignore desugarings here: spans are equivalent even
+            // if one is the result of a desugaring and the other is not.
+            let mut span = error.obligation.cause.span;
+            let expn_data = span.ctxt().outer_expn_data();
+            if let ExpnKind::Desugaring(_) = expn_data.kind {
+                span = expn_data.call_site;
+            }
+
+            error_map.entry(span).or_default().push(ErrorDescriptor {
+                predicate: error.obligation.predicate.clone(),
+                index: Some(index),
+            });
+
+            self.reported_trait_errors
+                .borrow_mut()
+                .entry(span)
+                .or_default()
+                .push(error.obligation.predicate.clone());
+        }
+
+        // We do this in 2 passes because we want to display errors in order, though
+        // maybe it *is* better to sort errors by span or something.
+        let mut is_suppressed = vec![false; errors.len()];
+        for (_, error_set) in error_map.iter() {
+            // We want to suppress "duplicate" errors with the same span.
+            for error in error_set {
+                if let Some(index) = error.index {
+                    // Suppress errors that are either:
+                    // 1) strictly implied by another error.
+                    // 2) implied by an error with a smaller index.
+                    for error2 in error_set {
+                        if error2.index.map_or(false, |index2| is_suppressed[index2]) {
+                            // Avoid errors being suppressed by already-suppressed
+                            // errors, to prevent all errors from being suppressed
+                            // at once.
+                            continue;
+                        }
+
+                        if self.error_implies(&error2.predicate, &error.predicate)
+                            && !(error2.index >= error.index
+                                && self.error_implies(&error.predicate, &error2.predicate))
+                        {
+                            info!("skipping {:?} (implied by {:?})", error, error2);
+                            is_suppressed[index] = true;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        for (error, suppressed) in errors.iter().zip(is_suppressed) {
+            if !suppressed {
+                self.report_fulfillment_error(error, body_id, fallback_has_occurred);
+            }
+        }
+    }
+
+    // returns if `cond` not occurring implies that `error` does not occur - i.e., that
+    // `error` occurring implies that `cond` occurs.
+    fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool {
+        if cond == error {
+            return true;
+        }
+
+        let (cond, error) = match (cond, error) {
+            (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error)) => (cond, error),
+            _ => {
+                // FIXME: make this work in other cases too.
+                return false;
+            }
+        };
+
+        for implication in super::elaborate_predicates(self.tcx, vec![cond.clone()]) {
+            if let ty::Predicate::Trait(implication) = implication {
+                let error = error.to_poly_trait_ref();
+                let implication = implication.to_poly_trait_ref();
+                // FIXME: I'm just not taking associated types at all here.
+                // Eventually I'll need to implement param-env-aware
+                // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
+                let param_env = ty::ParamEnv::empty();
+                if self.can_sub(param_env, error, implication).is_ok() {
+                    debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
+                    return true;
+                }
+            }
+        }
+
+        false
+    }
+
+    fn report_fulfillment_error(
+        &self,
+        error: &FulfillmentError<'tcx>,
+        body_id: Option<hir::BodyId>,
+        fallback_has_occurred: bool,
+    ) {
+        debug!("report_fulfillment_error({:?})", error);
+        match error.code {
+            FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
+                self.report_selection_error(
+                    &error.obligation,
+                    selection_error,
+                    fallback_has_occurred,
+                    error.points_at_arg_span,
+                );
+            }
+            FulfillmentErrorCode::CodeProjectionError(ref e) => {
+                self.report_projection_error(&error.obligation, e);
+            }
+            FulfillmentErrorCode::CodeAmbiguity => {
+                self.maybe_report_ambiguity(&error.obligation, body_id);
+            }
+            FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
+                self.report_mismatched_types(
+                    &error.obligation.cause,
+                    expected_found.expected,
+                    expected_found.found,
+                    err.clone(),
+                )
+                .emit();
+            }
+        }
+    }
+
+    fn report_projection_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        error: &MismatchedProjectionTypes<'tcx>,
+    ) {
+        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+
+        if predicate.references_error() {
+            return;
+        }
+
+        self.probe(|_| {
+            let err_buf;
+            let mut err = &error.err;
+            let mut values = None;
+
+            // try to find the mismatched types to report the error with.
+            //
+            // this can fail if the problem was higher-ranked, in which
+            // cause I have no idea for a good error message.
+            if let ty::Predicate::Projection(ref data) = predicate {
+                let mut selcx = SelectionContext::new(self);
+                let (data, _) = self.replace_bound_vars_with_fresh_vars(
+                    obligation.cause.span,
+                    infer::LateBoundRegionConversionTime::HigherRankedType,
+                    data,
+                );
+                let mut obligations = vec![];
+                let normalized_ty = super::normalize_projection_type(
+                    &mut selcx,
+                    obligation.param_env,
+                    data.projection_ty,
+                    obligation.cause.clone(),
+                    0,
+                    &mut obligations,
+                );
+
+                debug!(
+                    "report_projection_error obligation.cause={:?} obligation.param_env={:?}",
+                    obligation.cause, obligation.param_env
+                );
+
+                debug!(
+                    "report_projection_error normalized_ty={:?} data.ty={:?}",
+                    normalized_ty, data.ty
+                );
+
+                let is_normalized_ty_expected = match &obligation.cause.code {
+                    ObligationCauseCode::ItemObligation(_)
+                    | ObligationCauseCode::BindingObligation(_, _)
+                    | ObligationCauseCode::ObjectCastObligation(_) => false,
+                    _ => true,
+                };
+
+                if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(
+                    is_normalized_ty_expected,
+                    normalized_ty,
+                    data.ty,
+                ) {
+                    values = Some(infer::ValuePairs::Types(ExpectedFound::new(
+                        is_normalized_ty_expected,
+                        normalized_ty,
+                        data.ty,
+                    )));
+
+                    err_buf = error;
+                    err = &err_buf;
+                }
+            }
+
+            let msg = format!("type mismatch resolving `{}`", predicate);
+            let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg);
+            let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
+            if fresh {
+                let mut diag = struct_span_err!(
+                    self.tcx.sess,
+                    obligation.cause.span,
+                    E0271,
+                    "type mismatch resolving `{}`",
+                    predicate
+                );
+                self.note_type_err(&mut diag, &obligation.cause, None, values, err);
+                self.note_obligation_cause(&mut diag, obligation);
+                diag.emit();
+            }
+        });
+    }
+
+    fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
+        /// returns the fuzzy category of a given type, or None
+        /// if the type can be equated to any type.
+        fn type_category(t: Ty<'_>) -> Option<u32> {
+            match t.kind {
+                ty::Bool => Some(0),
+                ty::Char => Some(1),
+                ty::Str => Some(2),
+                ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3),
+                ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4),
+                ty::Ref(..) | ty::RawPtr(..) => Some(5),
+                ty::Array(..) | ty::Slice(..) => Some(6),
+                ty::FnDef(..) | ty::FnPtr(..) => Some(7),
+                ty::Dynamic(..) => Some(8),
+                ty::Closure(..) => Some(9),
+                ty::Tuple(..) => Some(10),
+                ty::Projection(..) => Some(11),
+                ty::Param(..) => Some(12),
+                ty::Opaque(..) => Some(13),
+                ty::Never => Some(14),
+                ty::Adt(adt, ..) => match adt.adt_kind() {
+                    AdtKind::Struct => Some(15),
+                    AdtKind::Union => Some(16),
+                    AdtKind::Enum => Some(17),
+                },
+                ty::Generator(..) => Some(18),
+                ty::Foreign(..) => Some(19),
+                ty::GeneratorWitness(..) => Some(20),
+                ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None,
+                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+            }
+        }
+
+        match (type_category(a), type_category(b)) {
+            (Some(cat_a), Some(cat_b)) => match (&a.kind, &b.kind) {
+                (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b,
+                _ => cat_a == cat_b,
+            },
+            // infer and error can be equated to all types
+            _ => true,
+        }
+    }
+
+    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
+        self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind {
+            hir::GeneratorKind::Gen => "a generator",
+            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block",
+            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function",
+            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure",
+        })
+    }
+
+    fn find_similar_impl_candidates(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Vec<ty::TraitRef<'tcx>> {
+        let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true);
+        let all_impls = self.tcx.all_impls(trait_ref.def_id());
+
+        match simp {
+            Some(simp) => all_impls
+                .iter()
+                .filter_map(|&def_id| {
+                    let imp = self.tcx.impl_trait_ref(def_id).unwrap();
+                    let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true);
+                    if let Some(imp_simp) = imp_simp {
+                        if simp != imp_simp {
+                            return None;
+                        }
+                    }
+
+                    Some(imp)
+                })
+                .collect(),
+            None => {
+                all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect()
+            }
+        }
+    }
+
+    fn report_similar_impl_candidates(
+        &self,
+        impl_candidates: Vec<ty::TraitRef<'tcx>>,
+        err: &mut DiagnosticBuilder<'_>,
+    ) {
+        if impl_candidates.is_empty() {
+            return;
+        }
+
+        let len = impl_candidates.len();
+        let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { 4 };
+
+        let normalize = |candidate| {
+            self.tcx.infer_ctxt().enter(|ref infcx| {
+                let normalized = infcx
+                    .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
+                    .normalize(candidate)
+                    .ok();
+                match normalized {
+                    Some(normalized) => format!("\n  {:?}", normalized.value),
+                    None => format!("\n  {:?}", candidate),
+                }
+            })
+        };
+
+        // Sort impl candidates so that ordering is consistent for UI tests.
+        let mut normalized_impl_candidates =
+            impl_candidates.iter().map(normalize).collect::<Vec<String>>();
+
+        // Sort before taking the `..end` range,
+        // because the ordering of `impl_candidates` may not be deterministic:
+        // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
+        normalized_impl_candidates.sort();
+
+        err.help(&format!(
+            "the following implementations were found:{}{}",
+            normalized_impl_candidates[..end].join(""),
+            if len > 5 { format!("\nand {} others", len - 4) } else { String::new() }
+        ));
+    }
+
+    /// Reports that an overflow has occurred and halts compilation. We
+    /// halt compilation unconditionally because it is important that
+    /// overflows never be masked -- they basically represent computations
+    /// whose result could not be truly determined and thus we can't say
+    /// if the program type checks or not -- and they are unusual
+    /// occurrences in any case.
+    pub fn report_overflow_error<T>(
+        &self,
+        obligation: &Obligation<'tcx, T>,
+        suggest_increasing_limit: bool,
+    ) -> !
+    where
+        T: fmt::Display + TypeFoldable<'tcx>,
+    {
+        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            obligation.cause.span,
+            E0275,
+            "overflow evaluating the requirement `{}`",
+            predicate
+        );
+
+        if suggest_increasing_limit {
+            self.suggest_new_overflow_limit(&mut err);
+        }
+
+        self.note_obligation_cause_code(
+            &mut err,
+            &obligation.predicate,
+            &obligation.cause.code,
+            &mut vec![],
+        );
+
+        err.emit();
+        self.tcx.sess.abort_if_errors();
+        bug!();
+    }
+
+    /// Reports that a cycle was detected which led to overflow and halts
+    /// compilation. This is equivalent to `report_overflow_error` except
+    /// that we can give a more helpful error message (and, in particular,
+    /// we do not suggest increasing the overflow limit, which is not
+    /// going to help).
+    pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
+        let cycle = self.resolve_vars_if_possible(&cycle.to_owned());
+        assert!(cycle.len() > 0);
+
+        debug!("report_overflow_error_cycle: cycle={:?}", cycle);
+
+        self.report_overflow_error(&cycle[0], false);
+    }
+
+    pub fn report_extra_impl_obligation(
+        &self,
+        error_span: Span,
+        item_name: ast::Name,
+        _impl_item_def_id: DefId,
+        trait_item_def_id: DefId,
+        requirement: &dyn fmt::Display,
+    ) -> DiagnosticBuilder<'tcx> {
+        let msg = "impl has stricter requirements than trait";
+        let sp = self.tcx.sess.source_map().def_span(error_span);
+
+        let mut err = struct_span_err!(self.tcx.sess, sp, E0276, "{}", msg);
+
+        if let Some(trait_item_span) = self.tcx.hir().span_if_local(trait_item_def_id) {
+            let span = self.tcx.sess.source_map().def_span(trait_item_span);
+            err.span_label(span, format!("definition of `{}` from trait", item_name));
+        }
+
+        err.span_label(sp, format!("impl has extra requirement {}", requirement));
+
+        err
+    }
+
+    /// Gets the parent trait chain start
+    fn get_parent_trait_ref(
+        &self,
+        code: &ObligationCauseCode<'tcx>,
+    ) -> Option<(String, Option<Span>)> {
+        match code {
+            &ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
+                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
+                match self.get_parent_trait_ref(&data.parent_code) {
+                    Some(t) => Some(t),
+                    None => {
+                        let ty = parent_trait_ref.skip_binder().self_ty();
+                        let span =
+                            TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id));
+                        Some((ty.to_string(), span))
+                    }
+                }
+            }
+            _ => None,
+        }
+    }
+
+    pub fn report_selection_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        error: &SelectionError<'tcx>,
+        fallback_has_occurred: bool,
+        points_at_arg: bool,
+    ) {
+        let tcx = self.tcx;
+        let span = obligation.cause.span;
+
+        let mut err = match *error {
+            SelectionError::Unimplemented => {
+                if let ObligationCauseCode::CompareImplMethodObligation {
+                    item_name,
+                    impl_item_def_id,
+                    trait_item_def_id,
+                }
+                | ObligationCauseCode::CompareImplTypeObligation {
+                    item_name,
+                    impl_item_def_id,
+                    trait_item_def_id,
+                } = obligation.cause.code
+                {
+                    self.report_extra_impl_obligation(
+                        span,
+                        item_name,
+                        impl_item_def_id,
+                        trait_item_def_id,
+                        &format!("`{}`", obligation.predicate),
+                    )
+                    .emit();
+                    return;
+                }
+                match obligation.predicate {
+                    ty::Predicate::Trait(ref trait_predicate) => {
+                        let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
+
+                        if self.tcx.sess.has_errors() && trait_predicate.references_error() {
+                            return;
+                        }
+                        let trait_ref = trait_predicate.to_poly_trait_ref();
+                        let (post_message, pre_message, type_def) = self
+                            .get_parent_trait_ref(&obligation.cause.code)
+                            .map(|(t, s)| {
+                                (
+                                    format!(" in `{}`", t),
+                                    format!("within `{}`, ", t),
+                                    s.map(|s| (format!("within this `{}`", t), s)),
+                                )
+                            })
+                            .unwrap_or_default();
+
+                        let OnUnimplementedNote { message, label, note, enclosing_scope } =
+                            self.on_unimplemented_note(trait_ref, obligation);
+                        let have_alt_message = message.is_some() || label.is_some();
+                        let is_try = self
+                            .tcx
+                            .sess
+                            .source_map()
+                            .span_to_snippet(span)
+                            .map(|s| &s == "?")
+                            .unwrap_or(false);
+                        let is_from = format!("{}", trait_ref.print_only_trait_path())
+                            .starts_with("std::convert::From<");
+                        let (message, note) = if is_try && is_from {
+                            (
+                                Some(format!(
+                                    "`?` couldn't convert the error to `{}`",
+                                    trait_ref.self_ty(),
+                                )),
+                                Some(
+                                    "the question mark operation (`?`) implicitly performs a \
+                                     conversion on the error value using the `From` trait"
+                                        .to_owned(),
+                                ),
+                            )
+                        } else {
+                            (message, note)
+                        };
+
+                        let mut err = struct_span_err!(
+                            self.tcx.sess,
+                            span,
+                            E0277,
+                            "{}",
+                            message.unwrap_or_else(|| format!(
+                                "the trait bound `{}` is not satisfied{}",
+                                trait_ref.to_predicate(),
+                                post_message,
+                            ))
+                        );
+
+                        let explanation =
+                            if obligation.cause.code == ObligationCauseCode::MainFunctionType {
+                                "consider using `()`, or a `Result`".to_owned()
+                            } else {
+                                format!(
+                                    "{}the trait `{}` is not implemented for `{}`",
+                                    pre_message,
+                                    trait_ref.print_only_trait_path(),
+                                    trait_ref.self_ty(),
+                                )
+                            };
+
+                        if self.suggest_add_reference_to_arg(
+                            &obligation,
+                            &mut err,
+                            &trait_ref,
+                            points_at_arg,
+                            have_alt_message,
+                        ) {
+                            self.note_obligation_cause(&mut err, obligation);
+                            err.emit();
+                            return;
+                        }
+                        if let Some(ref s) = label {
+                            // If it has a custom `#[rustc_on_unimplemented]`
+                            // error message, let's display it as the label!
+                            err.span_label(span, s.as_str());
+                            err.help(&explanation);
+                        } else {
+                            err.span_label(span, explanation);
+                        }
+                        if let Some((msg, span)) = type_def {
+                            err.span_label(span, &msg);
+                        }
+                        if let Some(ref s) = note {
+                            // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
+                            err.note(s.as_str());
+                        }
+                        if let Some(ref s) = enclosing_scope {
+                            let enclosing_scope_span = tcx.def_span(
+                                tcx.hir()
+                                    .opt_local_def_id(obligation.cause.body_id)
+                                    .unwrap_or_else(|| {
+                                        tcx.hir().body_owner_def_id(hir::BodyId {
+                                            hir_id: obligation.cause.body_id,
+                                        })
+                                    }),
+                            );
+
+                            err.span_label(enclosing_scope_span, s.as_str());
+                        }
+
+                        self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
+                        self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg);
+                        self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
+                        self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
+                        self.note_version_mismatch(&mut err, &trait_ref);
+                        if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) {
+                            err.emit();
+                            return;
+                        }
+
+                        // Try to report a help message
+                        if !trait_ref.has_infer_types()
+                            && self.predicate_can_apply(obligation.param_env, trait_ref)
+                        {
+                            // If a where-clause may be useful, remind the
+                            // user that they can add it.
+                            //
+                            // don't display an on-unimplemented note, as
+                            // these notes will often be of the form
+                            //     "the type `T` can't be frobnicated"
+                            // which is somewhat confusing.
+                            self.suggest_restricting_param_bound(
+                                &mut err,
+                                &trait_ref,
+                                obligation.cause.body_id,
+                            );
+                        } else {
+                            if !have_alt_message {
+                                // Can't show anything else useful, try to find similar impls.
+                                let impl_candidates = self.find_similar_impl_candidates(trait_ref);
+                                self.report_similar_impl_candidates(impl_candidates, &mut err);
+                            }
+                            self.suggest_change_mut(
+                                &obligation,
+                                &mut err,
+                                &trait_ref,
+                                points_at_arg,
+                            );
+                        }
+
+                        // If this error is due to `!: Trait` not implemented but `(): Trait` is
+                        // implemented, and fallback has occurred, then it could be due to a
+                        // variable that used to fallback to `()` now falling back to `!`. Issue a
+                        // note informing about the change in behaviour.
+                        if trait_predicate.skip_binder().self_ty().is_never()
+                            && fallback_has_occurred
+                        {
+                            let predicate = trait_predicate.map_bound(|mut trait_pred| {
+                                trait_pred.trait_ref.substs = self.tcx.mk_substs_trait(
+                                    self.tcx.mk_unit(),
+                                    &trait_pred.trait_ref.substs[1..],
+                                );
+                                trait_pred
+                            });
+                            let unit_obligation = Obligation {
+                                predicate: ty::Predicate::Trait(predicate),
+                                ..obligation.clone()
+                            };
+                            if self.predicate_may_hold(&unit_obligation) {
+                                err.note(
+                                    "the trait is implemented for `()`. \
+                                         Possibly this error has been caused by changes to \
+                                         Rust's type-inference algorithm \
+                                         (see: https://github.com/rust-lang/rust/issues/48950 \
+                                         for more info). Consider whether you meant to use the \
+                                         type `()` here instead.",
+                                );
+                            }
+                        }
+
+                        err
+                    }
+
+                    ty::Predicate::Subtype(ref predicate) => {
+                        // Errors for Subtype predicates show up as
+                        // `FulfillmentErrorCode::CodeSubtypeError`,
+                        // not selection error.
+                        span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
+                    }
+
+                    ty::Predicate::RegionOutlives(ref predicate) => {
+                        let predicate = self.resolve_vars_if_possible(predicate);
+                        let err = self
+                            .region_outlives_predicate(&obligation.cause, &predicate)
+                            .err()
+                            .unwrap();
+                        struct_span_err!(
+                            self.tcx.sess,
+                            span,
+                            E0279,
+                            "the requirement `{}` is not satisfied (`{}`)",
+                            predicate,
+                            err,
+                        )
+                    }
+
+                    ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
+                        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+                        struct_span_err!(
+                            self.tcx.sess,
+                            span,
+                            E0280,
+                            "the requirement `{}` is not satisfied",
+                            predicate
+                        )
+                    }
+
+                    ty::Predicate::ObjectSafe(trait_def_id) => {
+                        let violations = object_safety_violations(self.tcx, trait_def_id);
+                        report_object_safety_error(self.tcx, span, trait_def_id, violations)
+                    }
+
+                    ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
+                        let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap();
+                        let closure_span = self
+                            .tcx
+                            .sess
+                            .source_map()
+                            .def_span(self.tcx.hir().span_if_local(closure_def_id).unwrap());
+                        let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id).unwrap();
+                        let mut err = struct_span_err!(
+                            self.tcx.sess,
+                            closure_span,
+                            E0525,
+                            "expected a closure that implements the `{}` trait, \
+                             but this closure only implements `{}`",
+                            kind,
+                            found_kind
+                        );
+
+                        err.span_label(
+                            closure_span,
+                            format!("this closure implements `{}`, not `{}`", found_kind, kind),
+                        );
+                        err.span_label(
+                            obligation.cause.span,
+                            format!("the requirement to implement `{}` derives from here", kind),
+                        );
+
+                        // Additional context information explaining why the closure only implements
+                        // a particular trait.
+                        if let Some(tables) = self.in_progress_tables {
+                            let tables = tables.borrow();
+                            match (found_kind, tables.closure_kind_origins().get(hir_id)) {
+                                (ty::ClosureKind::FnOnce, Some((span, name))) => {
+                                    err.span_label(
+                                        *span,
+                                        format!(
+                                            "closure is `FnOnce` because it moves the \
+                                         variable `{}` out of its environment",
+                                            name
+                                        ),
+                                    );
+                                }
+                                (ty::ClosureKind::FnMut, Some((span, name))) => {
+                                    err.span_label(
+                                        *span,
+                                        format!(
+                                            "closure is `FnMut` because it mutates the \
+                                         variable `{}` here",
+                                            name
+                                        ),
+                                    );
+                                }
+                                _ => {}
+                            }
+                        }
+
+                        err.emit();
+                        return;
+                    }
+
+                    ty::Predicate::WellFormed(ty) => {
+                        if !self.tcx.sess.opts.debugging_opts.chalk {
+                            // WF predicates cannot themselves make
+                            // errors. They can only block due to
+                            // ambiguity; otherwise, they always
+                            // degenerate into other obligations
+                            // (which may fail).
+                            span_bug!(span, "WF predicate not satisfied for {:?}", ty);
+                        } else {
+                            // FIXME: we'll need a better message which takes into account
+                            // which bounds actually failed to hold.
+                            self.tcx.sess.struct_span_err(
+                                span,
+                                &format!("the type `{}` is not well-formed (chalk)", ty),
+                            )
+                        }
+                    }
+
+                    ty::Predicate::ConstEvaluatable(..) => {
+                        // Errors for `ConstEvaluatable` predicates show up as
+                        // `SelectionError::ConstEvalFailure`,
+                        // not `Unimplemented`.
+                        span_bug!(
+                            span,
+                            "const-evaluatable requirement gave wrong error: `{:?}`",
+                            obligation
+                        )
+                    }
+                }
+            }
+
+            OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => {
+                let found_trait_ref = self.resolve_vars_if_possible(&*found_trait_ref);
+                let expected_trait_ref = self.resolve_vars_if_possible(&*expected_trait_ref);
+
+                if expected_trait_ref.self_ty().references_error() {
+                    return;
+                }
+
+                let found_trait_ty = found_trait_ref.self_ty();
+
+                let found_did = match found_trait_ty.kind {
+                    ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did),
+                    ty::Adt(def, _) => Some(def.did),
+                    _ => None,
+                };
+
+                let found_span = found_did
+                    .and_then(|did| self.tcx.hir().span_if_local(did))
+                    .map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def
+
+                if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
+                    // We check closures twice, with obligations flowing in different directions,
+                    // but we want to complain about them only once.
+                    return;
+                }
+
+                self.reported_closure_mismatch.borrow_mut().insert((span, found_span));
+
+                let found = match found_trait_ref.skip_binder().substs.type_at(1).kind {
+                    ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()],
+                    _ => vec![ArgKind::empty()],
+                };
+
+                let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1);
+                let expected = match expected_ty.kind {
+                    ty::Tuple(ref tys) => tys
+                        .iter()
+                        .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span)))
+                        .collect(),
+                    _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())],
+                };
+
+                if found.len() == expected.len() {
+                    self.report_closure_arg_mismatch(
+                        span,
+                        found_span,
+                        found_trait_ref,
+                        expected_trait_ref,
+                    )
+                } else {
+                    let (closure_span, found) = found_did
+                        .and_then(|did| self.tcx.hir().get_if_local(did))
+                        .map(|node| {
+                            let (found_span, found) = self.get_fn_like_arguments(node);
+                            (Some(found_span), found)
+                        })
+                        .unwrap_or((found_span, found));
+
+                    self.report_arg_count_mismatch(
+                        span,
+                        closure_span,
+                        expected,
+                        found,
+                        found_trait_ty.is_closure(),
+                    )
+                }
+            }
+
+            TraitNotObjectSafe(did) => {
+                let violations = object_safety_violations(self.tcx, did);
+                report_object_safety_error(self.tcx, span, did, violations)
+            }
+
+            // already reported in the query
+            ConstEvalFailure(err) => {
+                if let ErrorHandled::TooGeneric = err {
+                    // Silence this error, as it can be produced during intermediate steps
+                    // when a constant is not yet able to be evaluated (but will be later).
+                    return;
+                }
+                self.tcx.sess.delay_span_bug(
+                    span,
+                    &format!("constant in type had an ignored error: {:?}", err),
+                );
+                return;
+            }
+
+            Overflow => {
+                bug!("overflow should be handled before the `report_selection_error` path");
+            }
+        };
+
+        self.note_obligation_cause(&mut err, obligation);
+        self.point_at_returns_when_relevant(&mut err, &obligation);
+
+        err.emit();
+    }
+
+    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
+    /// with the same path as `trait_ref`, a help message about
+    /// a probable version mismatch is added to `err`
+    fn note_version_mismatch(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        trait_ref: &ty::PolyTraitRef<'tcx>,
+    ) {
+        let get_trait_impl = |trait_def_id| {
+            let mut trait_impl = None;
+            self.tcx.for_each_relevant_impl(trait_def_id, trait_ref.self_ty(), |impl_def_id| {
+                if trait_impl.is_none() {
+                    trait_impl = Some(impl_def_id);
+                }
+            });
+            trait_impl
+        };
+        let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
+        let all_traits = self.tcx.all_traits(LOCAL_CRATE);
+        let traits_with_same_path: std::collections::BTreeSet<_> = all_traits
+            .iter()
+            .filter(|trait_def_id| **trait_def_id != trait_ref.def_id())
+            .filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path)
+            .collect();
+        for trait_with_same_path in traits_with_same_path {
+            if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) {
+                let impl_span = self.tcx.def_span(impl_def_id);
+                err.span_help(impl_span, "trait impl with same name found");
+                let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
+                let crate_msg = format!(
+                    "perhaps two different versions of crate `{}` are being used?",
+                    trait_crate
+                );
+                err.note(&crate_msg);
+            }
+        }
+    }
+
+    fn mk_obligation_for_def_id(
+        &self,
+        def_id: DefId,
+        output_ty: Ty<'tcx>,
+        cause: ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> PredicateObligation<'tcx> {
+        let new_trait_ref =
+            ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
+        Obligation::new(cause, param_env, new_trait_ref.to_predicate())
+    }
+}
+
+pub fn recursive_type_with_infinite_size_error(
+    tcx: TyCtxt<'tcx>,
+    type_def_id: DefId,
+) -> DiagnosticBuilder<'tcx> {
+    assert!(type_def_id.is_local());
+    let span = tcx.hir().span_if_local(type_def_id).unwrap();
+    let span = tcx.sess.source_map().def_span(span);
+    let mut err = struct_span_err!(
+        tcx.sess,
+        span,
+        E0072,
+        "recursive type `{}` has infinite size",
+        tcx.def_path_str(type_def_id)
+    );
+    err.span_label(span, "recursive type has infinite size");
+    err.help(&format!(
+        "insert indirection (e.g., a `Box`, `Rc`, or `&`) \
+                           at some point to make `{}` representable",
+        tcx.def_path_str(type_def_id)
+    ));
+    err
+}
+
+pub fn report_object_safety_error(
+    tcx: TyCtxt<'tcx>,
+    span: Span,
+    trait_def_id: DefId,
+    violations: Vec<ObjectSafetyViolation>,
+) -> DiagnosticBuilder<'tcx> {
+    let trait_str = tcx.def_path_str(trait_def_id);
+    let span = tcx.sess.source_map().def_span(span);
+    let mut err = struct_span_err!(
+        tcx.sess,
+        span,
+        E0038,
+        "the trait `{}` cannot be made into an object",
+        trait_str
+    );
+    err.span_label(span, format!("the trait `{}` cannot be made into an object", trait_str));
+
+    let mut reported_violations = FxHashSet::default();
+    for violation in violations {
+        if reported_violations.insert(violation.clone()) {
+            match violation.span() {
+                Some(span) => err.span_label(span, violation.error_msg()),
+                None => err.note(&violation.error_msg()),
+            };
+        }
+    }
+
+    if tcx.sess.trait_methods_not_found.borrow().contains(&span) {
+        // Avoid emitting error caused by non-existing method (#58734)
+        err.cancel();
+    }
+
+    err
+}
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+    fn maybe_report_ambiguity(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        body_id: Option<hir::BodyId>,
+    ) {
+        // Unable to successfully determine, probably means
+        // insufficient type information, but could mean
+        // ambiguous impls. The latter *ought* to be a
+        // coherence violation, so we don't report it here.
+
+        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+        let span = obligation.cause.span;
+
+        debug!(
+            "maybe_report_ambiguity(predicate={:?}, obligation={:?} body_id={:?}, code={:?})",
+            predicate, obligation, body_id, obligation.cause.code,
+        );
+
+        // Ambiguity errors are often caused as fallout from earlier
+        // errors. So just ignore them if this infcx is tainted.
+        if self.is_tainted_by_errors() {
+            return;
+        }
+
+        let mut err = match predicate {
+            ty::Predicate::Trait(ref data) => {
+                let trait_ref = data.to_poly_trait_ref();
+                let self_ty = trait_ref.self_ty();
+                debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref);
+
+                if predicate.references_error() {
+                    return;
+                }
+                // Typically, this ambiguity should only happen if
+                // there are unresolved type inference variables
+                // (otherwise it would suggest a coherence
+                // failure). But given #21974 that is not necessarily
+                // the case -- we can have multiple where clauses that
+                // are only distinguished by a region, which results
+                // in an ambiguity even when all types are fully
+                // known, since we don't dispatch based on region
+                // relationships.
+
+                // This is kind of a hack: it frequently happens that some earlier
+                // error prevents types from being fully inferred, and then we get
+                // a bunch of uninteresting errors saying something like "<generic
+                // #0> doesn't implement Sized".  It may even be true that we
+                // could just skip over all checks where the self-ty is an
+                // inference variable, but I was afraid that there might be an
+                // inference variable created, registered as an obligation, and
+                // then never forced by writeback, and hence by skipping here we'd
+                // be ignoring the fact that we don't KNOW the type works
+                // out. Though even that would probably be harmless, given that
+                // we're only talking about builtin traits, which are known to be
+                // inhabited. We used to check for `self.tcx.sess.has_errors()` to
+                // avoid inundating the user with unnecessary errors, but we now
+                // check upstream for type errors and dont add the obligations to
+                // begin with in those cases.
+                if self
+                    .tcx
+                    .lang_items()
+                    .sized_trait()
+                    .map_or(false, |sized_id| sized_id == trait_ref.def_id())
+                {
+                    self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
+                    return;
+                }
+                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283);
+                err.note(&format!("cannot resolve `{}`", predicate));
+                if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
+                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
+                } else if let (
+                    Ok(ref snippet),
+                    ObligationCauseCode::BindingObligation(ref def_id, _),
+                ) =
+                    (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code)
+                {
+                    let generics = self.tcx.generics_of(*def_id);
+                    if !generics.params.is_empty() && !snippet.ends_with('>') {
+                        // FIXME: To avoid spurious suggestions in functions where type arguments
+                        // where already supplied, we check the snippet to make sure it doesn't
+                        // end with a turbofish. Ideally we would have access to a `PathSegment`
+                        // instead. Otherwise we would produce the following output:
+                        //
+                        // error[E0283]: type annotations needed
+                        //   --> $DIR/issue-54954.rs:3:24
+                        //    |
+                        // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
+                        //    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+                        //    |                        |
+                        //    |                        cannot infer type
+                        //    |                        help: consider specifying the type argument
+                        //    |                        in the function call:
+                        //    |                        `Tt::const_val::<[i8; 123]>::<T>`
+                        // ...
+                        // LL |     const fn const_val<T: Sized>() -> usize {
+                        //    |              --------- - required by this bound in `Tt::const_val`
+                        //    |
+                        //    = note: cannot resolve `_: Tt`
+
+                        err.span_suggestion(
+                            span,
+                            &format!(
+                                "consider specifying the type argument{} in the function call",
+                                if generics.params.len() > 1 { "s" } else { "" },
+                            ),
+                            format!(
+                                "{}::<{}>",
+                                snippet,
+                                generics
+                                    .params
+                                    .iter()
+                                    .map(|p| p.name.to_string())
+                                    .collect::<Vec<String>>()
+                                    .join(", ")
+                            ),
+                            Applicability::HasPlaceholders,
+                        );
+                    }
+                }
+                err
+            }
+
+            ty::Predicate::WellFormed(ty) => {
+                // Same hacky approach as above to avoid deluging user
+                // with error messages.
+                if ty.references_error() || self.tcx.sess.has_errors() {
+                    return;
+                }
+                self.need_type_info_err(body_id, span, ty, ErrorCode::E0282)
+            }
+
+            ty::Predicate::Subtype(ref data) => {
+                if data.references_error() || self.tcx.sess.has_errors() {
+                    // no need to overload user in such cases
+                    return;
+                }
+                let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
+                // both must be type variables, or the other would've been instantiated
+                assert!(a.is_ty_var() && b.is_ty_var());
+                self.need_type_info_err(body_id, span, a, ErrorCode::E0282)
+            }
+            ty::Predicate::Projection(ref data) => {
+                let trait_ref = data.to_poly_trait_ref(self.tcx);
+                let self_ty = trait_ref.self_ty();
+                if predicate.references_error() {
+                    return;
+                }
+                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284);
+                err.note(&format!("cannot resolve `{}`", predicate));
+                err
+            }
+
+            _ => {
+                if self.tcx.sess.has_errors() {
+                    return;
+                }
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0284,
+                    "type annotations needed: cannot resolve `{}`",
+                    predicate,
+                );
+                err.span_label(span, &format!("cannot resolve `{}`", predicate));
+                err
+            }
+        };
+        self.note_obligation_cause(&mut err, obligation);
+        err.emit();
+    }
+
+    /// Returns `true` if the trait predicate may apply for *some* assignment
+    /// to the type parameters.
+    fn predicate_can_apply(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        pred: ty::PolyTraitRef<'tcx>,
+    ) -> bool {
+        struct ParamToVarFolder<'a, 'tcx> {
+            infcx: &'a InferCtxt<'a, 'tcx>,
+            var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
+        }
+
+        impl<'a, 'tcx> TypeFolder<'tcx> for ParamToVarFolder<'a, 'tcx> {
+            fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+                self.infcx.tcx
+            }
+
+            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+                if let ty::Param(ty::ParamTy { name, .. }) = ty.kind {
+                    let infcx = self.infcx;
+                    self.var_map.entry(ty).or_insert_with(|| {
+                        infcx.next_ty_var(TypeVariableOrigin {
+                            kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
+                            span: DUMMY_SP,
+                        })
+                    })
+                } else {
+                    ty.super_fold_with(self)
+                }
+            }
+        }
+
+        self.probe(|_| {
+            let mut selcx = SelectionContext::new(self);
+
+            let cleaned_pred =
+                pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() });
+
+            let cleaned_pred = super::project::normalize(
+                &mut selcx,
+                param_env,
+                ObligationCause::dummy(),
+                &cleaned_pred,
+            )
+            .value;
+
+            let obligation =
+                Obligation::new(ObligationCause::dummy(), param_env, cleaned_pred.to_predicate());
+
+            self.predicate_may_hold(&obligation)
+        })
+    }
+
+    fn note_obligation_cause(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        obligation: &PredicateObligation<'tcx>,
+    ) {
+        // First, attempt to add note to this error with an async-await-specific
+        // message, and fall back to regular note otherwise.
+        if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
+            self.note_obligation_cause_code(
+                err,
+                &obligation.predicate,
+                &obligation.cause.code,
+                &mut vec![],
+            );
+        }
+    }
+
+    fn is_recursive_obligation(
+        &self,
+        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
+        cause_code: &ObligationCauseCode<'tcx>,
+    ) -> bool {
+        if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
+            let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
+
+            if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) {
+                return true;
+            }
+        }
+        false
+    }
+}
+
+/// Summarizes information
+#[derive(Clone)]
+pub enum ArgKind {
+    /// An argument of non-tuple type. Parameters are (name, ty)
+    Arg(String, String),
+
+    /// An argument of tuple type. For a "found" argument, the span is
+    /// the locationo in the source of the pattern. For a "expected"
+    /// argument, it will be None. The vector is a list of (name, ty)
+    /// strings for the components of the tuple.
+    Tuple(Option<Span>, Vec<(String, String)>),
+}
+
+impl ArgKind {
+    fn empty() -> ArgKind {
+        ArgKind::Arg("_".to_owned(), "_".to_owned())
+    }
+
+    /// Creates an `ArgKind` from the expected type of an
+    /// argument. It has no name (`_`) and an optional source span.
+    pub fn from_expected_ty(t: Ty<'_>, span: Option<Span>) -> ArgKind {
+        match t.kind {
+            ty::Tuple(ref tys) => ArgKind::Tuple(
+                span,
+                tys.iter().map(|ty| ("_".to_owned(), ty.to_string())).collect::<Vec<_>>(),
+            ),
+            _ => ArgKind::Arg("_".to_owned(), t.to_string()),
+        }
+    }
+}
+
+/// Suggest restricting a type param with a new bound.
+pub fn suggest_constraining_type_param(
+    generics: &hir::Generics<'_>,
+    err: &mut DiagnosticBuilder<'_>,
+    param_name: &str,
+    constraint: &str,
+    source_map: &SourceMap,
+    span: Span,
+) -> bool {
+    let restrict_msg = "consider further restricting this bound";
+    if let Some(param) =
+        generics.params.iter().filter(|p| p.name.ident().as_str() == param_name).next()
+    {
+        if param_name.starts_with("impl ") {
+            // `impl Trait` in argument:
+            // `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
+            err.span_suggestion(
+                param.span,
+                restrict_msg,
+                // `impl CurrentTrait + MissingTrait`
+                format!("{} + {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else if generics.where_clause.predicates.is_empty() && param.bounds.is_empty() {
+            // If there are no bounds whatsoever, suggest adding a constraint
+            // to the type parameter:
+            // `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
+            err.span_suggestion(
+                param.span,
+                "consider restricting this bound",
+                format!("{}: {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else if !generics.where_clause.predicates.is_empty() {
+            // There is a `where` clause, so suggest expanding it:
+            // `fn foo<T>(t: T) where T: Debug {}` →
+            // `fn foo<T>(t: T) where T: Debug, T: Trait {}`
+            err.span_suggestion(
+                generics.where_clause.span().unwrap().shrink_to_hi(),
+                &format!("consider further restricting type parameter `{}`", param_name),
+                format!(", {}: {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            // If there is no `where` clause lean towards constraining to the
+            // type parameter:
+            // `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
+            // `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
+            let sp = param.span.with_hi(span.hi());
+            let span = source_map.span_through_char(sp, ':');
+            if sp != param.span && sp != span {
+                // Only suggest if we have high certainty that the span
+                // covers the colon in `foo<T: Trait>`.
+                err.span_suggestion(
+                    span,
+                    restrict_msg,
+                    format!("{}: {} + ", param_name, constraint),
+                    Applicability::MachineApplicable,
+                );
+            } else {
+                err.span_label(
+                    param.span,
+                    &format!("consider adding a `where {}: {}` bound", param_name, constraint),
+                );
+            }
+        }
+        return true;
+    }
+    false
+}
diff --git a/src/librustc/traits/error_reporting/on_unimplemented.rs b/src/librustc/traits/error_reporting/on_unimplemented.rs
new file mode 100644
index 00000000000..9f3fc91548b
--- /dev/null
+++ b/src/librustc/traits/error_reporting/on_unimplemented.rs
@@ -0,0 +1,199 @@
+use super::{
+    ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, PredicateObligation,
+};
+use crate::infer::InferCtxt;
+use crate::ty::subst::Subst;
+use crate::ty::{self, GenericParamDefKind};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_span::symbol::sym;
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+    fn impl_similar_to(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> Option<DefId> {
+        let tcx = self.tcx;
+        let param_env = obligation.param_env;
+        let trait_ref = tcx.erase_late_bound_regions(&trait_ref);
+        let trait_self_ty = trait_ref.self_ty();
+
+        let mut self_match_impls = vec![];
+        let mut fuzzy_match_impls = vec![];
+
+        self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| {
+            let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id);
+            let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().subst(tcx, impl_substs);
+
+            let impl_self_ty = impl_trait_ref.self_ty();
+
+            if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) {
+                self_match_impls.push(def_id);
+
+                if trait_ref
+                    .substs
+                    .types()
+                    .skip(1)
+                    .zip(impl_trait_ref.substs.types().skip(1))
+                    .all(|(u, v)| self.fuzzy_match_tys(u, v))
+                {
+                    fuzzy_match_impls.push(def_id);
+                }
+            }
+        });
+
+        let impl_def_id = if self_match_impls.len() == 1 {
+            self_match_impls[0]
+        } else if fuzzy_match_impls.len() == 1 {
+            fuzzy_match_impls[0]
+        } else {
+            return None;
+        };
+
+        tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented).then_some(impl_def_id)
+    }
+
+    /// Used to set on_unimplemented's `ItemContext`
+    /// to be the enclosing (async) block/function/closure
+    fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> {
+        let hir = &self.tcx.hir();
+        let node = hir.find(hir_id)?;
+        if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) = &node {
+            self.describe_generator(*body_id).or_else(|| {
+                Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
+                    "an async function"
+                } else {
+                    "a function"
+                })
+            })
+        } else if let hir::Node::Expr(hir::Expr {
+            kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability),
+            ..
+        }) = &node
+        {
+            self.describe_generator(*body_id).or_else(|| {
+                Some(if gen_movability.is_some() { "an async closure" } else { "a closure" })
+            })
+        } else if let hir::Node::Expr(hir::Expr { .. }) = &node {
+            let parent_hid = hir.get_parent_node(hir_id);
+            if parent_hid != hir_id {
+                return self.describe_enclosure(parent_hid);
+            } else {
+                None
+            }
+        } else {
+            None
+        }
+    }
+
+    crate fn on_unimplemented_note(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> OnUnimplementedNote {
+        let def_id =
+            self.impl_similar_to(trait_ref, obligation).unwrap_or_else(|| trait_ref.def_id());
+        let trait_ref = *trait_ref.skip_binder();
+
+        let mut flags = vec![];
+        flags.push((
+            sym::item_context,
+            self.describe_enclosure(obligation.cause.body_id).map(|s| s.to_owned()),
+        ));
+
+        match obligation.cause.code {
+            ObligationCauseCode::BuiltinDerivedObligation(..)
+            | ObligationCauseCode::ImplDerivedObligation(..) => {}
+            _ => {
+                // this is a "direct", user-specified, rather than derived,
+                // obligation.
+                flags.push((sym::direct, None));
+            }
+        }
+
+        if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code {
+            // FIXME: maybe also have some way of handling methods
+            // from other traits? That would require name resolution,
+            // which we might want to be some sort of hygienic.
+            //
+            // Currently I'm leaving it for what I need for `try`.
+            if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
+                let method = self.tcx.item_name(item);
+                flags.push((sym::from_method, None));
+                flags.push((sym::from_method, Some(method.to_string())));
+            }
+        }
+        if let Some((t, _)) = self.get_parent_trait_ref(&obligation.cause.code) {
+            flags.push((sym::parent_trait, Some(t)));
+        }
+
+        if let Some(k) = obligation.cause.span.desugaring_kind() {
+            flags.push((sym::from_desugaring, None));
+            flags.push((sym::from_desugaring, Some(format!("{:?}", k))));
+        }
+        let generics = self.tcx.generics_of(def_id);
+        let self_ty = trait_ref.self_ty();
+        // This is also included through the generics list as `Self`,
+        // but the parser won't allow you to use it
+        flags.push((sym::_Self, Some(self_ty.to_string())));
+        if let Some(def) = self_ty.ty_adt_def() {
+            // We also want to be able to select self's original
+            // signature with no type arguments resolved
+            flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string())));
+        }
+
+        for param in generics.params.iter() {
+            let value = match param.kind {
+                GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
+                    trait_ref.substs[param.index as usize].to_string()
+                }
+                GenericParamDefKind::Lifetime => continue,
+            };
+            let name = param.name;
+            flags.push((name, Some(value)));
+        }
+
+        if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) {
+            flags.push((sym::crate_local, None));
+        }
+
+        // Allow targeting all integers using `{integral}`, even if the exact type was resolved
+        if self_ty.is_integral() {
+            flags.push((sym::_Self, Some("{integral}".to_owned())));
+        }
+
+        if let ty::Array(aty, len) = self_ty.kind {
+            flags.push((sym::_Self, Some("[]".to_owned())));
+            flags.push((sym::_Self, Some(format!("[{}]", aty))));
+            if let Some(def) = aty.ty_adt_def() {
+                // We also want to be able to select the array's type's original
+                // signature with no type arguments resolved
+                flags.push((
+                    sym::_Self,
+                    Some(format!("[{}]", self.tcx.type_of(def.did).to_string())),
+                ));
+                let tcx = self.tcx;
+                if let Some(len) = len.try_eval_usize(tcx, ty::ParamEnv::empty()) {
+                    flags.push((
+                        sym::_Self,
+                        Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)),
+                    ));
+                } else {
+                    flags.push((
+                        sym::_Self,
+                        Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())),
+                    ));
+                }
+            }
+        }
+
+        if let Ok(Some(command)) =
+            OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id)
+        {
+            command.evaluate(self.tcx, trait_ref, &flags[..])
+        } else {
+            OnUnimplementedNote::default()
+        }
+    }
+}
diff --git a/src/librustc/traits/error_reporting/suggestions.rs b/src/librustc/traits/error_reporting/suggestions.rs
new file mode 100644
index 00000000000..bf6891214ac
--- /dev/null
+++ b/src/librustc/traits/error_reporting/suggestions.rs
@@ -0,0 +1,1718 @@
+use super::{
+    ArgKind, EvaluationResult, Obligation, ObligationCause, ObligationCauseCode,
+    PredicateObligation,
+};
+
+use crate::infer::InferCtxt;
+use crate::traits::object_safety::object_safety_violations;
+use crate::ty::TypeckTables;
+use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
+
+use rustc_errors::{
+    error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style,
+};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::Visitor;
+use rustc_hir::Node;
+use rustc_span::source_map::SourceMap;
+use rustc_span::symbol::{kw, sym};
+use rustc_span::{MultiSpan, Span, DUMMY_SP};
+use std::fmt;
+
+use rustc_error_codes::*;
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+    crate fn suggest_restricting_param_bound(
+        &self,
+        mut err: &mut DiagnosticBuilder<'_>,
+        trait_ref: &ty::PolyTraitRef<'_>,
+        body_id: hir::HirId,
+    ) {
+        let self_ty = trait_ref.self_ty();
+        let (param_ty, projection) = match &self_ty.kind {
+            ty::Param(_) => (true, None),
+            ty::Projection(projection) => (false, Some(projection)),
+            _ => return,
+        };
+
+        let suggest_restriction =
+            |generics: &hir::Generics<'_>, msg, err: &mut DiagnosticBuilder<'_>| {
+                let span = generics.where_clause.span_for_predicates_or_empty_place();
+                if !span.from_expansion() && span.desugaring_kind().is_none() {
+                    err.span_suggestion(
+                        generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(),
+                        &format!("consider further restricting {}", msg),
+                        format!(
+                            "{} {} ",
+                            if !generics.where_clause.predicates.is_empty() {
+                                ","
+                            } else {
+                                " where"
+                            },
+                            trait_ref.to_predicate(),
+                        ),
+                        Applicability::MachineApplicable,
+                    );
+                }
+            };
+
+        // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
+        //        don't suggest `T: Sized + ?Sized`.
+        let mut hir_id = body_id;
+        while let Some(node) = self.tcx.hir().find(hir_id) {
+            match node {
+                hir::Node::TraitItem(hir::TraitItem {
+                    generics,
+                    kind: hir::TraitItemKind::Method(..),
+                    ..
+                }) if param_ty && self_ty == self.tcx.types.self_param => {
+                    // Restricting `Self` for a single method.
+                    suggest_restriction(&generics, "`Self`", err);
+                    return;
+                }
+
+                hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
+                | hir::Node::TraitItem(hir::TraitItem {
+                    generics,
+                    kind: hir::TraitItemKind::Method(..),
+                    ..
+                })
+                | hir::Node::ImplItem(hir::ImplItem {
+                    generics,
+                    kind: hir::ImplItemKind::Method(..),
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Trait(_, _, generics, _, _),
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Impl(_, _, _, generics, ..),
+                    ..
+                }) if projection.is_some() => {
+                    // Missing associated type bound.
+                    suggest_restriction(&generics, "the associated type", err);
+                    return;
+                }
+
+                hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Struct(_, generics),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Enum(_, generics), span, ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Union(_, generics),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Trait(_, _, generics, ..),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Impl(_, _, _, generics, ..),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Fn(_, generics, _),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::TyAlias(_, generics),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::TraitAlias(generics, _),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }),
+                    span,
+                    ..
+                })
+                | hir::Node::TraitItem(hir::TraitItem { generics, span, .. })
+                | hir::Node::ImplItem(hir::ImplItem { generics, span, .. })
+                    if param_ty =>
+                {
+                    // Missing generic type parameter bound.
+                    let param_name = self_ty.to_string();
+                    let constraint = trait_ref.print_only_trait_path().to_string();
+                    if suggest_constraining_type_param(
+                        generics,
+                        &mut err,
+                        &param_name,
+                        &constraint,
+                        self.tcx.sess.source_map(),
+                        *span,
+                    ) {
+                        return;
+                    }
+                }
+
+                hir::Node::Crate => return,
+
+                _ => {}
+            }
+
+            hir_id = self.tcx.hir().get_parent_item(hir_id);
+        }
+    }
+
+    /// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a
+    /// suggestion to borrow the initializer in order to use have a slice instead.
+    crate fn suggest_borrow_on_unsized_slice(
+        &self,
+        code: &ObligationCauseCode<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+    ) {
+        if let &ObligationCauseCode::VariableType(hir_id) = code {
+            let parent_node = self.tcx.hir().get_parent_node(hir_id);
+            if let Some(Node::Local(ref local)) = self.tcx.hir().find(parent_node) {
+                if let Some(ref expr) = local.init {
+                    if let hir::ExprKind::Index(_, _) = expr.kind {
+                        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
+                            err.span_suggestion(
+                                expr.span,
+                                "consider borrowing here",
+                                format!("&{}", snippet),
+                                Applicability::MachineApplicable,
+                            );
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /// Given a closure's `DefId`, return the given name of the closure.
+    ///
+    /// This doesn't account for reassignments, but it's only used for suggestions.
+    crate fn get_closure_name(
+        &self,
+        def_id: DefId,
+        err: &mut DiagnosticBuilder<'_>,
+        msg: &str,
+    ) -> Option<String> {
+        let get_name =
+            |err: &mut DiagnosticBuilder<'_>, kind: &hir::PatKind<'_>| -> Option<String> {
+                // Get the local name of this closure. This can be inaccurate because
+                // of the possibility of reassignment, but this should be good enough.
+                match &kind {
+                    hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => {
+                        Some(format!("{}", name))
+                    }
+                    _ => {
+                        err.note(&msg);
+                        None
+                    }
+                }
+            };
+
+        let hir = self.tcx.hir();
+        let hir_id = hir.as_local_hir_id(def_id)?;
+        let parent_node = hir.get_parent_node(hir_id);
+        match hir.find(parent_node) {
+            Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. })) => {
+                get_name(err, &local.pat.kind)
+            }
+            // Different to previous arm because one is `&hir::Local` and the other
+            // is `P<hir::Local>`.
+            Some(hir::Node::Local(local)) => get_name(err, &local.pat.kind),
+            _ => return None,
+        }
+    }
+
+    /// We tried to apply the bound to an `fn` or closure. Check whether calling it would
+    /// evaluate to a type that *would* satisfy the trait binding. If it would, suggest calling
+    /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
+    crate fn suggest_fn_call(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'_>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+        points_at_arg: bool,
+    ) {
+        let self_ty = trait_ref.self_ty();
+        let (def_id, output_ty, callable) = match self_ty.kind {
+            ty::Closure(def_id, substs) => {
+                (def_id, self.closure_sig(def_id, substs).output(), "closure")
+            }
+            ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"),
+            _ => return,
+        };
+        let msg = format!("use parentheses to call the {}", callable);
+
+        let obligation = self.mk_obligation_for_def_id(
+            trait_ref.def_id(),
+            output_ty.skip_binder(),
+            obligation.cause.clone(),
+            obligation.param_env,
+        );
+
+        match self.evaluate_obligation(&obligation) {
+            Ok(EvaluationResult::EvaluatedToOk)
+            | Ok(EvaluationResult::EvaluatedToOkModuloRegions)
+            | Ok(EvaluationResult::EvaluatedToAmbig) => {}
+            _ => return,
+        }
+        let hir = self.tcx.hir();
+        // Get the name of the callable and the arguments to be used in the suggestion.
+        let snippet = match hir.get_if_local(def_id) {
+            Some(hir::Node::Expr(hir::Expr {
+                kind: hir::ExprKind::Closure(_, decl, _, span, ..),
+                ..
+            })) => {
+                err.span_label(*span, "consider calling this closure");
+                let name = match self.get_closure_name(def_id, err, &msg) {
+                    Some(name) => name,
+                    None => return,
+                };
+                let args = decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
+                format!("{}({})", name, args)
+            }
+            Some(hir::Node::Item(hir::Item {
+                ident,
+                kind: hir::ItemKind::Fn(.., body_id),
+                ..
+            })) => {
+                err.span_label(ident.span, "consider calling this function");
+                let body = hir.body(*body_id);
+                let args = body
+                    .params
+                    .iter()
+                    .map(|arg| match &arg.pat.kind {
+                        hir::PatKind::Binding(_, _, ident, None)
+                        // FIXME: provide a better suggestion when encountering `SelfLower`, it
+                        // should suggest a method call.
+                        if ident.name != kw::SelfLower => ident.to_string(),
+                        _ => "_".to_string(),
+                    })
+                    .collect::<Vec<_>>()
+                    .join(", ");
+                format!("{}({})", ident, args)
+            }
+            _ => return,
+        };
+        if points_at_arg {
+            // When the obligation error has been ensured to have been caused by
+            // an argument, the `obligation.cause.span` points at the expression
+            // of the argument, so we can provide a suggestion. This is signaled
+            // by `points_at_arg`. Otherwise, we give a more general note.
+            err.span_suggestion(
+                obligation.cause.span,
+                &msg,
+                snippet,
+                Applicability::HasPlaceholders,
+            );
+        } else {
+            err.help(&format!("{}: `{}`", msg, snippet));
+        }
+    }
+
+    crate fn suggest_add_reference_to_arg(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+        points_at_arg: bool,
+        has_custom_message: bool,
+    ) -> bool {
+        if !points_at_arg {
+            return false;
+        }
+
+        let span = obligation.cause.span;
+        let param_env = obligation.param_env;
+        let trait_ref = trait_ref.skip_binder();
+
+        if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code {
+            // Try to apply the original trait binding obligation by borrowing.
+            let self_ty = trait_ref.self_ty();
+            let found = self_ty.to_string();
+            let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
+            let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
+            let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
+            let new_obligation =
+                Obligation::new(ObligationCause::dummy(), param_env, new_trait_ref.to_predicate());
+            if self.predicate_must_hold_modulo_regions(&new_obligation) {
+                if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+                    // We have a very specific type of error, where just borrowing this argument
+                    // might solve the problem. In cases like this, the important part is the
+                    // original type obligation, not the last one that failed, which is arbitrary.
+                    // Because of this, we modify the error to refer to the original obligation and
+                    // return early in the caller.
+                    let msg = format!(
+                        "the trait bound `{}: {}` is not satisfied",
+                        found,
+                        obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
+                    );
+                    if has_custom_message {
+                        err.note(&msg);
+                    } else {
+                        err.message = vec![(msg, Style::NoStyle)];
+                    }
+                    if snippet.starts_with('&') {
+                        // This is already a literal borrow and the obligation is failing
+                        // somewhere else in the obligation chain. Do not suggest non-sense.
+                        return false;
+                    }
+                    err.span_label(
+                        span,
+                        &format!(
+                            "expected an implementor of trait `{}`",
+                            obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
+                        ),
+                    );
+                    err.span_suggestion(
+                        span,
+                        "consider borrowing here",
+                        format!("&{}", snippet),
+                        Applicability::MaybeIncorrect,
+                    );
+                    return true;
+                }
+            }
+        }
+        false
+    }
+
+    /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
+    /// suggest removing these references until we reach a type that implements the trait.
+    crate fn suggest_remove_reference(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    ) {
+        let trait_ref = trait_ref.skip_binder();
+        let span = obligation.cause.span;
+
+        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+            let refs_number =
+                snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
+            if let Some('\'') =
+                snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next()
+            {
+                // Do not suggest removal of borrow from type arguments.
+                return;
+            }
+
+            let mut trait_type = trait_ref.self_ty();
+
+            for refs_remaining in 0..refs_number {
+                if let ty::Ref(_, t_type, _) = trait_type.kind {
+                    trait_type = t_type;
+
+                    let new_obligation = self.mk_obligation_for_def_id(
+                        trait_ref.def_id,
+                        trait_type,
+                        ObligationCause::dummy(),
+                        obligation.param_env,
+                    );
+
+                    if self.predicate_may_hold(&new_obligation) {
+                        let sp = self
+                            .tcx
+                            .sess
+                            .source_map()
+                            .span_take_while(span, |c| c.is_whitespace() || *c == '&');
+
+                        let remove_refs = refs_remaining + 1;
+                        let format_str =
+                            format!("consider removing {} leading `&`-references", remove_refs);
+
+                        err.span_suggestion_short(
+                            sp,
+                            &format_str,
+                            String::new(),
+                            Applicability::MachineApplicable,
+                        );
+                        break;
+                    }
+                } else {
+                    break;
+                }
+            }
+        }
+    }
+
+    /// Check if the trait bound is implemented for a different mutability and note it in the
+    /// final error.
+    crate fn suggest_change_mut(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+        points_at_arg: bool,
+    ) {
+        let span = obligation.cause.span;
+        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+            let refs_number =
+                snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
+            if let Some('\'') =
+                snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next()
+            {
+                // Do not suggest removal of borrow from type arguments.
+                return;
+            }
+            let trait_ref = self.resolve_vars_if_possible(trait_ref);
+            if trait_ref.has_infer_types() {
+                // Do not ICE while trying to find if a reborrow would succeed on a trait with
+                // unresolved bindings.
+                return;
+            }
+
+            if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind {
+                let trait_type = match mutability {
+                    hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type),
+                    hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type),
+                };
+
+                let new_obligation = self.mk_obligation_for_def_id(
+                    trait_ref.skip_binder().def_id,
+                    trait_type,
+                    ObligationCause::dummy(),
+                    obligation.param_env,
+                );
+
+                if self.evaluate_obligation_no_overflow(&new_obligation).must_apply_modulo_regions()
+                {
+                    let sp = self
+                        .tcx
+                        .sess
+                        .source_map()
+                        .span_take_while(span, |c| c.is_whitespace() || *c == '&');
+                    if points_at_arg && mutability == hir::Mutability::Not && refs_number > 0 {
+                        err.span_suggestion(
+                            sp,
+                            "consider changing this borrow's mutability",
+                            "&mut ".to_string(),
+                            Applicability::MachineApplicable,
+                        );
+                    } else {
+                        err.note(&format!(
+                            "`{}` is implemented for `{:?}`, but not for `{:?}`",
+                            trait_ref.print_only_trait_path(),
+                            trait_type,
+                            trait_ref.skip_binder().self_ty(),
+                        ));
+                    }
+                }
+            }
+        }
+    }
+
+    crate fn suggest_semicolon_removal(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        span: Span,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    ) {
+        let hir = self.tcx.hir();
+        let parent_node = hir.get_parent_node(obligation.cause.body_id);
+        let node = hir.find(parent_node);
+        if let Some(hir::Node::Item(hir::Item {
+            kind: hir::ItemKind::Fn(sig, _, body_id), ..
+        })) = node
+        {
+            let body = hir.body(*body_id);
+            if let hir::ExprKind::Block(blk, _) = &body.value.kind {
+                if sig.decl.output.span().overlaps(span)
+                    && blk.expr.is_none()
+                    && "()" == &trait_ref.self_ty().to_string()
+                {
+                    // FIXME(estebank): When encountering a method with a trait
+                    // bound not satisfied in the return type with a body that has
+                    // no return, suggest removal of semicolon on last statement.
+                    // Once that is added, close #54771.
+                    if let Some(ref stmt) = blk.stmts.last() {
+                        let sp = self.tcx.sess.source_map().end_point(stmt.span);
+                        err.span_label(sp, "consider removing this semicolon");
+                    }
+                }
+            }
+        }
+    }
+
+    /// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if
+    /// applicable and signal that the error has been expanded appropriately and needs to be
+    /// emitted.
+    crate fn suggest_impl_trait(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        span: Span,
+        obligation: &PredicateObligation<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    ) -> bool {
+        match obligation.cause.code.peel_derives() {
+            // Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`.
+            ObligationCauseCode::SizedReturnType => {}
+            _ => return false,
+        }
+
+        let hir = self.tcx.hir();
+        let parent_node = hir.get_parent_node(obligation.cause.body_id);
+        let node = hir.find(parent_node);
+        let (sig, body_id) = if let Some(hir::Node::Item(hir::Item {
+            kind: hir::ItemKind::Fn(sig, _, body_id),
+            ..
+        })) = node
+        {
+            (sig, body_id)
+        } else {
+            return false;
+        };
+        let body = hir.body(*body_id);
+        let trait_ref = self.resolve_vars_if_possible(trait_ref);
+        let ty = trait_ref.skip_binder().self_ty();
+        let is_object_safe = match ty.kind {
+            ty::Dynamic(predicates, _) => {
+                // If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
+                predicates
+                    .principal_def_id()
+                    .map_or(true, |def_id| object_safety_violations(self.tcx, def_id).is_empty())
+            }
+            // We only want to suggest `impl Trait` to `dyn Trait`s.
+            // For example, `fn foo() -> str` needs to be filtered out.
+            _ => return false,
+        };
+
+        let ret_ty = if let hir::FunctionRetTy::Return(ret_ty) = sig.decl.output {
+            ret_ty
+        } else {
+            return false;
+        };
+
+        // Use `TypeVisitor` instead of the output type directly to find the span of `ty` for
+        // cases like `fn foo() -> (dyn Trait, i32) {}`.
+        // Recursively look for `TraitObject` types and if there's only one, use that span to
+        // suggest `impl Trait`.
+
+        // Visit to make sure there's a single `return` type to suggest `impl Trait`,
+        // otherwise suggest using `Box<dyn Trait>` or an enum.
+        let mut visitor = ReturnsVisitor(vec![]);
+        visitor.visit_body(&body);
+
+        let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
+
+        let mut ret_types = visitor.0.iter().filter_map(|expr| tables.node_type_opt(expr.hir_id));
+        let (last_ty, all_returns_have_same_type) =
+            ret_types.clone().fold((None, true), |(last_ty, mut same), returned_ty| {
+                same &= last_ty.map_or(true, |ty| ty == returned_ty);
+                (Some(returned_ty), same)
+            });
+        let all_returns_conform_to_trait =
+            if let Some(ty_ret_ty) = tables.node_type_opt(ret_ty.hir_id) {
+                match ty_ret_ty.kind {
+                    ty::Dynamic(predicates, _) => {
+                        let cause = ObligationCause::misc(ret_ty.span, ret_ty.hir_id);
+                        let param_env = ty::ParamEnv::empty();
+                        ret_types.all(|returned_ty| {
+                            predicates.iter().all(|predicate| {
+                                let pred = predicate.with_self_ty(self.tcx, returned_ty);
+                                let obl = Obligation::new(cause.clone(), param_env, pred);
+                                self.predicate_may_hold(&obl)
+                            })
+                        })
+                    }
+                    _ => true,
+                }
+            } else {
+                true
+            };
+
+        let (snippet, last_ty) =
+            if let (true, hir::TyKind::TraitObject(..), Ok(snippet), true, Some(last_ty)) = (
+                // Verify that we're dealing with a return `dyn Trait`
+                ret_ty.span.overlaps(span),
+                &ret_ty.kind,
+                self.tcx.sess.source_map().span_to_snippet(ret_ty.span),
+                // If any of the return types does not conform to the trait, then we can't
+                // suggest `impl Trait` nor trait objects, it is a type mismatch error.
+                all_returns_conform_to_trait,
+                last_ty,
+            ) {
+                (snippet, last_ty)
+            } else {
+                return false;
+            };
+        err.code(error_code!(E0746));
+        err.set_primary_message("return type cannot have an unboxed trait object");
+        err.children.clear();
+        let impl_trait_msg = "for information on `impl Trait`, see \
+            <https://doc.rust-lang.org/book/ch10-02-traits.html\
+            #returning-types-that-implement-traits>";
+        let trait_obj_msg = "for information on trait objects, see \
+            <https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
+            #using-trait-objects-that-allow-for-values-of-different-types>";
+        let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn");
+        let trait_obj = if has_dyn { &snippet[4..] } else { &snippet[..] };
+        if all_returns_have_same_type {
+            // Suggest `-> impl Trait`.
+            err.span_suggestion(
+                ret_ty.span,
+                &format!(
+                    "return `impl {1}` instead, as all return paths are of type `{}`, \
+                        which implements `{1}`",
+                    last_ty, trait_obj,
+                ),
+                format!("impl {}", trait_obj),
+                Applicability::MachineApplicable,
+            );
+            err.note(impl_trait_msg);
+        } else {
+            if is_object_safe {
+                // Suggest `-> Box<dyn Trait>` and `Box::new(returned_value)`.
+                // Get all the return values and collect their span and suggestion.
+                let mut suggestions = visitor
+                    .0
+                    .iter()
+                    .map(|expr| {
+                        (
+                            expr.span,
+                            format!(
+                                "Box::new({})",
+                                self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap()
+                            ),
+                        )
+                    })
+                    .collect::<Vec<_>>();
+                // Add the suggestion for the return type.
+                suggestions.push((
+                    ret_ty.span,
+                    format!("Box<{}{}>", if has_dyn { "" } else { "dyn " }, snippet),
+                ));
+                err.multipart_suggestion(
+                    "return a boxed trait object instead",
+                    suggestions,
+                    Applicability::MaybeIncorrect,
+                );
+            } else {
+                // This is currently not possible to trigger because E0038 takes precedence, but
+                // leave it in for completeness in case anything changes in an earlier stage.
+                err.note(&format!(
+                    "if trait `{}` was object safe, you could return a trait object",
+                    trait_obj,
+                ));
+            }
+            err.note(trait_obj_msg);
+            err.note(&format!(
+                "if all the returned values were of the same type you could use \
+                    `impl {}` as the return type",
+                trait_obj,
+            ));
+            err.note(impl_trait_msg);
+            err.note("you can create a new `enum` with a variant for each returned type");
+        }
+        true
+    }
+
+    crate fn point_at_returns_when_relevant(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) {
+        match obligation.cause.code.peel_derives() {
+            ObligationCauseCode::SizedReturnType => {}
+            _ => return,
+        }
+
+        let hir = self.tcx.hir();
+        let parent_node = hir.get_parent_node(obligation.cause.body_id);
+        let node = hir.find(parent_node);
+        if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) =
+            node
+        {
+            let body = hir.body(*body_id);
+            // Point at all the `return`s in the function as they have failed trait bounds.
+            let mut visitor = ReturnsVisitor(vec![]);
+            visitor.visit_body(&body);
+            let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
+            for expr in &visitor.0 {
+                if let Some(returned_ty) = tables.node_type_opt(expr.hir_id) {
+                    let ty = self.resolve_vars_if_possible(&returned_ty);
+                    err.span_label(expr.span, &format!("this returned value is of type `{}`", ty));
+                }
+            }
+        }
+    }
+
+    /// Given some node representing a fn-like thing in the HIR map,
+    /// returns a span and `ArgKind` information that describes the
+    /// arguments it expects. This can be supplied to
+    /// `report_arg_count_mismatch`.
+    pub fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>) {
+        match node {
+            Node::Expr(&hir::Expr {
+                kind: hir::ExprKind::Closure(_, ref _decl, id, span, _),
+                ..
+            }) => (
+                self.tcx.sess.source_map().def_span(span),
+                self.tcx
+                    .hir()
+                    .body(id)
+                    .params
+                    .iter()
+                    .map(|arg| {
+                        if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
+                            *arg.pat
+                        {
+                            ArgKind::Tuple(
+                                Some(span),
+                                args.iter()
+                                    .map(|pat| {
+                                        let snippet = self
+                                            .tcx
+                                            .sess
+                                            .source_map()
+                                            .span_to_snippet(pat.span)
+                                            .unwrap();
+                                        (snippet, "_".to_owned())
+                                    })
+                                    .collect::<Vec<_>>(),
+                            )
+                        } else {
+                            let name =
+                                self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap();
+                            ArgKind::Arg(name, "_".to_owned())
+                        }
+                    })
+                    .collect::<Vec<ArgKind>>(),
+            ),
+            Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. })
+            | Node::ImplItem(&hir::ImplItem {
+                span,
+                kind: hir::ImplItemKind::Method(ref sig, _),
+                ..
+            })
+            | Node::TraitItem(&hir::TraitItem {
+                span,
+                kind: hir::TraitItemKind::Method(ref sig, _),
+                ..
+            }) => (
+                self.tcx.sess.source_map().def_span(span),
+                sig.decl
+                    .inputs
+                    .iter()
+                    .map(|arg| match arg.clone().kind {
+                        hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
+                            Some(arg.span),
+                            vec![("_".to_owned(), "_".to_owned()); tys.len()],
+                        ),
+                        _ => ArgKind::empty(),
+                    })
+                    .collect::<Vec<ArgKind>>(),
+            ),
+            Node::Ctor(ref variant_data) => {
+                let span = variant_data
+                    .ctor_hir_id()
+                    .map(|hir_id| self.tcx.hir().span(hir_id))
+                    .unwrap_or(DUMMY_SP);
+                let span = self.tcx.sess.source_map().def_span(span);
+
+                (span, vec![ArgKind::empty(); variant_data.fields().len()])
+            }
+            _ => panic!("non-FnLike node found: {:?}", node),
+        }
+    }
+
+    /// Reports an error when the number of arguments needed by a
+    /// trait match doesn't match the number that the expression
+    /// provides.
+    pub fn report_arg_count_mismatch(
+        &self,
+        span: Span,
+        found_span: Option<Span>,
+        expected_args: Vec<ArgKind>,
+        found_args: Vec<ArgKind>,
+        is_closure: bool,
+    ) -> DiagnosticBuilder<'tcx> {
+        let kind = if is_closure { "closure" } else { "function" };
+
+        let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
+            let arg_length = arguments.len();
+            let distinct = match &other[..] {
+                &[ArgKind::Tuple(..)] => true,
+                _ => false,
+            };
+            match (arg_length, arguments.get(0)) {
+                (1, Some(&ArgKind::Tuple(_, ref fields))) => {
+                    format!("a single {}-tuple as argument", fields.len())
+                }
+                _ => format!(
+                    "{} {}argument{}",
+                    arg_length,
+                    if distinct && arg_length > 1 { "distinct " } else { "" },
+                    pluralize!(arg_length)
+                ),
+            }
+        };
+
+        let expected_str = args_str(&expected_args, &found_args);
+        let found_str = args_str(&found_args, &expected_args);
+
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            span,
+            E0593,
+            "{} is expected to take {}, but it takes {}",
+            kind,
+            expected_str,
+            found_str,
+        );
+
+        err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
+
+        if let Some(found_span) = found_span {
+            err.span_label(found_span, format!("takes {}", found_str));
+
+            // move |_| { ... }
+            // ^^^^^^^^-- def_span
+            //
+            // move |_| { ... }
+            // ^^^^^-- prefix
+            let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
+            // move |_| { ... }
+            //      ^^^-- pipe_span
+            let pipe_span =
+                if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span };
+
+            // Suggest to take and ignore the arguments with expected_args_length `_`s if
+            // found arguments is empty (assume the user just wants to ignore args in this case).
+            // For example, if `expected_args_length` is 2, suggest `|_, _|`.
+            if found_args.is_empty() && is_closure {
+                let underscores = vec!["_"; expected_args.len()].join(", ");
+                err.span_suggestion(
+                    pipe_span,
+                    &format!(
+                        "consider changing the closure to take and ignore the expected argument{}",
+                        if expected_args.len() < 2 { "" } else { "s" }
+                    ),
+                    format!("|{}|", underscores),
+                    Applicability::MachineApplicable,
+                );
+            }
+
+            if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
+                if fields.len() == expected_args.len() {
+                    let sugg = fields
+                        .iter()
+                        .map(|(name, _)| name.to_owned())
+                        .collect::<Vec<String>>()
+                        .join(", ");
+                    err.span_suggestion(
+                        found_span,
+                        "change the closure to take multiple arguments instead of a single tuple",
+                        format!("|{}|", sugg),
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
+                if fields.len() == found_args.len() && is_closure {
+                    let sugg = format!(
+                        "|({}){}|",
+                        found_args
+                            .iter()
+                            .map(|arg| match arg {
+                                ArgKind::Arg(name, _) => name.to_owned(),
+                                _ => "_".to_owned(),
+                            })
+                            .collect::<Vec<String>>()
+                            .join(", "),
+                        // add type annotations if available
+                        if found_args.iter().any(|arg| match arg {
+                            ArgKind::Arg(_, ty) => ty != "_",
+                            _ => false,
+                        }) {
+                            format!(
+                                ": ({})",
+                                fields
+                                    .iter()
+                                    .map(|(_, ty)| ty.to_owned())
+                                    .collect::<Vec<String>>()
+                                    .join(", ")
+                            )
+                        } else {
+                            String::new()
+                        },
+                    );
+                    err.span_suggestion(
+                        found_span,
+                        "change the closure to accept a tuple instead of individual arguments",
+                        sugg,
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+        }
+
+        err
+    }
+
+    crate fn report_closure_arg_mismatch(
+        &self,
+        span: Span,
+        found_span: Option<Span>,
+        expected_ref: ty::PolyTraitRef<'tcx>,
+        found: ty::PolyTraitRef<'tcx>,
+    ) -> DiagnosticBuilder<'tcx> {
+        crate fn build_fn_sig_string<'tcx>(
+            tcx: TyCtxt<'tcx>,
+            trait_ref: &ty::TraitRef<'tcx>,
+        ) -> String {
+            let inputs = trait_ref.substs.type_at(1);
+            let sig = if let ty::Tuple(inputs) = inputs.kind {
+                tcx.mk_fn_sig(
+                    inputs.iter().map(|k| k.expect_ty()),
+                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
+                    false,
+                    hir::Unsafety::Normal,
+                    ::rustc_target::spec::abi::Abi::Rust,
+                )
+            } else {
+                tcx.mk_fn_sig(
+                    ::std::iter::once(inputs),
+                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
+                    false,
+                    hir::Unsafety::Normal,
+                    ::rustc_target::spec::abi::Abi::Rust,
+                )
+            };
+            ty::Binder::bind(sig).to_string()
+        }
+
+        let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            span,
+            E0631,
+            "type mismatch in {} arguments",
+            if argument_is_closure { "closure" } else { "function" }
+        );
+
+        let found_str = format!(
+            "expected signature of `{}`",
+            build_fn_sig_string(self.tcx, found.skip_binder())
+        );
+        err.span_label(span, found_str);
+
+        let found_span = found_span.unwrap_or(span);
+        let expected_str = format!(
+            "found signature of `{}`",
+            build_fn_sig_string(self.tcx, expected_ref.skip_binder())
+        );
+        err.span_label(found_span, expected_str);
+
+        err
+    }
+}
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+    crate fn suggest_fully_qualified_path(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        def_id: DefId,
+        span: Span,
+        trait_ref: DefId,
+    ) {
+        if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) {
+            if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind {
+                err.note(&format!(
+                    "{}s cannot be accessed directly on a `trait`, they can only be \
+                        accessed through a specific `impl`",
+                    assoc_item.kind.suggestion_descr(),
+                ));
+                err.span_suggestion(
+                    span,
+                    "use the fully qualified path to an implementation",
+                    format!("<Type as {}>::{}", self.tcx.def_path_str(trait_ref), assoc_item.ident),
+                    Applicability::HasPlaceholders,
+                );
+            }
+        }
+    }
+
+    /// Adds an async-await specific note to the diagnostic when the future does not implement
+    /// an auto trait because of a captured type.
+    ///
+    /// ```ignore (diagnostic)
+    /// note: future does not implement `Qux` as this value is used across an await
+    ///   --> $DIR/issue-64130-3-other.rs:17:5
+    ///    |
+    /// LL |     let x = Foo;
+    ///    |         - has type `Foo`
+    /// LL |     baz().await;
+    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
+    /// LL | }
+    ///    | - `x` is later dropped here
+    /// ```
+    ///
+    /// When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
+    /// is "replaced" with a different message and a more specific error.
+    ///
+    /// ```ignore (diagnostic)
+    /// error: future cannot be sent between threads safely
+    ///   --> $DIR/issue-64130-2-send.rs:21:5
+    ///    |
+    /// LL | fn is_send<T: Send>(t: T) { }
+    ///    |    -------    ---- required by this bound in `is_send`
+    /// ...
+    /// LL |     is_send(bar());
+    ///    |     ^^^^^^^ future returned by `bar` is not send
+    ///    |
+    ///    = help: within `impl std::future::Future`, the trait `std::marker::Send` is not
+    ///            implemented for `Foo`
+    /// note: future is not send as this value is used across an await
+    ///   --> $DIR/issue-64130-2-send.rs:15:5
+    ///    |
+    /// LL |     let x = Foo;
+    ///    |         - has type `Foo`
+    /// LL |     baz().await;
+    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
+    /// LL | }
+    ///    | - `x` is later dropped here
+    /// ```
+    ///
+    /// Returns `true` if an async-await specific note was added to the diagnostic.
+    crate fn maybe_note_obligation_cause_for_async_await(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> bool {
+        debug!(
+            "maybe_note_obligation_cause_for_async_await: obligation.predicate={:?} \
+                obligation.cause.span={:?}",
+            obligation.predicate, obligation.cause.span
+        );
+        let source_map = self.tcx.sess.source_map();
+
+        // Attempt to detect an async-await error by looking at the obligation causes, looking
+        // for a generator to be present.
+        //
+        // When a future does not implement a trait because of a captured type in one of the
+        // generators somewhere in the call stack, then the result is a chain of obligations.
+        //
+        // Given a `async fn` A that calls a `async fn` B which captures a non-send type and that
+        // future is passed as an argument to a function C which requires a `Send` type, then the
+        // chain looks something like this:
+        //
+        // - `BuiltinDerivedObligation` with a generator witness (B)
+        // - `BuiltinDerivedObligation` with a generator (B)
+        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (B)
+        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
+        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
+        // - `BuiltinDerivedObligation` with a generator witness (A)
+        // - `BuiltinDerivedObligation` with a generator (A)
+        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (A)
+        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
+        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
+        // - `BindingObligation` with `impl_send (Send requirement)
+        //
+        // The first obligation in the chain is the most useful and has the generator that captured
+        // the type. The last generator has information about where the bound was introduced. At
+        // least one generator should be present for this diagnostic to be modified.
+        let (mut trait_ref, mut target_ty) = match obligation.predicate {
+            ty::Predicate::Trait(p) => {
+                (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty()))
+            }
+            _ => (None, None),
+        };
+        let mut generator = None;
+        let mut last_generator = None;
+        let mut next_code = Some(&obligation.cause.code);
+        while let Some(code) = next_code {
+            debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
+            match code {
+                ObligationCauseCode::BuiltinDerivedObligation(derived_obligation)
+                | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => {
+                    let ty = derived_obligation.parent_trait_ref.self_ty();
+                    debug!(
+                        "maybe_note_obligation_cause_for_async_await: \
+                            parent_trait_ref={:?} self_ty.kind={:?}",
+                        derived_obligation.parent_trait_ref, ty.kind
+                    );
+
+                    match ty.kind {
+                        ty::Generator(did, ..) => {
+                            generator = generator.or(Some(did));
+                            last_generator = Some(did);
+                        }
+                        ty::GeneratorWitness(..) => {}
+                        _ if generator.is_none() => {
+                            trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder());
+                            target_ty = Some(ty);
+                        }
+                        _ => {}
+                    }
+
+                    next_code = Some(derived_obligation.parent_code.as_ref());
+                }
+                _ => break,
+            }
+        }
+
+        // Only continue if a generator was found.
+        debug!(
+            "maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \
+                target_ty={:?}",
+            generator, trait_ref, target_ty
+        );
+        let (generator_did, trait_ref, target_ty) = match (generator, trait_ref, target_ty) {
+            (Some(generator_did), Some(trait_ref), Some(target_ty)) => {
+                (generator_did, trait_ref, target_ty)
+            }
+            _ => return false,
+        };
+
+        let span = self.tcx.def_span(generator_did);
+
+        // Do not ICE on closure typeck (#66868).
+        if self.tcx.hir().as_local_hir_id(generator_did).is_none() {
+            return false;
+        }
+
+        // Get the tables from the infcx if the generator is the function we are
+        // currently type-checking; otherwise, get them by performing a query.
+        // This is needed to avoid cycles.
+        let in_progress_tables = self.in_progress_tables.map(|t| t.borrow());
+        let generator_did_root = self.tcx.closure_base_def_id(generator_did);
+        debug!(
+            "maybe_note_obligation_cause_for_async_await: generator_did={:?} \
+             generator_did_root={:?} in_progress_tables.local_id_root={:?} span={:?}",
+            generator_did,
+            generator_did_root,
+            in_progress_tables.as_ref().map(|t| t.local_id_root),
+            span
+        );
+        let query_tables;
+        let tables: &TypeckTables<'tcx> = match &in_progress_tables {
+            Some(t) if t.local_id_root == Some(generator_did_root) => t,
+            _ => {
+                query_tables = self.tcx.typeck_tables_of(generator_did);
+                &query_tables
+            }
+        };
+
+        // Look for a type inside the generator interior that matches the target type to get
+        // a span.
+        let target_ty_erased = self.tcx.erase_regions(&target_ty);
+        let target_span = tables
+            .generator_interior_types
+            .iter()
+            .find(|ty::GeneratorInteriorTypeCause { ty, .. }| {
+                // Careful: the regions for types that appear in the
+                // generator interior are not generally known, so we
+                // want to erase them when comparing (and anyway,
+                // `Send` and other bounds are generally unaffected by
+                // the choice of region).  When erasing regions, we
+                // also have to erase late-bound regions. This is
+                // because the types that appear in the generator
+                // interior generally contain "bound regions" to
+                // represent regions that are part of the suspended
+                // generator frame. Bound regions are preserved by
+                // `erase_regions` and so we must also call
+                // `erase_late_bound_regions`.
+                let ty_erased = self.tcx.erase_late_bound_regions(&ty::Binder::bind(*ty));
+                let ty_erased = self.tcx.erase_regions(&ty_erased);
+                let eq = ty::TyS::same_type(ty_erased, target_ty_erased);
+                debug!(
+                    "maybe_note_obligation_cause_for_async_await: ty_erased={:?} \
+                        target_ty_erased={:?} eq={:?}",
+                    ty_erased, target_ty_erased, eq
+                );
+                eq
+            })
+            .map(|ty::GeneratorInteriorTypeCause { span, scope_span, expr, .. }| {
+                (span, source_map.span_to_snippet(*span), scope_span, expr)
+            });
+
+        debug!(
+            "maybe_note_obligation_cause_for_async_await: target_ty={:?} \
+                generator_interior_types={:?} target_span={:?}",
+            target_ty, tables.generator_interior_types, target_span
+        );
+        if let Some((target_span, Ok(snippet), scope_span, expr)) = target_span {
+            self.note_obligation_cause_for_async_await(
+                err,
+                *target_span,
+                scope_span,
+                *expr,
+                snippet,
+                generator_did,
+                last_generator,
+                trait_ref,
+                target_ty,
+                tables,
+                obligation,
+                next_code,
+            );
+            true
+        } else {
+            false
+        }
+    }
+
+    /// Unconditionally adds the diagnostic note described in
+    /// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
+    crate fn note_obligation_cause_for_async_await(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        target_span: Span,
+        scope_span: &Option<Span>,
+        expr: Option<hir::HirId>,
+        snippet: String,
+        first_generator: DefId,
+        last_generator: Option<DefId>,
+        trait_ref: ty::TraitRef<'_>,
+        target_ty: Ty<'tcx>,
+        tables: &ty::TypeckTables<'_>,
+        obligation: &PredicateObligation<'tcx>,
+        next_code: Option<&ObligationCauseCode<'tcx>>,
+    ) {
+        let source_map = self.tcx.sess.source_map();
+
+        let is_async_fn = self
+            .tcx
+            .parent(first_generator)
+            .map(|parent_did| self.tcx.asyncness(parent_did))
+            .map(|parent_asyncness| parent_asyncness == hir::IsAsync::Async)
+            .unwrap_or(false);
+        let is_async_move = self
+            .tcx
+            .hir()
+            .as_local_hir_id(first_generator)
+            .and_then(|hir_id| self.tcx.hir().maybe_body_owned_by(hir_id))
+            .map(|body_id| self.tcx.hir().body(body_id))
+            .and_then(|body| body.generator_kind())
+            .map(|generator_kind| match generator_kind {
+                hir::GeneratorKind::Async(..) => true,
+                _ => false,
+            })
+            .unwrap_or(false);
+        let await_or_yield = if is_async_fn || is_async_move { "await" } else { "yield" };
+
+        // Special case the primary error message when send or sync is the trait that was
+        // not implemented.
+        let is_send = self.tcx.is_diagnostic_item(sym::send_trait, trait_ref.def_id);
+        let is_sync = self.tcx.is_diagnostic_item(sym::sync_trait, trait_ref.def_id);
+        let hir = self.tcx.hir();
+        let trait_explanation = if is_send || is_sync {
+            let (trait_name, trait_verb) =
+                if is_send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
+
+            err.clear_code();
+            err.set_primary_message(format!(
+                "future cannot be {} between threads safely",
+                trait_verb
+            ));
+
+            let original_span = err.span.primary_span().unwrap();
+            let mut span = MultiSpan::from_span(original_span);
+
+            let message = if let Some(name) = last_generator
+                .and_then(|generator_did| self.tcx.parent(generator_did))
+                .and_then(|parent_did| hir.as_local_hir_id(parent_did))
+                .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
+            {
+                format!("future returned by `{}` is not {}", name, trait_name)
+            } else {
+                format!("future is not {}", trait_name)
+            };
+
+            span.push_span_label(original_span, message);
+            err.set_span(span);
+
+            format!("is not {}", trait_name)
+        } else {
+            format!("does not implement `{}`", trait_ref.print_only_trait_path())
+        };
+
+        // Look at the last interior type to get a span for the `.await`.
+        let await_span = tables.generator_interior_types.iter().map(|t| t.span).last().unwrap();
+        let mut span = MultiSpan::from_span(await_span);
+        span.push_span_label(
+            await_span,
+            format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet),
+        );
+
+        span.push_span_label(target_span, format!("has type `{}`", target_ty));
+
+        // If available, use the scope span to annotate the drop location.
+        if let Some(scope_span) = scope_span {
+            span.push_span_label(
+                source_map.end_point(*scope_span),
+                format!("`{}` is later dropped here", snippet),
+            );
+        }
+
+        err.span_note(
+            span,
+            &format!(
+                "future {} as this value is used across an {}",
+                trait_explanation, await_or_yield,
+            ),
+        );
+
+        if let Some(expr_id) = expr {
+            let expr = hir.expect_expr(expr_id);
+            let is_ref = tables.expr_adjustments(expr).iter().any(|adj| adj.is_region_borrow());
+            let parent = hir.get_parent_node(expr_id);
+            if let Some(hir::Node::Expr(e)) = hir.find(parent) {
+                let method_span = hir.span(parent);
+                if tables.is_method_call(e) && is_ref {
+                    err.span_help(
+                        method_span,
+                        "consider moving this method call into a `let` \
+                        binding to create a shorter lived borrow",
+                    );
+                }
+            }
+        }
+
+        // Add a note for the item obligation that remains - normally a note pointing to the
+        // bound that introduced the obligation (e.g. `T: Send`).
+        debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code);
+        self.note_obligation_cause_code(
+            err,
+            &obligation.predicate,
+            next_code.unwrap(),
+            &mut Vec::new(),
+        );
+    }
+
+    crate fn note_obligation_cause_code<T>(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        predicate: &T,
+        cause_code: &ObligationCauseCode<'tcx>,
+        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
+    ) where
+        T: fmt::Display,
+    {
+        let tcx = self.tcx;
+        match *cause_code {
+            ObligationCauseCode::ExprAssignable
+            | ObligationCauseCode::MatchExpressionArm { .. }
+            | ObligationCauseCode::Pattern { .. }
+            | ObligationCauseCode::IfExpression { .. }
+            | ObligationCauseCode::IfExpressionWithNoElse
+            | ObligationCauseCode::MainFunctionType
+            | ObligationCauseCode::StartFunctionType
+            | ObligationCauseCode::IntrinsicType
+            | ObligationCauseCode::MethodReceiver
+            | ObligationCauseCode::ReturnNoExpression
+            | ObligationCauseCode::MiscObligation => {}
+            ObligationCauseCode::SliceOrArrayElem => {
+                err.note("slice and array elements must have `Sized` type");
+            }
+            ObligationCauseCode::TupleElem => {
+                err.note("only the last element of a tuple may have a dynamically sized type");
+            }
+            ObligationCauseCode::ProjectionWf(data) => {
+                err.note(&format!("required so that the projection `{}` is well-formed", data,));
+            }
+            ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
+                err.note(&format!(
+                    "required so that reference `{}` does not outlive its referent",
+                    ref_ty,
+                ));
+            }
+            ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
+                err.note(&format!(
+                    "required so that the lifetime bound of `{}` for `{}` is satisfied",
+                    region, object_ty,
+                ));
+            }
+            ObligationCauseCode::ItemObligation(item_def_id) => {
+                let item_name = tcx.def_path_str(item_def_id);
+                let msg = format!("required by `{}`", item_name);
+
+                if let Some(sp) = tcx.hir().span_if_local(item_def_id) {
+                    let sp = tcx.sess.source_map().def_span(sp);
+                    err.span_label(sp, &msg);
+                } else {
+                    err.note(&msg);
+                }
+            }
+            ObligationCauseCode::BindingObligation(item_def_id, span) => {
+                let item_name = tcx.def_path_str(item_def_id);
+                let msg = format!("required by this bound in `{}`", item_name);
+                if let Some(ident) = tcx.opt_item_name(item_def_id) {
+                    err.span_label(ident.span, "");
+                }
+                if span != DUMMY_SP {
+                    err.span_label(span, &msg);
+                } else {
+                    err.note(&msg);
+                }
+            }
+            ObligationCauseCode::ObjectCastObligation(object_ty) => {
+                err.note(&format!(
+                    "required for the cast to the object type `{}`",
+                    self.ty_to_string(object_ty)
+                ));
+            }
+            ObligationCauseCode::Coercion { source: _, target } => {
+                err.note(&format!("required by cast to type `{}`", self.ty_to_string(target)));
+            }
+            ObligationCauseCode::RepeatVec(suggest_const_in_array_repeat_expressions) => {
+                err.note(
+                    "the `Copy` trait is required because the repeated element will be copied",
+                );
+                if suggest_const_in_array_repeat_expressions {
+                    err.note(
+                        "this array initializer can be evaluated at compile-time, for more \
+                         information, see issue \
+                         https://github.com/rust-lang/rust/issues/49147",
+                    );
+                    if tcx.sess.opts.unstable_features.is_nightly_build() {
+                        err.help(
+                            "add `#![feature(const_in_array_repeat_expressions)]` to the \
+                             crate attributes to enable",
+                        );
+                    }
+                }
+            }
+            ObligationCauseCode::VariableType(_) => {
+                err.note("all local variables must have a statically known size");
+                if !self.tcx.features().unsized_locals {
+                    err.help("unsized locals are gated as an unstable feature");
+                }
+            }
+            ObligationCauseCode::SizedArgumentType => {
+                err.note("all function arguments must have a statically known size");
+                if !self.tcx.features().unsized_locals {
+                    err.help("unsized locals are gated as an unstable feature");
+                }
+            }
+            ObligationCauseCode::SizedReturnType => {
+                err.note("the return type of a function must have a statically known size");
+            }
+            ObligationCauseCode::SizedYieldType => {
+                err.note("the yield type of a generator must have a statically known size");
+            }
+            ObligationCauseCode::AssignmentLhsSized => {
+                err.note("the left-hand-side of an assignment must have a statically known size");
+            }
+            ObligationCauseCode::TupleInitializerSized => {
+                err.note("tuples must have a statically known size to be initialized");
+            }
+            ObligationCauseCode::StructInitializerSized => {
+                err.note("structs must have a statically known size to be initialized");
+            }
+            ObligationCauseCode::FieldSized { adt_kind: ref item, last } => match *item {
+                AdtKind::Struct => {
+                    if last {
+                        err.note(
+                            "the last field of a packed struct may only have a \
+                             dynamically sized type if it does not need drop to be run",
+                        );
+                    } else {
+                        err.note(
+                            "only the last field of a struct may have a dynamically sized type",
+                        );
+                    }
+                }
+                AdtKind::Union => {
+                    err.note("no field of a union may have a dynamically sized type");
+                }
+                AdtKind::Enum => {
+                    err.note("no field of an enum variant may have a dynamically sized type");
+                }
+            },
+            ObligationCauseCode::ConstSized => {
+                err.note("constant expressions must have a statically known size");
+            }
+            ObligationCauseCode::ConstPatternStructural => {
+                err.note("constants used for pattern-matching must derive `PartialEq` and `Eq`");
+            }
+            ObligationCauseCode::SharedStatic => {
+                err.note("shared static variables must have a type that implements `Sync`");
+            }
+            ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
+                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
+                let ty = parent_trait_ref.skip_binder().self_ty();
+                err.note(&format!("required because it appears within the type `{}`", ty));
+                obligated_types.push(ty);
+
+                let parent_predicate = parent_trait_ref.to_predicate();
+                if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
+                    self.note_obligation_cause_code(
+                        err,
+                        &parent_predicate,
+                        &data.parent_code,
+                        obligated_types,
+                    );
+                }
+            }
+            ObligationCauseCode::ImplDerivedObligation(ref data) => {
+                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
+                err.note(&format!(
+                    "required because of the requirements on the impl of `{}` for `{}`",
+                    parent_trait_ref.print_only_trait_path(),
+                    parent_trait_ref.skip_binder().self_ty()
+                ));
+                let parent_predicate = parent_trait_ref.to_predicate();
+                self.note_obligation_cause_code(
+                    err,
+                    &parent_predicate,
+                    &data.parent_code,
+                    obligated_types,
+                );
+            }
+            ObligationCauseCode::CompareImplMethodObligation { .. } => {
+                err.note(&format!(
+                    "the requirement `{}` appears on the impl method \
+                     but not on the corresponding trait method",
+                    predicate
+                ));
+            }
+            ObligationCauseCode::CompareImplTypeObligation { .. } => {
+                err.note(&format!(
+                    "the requirement `{}` appears on the associated impl type \
+                     but not on the corresponding associated trait type",
+                    predicate
+                ));
+            }
+            ObligationCauseCode::ReturnType
+            | ObligationCauseCode::ReturnValue(_)
+            | ObligationCauseCode::BlockTailExpression(_) => (),
+            ObligationCauseCode::TrivialBound => {
+                err.help("see issue #48214");
+                if tcx.sess.opts.unstable_features.is_nightly_build() {
+                    err.help("add `#![feature(trivial_bounds)]` to the crate attributes to enable");
+                }
+            }
+            ObligationCauseCode::AssocTypeBound(ref data) => {
+                err.span_label(data.original, "associated type defined here");
+                if let Some(sp) = data.impl_span {
+                    err.span_label(sp, "in this `impl` item");
+                }
+                for sp in &data.bounds {
+                    err.span_label(*sp, "restricted in this bound");
+                }
+            }
+        }
+    }
+
+    crate fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
+        let current_limit = self.tcx.sess.recursion_limit.get();
+        let suggested_limit = current_limit * 2;
+        err.help(&format!(
+            "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
+            suggested_limit
+        ));
+    }
+}
+
+/// Suggest restricting a type param with a new bound.
+pub fn suggest_constraining_type_param(
+    generics: &hir::Generics<'_>,
+    err: &mut DiagnosticBuilder<'_>,
+    param_name: &str,
+    constraint: &str,
+    source_map: &SourceMap,
+    span: Span,
+) -> bool {
+    let restrict_msg = "consider further restricting this bound";
+    if let Some(param) =
+        generics.params.iter().filter(|p| p.name.ident().as_str() == param_name).next()
+    {
+        if param_name.starts_with("impl ") {
+            // `impl Trait` in argument:
+            // `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
+            err.span_suggestion(
+                param.span,
+                restrict_msg,
+                // `impl CurrentTrait + MissingTrait`
+                format!("{} + {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else if generics.where_clause.predicates.is_empty() && param.bounds.is_empty() {
+            // If there are no bounds whatsoever, suggest adding a constraint
+            // to the type parameter:
+            // `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
+            err.span_suggestion(
+                param.span,
+                "consider restricting this bound",
+                format!("{}: {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else if !generics.where_clause.predicates.is_empty() {
+            // There is a `where` clause, so suggest expanding it:
+            // `fn foo<T>(t: T) where T: Debug {}` →
+            // `fn foo<T>(t: T) where T: Debug, T: Trait {}`
+            err.span_suggestion(
+                generics.where_clause.span().unwrap().shrink_to_hi(),
+                &format!("consider further restricting type parameter `{}`", param_name),
+                format!(", {}: {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            // If there is no `where` clause lean towards constraining to the
+            // type parameter:
+            // `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
+            // `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
+            let sp = param.span.with_hi(span.hi());
+            let span = source_map.span_through_char(sp, ':');
+            if sp != param.span && sp != span {
+                // Only suggest if we have high certainty that the span
+                // covers the colon in `foo<T: Trait>`.
+                err.span_suggestion(
+                    span,
+                    restrict_msg,
+                    format!("{}: {} + ", param_name, constraint),
+                    Applicability::MachineApplicable,
+                );
+            } else {
+                err.span_label(
+                    param.span,
+                    &format!("consider adding a `where {}: {}` bound", param_name, constraint),
+                );
+            }
+        }
+        return true;
+    }
+    false
+}
+
+/// Collect all the returned expressions within the input expression.
+/// Used to point at the return spans when we want to suggest some change to them.
+struct ReturnsVisitor<'v>(Vec<&'v hir::Expr<'v>>);
+
+impl<'v> Visitor<'v> for ReturnsVisitor<'v> {
+    type Map = rustc::hir::map::Map<'v>;
+
+    fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<'_, Self::Map> {
+        hir::intravisit::NestedVisitorMap::None
+    }
+
+    fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
+        if let hir::ExprKind::Ret(Some(ex)) = ex.kind {
+            self.0.push(ex);
+        }
+        hir::intravisit::walk_expr(self, ex);
+    }
+
+    fn visit_body(&mut self, body: &'v hir::Body<'v>) {
+        if body.generator_kind().is_none() {
+            if let hir::ExprKind::Block(block, None) = body.value.kind {
+                if let Some(expr) = block.expr {
+                    self.0.push(expr);
+                }
+            }
+        }
+        hir::intravisit::walk_body(self, body);
+    }
+}
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 31de5409fc8..2e5da2b0382 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -155,8 +155,8 @@ pub struct ObligationCause<'tcx> {
     pub code: ObligationCauseCode<'tcx>,
 }
 
-impl<'tcx> ObligationCause<'tcx> {
-    pub fn span(&self, tcx: TyCtxt<'tcx>) -> Span {
+impl ObligationCause<'_> {
+    pub fn span(&self, tcx: TyCtxt<'_>) -> Span {
         match self.code {
             ObligationCauseCode::CompareImplMethodObligation { .. }
             | ObligationCauseCode::MainFunctionType
@@ -1171,6 +1171,17 @@ impl<'tcx> ObligationCause<'tcx> {
     }
 }
 
+impl ObligationCauseCode<'_> {
+    // Return the base obligation, ignoring derived obligations.
+    pub fn peel_derives(&self) -> &Self {
+        let mut base_cause = self;
+        while let BuiltinDerivedObligation(cause) | ImplDerivedObligation(cause) = base_cause {
+            base_cause = &cause.parent_code;
+        }
+        base_cause
+    }
+}
+
 impl<'tcx, N> Vtable<'tcx, N> {
     pub fn nested_obligations(self) -> Vec<N> {
         match self {
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index f7612874e05..217ca0ca3f6 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -244,9 +244,9 @@ impl<'tcx> ty::TyS<'tcx> {
             ty::FnPtr(_) => "fn pointer".into(),
             ty::Dynamic(ref inner, ..) => {
                 if let Some(principal) = inner.principal() {
-                    format!("trait `{}`", tcx.def_path_str(principal.def_id())).into()
+                    format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into()
                 } else {
-                    "trait".into()
+                    "trait object".into()
                 }
             }
             ty::Closure(..) => "closure".into(),
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index 272147e28a4..180ccb15977 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -414,6 +414,7 @@ E0742: include_str!("./error_codes/E0742.md"),
 E0743: include_str!("./error_codes/E0743.md"),
 E0744: include_str!("./error_codes/E0744.md"),
 E0745: include_str!("./error_codes/E0745.md"),
+E0746: include_str!("./error_codes/E0746.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
diff --git a/src/librustc_error_codes/error_codes/E0746.md b/src/librustc_error_codes/error_codes/E0746.md
new file mode 100644
index 00000000000..16b2722f0ea
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0746.md
@@ -0,0 +1,138 @@
+Return types cannot be `dyn Trait`s as they must be `Sized`.
+
+Erroneous code example:
+
+```compile_fail,E0277
+# // FIXME: after E0746 is in beta, change the above
+trait T {
+    fn bar(&self);
+}
+struct S(usize);
+impl T for S {
+    fn bar(&self) {}
+}
+
+// Having the trait `T` as return type is invalid because
+// unboxed trait objects do not have a statically known size:
+fn foo() -> dyn T {
+    S(42)
+}
+```
+
+To avoid the error there are a couple of options.
+
+If there is a single type involved, you can use [`impl Trait`]:
+
+```
+# trait T {
+#     fn bar(&self);
+# }
+# struct S(usize);
+# impl T for S {
+#     fn bar(&self) {}
+# }
+// The compiler will select `S(usize)` as the materialized return type of this
+// function, but callers will only know that the return type implements `T`.
+fn foo() -> impl T {
+    S(42)
+}
+```
+
+If there are multiple types involved, the only way you care to interact with
+them is through the trait's interface, and having to rely on dynamic dispatch
+is acceptable, then you can use [trait objects] with `Box`, or other container
+types like `Rc` or `Arc`:
+
+```
+# trait T {
+#     fn bar(&self);
+# }
+# struct S(usize);
+# impl T for S {
+#     fn bar(&self) {}
+# }
+struct O(&'static str);
+impl T for O {
+    fn bar(&self) {}
+}
+
+// This now returns a "trait object" and callers are only be able to access
+// associated items from `T`.
+fn foo(x: bool) -> Box<dyn T> {
+    if x {
+        Box::new(S(42))
+    } else {
+        Box::new(O("val"))
+    }
+}
+```
+
+Finally, if you wish to still be able to access the original type, you can
+create a new `enum` with a variant for each type:
+
+```
+# trait T {
+#     fn bar(&self);
+# }
+# struct S(usize);
+# impl T for S {
+#     fn bar(&self) {}
+# }
+# struct O(&'static str);
+# impl T for O {
+#     fn bar(&self) {}
+# }
+enum E {
+    S(S),
+    O(O),
+}
+
+// The caller can access the original types directly, but it needs to match on
+// the returned `enum E`.
+fn foo(x: bool) -> E {
+    if x {
+        E::S(S(42))
+    } else {
+        E::O(O("val"))
+    }
+}
+```
+
+You can even implement the `trait` on the returned `enum` so the callers
+*don't* have to match on the returned value to invoke the associated items:
+
+```
+# trait T {
+#     fn bar(&self);
+# }
+# struct S(usize);
+# impl T for S {
+#     fn bar(&self) {}
+# }
+# struct O(&'static str);
+# impl T for O {
+#     fn bar(&self) {}
+# }
+# enum E {
+#     S(S),
+#     O(O),
+# }
+impl T for E {
+    fn bar(&self) {
+        match self {
+            E::S(s) => s.bar(),
+            E::O(o) => o.bar(),
+        }
+    }
+}
+```
+
+If you decide to use trait objects, be aware that these rely on
+[dynamic dispatch], which has performance implications, as the compiler needs
+to emit code that will figure out which method to call *at runtime* instead of
+during compilation. Using trait objects we are trading flexibility for
+performance.
+
+[`impl Trait`]: https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits
+[trait objects]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types
+[dynamic dispatch]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#trait-objects-perform-dynamic-dispatch
diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index 550e3654d08..5c1d600c837 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -377,6 +377,13 @@ pub enum GenericBound<'hir> {
 }
 
 impl GenericBound<'_> {
+    pub fn trait_def_id(&self) -> Option<DefId> {
+        match self {
+            GenericBound::Trait(data, _) => Some(data.trait_ref.trait_def_id()),
+            _ => None,
+        }
+    }
+
     pub fn span(&self) -> Span {
         match self {
             &GenericBound::Trait(ref t, ..) => t.span,
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index cb676821fd4..0bcdf9ae3c1 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -580,10 +580,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                 let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
                 Ok((layout.size, layout.align.abi))
             }
-            Some(GlobalAlloc::Memory(alloc)) =>
-            // Need to duplicate the logic here, because the global allocations have
-            // different associated types than the interpreter-local ones.
-            {
+            Some(GlobalAlloc::Memory(alloc)) => {
+                // Need to duplicate the logic here, because the global allocations have
+                // different associated types than the interpreter-local ones.
                 Ok((alloc.size, alloc.align))
             }
             Some(GlobalAlloc::Function(_)) => bug!("We already checked function pointers above"),
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index b37eff3f406..d1c08da6cbe 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -684,16 +684,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                             let variant_index = variants_start
                                 .checked_add(variant_index_relative)
                                 .expect("oveflow computing absolute variant idx");
-                            assert!(
-                                (variant_index as usize)
-                                    < rval
-                                        .layout
-                                        .ty
-                                        .ty_adt_def()
-                                        .expect("tagged layout for non adt")
-                                        .variants
-                                        .len()
-                            );
+                            let variants_len = rval
+                                .layout
+                                .ty
+                                .ty_adt_def()
+                                .expect("tagged layout for non adt")
+                                .variants
+                                .len();
+                            assert!((variant_index as usize) < variants_len);
                             (u128::from(variant_index), VariantIdx::from_u32(variant_index))
                         } else {
                             (u128::from(dataful_variant.as_u32()), dataful_variant)
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 8888e3fd463..4f96cb69891 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -432,12 +432,11 @@ where
             // happens at run-time so that's okay.
             let align = match self.size_and_align_of(base.meta, field_layout)? {
                 Some((_, align)) => align,
-                None if offset == Size::ZERO =>
-                // An extern type at offset 0, we fall back to its static alignment.
-                // FIXME: Once we have made decisions for how to handle size and alignment
-                // of `extern type`, this should be adapted.  It is just a temporary hack
-                // to get some code to work that probably ought to work.
-                {
+                None if offset == Size::ZERO => {
+                    // An extern type at offset 0, we fall back to its static alignment.
+                    // FIXME: Once we have made decisions for how to handle size and alignment
+                    // of `extern type`, this should be adapted.  It is just a temporary hack
+                    // to get some code to work that probably ought to work.
                     field_layout.align.abi
                 }
                 None => bug!("Cannot compute offset for extern type field at non-0 offset"),
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index 6934ec0bdb6..aa2b3040a71 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -114,14 +114,11 @@ fn write_path(out: &mut String, path: &Vec<PathElem>) {
             ClosureVar(name) => write!(out, ".<closure-var({})>", name),
             TupleElem(idx) => write!(out, ".{}", idx),
             ArrayElem(idx) => write!(out, "[{}]", idx),
-            Deref =>
-            // This does not match Rust syntax, but it is more readable for long paths -- and
+            // `.<deref>` does not match Rust syntax, but it is more readable for long paths -- and
             // some of the other items here also are not Rust syntax.  Actually we can't
             // even use the usual syntax because we are just showing the projections,
             // not the root.
-            {
-                write!(out, ".<deref>")
-            }
+            Deref => write!(out, ".<deref>"),
             Tag => write!(out, ".<enum-tag>"),
             DynDowncast => write!(out, ".<dyn-downcast>"),
         }
@@ -206,9 +203,8 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
             ty::Adt(def, ..) if def.is_enum() => {
                 // we might be projecting *to* a variant, or to a field *in*a variant.
                 match layout.variants {
-                    layout::Variants::Single { index } =>
-                    // Inside a variant
-                    {
+                    layout::Variants::Single { index } => {
+                        // Inside a variant
                         PathElem::Field(def.variants[index].fields[field].ident.name)
                     }
                     _ => bug!(),
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 97420679754..a433ae8ed67 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -8,7 +8,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_feature::BUILTIN_ATTRIBUTES;
 use rustc_hir::def::Namespace::{self, *};
-use rustc_hir::def::{self, DefKind, NonMacroAttrKind};
+use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::SourceMap;
@@ -20,8 +20,9 @@ use syntax::util::lev_distance::find_best_match_for_name;
 
 use crate::imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
 use crate::path_names_to_string;
-use crate::VisResolutionError;
+use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind};
 use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot};
+use crate::{NameBinding, NameBindingKind, PrivacyError, VisResolutionError};
 use crate::{ParentScope, PathResult, ResolutionError, Resolver, Scope, ScopeSet, Segment};
 
 use rustc_error_codes::*;
@@ -802,6 +803,163 @@ impl<'a> Resolver<'a> {
         }
         false
     }
+
+    fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String {
+        let res = b.res();
+        if b.span.is_dummy() {
+            let add_built_in = match b.res() {
+                // These already contain the "built-in" prefix or look bad with it.
+                Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod => false,
+                _ => true,
+            };
+            let (built_in, from) = if from_prelude {
+                ("", " from prelude")
+            } else if b.is_extern_crate()
+                && !b.is_import()
+                && self.session.opts.externs.get(&ident.as_str()).is_some()
+            {
+                ("", " passed with `--extern`")
+            } else if add_built_in {
+                (" built-in", "")
+            } else {
+                ("", "")
+            };
+
+            let article = if built_in.is_empty() { res.article() } else { "a" };
+            format!(
+                "{a}{built_in} {thing}{from}",
+                a = article,
+                thing = res.descr(),
+                built_in = built_in,
+                from = from
+            )
+        } else {
+            let introduced = if b.is_import() { "imported" } else { "defined" };
+            format!("the {thing} {introduced} here", thing = res.descr(), introduced = introduced)
+        }
+    }
+
+    crate fn report_ambiguity_error(&self, ambiguity_error: &AmbiguityError<'_>) {
+        let AmbiguityError { kind, ident, b1, b2, misc1, misc2 } = *ambiguity_error;
+        let (b1, b2, misc1, misc2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
+            // We have to print the span-less alternative first, otherwise formatting looks bad.
+            (b2, b1, misc2, misc1, true)
+        } else {
+            (b1, b2, misc1, misc2, false)
+        };
+
+        let mut err = struct_span_err!(
+            self.session,
+            ident.span,
+            E0659,
+            "`{ident}` is ambiguous ({why})",
+            ident = ident,
+            why = kind.descr()
+        );
+        err.span_label(ident.span, "ambiguous name");
+
+        let mut could_refer_to = |b: &NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| {
+            let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude);
+            let note_msg = format!(
+                "`{ident}` could{also} refer to {what}",
+                ident = ident,
+                also = also,
+                what = what
+            );
+
+            let thing = b.res().descr();
+            let mut help_msgs = Vec::new();
+            if b.is_glob_import()
+                && (kind == AmbiguityKind::GlobVsGlob
+                    || kind == AmbiguityKind::GlobVsExpanded
+                    || kind == AmbiguityKind::GlobVsOuter && swapped != also.is_empty())
+            {
+                help_msgs.push(format!(
+                    "consider adding an explicit import of \
+                     `{ident}` to disambiguate",
+                    ident = ident
+                ))
+            }
+            if b.is_extern_crate() && ident.span.rust_2018() {
+                help_msgs.push(format!(
+                    "use `::{ident}` to refer to this {thing} unambiguously",
+                    ident = ident,
+                    thing = thing,
+                ))
+            }
+            if misc == AmbiguityErrorMisc::SuggestCrate {
+                help_msgs.push(format!(
+                    "use `crate::{ident}` to refer to this {thing} unambiguously",
+                    ident = ident,
+                    thing = thing,
+                ))
+            } else if misc == AmbiguityErrorMisc::SuggestSelf {
+                help_msgs.push(format!(
+                    "use `self::{ident}` to refer to this {thing} unambiguously",
+                    ident = ident,
+                    thing = thing,
+                ))
+            }
+
+            err.span_note(b.span, &note_msg);
+            for (i, help_msg) in help_msgs.iter().enumerate() {
+                let or = if i == 0 { "" } else { "or " };
+                err.help(&format!("{}{}", or, help_msg));
+            }
+        };
+
+        could_refer_to(b1, misc1, "");
+        could_refer_to(b2, misc2, " also");
+        err.emit();
+    }
+
+    crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) {
+        let PrivacyError { ident, binding, .. } = *privacy_error;
+        let session = &self.session;
+        let mk_struct_span_error = |is_constructor| {
+            let mut descr = binding.res().descr().to_string();
+            if is_constructor {
+                descr += " constructor";
+            }
+            if binding.is_import() {
+                descr += " import";
+            }
+
+            let mut err =
+                struct_span_err!(session, ident.span, E0603, "{} `{}` is private", descr, ident);
+
+            err.span_label(ident.span, &format!("this {} is private", descr));
+            err.span_note(
+                session.source_map().def_span(binding.span),
+                &format!("the {} `{}` is defined here", descr, ident),
+            );
+
+            err
+        };
+
+        let mut err = if let NameBindingKind::Res(
+            Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id),
+            _,
+        ) = binding.kind
+        {
+            let def_id = (&*self).parent(ctor_def_id).expect("no parent for a constructor");
+            if let Some(fields) = self.field_names.get(&def_id) {
+                let mut err = mk_struct_span_error(true);
+                let first_field = fields.first().expect("empty field list in the map");
+                err.span_label(
+                    fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)),
+                    "a constructor is private if any of the fields is private",
+                );
+                err
+            } else {
+                mk_struct_span_error(false)
+            }
+        } else {
+            mk_struct_span_error(false)
+        };
+
+        err.emit();
+    }
 }
 
 impl<'a, 'b> ImportResolver<'a, 'b> {
diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs
index 5bd10303162..9f459834175 100644
--- a/src/librustc_resolve/imports.rs
+++ b/src/librustc_resolve/imports.rs
@@ -319,7 +319,11 @@ impl<'a> Resolver<'a> {
                        // Remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`
                        !(self.last_import_segment && binding.is_extern_crate())
                         {
-                            self.privacy_errors.push(PrivacyError(path_span, ident, binding));
+                            self.privacy_errors.push(PrivacyError {
+                                ident,
+                                binding,
+                                dedup_span: path_span,
+                            });
                         }
 
                         Ok(binding)
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 8d5afb194a1..60a0049f5da 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -2,12 +2,9 @@
 //!
 //! Module structure of the crate is built here.
 //! Paths in macros, imports, expressions, types, patterns are resolved here.
-//! Label names are resolved here as well.
+//! Label and lifetime names are resolved here as well.
 //!
 //! Type-relative name resolution (methods, fields, associated items) happens in `librustc_typeck`.
-//! Lifetime names are resolved in `librustc/middle/resolve_lifetime.rs`.
-
-// ignore-tidy-filelength
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(bool_to_option)]
@@ -33,7 +30,7 @@ use rustc_data_structures::sync::Lrc;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_expand::base::SyntaxExtension;
 use rustc_hir::def::Namespace::*;
-use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PartialRes};
+use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::PrimTy::{self, Bool, Char, Float, Int, Str, Uint};
 use rustc_hir::{GlobMap, TraitMap};
@@ -604,7 +601,11 @@ impl<'a> NameBindingKind<'a> {
     }
 }
 
-struct PrivacyError<'a>(Span, Ident, &'a NameBinding<'a>);
+struct PrivacyError<'a> {
+    ident: Ident,
+    binding: &'a NameBinding<'a>,
+    dedup_span: Span,
+}
 
 struct UseError<'a> {
     err: DiagnosticBuilder<'a>,
@@ -2446,115 +2447,6 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String {
-        let res = b.res();
-        if b.span.is_dummy() {
-            let add_built_in = match b.res() {
-                // These already contain the "built-in" prefix or look bad with it.
-                Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod => false,
-                _ => true,
-            };
-            let (built_in, from) = if from_prelude {
-                ("", " from prelude")
-            } else if b.is_extern_crate()
-                && !b.is_import()
-                && self.session.opts.externs.get(&ident.as_str()).is_some()
-            {
-                ("", " passed with `--extern`")
-            } else if add_built_in {
-                (" built-in", "")
-            } else {
-                ("", "")
-            };
-
-            let article = if built_in.is_empty() { res.article() } else { "a" };
-            format!(
-                "{a}{built_in} {thing}{from}",
-                a = article,
-                thing = res.descr(),
-                built_in = built_in,
-                from = from
-            )
-        } else {
-            let introduced = if b.is_import() { "imported" } else { "defined" };
-            format!("the {thing} {introduced} here", thing = res.descr(), introduced = introduced)
-        }
-    }
-
-    fn report_ambiguity_error(&self, ambiguity_error: &AmbiguityError<'_>) {
-        let AmbiguityError { kind, ident, b1, b2, misc1, misc2 } = *ambiguity_error;
-        let (b1, b2, misc1, misc2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
-            // We have to print the span-less alternative first, otherwise formatting looks bad.
-            (b2, b1, misc2, misc1, true)
-        } else {
-            (b1, b2, misc1, misc2, false)
-        };
-
-        let mut err = struct_span_err!(
-            self.session,
-            ident.span,
-            E0659,
-            "`{ident}` is ambiguous ({why})",
-            ident = ident,
-            why = kind.descr()
-        );
-        err.span_label(ident.span, "ambiguous name");
-
-        let mut could_refer_to = |b: &NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| {
-            let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude);
-            let note_msg = format!(
-                "`{ident}` could{also} refer to {what}",
-                ident = ident,
-                also = also,
-                what = what
-            );
-
-            let thing = b.res().descr();
-            let mut help_msgs = Vec::new();
-            if b.is_glob_import()
-                && (kind == AmbiguityKind::GlobVsGlob
-                    || kind == AmbiguityKind::GlobVsExpanded
-                    || kind == AmbiguityKind::GlobVsOuter && swapped != also.is_empty())
-            {
-                help_msgs.push(format!(
-                    "consider adding an explicit import of \
-                     `{ident}` to disambiguate",
-                    ident = ident
-                ))
-            }
-            if b.is_extern_crate() && ident.span.rust_2018() {
-                help_msgs.push(format!(
-                    "use `::{ident}` to refer to this {thing} unambiguously",
-                    ident = ident,
-                    thing = thing,
-                ))
-            }
-            if misc == AmbiguityErrorMisc::SuggestCrate {
-                help_msgs.push(format!(
-                    "use `crate::{ident}` to refer to this {thing} unambiguously",
-                    ident = ident,
-                    thing = thing,
-                ))
-            } else if misc == AmbiguityErrorMisc::SuggestSelf {
-                help_msgs.push(format!(
-                    "use `self::{ident}` to refer to this {thing} unambiguously",
-                    ident = ident,
-                    thing = thing,
-                ))
-            }
-
-            err.span_note(b.span, &note_msg);
-            for (i, help_msg) in help_msgs.iter().enumerate() {
-                let or = if i == 0 { "" } else { "or " };
-                err.help(&format!("{}{}", or, help_msg));
-            }
-        };
-
-        could_refer_to(b1, misc1, "");
-        could_refer_to(b2, misc2, " also");
-        err.emit();
-    }
-
     fn report_errors(&mut self, krate: &Crate) {
         self.report_with_use_injections(krate);
 
@@ -2575,43 +2467,9 @@ impl<'a> Resolver<'a> {
         }
 
         let mut reported_spans = FxHashSet::default();
-        for &PrivacyError(dedup_span, ident, binding) in &self.privacy_errors {
-            if reported_spans.insert(dedup_span) {
-                let session = &self.session;
-                let mk_struct_span_error = |is_constructor| {
-                    struct_span_err!(
-                        session,
-                        ident.span,
-                        E0603,
-                        "{}{} `{}` is private",
-                        binding.res().descr(),
-                        if is_constructor { " constructor" } else { "" },
-                        ident.name,
-                    )
-                };
-
-                let mut err = if let NameBindingKind::Res(
-                    Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id),
-                    _,
-                ) = binding.kind
-                {
-                    let def_id = (&*self).parent(ctor_def_id).expect("no parent for a constructor");
-                    if let Some(fields) = self.field_names.get(&def_id) {
-                        let mut err = mk_struct_span_error(true);
-                        let first_field = fields.first().expect("empty field list in the map");
-                        err.span_label(
-                            fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)),
-                            "a constructor is private if any of the fields is private",
-                        );
-                        err
-                    } else {
-                        mk_struct_span_error(false)
-                    }
-                } else {
-                    mk_struct_span_error(false)
-                };
-
-                err.emit();
+        for error in &self.privacy_errors {
+            if reported_spans.insert(error.dedup_span) {
+                self.report_privacy_error(error);
             }
         }
     }
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 1afb703ca15..a32fbff7bfe 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -50,10 +50,12 @@
 //! sort of a minor point so I've opted to leave it for later -- after all,
 //! we may want to adjust precisely when coercions occur.
 
+use crate::astconv::AstConv;
 use crate::check::{FnCtxt, Needs};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::infer::{Coercion, InferOk, InferResult};
 use rustc::session::parse::feature_err;
+use rustc::traits::object_safety_violations;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode};
 use rustc::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
@@ -67,8 +69,8 @@ use rustc_error_codes::*;
 use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_span;
 use rustc_span::symbol::sym;
+use rustc_span::{self, Span};
 use rustc_target::spec::abi::Abi;
 use smallvec::{smallvec, SmallVec};
 use std::ops::Deref;
@@ -1222,6 +1224,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                 };
 
                 let mut err;
+                let mut unsized_return = false;
                 match cause.code {
                     ObligationCauseCode::ReturnNoExpression => {
                         err = struct_span_err!(
@@ -1243,6 +1246,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                             parent_id,
                             expression.map(|expr| (expr, blk_id)),
                         );
+                        if !fcx.tcx.features().unsized_locals {
+                            unsized_return = self.is_return_ty_unsized(fcx, blk_id);
+                        }
                     }
                     ObligationCauseCode::ReturnValue(id) => {
                         err = self.report_return_mismatched_types(
@@ -1254,6 +1260,10 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                             id,
                             None,
                         );
+                        if !fcx.tcx.features().unsized_locals {
+                            let id = fcx.tcx.hir().get_parent_node(id);
+                            unsized_return = self.is_return_ty_unsized(fcx, id);
+                        }
                     }
                     _ => {
                         err = fcx.report_mismatched_types(cause, expected, found, coercion_error);
@@ -1282,7 +1292,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                     .filter(|e| fcx.is_assign_to_bool(e, self.expected_ty()))
                     .is_some();
 
-                err.emit_unless(assign_to_bool);
+                err.emit_unless(assign_to_bool || unsized_return);
 
                 self.final_ty = Some(fcx.tcx.types.err);
             }
@@ -1302,7 +1312,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         let mut err = fcx.report_mismatched_types(cause, expected, found, ty_err);
 
         let mut pointing_at_return_type = false;
-        let mut return_sp = None;
+        let mut fn_output = None;
 
         // Verify that this is a tail expression of a function, otherwise the
         // label pointing out the cause for the type coercion will be wrong
@@ -1339,19 +1349,98 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                 );
             }
             if !pointing_at_return_type {
-                return_sp = Some(fn_decl.output.span()); // `impl Trait` return type
+                fn_output = Some(&fn_decl.output); // `impl Trait` return type
             }
         }
-        if let (Some(sp), Some(return_sp)) = (fcx.ret_coercion_span.borrow().as_ref(), return_sp) {
-            err.span_label(return_sp, "expected because this return type...");
-            err.span_label( *sp, format!(
-                "...is found to be `{}` here",
-                fcx.resolve_vars_with_obligations(expected),
-            ));
+        if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.borrow().as_ref(), fn_output) {
+            self.add_impl_trait_explanation(&mut err, fcx, expected, *sp, fn_output);
         }
         err
     }
 
+    fn add_impl_trait_explanation<'a>(
+        &self,
+        err: &mut DiagnosticBuilder<'a>,
+        fcx: &FnCtxt<'a, 'tcx>,
+        expected: Ty<'tcx>,
+        sp: Span,
+        fn_output: &hir::FunctionRetTy<'_>,
+    ) {
+        let return_sp = fn_output.span();
+        err.span_label(return_sp, "expected because this return type...");
+        err.span_label(
+            sp,
+            format!("...is found to be `{}` here", fcx.resolve_vars_with_obligations(expected)),
+        );
+        let impl_trait_msg = "for information on `impl Trait`, see \
+                <https://doc.rust-lang.org/book/ch10-02-traits.html\
+                #returning-types-that-implement-traits>";
+        let trait_obj_msg = "for information on trait objects, see \
+                <https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
+                #using-trait-objects-that-allow-for-values-of-different-types>";
+        err.note("to return `impl Trait`, all returned values must be of the same type");
+        err.note(impl_trait_msg);
+        let snippet = fcx
+            .tcx
+            .sess
+            .source_map()
+            .span_to_snippet(return_sp)
+            .unwrap_or_else(|_| "dyn Trait".to_string());
+        let mut snippet_iter = snippet.split_whitespace();
+        let has_impl = snippet_iter.next().map_or(false, |s| s == "impl");
+        // Only suggest `Box<dyn Trait>` if `Trait` in `impl Trait` is object safe.
+        let mut is_object_safe = false;
+        if let hir::FunctionRetTy::Return(ty) = fn_output {
+            // Get the return type.
+            if let hir::TyKind::Def(..) = ty.kind {
+                let ty = AstConv::ast_ty_to_ty(fcx, ty);
+                // Get the `impl Trait`'s `DefId`.
+                if let ty::Opaque(def_id, _) = ty.kind {
+                    let hir_id = fcx.tcx.hir().as_local_hir_id(def_id).unwrap();
+                    // Get the `impl Trait`'s `Item` so that we can get its trait bounds and
+                    // get the `Trait`'s `DefId`.
+                    if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) =
+                        fcx.tcx.hir().expect_item(hir_id).kind
+                    {
+                        // Are of this `impl Trait`'s traits object safe?
+                        is_object_safe = bounds.iter().all(|bound| {
+                            bound.trait_def_id().map_or(false, |def_id| {
+                                object_safety_violations(fcx.tcx, def_id).is_empty()
+                            })
+                        })
+                    }
+                }
+            }
+        };
+        if has_impl {
+            if is_object_safe {
+                err.help(&format!(
+                    "you can instead return a boxed trait object using `Box<dyn {}>`",
+                    &snippet[5..]
+                ));
+            } else {
+                err.help(&format!(
+                    "if the trait `{}` were object safe, you could return a boxed trait object",
+                    &snippet[5..]
+                ));
+            }
+            err.note(trait_obj_msg);
+        }
+        err.help("alternatively, create a new `enum` with a variant for each returned type");
+    }
+
+    fn is_return_ty_unsized(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool {
+        if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id) {
+            if let hir::FunctionRetTy::Return(ty) = fn_decl.output {
+                let ty = AstConv::ast_ty_to_ty(fcx, ty);
+                if let ty::Dynamic(..) = ty.kind {
+                    return true;
+                }
+            }
+        }
+        false
+    }
+
     pub fn complete<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> {
         if let Some(final_ty) = self.final_ty {
             final_ty
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index baf9ae1ac29..dff68b9986c 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -122,7 +122,7 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_hir::{ExprKind, GenericArg, HirIdMap, ItemKind, Node, PatKind, QPath};
+use rustc_hir::{ExprKind, GenericArg, HirIdMap, Item, ItemKind, Node, PatKind, QPath};
 use rustc_index::vec::Idx;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::{original_sp, DUMMY_SP};
@@ -2312,44 +2312,81 @@ fn check_packed(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) {
                 "type has conflicting packed and align representation hints"
             )
             .emit();
-        } else if check_packed_inner(tcx, def_id, &mut Vec::new()) {
-            struct_span_err!(
-                tcx.sess,
-                sp,
-                E0588,
-                "packed type cannot transitively contain a `[repr(align)]` type"
-            )
-            .emit();
+        } else {
+            if let Some(def_spans) = check_packed_inner(tcx, def_id, &mut vec![]) {
+                let mut err = struct_span_err!(
+                    tcx.sess,
+                    sp,
+                    E0588,
+                    "packed type cannot transitively contain a `#[repr(align)]` type"
+                );
+
+                let hir = tcx.hir();
+                if let Some(hir_id) = hir.as_local_hir_id(def_spans[0].0) {
+                    if let Node::Item(Item { ident, .. }) = hir.get(hir_id) {
+                        err.span_note(
+                            tcx.def_span(def_spans[0].0),
+                            &format!("`{}` has a `#[repr(align)]` attribute", ident),
+                        );
+                    }
+                }
+
+                if def_spans.len() > 2 {
+                    let mut first = true;
+                    for (adt_def, span) in def_spans.iter().skip(1).rev() {
+                        if let Some(hir_id) = hir.as_local_hir_id(*adt_def) {
+                            if let Node::Item(Item { ident, .. }) = hir.get(hir_id) {
+                                err.span_note(
+                                    *span,
+                                    &if first {
+                                        format!(
+                                            "`{}` contains a field of type `{}`",
+                                            tcx.type_of(def_id),
+                                            ident
+                                        )
+                                    } else {
+                                        format!("...which contains a field of type `{}`", ident)
+                                    },
+                                );
+                                first = false;
+                            }
+                        }
+                    }
+                }
+
+                err.emit();
+            }
         }
     }
 }
 
-fn check_packed_inner(tcx: TyCtxt<'_>, def_id: DefId, stack: &mut Vec<DefId>) -> bool {
-    let t = tcx.type_of(def_id);
-    if stack.contains(&def_id) {
-        debug!("check_packed_inner: {:?} is recursive", t);
-        return false;
-    }
-    if let ty::Adt(def, substs) = t.kind {
+fn check_packed_inner(
+    tcx: TyCtxt<'_>,
+    def_id: DefId,
+    stack: &mut Vec<DefId>,
+) -> Option<Vec<(DefId, Span)>> {
+    if let ty::Adt(def, substs) = tcx.type_of(def_id).kind {
         if def.is_struct() || def.is_union() {
-            if tcx.adt_def(def.did).repr.align.is_some() {
-                return true;
+            if def.repr.align.is_some() {
+                return Some(vec![(def.did, DUMMY_SP)]);
             }
-            // push struct def_id before checking fields
+
             stack.push(def_id);
             for field in &def.non_enum_variant().fields {
-                let f = field.ty(tcx, substs);
-                if let ty::Adt(def, _) = f.kind {
-                    if check_packed_inner(tcx, def.did, stack) {
-                        return true;
+                if let ty::Adt(def, _) = field.ty(tcx, substs).kind {
+                    if !stack.contains(&def.did) {
+                        if let Some(mut defs) = check_packed_inner(tcx, def.did, stack) {
+                            defs.push((def.did, field.ident.span));
+                            return Some(defs);
+                        }
                     }
                 }
             }
-            // only need to pop if not early out
             stack.pop();
         }
     }
-    false
+
+    None
 }
 
 /// Emit an error when encountering more or less than one variant in a transparent enum.
diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr
index 77d0885c38d..f59dbc26384 100644
--- a/src/test/ui/async-await/issue-64130-4-async-move.stderr
+++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr
@@ -1,8 +1,17 @@
 error: future cannot be sent between threads safely
   --> $DIR/issue-64130-4-async-move.rs:15:17
    |
-LL | pub fn foo() -> impl Future + Send {
-   |                 ^^^^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
+LL |   pub fn foo() -> impl Future + Send {
+   |                   ^^^^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
+...
+LL | /     async move {
+LL | |         match client.status() {
+LL | |             200 => {
+LL | |                 let _x = get().await;
+...  |
+LL | |         }
+LL | |     }
+   | |_____- this returned value is of type `impl std::future::Future`
    |
    = help: the trait `std::marker::Sync` is not implemented for `(dyn std::any::Any + std::marker::Send + 'static)`
 note: future is not `Send` as this value is used across an await
diff --git a/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr b/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr
index 303d83d3426..44e5c6a99f7 100644
--- a/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr
+++ b/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr
@@ -29,7 +29,7 @@ error[E0308]: mismatched types
   --> $DIR/coerce-expect-unsized-ascribed.rs:13:13
    |
 LL |     let _ = box { |x| (x as u8) }: Box<dyn Fn(i32) -> _>;
-   |             ^^^^^^^^^^^^^^^^^^^^^ expected trait `std::ops::Fn`, found closure
+   |             ^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::ops::Fn`, found closure
    |
    = note: expected struct `std::boxed::Box<dyn std::ops::Fn(i32) -> u8>`
               found struct `std::boxed::Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:13:19: 13:32]>`
@@ -38,7 +38,7 @@ error[E0308]: mismatched types
   --> $DIR/coerce-expect-unsized-ascribed.rs:14:13
    |
 LL |     let _ = box if true { false } else { true }: Box<dyn Debug>;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::fmt::Debug`, found `bool`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::fmt::Debug`, found `bool`
    |
    = note: expected struct `std::boxed::Box<dyn std::fmt::Debug>`
               found struct `std::boxed::Box<bool>`
@@ -47,7 +47,7 @@ error[E0308]: mismatched types
   --> $DIR/coerce-expect-unsized-ascribed.rs:15:13
    |
 LL |     let _ = box match true { true => 'a', false => 'b' }: Box<dyn Debug>;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::fmt::Debug`, found `char`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::fmt::Debug`, found `char`
    |
    = note: expected struct `std::boxed::Box<dyn std::fmt::Debug>`
               found struct `std::boxed::Box<char>`
@@ -83,7 +83,7 @@ error[E0308]: mismatched types
   --> $DIR/coerce-expect-unsized-ascribed.rs:21:13
    |
 LL |     let _ = &{ |x| (x as u8) }: &dyn Fn(i32) -> _;
-   |             ^^^^^^^^^^^^^^^^^^ expected trait `std::ops::Fn`, found closure
+   |             ^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::ops::Fn`, found closure
    |
    = note: expected reference `&dyn std::ops::Fn(i32) -> u8`
               found reference `&[closure@$DIR/coerce-expect-unsized-ascribed.rs:21:16: 21:29]`
@@ -92,7 +92,7 @@ error[E0308]: mismatched types
   --> $DIR/coerce-expect-unsized-ascribed.rs:22:13
    |
 LL |     let _ = &if true { false } else { true }: &dyn Debug;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::fmt::Debug`, found `bool`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::fmt::Debug`, found `bool`
    |
    = note: expected reference `&dyn std::fmt::Debug`
               found reference `&bool`
@@ -101,7 +101,7 @@ error[E0308]: mismatched types
   --> $DIR/coerce-expect-unsized-ascribed.rs:23:13
    |
 LL |     let _ = &match true { true => 'a', false => 'b' }: &dyn Debug;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::fmt::Debug`, found `char`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::fmt::Debug`, found `char`
    |
    = note: expected reference `&dyn std::fmt::Debug`
               found reference `&char`
@@ -119,7 +119,7 @@ error[E0308]: mismatched types
   --> $DIR/coerce-expect-unsized-ascribed.rs:26:13
    |
 LL |     let _ = Box::new(|x| (x as u8)): Box<dyn Fn(i32) -> _>;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::ops::Fn`, found closure
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::ops::Fn`, found closure
    |
    = note: expected struct `std::boxed::Box<dyn std::ops::Fn(i32) -> _>`
               found struct `std::boxed::Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:26:22: 26:35]>`
diff --git a/src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.stderr
index 5c37468130c..6e5afcdb8bb 100644
--- a/src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.stderr
+++ b/src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.stderr
@@ -3,6 +3,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_vec_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]>
    |                                           ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+...
+LL |     Vec::<A>::new()
+   |     --------------- this returned value is of type `std::vec::Vec<A>`
    |
    = note: required because of the requirements on the impl of `std::cmp::PartialEq<[B; 33]>` for `std::vec::Vec<A>`
    = note: the return type of a function must have a statically known size
@@ -12,6 +15,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_vec_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]>
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+...
+LL |     Vec::<A>::new()
+   |     --------------- this returned value is of type `std::vec::Vec<A>`
    |
    = note: required because of the requirements on the impl of `std::cmp::PartialEq<&'a [B; 33]>` for `std::vec::Vec<A>`
    = note: the return type of a function must have a statically known size
@@ -21,6 +27,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_vecdeque_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]>
    |                                                ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+...
+LL |     VecDeque::<A>::new()
+   |     -------------------- this returned value is of type `std::collections::VecDeque<A>`
    |
    = note: required because of the requirements on the impl of `std::cmp::PartialEq<[B; 33]>` for `std::collections::VecDeque<A>`
    = note: the return type of a function must have a statically known size
@@ -30,6 +39,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_vecdeque_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]>
    |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+...
+LL |     VecDeque::<A>::new()
+   |     -------------------- this returned value is of type `std::collections::VecDeque<A>`
    |
    = note: required because of the requirements on the impl of `std::cmp::PartialEq<&'a [B; 33]>` for `std::collections::VecDeque<A>`
    = note: the return type of a function must have a statically known size
@@ -39,6 +51,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_vecdeque_partial_eq_ref_mut_array<'a, A, B>() -> impl PartialEq<&'a mut [B; 33]>
    |                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+...
+LL |     VecDeque::<A>::new()
+   |     -------------------- this returned value is of type `std::collections::VecDeque<A>`
    |
    = note: required because of the requirements on the impl of `std::cmp::PartialEq<&'a mut [B; 33]>` for `std::collections::VecDeque<A>`
    = note: the return type of a function must have a statically known size
diff --git a/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr
index bfdff8e3bbe..4869f483634 100644
--- a/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr
+++ b/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr
@@ -11,6 +11,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_iterator() -> impl Iterator<Item = i32> {
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
@@ -28,6 +31,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_double_ended_iterator() -> impl DoubleEndedIterator {
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::iter::DoubleEndedIterator` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
@@ -45,6 +51,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_exact_size_iterator() -> impl ExactSizeIterator {
    |                                    ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::iter::ExactSizeIterator` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
@@ -62,6 +71,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_fused_iterator() -> impl FusedIterator {
    |                               ^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::iter::FusedIterator` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
@@ -79,6 +91,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_trusted_len() -> impl TrustedLen {
    |                            ^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::iter::TrustedLen` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
@@ -96,6 +111,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_clone() -> impl Clone {
    |                      ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::clone::Clone` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
@@ -113,6 +131,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_debug() -> impl Debug {
    |                      ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::fmt::Debug` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
diff --git a/src/test/ui/destructure-trait-ref.rs b/src/test/ui/destructure-trait-ref.rs
index fb92196b2bd..34e7cad935a 100644
--- a/src/test/ui/destructure-trait-ref.rs
+++ b/src/test/ui/destructure-trait-ref.rs
@@ -33,12 +33,10 @@ fn main() {
     //~^ ERROR mismatched types
     //~| expected trait object `dyn T`
     //~| found reference `&_`
-    //~| expected trait `T`, found reference
     let &&&x = &(&1isize as &dyn T);
     //~^ ERROR mismatched types
     //~| expected trait object `dyn T`
     //~| found reference `&_`
-    //~| expected trait `T`, found reference
     let box box x = box 1isize as Box<dyn T>;
     //~^ ERROR mismatched types
     //~| expected trait object `dyn T`
diff --git a/src/test/ui/destructure-trait-ref.stderr b/src/test/ui/destructure-trait-ref.stderr
index c78166f411d..f99bf2ffdc9 100644
--- a/src/test/ui/destructure-trait-ref.stderr
+++ b/src/test/ui/destructure-trait-ref.stderr
@@ -22,31 +22,31 @@ error[E0308]: mismatched types
 LL |     let &&x = &1isize as &dyn T;
    |          ^^
    |          |
-   |          expected trait `T`, found reference
+   |          expected trait object `dyn T`, found reference
    |          help: you can probably remove the explicit borrow: `x`
    |
    = note: expected trait object `dyn T`
                  found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/destructure-trait-ref.rs:37:11
+  --> $DIR/destructure-trait-ref.rs:36:11
    |
 LL |     let &&&x = &(&1isize as &dyn T);
    |           ^^
    |           |
-   |           expected trait `T`, found reference
+   |           expected trait object `dyn T`, found reference
    |           help: you can probably remove the explicit borrow: `x`
    |
    = note: expected trait object `dyn T`
                  found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/destructure-trait-ref.rs:42:13
+  --> $DIR/destructure-trait-ref.rs:40:13
    |
 LL |     let box box x = box 1isize as Box<dyn T>;
    |             ^^^^^   ------------------------ this expression has type `std::boxed::Box<dyn T>`
    |             |
-   |             expected trait `T`, found struct `std::boxed::Box`
+   |             expected trait object `dyn T`, found struct `std::boxed::Box`
    |
    = note: expected trait object `dyn T`
                     found struct `std::boxed::Box<_>`
diff --git a/src/test/ui/dst/dst-bad-assign-3.rs b/src/test/ui/dst/dst-bad-assign-3.rs
index e3b621b909a..d05b3937c99 100644
--- a/src/test/ui/dst/dst-bad-assign-3.rs
+++ b/src/test/ui/dst/dst-bad-assign-3.rs
@@ -32,7 +32,7 @@ pub fn main() {
     let z: Box<dyn ToBar> = Box::new(Bar1 {f: 36});
     f5.2 = Bar1 {f: 36};
     //~^ ERROR mismatched types
-    //~| expected trait `ToBar`, found struct `Bar1`
+    //~| expected trait object `dyn ToBar`, found struct `Bar1`
     //~| expected trait object `dyn ToBar`
     //~| found struct `Bar1`
     //~| ERROR the size for values of type
diff --git a/src/test/ui/dst/dst-bad-assign-3.stderr b/src/test/ui/dst/dst-bad-assign-3.stderr
index dc03f38e103..0b6f9df2d83 100644
--- a/src/test/ui/dst/dst-bad-assign-3.stderr
+++ b/src/test/ui/dst/dst-bad-assign-3.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/dst-bad-assign-3.rs:33:12
    |
 LL |     f5.2 = Bar1 {f: 36};
-   |            ^^^^^^^^^^^^ expected trait `ToBar`, found struct `Bar1`
+   |            ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1`
    |
    = note: expected trait object `dyn ToBar`
                     found struct `Bar1`
diff --git a/src/test/ui/dst/dst-bad-assign.rs b/src/test/ui/dst/dst-bad-assign.rs
index ed94242f5bf..496e01ae005 100644
--- a/src/test/ui/dst/dst-bad-assign.rs
+++ b/src/test/ui/dst/dst-bad-assign.rs
@@ -34,7 +34,7 @@ pub fn main() {
     let z: Box<dyn ToBar> = Box::new(Bar1 {f: 36});
     f5.ptr = Bar1 {f: 36};
     //~^ ERROR mismatched types
-    //~| expected trait `ToBar`, found struct `Bar1`
+    //~| expected trait object `dyn ToBar`, found struct `Bar1`
     //~| expected trait object `dyn ToBar`
     //~| found struct `Bar1`
     //~| ERROR the size for values of type
diff --git a/src/test/ui/dst/dst-bad-assign.stderr b/src/test/ui/dst/dst-bad-assign.stderr
index 8031f162482..434c460759f 100644
--- a/src/test/ui/dst/dst-bad-assign.stderr
+++ b/src/test/ui/dst/dst-bad-assign.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/dst-bad-assign.rs:35:14
    |
 LL |     f5.ptr = Bar1 {f: 36};
-   |              ^^^^^^^^^^^^ expected trait `ToBar`, found struct `Bar1`
+   |              ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1`
    |
    = note: expected trait object `dyn ToBar`
                     found struct `Bar1`
diff --git a/src/test/ui/error-codes/E0603.stderr b/src/test/ui/error-codes/E0603.stderr
index 444005e086f..724d04954a3 100644
--- a/src/test/ui/error-codes/E0603.stderr
+++ b/src/test/ui/error-codes/E0603.stderr
@@ -2,7 +2,13 @@ error[E0603]: constant `PRIVATE` is private
   --> $DIR/E0603.rs:6:17
    |
 LL |     SomeModule::PRIVATE;
-   |                 ^^^^^^^
+   |                 ^^^^^^^ this constant is private
+   |
+note: the constant `PRIVATE` is defined here
+  --> $DIR/E0603.rs:2:5
+   |
+LL |     const PRIVATE: u32 = 0x_a_bad_1dea_u32;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0746.fixed b/src/test/ui/error-codes/E0746.fixed
new file mode 100644
index 00000000000..ca8319aa020
--- /dev/null
+++ b/src/test/ui/error-codes/E0746.fixed
@@ -0,0 +1,18 @@
+// run-rustfix
+#![allow(dead_code)]
+struct Struct;
+trait Trait {}
+impl Trait for Struct {}
+impl Trait for u32 {}
+
+fn foo() -> impl Trait { Struct }
+//~^ ERROR E0746
+
+fn bar() -> impl Trait { //~ ERROR E0746
+    if true {
+        return 0;
+    }
+    42
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0746.rs b/src/test/ui/error-codes/E0746.rs
new file mode 100644
index 00000000000..bf5ba8fff56
--- /dev/null
+++ b/src/test/ui/error-codes/E0746.rs
@@ -0,0 +1,18 @@
+// run-rustfix
+#![allow(dead_code)]
+struct Struct;
+trait Trait {}
+impl Trait for Struct {}
+impl Trait for u32 {}
+
+fn foo() -> dyn Trait { Struct }
+//~^ ERROR E0746
+
+fn bar() -> dyn Trait { //~ ERROR E0746
+    if true {
+        return 0;
+    }
+    42
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0746.stderr b/src/test/ui/error-codes/E0746.stderr
new file mode 100644
index 00000000000..e7a8fd304ca
--- /dev/null
+++ b/src/test/ui/error-codes/E0746.stderr
@@ -0,0 +1,27 @@
+error[E0746]: return type cannot have an unboxed trait object
+  --> $DIR/E0746.rs:8:13
+   |
+LL | fn foo() -> dyn Trait { Struct }
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: return `impl Trait` instead, as all return paths are of type `Struct`, which implements `Trait`
+   |
+LL | fn foo() -> impl Trait { Struct }
+   |             ^^^^^^^^^^
+
+error[E0746]: return type cannot have an unboxed trait object
+  --> $DIR/E0746.rs:11:13
+   |
+LL | fn bar() -> dyn Trait {
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: return `impl Trait` instead, as all return paths are of type `{integer}`, which implements `Trait`
+   |
+LL | fn bar() -> impl Trait {
+   |             ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0746`.
diff --git a/src/test/ui/error-festival.stderr b/src/test/ui/error-festival.stderr
index 6b80d99b3af..9b69b373364 100644
--- a/src/test/ui/error-festival.stderr
+++ b/src/test/ui/error-festival.stderr
@@ -8,7 +8,13 @@ error[E0603]: constant `FOO` is private
   --> $DIR/error-festival.rs:22:10
    |
 LL |     foo::FOO;
-   |          ^^^
+   |          ^^^ this constant is private
+   |
+note: the constant `FOO` is defined here
+  --> $DIR/error-festival.rs:7:5
+   |
+LL |     const FOO: u32 = 0;
+   |     ^^^^^^^^^^^^^^^^^^^
 
 error[E0368]: binary assignment operation `+=` cannot be applied to type `&str`
   --> $DIR/error-festival.rs:12:5
diff --git a/src/test/ui/export-import.stderr b/src/test/ui/export-import.stderr
index e02952e0fe0..8160775ab58 100644
--- a/src/test/ui/export-import.stderr
+++ b/src/test/ui/export-import.stderr
@@ -2,7 +2,13 @@ error[E0603]: function `unexported` is private
   --> $DIR/export-import.rs:1:8
    |
 LL | use m::unexported;
-   |        ^^^^^^^^^^
+   |        ^^^^^^^^^^ this function is private
+   |
+note: the function `unexported` is defined here
+  --> $DIR/export-import.rs:7:5
+   |
+LL |     fn unexported() { }
+   |     ^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/export-tag-variant.stderr b/src/test/ui/export-tag-variant.stderr
index b5a2c12c436..f4537a2fb6f 100644
--- a/src/test/ui/export-tag-variant.stderr
+++ b/src/test/ui/export-tag-variant.stderr
@@ -2,7 +2,13 @@ error[E0603]: enum `Y` is private
   --> $DIR/export-tag-variant.rs:7:26
    |
 LL | fn main() { let z = foo::Y::Y1; }
-   |                          ^
+   |                          ^ this enum is private
+   |
+note: the enum `Y` is defined here
+  --> $DIR/export-tag-variant.rs:4:5
+   |
+LL |     enum Y { Y1 }
+   |     ^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/export.stderr b/src/test/ui/export.stderr
index a3668a502cd..107f531c09a 100644
--- a/src/test/ui/export.stderr
+++ b/src/test/ui/export.stderr
@@ -26,7 +26,13 @@ error[E0603]: function `z` is private
   --> $DIR/export.rs:10:18
    |
 LL | fn main() { foo::z(10); }
-   |                  ^
+   |                  ^ this function is private
+   |
+note: the function `z` is defined here
+  --> $DIR/export.rs:5:5
+   |
+LL |     fn z(y: isize) { log(debug, y); }
+   |     ^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/extern/extern-crate-visibility.rs b/src/test/ui/extern/extern-crate-visibility.rs
index e0a5cd5e98f..cda1227cc8e 100644
--- a/src/test/ui/extern/extern-crate-visibility.rs
+++ b/src/test/ui/extern/extern-crate-visibility.rs
@@ -3,10 +3,10 @@ mod foo {
 }
 
 // Check that private crates can be used from outside their modules, albeit with warnings
-use foo::core::cell; //~ ERROR crate `core` is private
+use foo::core::cell; //~ ERROR crate import `core` is private
 
 fn f() {
-    foo::core::cell::Cell::new(0); //~ ERROR crate `core` is private
+    foo::core::cell::Cell::new(0); //~ ERROR crate import `core` is private
 
     use foo::*;
     mod core {} // Check that private crates are not glob imported
diff --git a/src/test/ui/extern/extern-crate-visibility.stderr b/src/test/ui/extern/extern-crate-visibility.stderr
index 38c791ab832..d0c073d67a4 100644
--- a/src/test/ui/extern/extern-crate-visibility.stderr
+++ b/src/test/ui/extern/extern-crate-visibility.stderr
@@ -1,14 +1,26 @@
-error[E0603]: crate `core` is private
+error[E0603]: crate import `core` is private
   --> $DIR/extern-crate-visibility.rs:6:10
    |
 LL | use foo::core::cell;
-   |          ^^^^
+   |          ^^^^ this crate import is private
+   |
+note: the crate import `core` is defined here
+  --> $DIR/extern-crate-visibility.rs:2:5
+   |
+LL |     extern crate core;
+   |     ^^^^^^^^^^^^^^^^^^
 
-error[E0603]: crate `core` is private
+error[E0603]: crate import `core` is private
   --> $DIR/extern-crate-visibility.rs:9:10
    |
 LL |     foo::core::cell::Cell::new(0);
-   |          ^^^^
+   |          ^^^^ this crate import is private
+   |
+note: the crate import `core` is defined here
+  --> $DIR/extern-crate-visibility.rs:2:5
+   |
+LL |     extern crate core;
+   |     ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr
index 01799007693..ca2350ff757 100644
--- a/src/test/ui/generic-associated-types/impl_bounds.stderr
+++ b/src/test/ui/generic-associated-types/impl_bounds.stderr
@@ -38,7 +38,7 @@ LL |     type C where Self: Copy = String;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
    |
    = note: required because of the requirements on the impl of `std::marker::Copy` for `Fooy<T>`
-   = note: the requirement `Fooy<T>: std::marker::Copy` appears on the associated impl typebut not on the corresponding associated trait type
+   = note: the requirement `Fooy<T>: std::marker::Copy` appears on the associated impl type but not on the corresponding associated trait type
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/hygiene/privacy.stderr b/src/test/ui/hygiene/privacy.stderr
index 80fb4dd0f31..0649dc0ec58 100644
--- a/src/test/ui/hygiene/privacy.stderr
+++ b/src/test/ui/hygiene/privacy.stderr
@@ -2,7 +2,13 @@ error[E0603]: function `f` is private
   --> $DIR/privacy.rs:16:14
    |
 LL |         foo::f()
-   |              ^
+   |              ^ this function is private
+   |
+note: the function `f` is defined here
+  --> $DIR/privacy.rs:4:5
+   |
+LL |     fn f() {}
+   |     ^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs
new file mode 100644
index 00000000000..b70a51dc825
--- /dev/null
+++ b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs
@@ -0,0 +1,34 @@
+#![allow(bare_trait_objects)]
+struct Struct;
+trait Trait {}
+impl Trait for Struct {}
+impl Trait for u32 {}
+
+fn fuz() -> (usize, Trait) { (42, Struct) }
+//~^ ERROR E0277
+//~| ERROR E0308
+fn bar() -> (usize, dyn Trait) { (42, Struct) }
+//~^ ERROR E0277
+//~| ERROR E0308
+fn bap() -> Trait { Struct }
+//~^ ERROR E0746
+fn ban() -> dyn Trait { Struct }
+//~^ ERROR E0746
+fn bak() -> dyn Trait { unimplemented!() } //~ ERROR E0277
+// Suggest using `Box<dyn Trait>`
+fn bal() -> dyn Trait { //~ ERROR E0746
+    if true {
+        return Struct;
+    }
+    42
+}
+
+// Suggest using `impl Trait`
+fn bat() -> dyn Trait { //~ ERROR E0746
+    if true {
+        return 0;
+    }
+    42
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
new file mode 100644
index 00000000000..977a7ef0e02
--- /dev/null
+++ b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
@@ -0,0 +1,113 @@
+error[E0308]: mismatched types
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:35
+   |
+LL | fn fuz() -> (usize, Trait) { (42, Struct) }
+   |                                   ^^^^^^ expected trait object `dyn Trait`, found struct `Struct`
+   |
+   = note: expected trait object `(dyn Trait + 'static)`
+                    found struct `Struct`
+
+error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:13
+   |
+LL | fn fuz() -> (usize, Trait) { (42, Struct) }
+   |             ^^^^^^^^^^^^^^   ------------ this returned value is of type `(usize, (dyn Trait + 'static))`
+   |             |
+   |             doesn't have a size known at compile-time
+   |
+   = help: within `(usize, (dyn Trait + 'static))`, the trait `std::marker::Sized` is not implemented for `(dyn Trait + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `(usize, (dyn Trait + 'static))`
+   = note: the return type of a function must have a statically known size
+
+error[E0308]: mismatched types
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:39
+   |
+LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
+   |                                       ^^^^^^ expected trait object `dyn Trait`, found struct `Struct`
+   |
+   = note: expected trait object `(dyn Trait + 'static)`
+                    found struct `Struct`
+
+error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:13
+   |
+LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
+   |             ^^^^^^^^^^^^^^^^^^   ------------ this returned value is of type `(usize, (dyn Trait + 'static))`
+   |             |
+   |             doesn't have a size known at compile-time
+   |
+   = help: within `(usize, (dyn Trait + 'static))`, the trait `std::marker::Sized` is not implemented for `(dyn Trait + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `(usize, (dyn Trait + 'static))`
+   = note: the return type of a function must have a statically known size
+
+error[E0746]: return type cannot have an unboxed trait object
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:13:13
+   |
+LL | fn bap() -> Trait { Struct }
+   |             ^^^^^ doesn't have a size known at compile-time
+   |
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: return `impl Trait` instead, as all return paths are of type `Struct`, which implements `Trait`
+   |
+LL | fn bap() -> impl Trait { Struct }
+   |             ^^^^^^^^^^
+
+error[E0746]: return type cannot have an unboxed trait object
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13
+   |
+LL | fn ban() -> dyn Trait { Struct }
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: return `impl Trait` instead, as all return paths are of type `Struct`, which implements `Trait`
+   |
+LL | fn ban() -> impl Trait { Struct }
+   |             ^^^^^^^^^^
+
+error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:17:13
+   |
+LL | fn bak() -> dyn Trait { unimplemented!() }
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn Trait + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: the return type of a function must have a statically known size
+
+error[E0746]: return type cannot have an unboxed trait object
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13
+   |
+LL | fn bal() -> dyn Trait {
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = note: if all the returned values were of the same type you could use `impl Trait` as the return type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = note: you can create a new `enum` with a variant for each returned type
+help: return a boxed trait object instead
+   |
+LL | fn bal() -> Box<dyn Trait> {
+LL |     if true {
+LL |         return Box::new(Struct);
+LL |     }
+LL |     Box::new(42)
+   |
+
+error[E0746]: return type cannot have an unboxed trait object
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:27:13
+   |
+LL | fn bat() -> dyn Trait {
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: return `impl Trait` instead, as all return paths are of type `{integer}`, which implements `Trait`
+   |
+LL | fn bat() -> impl Trait {
+   |             ^^^^^^^^^^
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0277, E0308, E0746.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr
index e53524e58d6..9178358b60a 100644
--- a/src/test/ui/impl-trait/equality.stderr
+++ b/src/test/ui/impl-trait/equality.stderr
@@ -9,6 +9,12 @@ LL |         return 1_i32;
 LL |     }
 LL |     0_u32
    |     ^^^^^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: if the trait `Foo` were object safe, you could return a boxed trait object
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error[E0277]: cannot add `impl Foo` to `u32`
   --> $DIR/equality.rs:24:11
diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs
new file mode 100644
index 00000000000..ab3086c78b3
--- /dev/null
+++ b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs
@@ -0,0 +1,35 @@
+#![allow(bare_trait_objects)]
+trait NotObjectSafe {
+    fn foo() -> Self;
+}
+
+struct A;
+struct B;
+
+impl NotObjectSafe for A {
+    fn foo() -> Self {
+        A
+    }
+}
+
+impl NotObjectSafe for B {
+    fn foo() -> Self {
+        B
+    }
+}
+
+fn car() -> dyn NotObjectSafe { //~ ERROR the trait `NotObjectSafe` cannot be made into an object
+    if true {
+        return A;
+    }
+    B
+}
+
+fn cat() -> Box<dyn NotObjectSafe> { //~ ERROR the trait `NotObjectSafe` cannot be made into an
+    if true {
+        return Box::new(A);
+    }
+    Box::new(B)
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr
new file mode 100644
index 00000000000..0c8d267c134
--- /dev/null
+++ b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr
@@ -0,0 +1,21 @@
+error[E0038]: the trait `NotObjectSafe` cannot be made into an object
+  --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:21:1
+   |
+LL |     fn foo() -> Self;
+   |        --- associated function `foo` has no `self` parameter
+...
+LL | fn car() -> dyn NotObjectSafe {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
+
+error[E0038]: the trait `NotObjectSafe` cannot be made into an object
+  --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:28:1
+   |
+LL |     fn foo() -> Self;
+   |        --- associated function `foo` has no `self` parameter
+...
+LL | fn cat() -> Box<dyn NotObjectSafe> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs
new file mode 100644
index 00000000000..503515013b9
--- /dev/null
+++ b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs
@@ -0,0 +1,46 @@
+trait NotObjectSafe {
+    fn foo() -> Self;
+}
+
+trait ObjectSafe {
+    fn bar(&self);
+}
+
+struct A;
+struct B;
+
+impl NotObjectSafe for A {
+    fn foo() -> Self {
+        A
+    }
+}
+
+impl NotObjectSafe for B {
+    fn foo() -> Self {
+        B
+    }
+}
+
+impl ObjectSafe for A {
+    fn bar(&self) {}
+}
+
+impl ObjectSafe for B {
+    fn bar(&self) {}
+}
+
+fn can() -> impl NotObjectSafe {
+    if true {
+        return A;
+    }
+    B //~ ERROR mismatched types
+}
+
+fn cat() -> impl ObjectSafe {
+    if true {
+        return A;
+    }
+    B //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr
new file mode 100644
index 00000000000..dd4260fbe4f
--- /dev/null
+++ b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr
@@ -0,0 +1,39 @@
+error[E0308]: mismatched types
+  --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:36:5
+   |
+LL | fn can() -> impl NotObjectSafe {
+   |             ------------------ expected because this return type...
+LL |     if true {
+LL |         return A;
+   |                - ...is found to be `A` here
+LL |     }
+LL |     B
+   |     ^ expected struct `A`, found struct `B`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: if the trait `NotObjectSafe` were object safe, you could return a boxed trait object
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
+
+error[E0308]: mismatched types
+  --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:43:5
+   |
+LL | fn cat() -> impl ObjectSafe {
+   |             --------------- expected because this return type...
+LL |     if true {
+LL |         return A;
+   |                - ...is found to be `A` here
+LL |     }
+LL |     B
+   |     ^ expected struct `A`, found struct `B`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn ObjectSafe>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/import.stderr b/src/test/ui/import.stderr
index 6b320b198a0..5219ffacd15 100644
--- a/src/test/ui/import.stderr
+++ b/src/test/ui/import.stderr
@@ -13,11 +13,17 @@ error[E0432]: unresolved import `foo`
 LL |     use foo;
    |         ^^^ no `foo` in the root
 
-error[E0603]: unresolved item `foo` is private
+error[E0603]: unresolved item import `foo` is private
   --> $DIR/import.rs:15:10
    |
 LL |     zed::foo();
-   |          ^^^
+   |          ^^^ this unresolved item import is private
+   |
+note: the unresolved item import `foo` is defined here
+  --> $DIR/import.rs:10:9
+   |
+LL |     use foo;
+   |         ^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/imports/issue-55884-2.rs b/src/test/ui/imports/issue-55884-2.rs
index 1b4f652c9fc..75bb4206f97 100644
--- a/src/test/ui/imports/issue-55884-2.rs
+++ b/src/test/ui/imports/issue-55884-2.rs
@@ -9,6 +9,6 @@ mod parser {
     use ParseOptions;
 }
 
-pub use parser::ParseOptions; //~ ERROR struct `ParseOptions` is private
+pub use parser::ParseOptions; //~ ERROR struct import `ParseOptions` is private
 
 fn main() {}
diff --git a/src/test/ui/imports/issue-55884-2.stderr b/src/test/ui/imports/issue-55884-2.stderr
index d3b43783ee9..f16d2adb365 100644
--- a/src/test/ui/imports/issue-55884-2.stderr
+++ b/src/test/ui/imports/issue-55884-2.stderr
@@ -1,8 +1,14 @@
-error[E0603]: struct `ParseOptions` is private
+error[E0603]: struct import `ParseOptions` is private
   --> $DIR/issue-55884-2.rs:12:17
    |
 LL | pub use parser::ParseOptions;
-   |                 ^^^^^^^^^^^^
+   |                 ^^^^^^^^^^^^ this struct import is private
+   |
+note: the struct import `ParseOptions` is defined here
+  --> $DIR/issue-55884-2.rs:9:9
+   |
+LL |     use ParseOptions;
+   |         ^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/imports/reexports.stderr b/src/test/ui/imports/reexports.stderr
index 4388e2c276b..b173884080f 100644
--- a/src/test/ui/imports/reexports.stderr
+++ b/src/test/ui/imports/reexports.stderr
@@ -10,17 +10,29 @@ note: consider marking `foo` as `pub` in the imported module
 LL |         pub use super::foo;
    |                 ^^^^^^^^^^
 
-error[E0603]: module `foo` is private
+error[E0603]: module import `foo` is private
   --> $DIR/reexports.rs:33:15
    |
 LL |     use b::a::foo::S;
-   |               ^^^
+   |               ^^^ this module import is private
+   |
+note: the module import `foo` is defined here
+  --> $DIR/reexports.rs:21:17
+   |
+LL |         pub use super::foo; // This is OK since the value `foo` is visible enough.
+   |                 ^^^^^^^^^^
 
-error[E0603]: module `foo` is private
+error[E0603]: module import `foo` is private
   --> $DIR/reexports.rs:34:15
    |
 LL |     use b::b::foo::S as T;
-   |               ^^^
+   |               ^^^ this module import is private
+   |
+note: the module import `foo` is defined here
+  --> $DIR/reexports.rs:26:17
+   |
+LL |         pub use super::*; // This is also OK since the value `foo` is visible enough.
+   |                 ^^^^^^^^
 
 warning: glob import doesn't reexport anything because no candidate is public enough
   --> $DIR/reexports.rs:9:17
diff --git a/src/test/ui/imports/unresolved-imports-used.stderr b/src/test/ui/imports/unresolved-imports-used.stderr
index b341e8e0592..d7280d2583a 100644
--- a/src/test/ui/imports/unresolved-imports-used.stderr
+++ b/src/test/ui/imports/unresolved-imports-used.stderr
@@ -38,7 +38,13 @@ error[E0603]: function `quz` is private
   --> $DIR/unresolved-imports-used.rs:9:10
    |
 LL | use qux::quz;
-   |          ^^^
+   |          ^^^ this function is private
+   |
+note: the function `quz` is defined here
+  --> $DIR/unresolved-imports-used.rs:5:4
+   |
+LL |    fn quz() {}
+   |    ^^^^^^^^
 
 error: unused import: `qux::quy`
   --> $DIR/unresolved-imports-used.rs:16:5
diff --git a/src/test/ui/issues/issue-10545.stderr b/src/test/ui/issues/issue-10545.stderr
index 59d4fedcd2b..4ed7028c0a0 100644
--- a/src/test/ui/issues/issue-10545.stderr
+++ b/src/test/ui/issues/issue-10545.stderr
@@ -2,7 +2,13 @@ error[E0603]: struct `S` is private
   --> $DIR/issue-10545.rs:6:14
    |
 LL | fn foo(_: a::S) {
-   |              ^
+   |              ^ this struct is private
+   |
+note: the struct `S` is defined here
+  --> $DIR/issue-10545.rs:2:5
+   |
+LL |     struct S;
+   |     ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-11593.stderr b/src/test/ui/issues/issue-11593.stderr
index c3e4412b042..bfb4d31323b 100644
--- a/src/test/ui/issues/issue-11593.stderr
+++ b/src/test/ui/issues/issue-11593.stderr
@@ -2,7 +2,13 @@ error[E0603]: trait `Foo` is private
   --> $DIR/issue-11593.rs:7:24
    |
 LL | impl private_trait_xc::Foo for Bar {}
-   |                        ^^^
+   |                        ^^^ this trait is private
+   |
+note: the trait `Foo` is defined here
+  --> $DIR/auxiliary/private-trait-xc.rs:1:1
+   |
+LL | trait Foo {}
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-11680.stderr b/src/test/ui/issues/issue-11680.stderr
index 35cb2476992..898ac10f7d9 100644
--- a/src/test/ui/issues/issue-11680.stderr
+++ b/src/test/ui/issues/issue-11680.stderr
@@ -2,13 +2,25 @@ error[E0603]: enum `Foo` is private
   --> $DIR/issue-11680.rs:6:21
    |
 LL |     let _b = other::Foo::Bar(1);
-   |                     ^^^
+   |                     ^^^ this enum is private
+   |
+note: the enum `Foo` is defined here
+  --> $DIR/auxiliary/issue-11680.rs:1:1
+   |
+LL | enum Foo {
+   | ^^^^^^^^
 
 error[E0603]: enum `Foo` is private
   --> $DIR/issue-11680.rs:9:27
    |
 LL |     let _b = other::test::Foo::Bar(1);
-   |                           ^^^
+   |                           ^^^ this enum is private
+   |
+note: the enum `Foo` is defined here
+  --> $DIR/auxiliary/issue-11680.rs:6:5
+   |
+LL |     enum Foo {
+   |     ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-13407.stderr b/src/test/ui/issues/issue-13407.stderr
index b280de3158f..f211d623ab1 100644
--- a/src/test/ui/issues/issue-13407.stderr
+++ b/src/test/ui/issues/issue-13407.stderr
@@ -2,7 +2,13 @@ error[E0603]: unit struct `C` is private
   --> $DIR/issue-13407.rs:6:8
    |
 LL |     A::C = 1;
-   |        ^
+   |        ^ this unit struct is private
+   |
+note: the unit struct `C` is defined here
+  --> $DIR/issue-13407.rs:2:5
+   |
+LL |     struct C;
+   |     ^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-13407.rs:6:12
diff --git a/src/test/ui/issues/issue-13641.stderr b/src/test/ui/issues/issue-13641.stderr
index 8e5001e3b69..f90cb18b6fc 100644
--- a/src/test/ui/issues/issue-13641.stderr
+++ b/src/test/ui/issues/issue-13641.stderr
@@ -2,13 +2,25 @@ error[E0603]: struct `Foo` is private
   --> $DIR/issue-13641.rs:9:8
    |
 LL |     a::Foo::new();
-   |        ^^^
+   |        ^^^ this struct is private
+   |
+note: the struct `Foo` is defined here
+  --> $DIR/issue-13641.rs:2:5
+   |
+LL |     struct Foo;
+   |     ^^^^^^^^^^^
 
 error[E0603]: enum `Bar` is private
   --> $DIR/issue-13641.rs:11:8
    |
 LL |     a::Bar::new();
-   |        ^^^
+   |        ^^^ this enum is private
+   |
+note: the enum `Bar` is defined here
+  --> $DIR/issue-13641.rs:4:5
+   |
+LL |     enum Bar {}
+   |     ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-16725.stderr b/src/test/ui/issues/issue-16725.stderr
index 562ad940423..e0a1ca8a5ac 100644
--- a/src/test/ui/issues/issue-16725.stderr
+++ b/src/test/ui/issues/issue-16725.stderr
@@ -2,7 +2,13 @@ error[E0603]: function `bar` is private
   --> $DIR/issue-16725.rs:6:19
    |
 LL |     unsafe { foo::bar(); }
-   |                   ^^^
+   |                   ^^^ this function is private
+   |
+note: the function `bar` is defined here
+  --> $DIR/auxiliary/issue-16725.rs:2:5
+   |
+LL |     fn bar();
+   |     ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17718-const-privacy.stderr b/src/test/ui/issues/issue-17718-const-privacy.stderr
index 0b0de8a5259..07d825ba9cb 100644
--- a/src/test/ui/issues/issue-17718-const-privacy.stderr
+++ b/src/test/ui/issues/issue-17718-const-privacy.stderr
@@ -2,13 +2,25 @@ error[E0603]: constant `B` is private
   --> $DIR/issue-17718-const-privacy.rs:5:8
    |
 LL | use a::B;
-   |        ^
+   |        ^ this constant is private
+   |
+note: the constant `B` is defined here
+  --> $DIR/issue-17718-const-privacy.rs:13:5
+   |
+LL |     const B: usize = 3;
+   |     ^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: constant `BAR` is private
   --> $DIR/issue-17718-const-privacy.rs:8:5
    |
 LL |     BAR,
-   |     ^^^
+   |     ^^^ this constant is private
+   |
+note: the constant `BAR` is defined here
+  --> $DIR/auxiliary/issue-17718-const-privacy.rs:4:1
+   |
+LL | const BAR: usize = 3;
+   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-28388-2.stderr b/src/test/ui/issues/issue-28388-2.stderr
index 7bbe0bc5ff1..58bd775f295 100644
--- a/src/test/ui/issues/issue-28388-2.stderr
+++ b/src/test/ui/issues/issue-28388-2.stderr
@@ -2,7 +2,13 @@ error[E0603]: module `n` is private
   --> $DIR/issue-28388-2.rs:7:8
    |
 LL | use m::n::{};
-   |        ^
+   |        ^ this module is private
+   |
+note: the module `n` is defined here
+  --> $DIR/issue-28388-2.rs:4:5
+   |
+LL |     mod n {}
+   |     ^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-29161.stderr b/src/test/ui/issues/issue-29161.stderr
index d30fd28a4a3..1bfa211ef79 100644
--- a/src/test/ui/issues/issue-29161.stderr
+++ b/src/test/ui/issues/issue-29161.stderr
@@ -8,7 +8,13 @@ error[E0603]: struct `A` is private
   --> $DIR/issue-29161.rs:13:8
    |
 LL |     a::A::default();
-   |        ^
+   |        ^ this struct is private
+   |
+note: the struct `A` is defined here
+  --> $DIR/issue-29161.rs:2:5
+   |
+LL |     struct A;
+   |     ^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-38857.rs b/src/test/ui/issues/issue-38857.rs
index 81d881c100b..c0695f82165 100644
--- a/src/test/ui/issues/issue-38857.rs
+++ b/src/test/ui/issues/issue-38857.rs
@@ -1,3 +1,8 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
+
 fn main() {
     let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() };
     //~^ ERROR failed to resolve: could not find `imp` in `sys` [E0433]
diff --git a/src/test/ui/issues/issue-38857.stderr b/src/test/ui/issues/issue-38857.stderr
index 5762e3d6ac0..ba0f1336ff0 100644
--- a/src/test/ui/issues/issue-38857.stderr
+++ b/src/test/ui/issues/issue-38857.stderr
@@ -1,14 +1,20 @@
 error[E0433]: failed to resolve: could not find `imp` in `sys`
-  --> $DIR/issue-38857.rs:2:23
+  --> $DIR/issue-38857.rs:7:23
    |
 LL |     let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() };
    |                       ^^^ could not find `imp` in `sys`
 
 error[E0603]: module `sys` is private
-  --> $DIR/issue-38857.rs:2:18
+  --> $DIR/issue-38857.rs:7:18
    |
 LL |     let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() };
-   |                  ^^^
+   |                  ^^^ this module is private
+   |
+note: the module `sys` is defined here
+  --> $SRC_DIR/libstd/lib.rs:LL:COL
+   |
+LL | mod sys;
+   | ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-3993.stderr b/src/test/ui/issues/issue-3993.stderr
index ce594a3f9bb..3fa8ed4af28 100644
--- a/src/test/ui/issues/issue-3993.stderr
+++ b/src/test/ui/issues/issue-3993.stderr
@@ -2,7 +2,13 @@ error[E0603]: function `fly` is private
   --> $DIR/issue-3993.rs:1:10
    |
 LL | use zoo::fly;
-   |          ^^^
+   |          ^^^ this function is private
+   |
+note: the function `fly` is defined here
+  --> $DIR/issue-3993.rs:4:5
+   |
+LL |     fn fly() {}
+   |     ^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-58344.stderr b/src/test/ui/issues/issue-58344.stderr
index 427d03b679d..e0c196e518b 100644
--- a/src/test/ui/issues/issue-58344.stderr
+++ b/src/test/ui/issues/issue-58344.stderr
@@ -3,6 +3,9 @@ error[E0277]: the trait bound `impl Trait<<u32 as std::ops::Add>::Output>: Trait
    |
 LL | ) -> Either<impl Trait<<u32 as Add<u32>>::Output>, impl Trait<<u32 as Add<u32>>::Output>> {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<u32>` is not implemented for `impl Trait<<u32 as std::ops::Add>::Output>`
+...
+LL |     add_generic(value, 1u32)
+   |     ------------------------ this returned value is of type `Either<impl Trait<<u32 as std::ops::Add>::Output>, impl Trait<<u32 as std::ops::Add>::Output>>`
    |
    = note: the return type of a function must have a statically known size
 
@@ -11,6 +14,9 @@ error[E0277]: the trait bound `impl Trait<<u32 as std::ops::Add>::Output>: Trait
    |
 LL | ) -> Either<impl Trait<<u32 as Add<u32>>::Output>, impl Trait<<u32 as Add<u32>>::Output>> {
    |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<u32>` is not implemented for `impl Trait<<u32 as std::ops::Add>::Output>`
+...
+LL |     add_generic(value, 1u32)
+   |     ------------------------ this returned value is of type `Either<impl Trait<<u32 as std::ops::Add>::Output>, impl Trait<<u32 as std::ops::Add>::Output>>`
    |
    = note: the return type of a function must have a statically known size
 
diff --git a/src/test/ui/issues/issue-5883.stderr b/src/test/ui/issues/issue-5883.stderr
index c2de1d09550..d886ecc11d1 100644
--- a/src/test/ui/issues/issue-5883.stderr
+++ b/src/test/ui/issues/issue-5883.stderr
@@ -14,6 +14,9 @@ error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at
    |
 LL |     -> Struct {
    |        ^^^^^^ doesn't have a size known at compile-time
+LL |
+LL |     Struct { r: r }
+   |     --------------- this returned value is of type `Struct`
    |
    = help: within `Struct`, the trait `std::marker::Sized` is not implemented for `(dyn A + 'static)`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr
index 228582d0001..e43fb6d0edf 100644
--- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr
+++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr
@@ -3,6 +3,9 @@ error[E0277]: the trait bound `std::result::Result<(), _>: Future` is not satisf
    |
 LL | fn foo() -> impl Future<Item=(), Error=Box<dyn Error>> {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `std::result::Result<(), _>`
+LL |
+LL |     Ok(())
+   |     ------ this returned value is of type `std::result::Result<(), _>`
    |
    = note: the return type of a function must have a statically known size
 
diff --git a/src/test/ui/macros/macro-local-data-key-priv.stderr b/src/test/ui/macros/macro-local-data-key-priv.stderr
index 9b44421808e..72994d1652c 100644
--- a/src/test/ui/macros/macro-local-data-key-priv.stderr
+++ b/src/test/ui/macros/macro-local-data-key-priv.stderr
@@ -2,7 +2,14 @@ error[E0603]: constant `baz` is private
   --> $DIR/macro-local-data-key-priv.rs:8:10
    |
 LL |     bar::baz.with(|_| ());
-   |          ^^^
+   |          ^^^ this constant is private
+   |
+note: the constant `baz` is defined here
+  --> $DIR/macro-local-data-key-priv.rs:4:5
+   |
+LL |     thread_local!(static baz: f64 = 0.0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr
index 837e90d6ceb..77288f1bada 100644
--- a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr
+++ b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr
@@ -3,8 +3,12 @@ error[E0277]: the trait bound `(): T` is not satisfied
    |
 LL | fn should_ret_unit() -> impl T {
    |                         ^^^^^^ the trait `T` is not implemented for `()`
+LL |
+LL |     panic!()
+   |     -------- this returned value is of type `()`
    |
    = note: the return type of a function must have a statically known size
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/macro/pub-item-macro.stderr b/src/test/ui/parser/macro/pub-item-macro.stderr
index fa25161ab50..ae981ac4cbe 100644
--- a/src/test/ui/parser/macro/pub-item-macro.stderr
+++ b/src/test/ui/parser/macro/pub-item-macro.stderr
@@ -13,7 +13,16 @@ error[E0603]: static `x` is private
   --> $DIR/pub-item-macro.rs:17:23
    |
 LL |     let y: u32 = foo::x;
-   |                       ^
+   |                       ^ this static is private
+   |
+note: the static `x` is defined here
+  --> $DIR/pub-item-macro.rs:4:5
+   |
+LL |     static x: u32 = 0;
+   |     ^^^^^^^^^^^^^^^^^^
+...
+LL |     pub_x!();
+   |     --------- in this macro invocation
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
index 27b86007451..b663cccbeef 100644
--- a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
+++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
@@ -9,6 +9,12 @@ LL |         return 0i32;
 LL |     }
 LL |     1u32
    |     ^^^^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:13:16
@@ -21,6 +27,12 @@ LL |         return 0i32;
 LL |     } else {
 LL |         return 1u32;
    |                ^^^^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:22:9
@@ -33,6 +45,12 @@ LL |         return 0i32;
 LL |     } else {
 LL |         1u32
    |         ^^^^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error[E0308]: `if` and `else` have incompatible types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:31:9
@@ -57,6 +75,12 @@ LL |         0 => return 0i32,
    |                     ---- ...is found to be `i32` here
 LL |         _ => 1u32,
    |              ^^^^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:45:5
@@ -71,6 +95,12 @@ LL | |         1 => 1u32,
 LL | |         _ => 2u32,
 LL | |     }
    | |_____^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:59:13
@@ -83,6 +113,12 @@ LL |             return 0i32;
 ...
 LL |             1u32
    |             ^^^^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/privacy/decl-macro.stderr b/src/test/ui/privacy/decl-macro.stderr
index 230cf95de62..ae2e1b4b644 100644
--- a/src/test/ui/privacy/decl-macro.stderr
+++ b/src/test/ui/privacy/decl-macro.stderr
@@ -2,7 +2,13 @@ error[E0603]: macro `mac` is private
   --> $DIR/decl-macro.rs:8:8
    |
 LL |     m::mac!();
-   |        ^^^
+   |        ^^^ this macro is private
+   |
+note: the macro `mac` is defined here
+  --> $DIR/decl-macro.rs:4:5
+   |
+LL |     macro mac() {}
+   |     ^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/privacy/privacy-in-paths.stderr b/src/test/ui/privacy/privacy-in-paths.stderr
index 4b9faca0457..8860d8f15f7 100644
--- a/src/test/ui/privacy/privacy-in-paths.stderr
+++ b/src/test/ui/privacy/privacy-in-paths.stderr
@@ -2,19 +2,37 @@ error[E0603]: module `bar` is private
   --> $DIR/privacy-in-paths.rs:24:16
    |
 LL |         ::foo::bar::baz::f();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `bar` is defined here
+  --> $DIR/privacy-in-paths.rs:3:5
+   |
+LL |     mod bar {
+   |     ^^^^^^^
 
 error[E0603]: module `bar` is private
   --> $DIR/privacy-in-paths.rs:25:16
    |
 LL |         ::foo::bar::S::f();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `bar` is defined here
+  --> $DIR/privacy-in-paths.rs:3:5
+   |
+LL |     mod bar {
+   |     ^^^^^^^
 
 error[E0603]: trait `T` is private
   --> $DIR/privacy-in-paths.rs:26:23
    |
 LL |         <() as ::foo::T>::Assoc::f();
-   |                       ^
+   |                       ^ this trait is private
+   |
+note: the trait `T` is defined here
+  --> $DIR/privacy-in-paths.rs:8:5
+   |
+LL |     trait T {
+   |     ^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/privacy/privacy-ns2.stderr b/src/test/ui/privacy/privacy-ns2.stderr
index 2871573130a..8b12109b373 100644
--- a/src/test/ui/privacy/privacy-ns2.stderr
+++ b/src/test/ui/privacy/privacy-ns2.stderr
@@ -58,19 +58,37 @@ error[E0603]: trait `Bar` is private
   --> $DIR/privacy-ns2.rs:63:15
    |
 LL |     use foo3::Bar;
-   |               ^^^
+   |               ^^^ this trait is private
+   |
+note: the trait `Bar` is defined here
+  --> $DIR/privacy-ns2.rs:55:5
+   |
+LL |     trait Bar {
+   |     ^^^^^^^^^
 
 error[E0603]: trait `Bar` is private
   --> $DIR/privacy-ns2.rs:67:15
    |
 LL |     use foo3::Bar;
-   |               ^^^
+   |               ^^^ this trait is private
+   |
+note: the trait `Bar` is defined here
+  --> $DIR/privacy-ns2.rs:55:5
+   |
+LL |     trait Bar {
+   |     ^^^^^^^^^
 
 error[E0603]: trait `Bar` is private
   --> $DIR/privacy-ns2.rs:74:16
    |
 LL |     use foo3::{Bar,Baz};
-   |                ^^^
+   |                ^^^ this trait is private
+   |
+note: the trait `Bar` is defined here
+  --> $DIR/privacy-ns2.rs:55:5
+   |
+LL |     trait Bar {
+   |     ^^^^^^^^^
 
 error[E0107]: wrong number of const arguments: expected 0, found 1
   --> $DIR/privacy-ns2.rs:41:18
diff --git a/src/test/ui/privacy/privacy-ufcs.stderr b/src/test/ui/privacy/privacy-ufcs.stderr
index 6be14df89d2..08640b802a2 100644
--- a/src/test/ui/privacy/privacy-ufcs.stderr
+++ b/src/test/ui/privacy/privacy-ufcs.stderr
@@ -2,7 +2,13 @@ error[E0603]: trait `Bar` is private
   --> $DIR/privacy-ufcs.rs:12:20
    |
 LL |     <i32 as ::foo::Bar>::baz();
-   |                    ^^^
+   |                    ^^^ this trait is private
+   |
+note: the trait `Bar` is defined here
+  --> $DIR/privacy-ufcs.rs:4:5
+   |
+LL |     trait Bar {
+   |     ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/privacy/privacy1.stderr b/src/test/ui/privacy/privacy1.stderr
index 29f53cd0e35..215df0dc754 100644
--- a/src/test/ui/privacy/privacy1.stderr
+++ b/src/test/ui/privacy/privacy1.stderr
@@ -2,79 +2,157 @@ error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:132:18
    |
 LL |         use bar::baz::{foo, bar};
-   |                  ^^^
+   |                  ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:132:18
    |
 LL |         use bar::baz::{foo, bar};
-   |                  ^^^
+   |                  ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:141:18
    |
 LL |         use bar::baz;
-   |                  ^^^
+   |                  ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `i` is private
   --> $DIR/privacy1.rs:165:20
    |
 LL |     use self::foo::i::A;
-   |                    ^
+   |                    ^ this module is private
+   |
+note: the module `i` is defined here
+  --> $DIR/privacy1.rs:170:9
+   |
+LL |         mod i {
+   |         ^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:104:16
    |
 LL |         ::bar::baz::A::foo();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:105:16
    |
 LL |         ::bar::baz::A::bar();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:107:16
    |
 LL |         ::bar::baz::A.foo2();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:108:16
    |
 LL |         ::bar::baz::A.bar2();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: trait `B` is private
   --> $DIR/privacy1.rs:112:16
    |
 LL |         ::bar::B::foo();
-   |                ^
+   |                ^ this trait is private
+   |
+note: the trait `B` is defined here
+  --> $DIR/privacy1.rs:40:5
+   |
+LL |     trait B {
+   |     ^^^^^^^
 
 error[E0603]: function `epriv` is private
   --> $DIR/privacy1.rs:118:20
    |
 LL |             ::bar::epriv();
-   |                    ^^^^^
+   |                    ^^^^^ this function is private
+   |
+note: the function `epriv` is defined here
+  --> $DIR/privacy1.rs:65:9
+   |
+LL |         fn epriv();
+   |         ^^^^^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:127:16
    |
 LL |         ::bar::baz::foo();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:128:16
    |
 LL |         ::bar::baz::bar();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: trait `B` is private
   --> $DIR/privacy1.rs:157:17
    |
 LL |     impl ::bar::B for f32 { fn foo() -> f32 { 1.0 } }
-   |                 ^
+   |                 ^ this trait is private
+   |
+note: the trait `B` is defined here
+  --> $DIR/privacy1.rs:40:5
+   |
+LL |     trait B {
+   |     ^^^^^^^
 
 error[E0624]: method `bar` is private
   --> $DIR/privacy1.rs:77:9
diff --git a/src/test/ui/privacy/privacy2.stderr b/src/test/ui/privacy/privacy2.stderr
index 9f2359657bd..719dc27ccf4 100644
--- a/src/test/ui/privacy/privacy2.stderr
+++ b/src/test/ui/privacy/privacy2.stderr
@@ -4,11 +4,17 @@ error[E0432]: unresolved import `bar::foo`
 LL |     use bar::foo;
    |         ^^^^^^^^ no `foo` in `bar`
 
-error[E0603]: function `foo` is private
+error[E0603]: function import `foo` is private
   --> $DIR/privacy2.rs:23:20
    |
 LL |     use bar::glob::foo;
-   |                    ^^^
+   |                    ^^^ this function import is private
+   |
+note: the function import `foo` is defined here
+  --> $DIR/privacy2.rs:10:13
+   |
+LL |         use foo;
+   |             ^^^
 
 error: requires `sized` lang_item
 
diff --git a/src/test/ui/privacy/privacy4.stderr b/src/test/ui/privacy/privacy4.stderr
index e4a20f920a0..e34b2d5049b 100644
--- a/src/test/ui/privacy/privacy4.stderr
+++ b/src/test/ui/privacy/privacy4.stderr
@@ -2,7 +2,13 @@ error[E0603]: module `glob` is private
   --> $DIR/privacy4.rs:21:14
    |
 LL |     use bar::glob::gpriv;
-   |              ^^^^
+   |              ^^^^ this module is private
+   |
+note: the module `glob` is defined here
+  --> $DIR/privacy4.rs:13:5
+   |
+LL |     mod glob {
+   |     ^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/privacy/privacy5.stderr b/src/test/ui/privacy/privacy5.stderr
index 2ee83149b69..197a857cc3d 100644
--- a/src/test/ui/privacy/privacy5.stderr
+++ b/src/test/ui/privacy/privacy5.stderr
@@ -5,7 +5,13 @@ LL |     pub struct A(());
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     let a = a::A(());
-   |                ^
+   |                ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/privacy5.rs:6:5
+   |
+LL |     pub struct A(());
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:52:16
@@ -14,7 +20,13 @@ LL |     pub struct B(isize);
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     let b = a::B(2);
-   |                ^
+   |                ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:53:16
@@ -23,7 +35,13 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     let c = a::C(2, 3);
-   |                ^
+   |                ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:56:12
@@ -32,7 +50,13 @@ LL |     pub struct A(());
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     let a::A(()) = a;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/privacy5.rs:6:5
+   |
+LL |     pub struct A(());
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:57:12
@@ -41,7 +65,13 @@ LL |     pub struct A(());
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     let a::A(_) = a;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/privacy5.rs:6:5
+   |
+LL |     pub struct A(());
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:58:18
@@ -50,7 +80,13 @@ LL |     pub struct A(());
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     match a { a::A(()) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/privacy5.rs:6:5
+   |
+LL |     pub struct A(());
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:59:18
@@ -59,7 +95,13 @@ LL |     pub struct A(());
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     match a { a::A(_) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/privacy5.rs:6:5
+   |
+LL |     pub struct A(());
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:61:12
@@ -68,7 +110,13 @@ LL |     pub struct B(isize);
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     let a::B(_) = b;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:62:12
@@ -77,7 +125,13 @@ LL |     pub struct B(isize);
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     let a::B(_b) = b;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:63:18
@@ -86,7 +140,13 @@ LL |     pub struct B(isize);
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     match b { a::B(_) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:64:18
@@ -95,7 +155,13 @@ LL |     pub struct B(isize);
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     match b { a::B(_b) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:65:18
@@ -104,7 +170,13 @@ LL |     pub struct B(isize);
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     match b { a::B(1) => {} a::B(_) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:65:32
@@ -113,7 +185,13 @@ LL |     pub struct B(isize);
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     match b { a::B(1) => {} a::B(_) => {} }
-   |                                ^
+   |                                ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:68:12
@@ -122,7 +200,13 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     let a::C(_, _) = c;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:69:12
@@ -131,7 +215,13 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     let a::C(_a, _) = c;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:70:12
@@ -140,7 +230,13 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     let a::C(_, _b) = c;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:71:12
@@ -149,7 +245,13 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     let a::C(_a, _b) = c;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:72:18
@@ -158,7 +260,13 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     match c { a::C(_, _) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:73:18
@@ -167,7 +275,13 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     match c { a::C(_a, _) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:74:18
@@ -176,7 +290,13 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     match c { a::C(_, _b) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:75:18
@@ -185,7 +305,13 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     match c { a::C(_a, _b) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:83:17
@@ -194,7 +320,13 @@ LL |     pub struct A(());
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     let a2 = a::A;
-   |                 ^
+   |                 ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/privacy5.rs:6:5
+   |
+LL |     pub struct A(());
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:84:17
@@ -203,7 +335,13 @@ LL |     pub struct B(isize);
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     let b2 = a::B;
-   |                 ^
+   |                 ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:85:17
@@ -212,271 +350,421 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     let c2 = a::C;
-   |                 ^
+   |                 ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:90:20
    |
 LL |     let a = other::A(());
-   |                    ^
+   |                    ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
 LL | pub struct A(());
    |              -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1
+   |
+LL | pub struct A(());
+   | ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:91:20
    |
 LL |     let b = other::B(2);
-   |                    ^
+   |                    ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:92:20
    |
 LL |     let c = other::C(2, 3);
-   |                    ^
+   |                    ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:95:16
    |
 LL |     let other::A(()) = a;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
 LL | pub struct A(());
    |              -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1
+   |
+LL | pub struct A(());
+   | ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:96:16
    |
 LL |     let other::A(_) = a;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
 LL | pub struct A(());
    |              -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1
+   |
+LL | pub struct A(());
+   | ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:97:22
    |
 LL |     match a { other::A(()) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
 LL | pub struct A(());
    |              -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1
+   |
+LL | pub struct A(());
+   | ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:98:22
    |
 LL |     match a { other::A(_) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
 LL | pub struct A(());
    |              -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1
+   |
+LL | pub struct A(());
+   | ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:100:16
    |
 LL |     let other::B(_) = b;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:101:16
    |
 LL |     let other::B(_b) = b;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:102:22
    |
 LL |     match b { other::B(_) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:103:22
    |
 LL |     match b { other::B(_b) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:104:22
    |
 LL |     match b { other::B(1) => {}
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:105:16
    |
 LL |         other::B(_) => {} }
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:107:16
    |
 LL |     let other::C(_, _) = c;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:108:16
    |
 LL |     let other::C(_a, _) = c;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:109:16
    |
 LL |     let other::C(_, _b) = c;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:110:16
    |
 LL |     let other::C(_a, _b) = c;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:111:22
    |
 LL |     match c { other::C(_, _) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:112:22
    |
 LL |     match c { other::C(_a, _) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:113:22
    |
 LL |     match c { other::C(_, _b) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:114:22
    |
 LL |     match c { other::C(_a, _b) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:122:21
    |
 LL |     let a2 = other::A;
-   |                     ^
+   |                     ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
 LL | pub struct A(());
    |              -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1
+   |
+LL | pub struct A(());
+   | ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:123:21
    |
 LL |     let b2 = other::B;
-   |                     ^
+   |                     ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:124:21
    |
 LL |     let c2 = other::C;
-   |                     ^
+   |                     ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 48 previous errors
 
diff --git a/src/test/ui/privacy/private-item-simple.stderr b/src/test/ui/privacy/private-item-simple.stderr
index 0d5435e1c50..f51b74f6cb5 100644
--- a/src/test/ui/privacy/private-item-simple.stderr
+++ b/src/test/ui/privacy/private-item-simple.stderr
@@ -2,7 +2,13 @@ error[E0603]: function `f` is private
   --> $DIR/private-item-simple.rs:6:8
    |
 LL |     a::f();
-   |        ^
+   |        ^ this function is private
+   |
+note: the function `f` is defined here
+  --> $DIR/private-item-simple.rs:2:5
+   |
+LL |     fn f() {}
+   |     ^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/privacy/restricted/test.stderr b/src/test/ui/privacy/restricted/test.stderr
index e6a61fbefb0..aac444b8e3c 100644
--- a/src/test/ui/privacy/restricted/test.stderr
+++ b/src/test/ui/privacy/restricted/test.stderr
@@ -26,13 +26,25 @@ error[E0603]: struct `Crate` is private
   --> $DIR/test.rs:38:25
    |
 LL |     use pub_restricted::Crate;
-   |                         ^^^^^
+   |                         ^^^^^ this struct is private
+   |
+note: the struct `Crate` is defined here
+  --> $DIR/auxiliary/pub_restricted.rs:3:1
+   |
+LL | pub(crate) struct Crate;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: function `f` is private
   --> $DIR/test.rs:30:19
    |
 LL |     use foo::bar::f;
-   |                   ^
+   |                   ^ this function is private
+   |
+note: the function `f` is defined here
+  --> $DIR/test.rs:8:9
+   |
+LL |         pub(super) fn f() {}
+   |         ^^^^^^^^^^^^^^^^^
 
 error[E0616]: field `x` of struct `foo::bar::S` is private
   --> $DIR/test.rs:31:5
diff --git a/src/test/ui/proc-macro/disappearing-resolution.rs b/src/test/ui/proc-macro/disappearing-resolution.rs
index a01b8f302ca..50f04b1eae1 100644
--- a/src/test/ui/proc-macro/disappearing-resolution.rs
+++ b/src/test/ui/proc-macro/disappearing-resolution.rs
@@ -8,7 +8,7 @@ extern crate test_macros;
 mod m {
     use test_macros::Empty;
 }
-use m::Empty; //~ ERROR derive macro `Empty` is private
+use m::Empty; //~ ERROR derive macro import `Empty` is private
 
 // To resolve `empty_helper` we need to resolve `Empty`.
 // During initial resolution `use m::Empty` introduces no entries, so we proceed to `macro_use`,
diff --git a/src/test/ui/proc-macro/disappearing-resolution.stderr b/src/test/ui/proc-macro/disappearing-resolution.stderr
index a3377ef515f..3beaedf61d7 100644
--- a/src/test/ui/proc-macro/disappearing-resolution.stderr
+++ b/src/test/ui/proc-macro/disappearing-resolution.stderr
@@ -4,11 +4,17 @@ error: cannot find attribute `empty_helper` in this scope
 LL | #[empty_helper]
    |   ^^^^^^^^^^^^
 
-error[E0603]: derive macro `Empty` is private
+error[E0603]: derive macro import `Empty` is private
   --> $DIR/disappearing-resolution.rs:11:8
    |
 LL | use m::Empty;
-   |        ^^^^^
+   |        ^^^^^ this derive macro import is private
+   |
+note: the derive macro import `Empty` is defined here
+  --> $DIR/disappearing-resolution.rs:9:9
+   |
+LL |     use test_macros::Empty;
+   |         ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/reachable/unreachable-variant.stderr b/src/test/ui/reachable/unreachable-variant.stderr
index 276c77f9b42..c2e1d774e28 100644
--- a/src/test/ui/reachable/unreachable-variant.stderr
+++ b/src/test/ui/reachable/unreachable-variant.stderr
@@ -2,7 +2,13 @@ error[E0603]: module `super_sekrit` is private
   --> $DIR/unreachable-variant.rs:6:21
    |
 LL |     let _x = other::super_sekrit::sooper_sekrit::baz;
-   |                     ^^^^^^^^^^^^
+   |                     ^^^^^^^^^^^^ this module is private
+   |
+note: the module `super_sekrit` is defined here
+  --> $DIR/auxiliary/unreachable_variant.rs:1:1
+   |
+LL | mod super_sekrit {
+   | ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/repr/repr-packed-contains-align.rs b/src/test/ui/repr/repr-packed-contains-align.rs
index a3610345173..67d87eb5cd5 100644
--- a/src/test/ui/repr/repr-packed-contains-align.rs
+++ b/src/test/ui/repr/repr-packed-contains-align.rs
@@ -16,34 +16,34 @@ union UB {
 }
 
 #[repr(packed)]
-struct SC(SA); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+struct SC(SA); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
 
 #[repr(packed)]
-struct SD(SB); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+struct SD(SB); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
 
 #[repr(packed)]
-struct SE(UA); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+struct SE(UA); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
 
 #[repr(packed)]
-struct SF(UB); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+struct SF(UB); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
 
 #[repr(packed)]
-union UC { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+union UC { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
     a: UA
 }
 
 #[repr(packed)]
-union UD { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+union UD { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
     n: UB
 }
 
 #[repr(packed)]
-union UE { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+union UE { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
     a: SA
 }
 
 #[repr(packed)]
-union UF { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+union UF { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
     n: SB
 }
 
diff --git a/src/test/ui/repr/repr-packed-contains-align.stderr b/src/test/ui/repr/repr-packed-contains-align.stderr
index df001d6b5f2..32f9bb8bf33 100644
--- a/src/test/ui/repr/repr-packed-contains-align.stderr
+++ b/src/test/ui/repr/repr-packed-contains-align.stderr
@@ -1,58 +1,154 @@
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:19:1
    |
 LL | struct SC(SA);
    | ^^^^^^^^^^^^^^
+   |
+note: `SA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:5:1
+   |
+LL | struct SA(i32);
+   | ^^^^^^^^^^^^^^^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:22:1
    |
 LL | struct SD(SB);
    | ^^^^^^^^^^^^^^
+   |
+note: `SA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:5:1
+   |
+LL | struct SA(i32);
+   | ^^^^^^^^^^^^^^^
+note: `SD` contains a field of type `SB`
+  --> $DIR/repr-packed-contains-align.rs:22:11
+   |
+LL | struct SD(SB);
+   |           ^^
+note: ...which contains a field of type `SA`
+  --> $DIR/repr-packed-contains-align.rs:7:11
+   |
+LL | struct SB(SA);
+   |           ^^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:25:1
    |
 LL | struct SE(UA);
    | ^^^^^^^^^^^^^^
+   |
+note: `UA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:10:1
+   |
+LL | / union UA {
+LL | |     i: i32
+LL | | }
+   | |_^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:28:1
    |
 LL | struct SF(UB);
    | ^^^^^^^^^^^^^^
+   |
+note: `UA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:10:1
+   |
+LL | / union UA {
+LL | |     i: i32
+LL | | }
+   | |_^
+note: `SF` contains a field of type `UB`
+  --> $DIR/repr-packed-contains-align.rs:28:11
+   |
+LL | struct SF(UB);
+   |           ^^
+note: ...which contains a field of type `UA`
+  --> $DIR/repr-packed-contains-align.rs:15:5
+   |
+LL |     a: UA
+   |     ^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:31:1
    |
 LL | / union UC {
 LL | |     a: UA
 LL | | }
    | |_^
+   |
+note: `UA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:10:1
+   |
+LL | / union UA {
+LL | |     i: i32
+LL | | }
+   | |_^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:36:1
    |
 LL | / union UD {
 LL | |     n: UB
 LL | | }
    | |_^
+   |
+note: `UA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:10:1
+   |
+LL | / union UA {
+LL | |     i: i32
+LL | | }
+   | |_^
+note: `UD` contains a field of type `UB`
+  --> $DIR/repr-packed-contains-align.rs:37:5
+   |
+LL |     n: UB
+   |     ^
+note: ...which contains a field of type `UA`
+  --> $DIR/repr-packed-contains-align.rs:15:5
+   |
+LL |     a: UA
+   |     ^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:41:1
    |
 LL | / union UE {
 LL | |     a: SA
 LL | | }
    | |_^
+   |
+note: `SA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:5:1
+   |
+LL | struct SA(i32);
+   | ^^^^^^^^^^^^^^^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:46:1
    |
 LL | / union UF {
 LL | |     n: SB
 LL | | }
    | |_^
+   |
+note: `SA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:5:1
+   |
+LL | struct SA(i32);
+   | ^^^^^^^^^^^^^^^
+note: `UF` contains a field of type `SB`
+  --> $DIR/repr-packed-contains-align.rs:47:5
+   |
+LL |     n: SB
+   |     ^
+note: ...which contains a field of type `SA`
+  --> $DIR/repr-packed-contains-align.rs:7:11
+   |
+LL | struct SB(SA);
+   |           ^^
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr
index 688720e8cd3..08a1d790197 100644
--- a/src/test/ui/resolve/privacy-enum-ctor.stderr
+++ b/src/test/ui/resolve/privacy-enum-ctor.stderr
@@ -253,25 +253,49 @@ error[E0603]: enum `Z` is private
   --> $DIR/privacy-enum-ctor.rs:57:22
    |
 LL |     let _: Z = m::n::Z;
-   |                      ^
+   |                      ^ this enum is private
+   |
+note: the enum `Z` is defined here
+  --> $DIR/privacy-enum-ctor.rs:11:9
+   |
+LL |         pub(in m) enum Z {
+   |         ^^^^^^^^^^^^^^^^
 
 error[E0603]: enum `Z` is private
   --> $DIR/privacy-enum-ctor.rs:61:22
    |
 LL |     let _: Z = m::n::Z::Fn;
-   |                      ^
+   |                      ^ this enum is private
+   |
+note: the enum `Z` is defined here
+  --> $DIR/privacy-enum-ctor.rs:11:9
+   |
+LL |         pub(in m) enum Z {
+   |         ^^^^^^^^^^^^^^^^
 
 error[E0603]: enum `Z` is private
   --> $DIR/privacy-enum-ctor.rs:64:22
    |
 LL |     let _: Z = m::n::Z::Struct;
-   |                      ^
+   |                      ^ this enum is private
+   |
+note: the enum `Z` is defined here
+  --> $DIR/privacy-enum-ctor.rs:11:9
+   |
+LL |         pub(in m) enum Z {
+   |         ^^^^^^^^^^^^^^^^
 
 error[E0603]: enum `Z` is private
   --> $DIR/privacy-enum-ctor.rs:68:22
    |
 LL |     let _: Z = m::n::Z::Unit {};
-   |                      ^
+   |                      ^ this enum is private
+   |
+note: the enum `Z` is defined here
+  --> $DIR/privacy-enum-ctor.rs:11:9
+   |
+LL |         pub(in m) enum Z {
+   |         ^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/privacy-enum-ctor.rs:27:20
diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr
index f1a1de4d9c0..1673ec46ba4 100644
--- a/src/test/ui/resolve/privacy-struct-ctor.stderr
+++ b/src/test/ui/resolve/privacy-struct-ctor.stderr
@@ -45,7 +45,13 @@ LL |         pub(in m) struct Z(pub(in m::n) u8);
    |                            --------------- a constructor is private if any of the fields is private
 ...
 LL |         n::Z;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `Z` is defined here
+  --> $DIR/privacy-struct-ctor.rs:12:9
+   |
+LL |         pub(in m) struct Z(pub(in m::n) u8);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `S` is private
   --> $DIR/privacy-struct-ctor.rs:29:8
@@ -54,7 +60,13 @@ LL |     pub struct S(u8);
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     m::S;
-   |        ^
+   |        ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `S` is defined here
+  --> $DIR/privacy-struct-ctor.rs:6:5
+   |
+LL |     pub struct S(u8);
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `S` is private
   --> $DIR/privacy-struct-ctor.rs:31:19
@@ -63,7 +75,13 @@ LL |     pub struct S(u8);
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     let _: S = m::S(2);
-   |                   ^
+   |                   ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `S` is defined here
+  --> $DIR/privacy-struct-ctor.rs:6:5
+   |
+LL |     pub struct S(u8);
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `Z` is private
   --> $DIR/privacy-struct-ctor.rs:35:11
@@ -72,29 +90,47 @@ LL |         pub(in m) struct Z(pub(in m::n) u8);
    |                            --------------- a constructor is private if any of the fields is private
 ...
 LL |     m::n::Z;
-   |           ^
+   |           ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `Z` is defined here
+  --> $DIR/privacy-struct-ctor.rs:12:9
+   |
+LL |         pub(in m) struct Z(pub(in m::n) u8);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `S` is private
   --> $DIR/privacy-struct-ctor.rs:41:16
    |
 LL |     xcrate::m::S;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy-struct-ctor.rs:2:18
    |
 LL |     pub struct S(u8);
    |                  -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `S` is defined here
+  --> $DIR/auxiliary/privacy-struct-ctor.rs:2:5
+   |
+LL |     pub struct S(u8);
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `Z` is private
   --> $DIR/privacy-struct-ctor.rs:45:19
    |
 LL |     xcrate::m::n::Z;
-   |                   ^
+   |                   ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy-struct-ctor.rs:5:28
    |
 LL |         pub(in m) struct Z(pub(in m::n) u8);
    |                            --------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `Z` is defined here
+  --> $DIR/auxiliary/privacy-struct-ctor.rs:5:9
+   |
+LL |         pub(in m) struct Z(pub(in m::n) u8);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 10 previous errors
 
diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
index 944965a15e3..f992988c93f 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
@@ -14,18 +14,30 @@ error[E0603]: tuple struct constructor `TupleStruct` is private
   --> $DIR/struct.rs:23:32
    |
 LL |     let ts_explicit = structs::TupleStruct(640, 480);
-   |                                ^^^^^^^^^^^
+   |                                ^^^^^^^^^^^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/structs.rs:11:24
    |
 LL | pub struct TupleStruct(pub u16, pub u16);
    |                        ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `TupleStruct` is defined here
+  --> $DIR/auxiliary/structs.rs:11:1
+   |
+LL | pub struct TupleStruct(pub u16, pub u16);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: unit struct `UnitStruct` is private
   --> $DIR/struct.rs:32:32
    |
 LL |     let us_explicit = structs::UnitStruct;
-   |                                ^^^^^^^^^^
+   |                                ^^^^^^^^^^ this unit struct is private
+   |
+note: the unit struct `UnitStruct` is defined here
+  --> $DIR/auxiliary/structs.rs:8:1
+   |
+LL | pub struct UnitStruct;
+   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0639]: cannot create non-exhaustive struct using struct expression
   --> $DIR/struct.rs:7:14
diff --git a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr
index d9d6ea21b8b..2a438753a2c 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr
@@ -2,31 +2,61 @@ error[E0603]: tuple variant `Tuple` is private
   --> $DIR/variant.rs:11:48
    |
 LL |     let variant_tuple = NonExhaustiveVariants::Tuple(640);
-   |                                                ^^^^^
+   |                                                ^^^^^ this tuple variant is private
+   |
+note: the tuple variant `Tuple` is defined here
+  --> $DIR/auxiliary/variants.rs:5:23
+   |
+LL |     #[non_exhaustive] Tuple(u32),
+   |                       ^^^^^^^^^^
 
 error[E0603]: unit variant `Unit` is private
   --> $DIR/variant.rs:14:47
    |
 LL |     let variant_unit = NonExhaustiveVariants::Unit;
-   |                                               ^^^^
+   |                                               ^^^^ this unit variant is private
+   |
+note: the unit variant `Unit` is defined here
+  --> $DIR/auxiliary/variants.rs:4:23
+   |
+LL |     #[non_exhaustive] Unit,
+   |                       ^^^^
 
 error[E0603]: unit variant `Unit` is private
   --> $DIR/variant.rs:18:32
    |
 LL |         NonExhaustiveVariants::Unit => "",
-   |                                ^^^^
+   |                                ^^^^ this unit variant is private
+   |
+note: the unit variant `Unit` is defined here
+  --> $DIR/auxiliary/variants.rs:4:23
+   |
+LL |     #[non_exhaustive] Unit,
+   |                       ^^^^
 
 error[E0603]: tuple variant `Tuple` is private
   --> $DIR/variant.rs:20:32
    |
 LL |         NonExhaustiveVariants::Tuple(fe_tpl) => "",
-   |                                ^^^^^
+   |                                ^^^^^ this tuple variant is private
+   |
+note: the tuple variant `Tuple` is defined here
+  --> $DIR/auxiliary/variants.rs:5:23
+   |
+LL |     #[non_exhaustive] Tuple(u32),
+   |                       ^^^^^^^^^^
 
 error[E0603]: tuple variant `Tuple` is private
   --> $DIR/variant.rs:26:35
    |
 LL |     if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct {
-   |                                   ^^^^^
+   |                                   ^^^^^ this tuple variant is private
+   |
+note: the tuple variant `Tuple` is defined here
+  --> $DIR/auxiliary/variants.rs:5:23
+   |
+LL |     #[non_exhaustive] Tuple(u32),
+   |                       ^^^^^^^^^^
 
 error[E0639]: cannot create non-exhaustive variant using struct expression
   --> $DIR/variant.rs:8:26
diff --git a/src/test/ui/shadowed/shadowed-use-visibility.rs b/src/test/ui/shadowed/shadowed-use-visibility.rs
index 8185e82ee83..6b801972f41 100644
--- a/src/test/ui/shadowed/shadowed-use-visibility.rs
+++ b/src/test/ui/shadowed/shadowed-use-visibility.rs
@@ -6,11 +6,11 @@ mod foo {
 }
 
 mod bar {
-    use foo::bar::f as g; //~ ERROR module `bar` is private
+    use foo::bar::f as g; //~ ERROR module import `bar` is private
 
     use foo as f;
     pub use foo::*;
 }
 
-use bar::f::f; //~ ERROR module `f` is private
+use bar::f::f; //~ ERROR module import `f` is private
 fn main() {}
diff --git a/src/test/ui/shadowed/shadowed-use-visibility.stderr b/src/test/ui/shadowed/shadowed-use-visibility.stderr
index 7c66fdf60b1..cd8ec13794c 100644
--- a/src/test/ui/shadowed/shadowed-use-visibility.stderr
+++ b/src/test/ui/shadowed/shadowed-use-visibility.stderr
@@ -1,14 +1,26 @@
-error[E0603]: module `bar` is private
+error[E0603]: module import `bar` is private
   --> $DIR/shadowed-use-visibility.rs:9:14
    |
 LL |     use foo::bar::f as g;
-   |              ^^^
+   |              ^^^ this module import is private
+   |
+note: the module import `bar` is defined here
+  --> $DIR/shadowed-use-visibility.rs:4:9
+   |
+LL |     use foo as bar;
+   |         ^^^^^^^^^^
 
-error[E0603]: module `f` is private
+error[E0603]: module import `f` is private
   --> $DIR/shadowed-use-visibility.rs:15:10
    |
 LL | use bar::f::f;
-   |          ^
+   |          ^ this module import is private
+   |
+note: the module import `f` is defined here
+  --> $DIR/shadowed-use-visibility.rs:11:9
+   |
+LL |     use foo as f;
+   |         ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/stability-in-private-module.rs b/src/test/ui/stability-in-private-module.rs
index f12e9198b0d..1815897f17a 100644
--- a/src/test/ui/stability-in-private-module.rs
+++ b/src/test/ui/stability-in-private-module.rs
@@ -1,3 +1,8 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
+
 fn main() {
     let _ = std::thread::thread_info::current_thread();
     //~^ERROR module `thread_info` is private
diff --git a/src/test/ui/stability-in-private-module.stderr b/src/test/ui/stability-in-private-module.stderr
index c3edd62a15e..3a974164f94 100644
--- a/src/test/ui/stability-in-private-module.stderr
+++ b/src/test/ui/stability-in-private-module.stderr
@@ -1,8 +1,14 @@
 error[E0603]: module `thread_info` is private
-  --> $DIR/stability-in-private-module.rs:2:26
+  --> $DIR/stability-in-private-module.rs:7:26
    |
 LL |     let _ = std::thread::thread_info::current_thread();
-   |                          ^^^^^^^^^^^
+   |                          ^^^^^^^^^^^ this module is private
+   |
+note: the module `thread_info` is defined here
+  --> $SRC_DIR/libstd/thread/mod.rs:LL:COL
+   |
+LL | use crate::sys_common::thread_info;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/static/static-priv-by-default2.stderr b/src/test/ui/static/static-priv-by-default2.stderr
index 95bcf076335..f6cd40412dd 100644
--- a/src/test/ui/static/static-priv-by-default2.stderr
+++ b/src/test/ui/static/static-priv-by-default2.stderr
@@ -2,13 +2,25 @@ error[E0603]: static `private` is private
   --> $DIR/static-priv-by-default2.rs:15:30
    |
 LL |     use child::childs_child::private;
-   |                              ^^^^^^^
+   |                              ^^^^^^^ this static is private
+   |
+note: the static `private` is defined here
+  --> $DIR/static-priv-by-default2.rs:7:9
+   |
+LL |         static private: isize = 0;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: static `private` is private
   --> $DIR/static-priv-by-default2.rs:23:33
    |
 LL |     use static_priv_by_default::private;
-   |                                 ^^^^^^^
+   |                                 ^^^^^^^ this static is private
+   |
+note: the static `private` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:3:1
+   |
+LL | static private: isize = 0;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/structs/struct-variant-privacy-xc.stderr b/src/test/ui/structs/struct-variant-privacy-xc.stderr
index 39241b6b3fc..0203b7b5242 100644
--- a/src/test/ui/structs/struct-variant-privacy-xc.stderr
+++ b/src/test/ui/structs/struct-variant-privacy-xc.stderr
@@ -2,13 +2,25 @@ error[E0603]: enum `Bar` is private
   --> $DIR/struct-variant-privacy-xc.rs:4:33
    |
 LL | fn f(b: struct_variant_privacy::Bar) {
-   |                                 ^^^
+   |                                 ^^^ this enum is private
+   |
+note: the enum `Bar` is defined here
+  --> $DIR/auxiliary/struct_variant_privacy.rs:1:1
+   |
+LL | enum Bar {
+   | ^^^^^^^^
 
 error[E0603]: enum `Bar` is private
   --> $DIR/struct-variant-privacy-xc.rs:6:33
    |
 LL |         struct_variant_privacy::Bar::Baz { a: _a } => {}
-   |                                 ^^^
+   |                                 ^^^ this enum is private
+   |
+note: the enum `Bar` is defined here
+  --> $DIR/auxiliary/struct_variant_privacy.rs:1:1
+   |
+LL | enum Bar {
+   | ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/structs/struct-variant-privacy.stderr b/src/test/ui/structs/struct-variant-privacy.stderr
index 127a6501044..d1b603f9d46 100644
--- a/src/test/ui/structs/struct-variant-privacy.stderr
+++ b/src/test/ui/structs/struct-variant-privacy.stderr
@@ -2,13 +2,25 @@ error[E0603]: enum `Bar` is private
   --> $DIR/struct-variant-privacy.rs:7:14
    |
 LL | fn f(b: foo::Bar) {
-   |              ^^^
+   |              ^^^ this enum is private
+   |
+note: the enum `Bar` is defined here
+  --> $DIR/struct-variant-privacy.rs:2:5
+   |
+LL |     enum Bar {
+   |     ^^^^^^^^
 
 error[E0603]: enum `Bar` is private
   --> $DIR/struct-variant-privacy.rs:9:14
    |
 LL |         foo::Bar::Baz { a: _a } => {}
-   |              ^^^
+   |              ^^^ this enum is private
+   |
+note: the enum `Bar` is defined here
+  --> $DIR/struct-variant-privacy.rs:2:5
+   |
+LL |     enum Bar {
+   |     ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr
index d4c7c7c7452..9e8414f9c15 100644
--- a/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr
@@ -18,6 +18,8 @@ LL | type Underconstrained<T: std::fmt::Debug> = impl 'static;
 ...
 LL | fn underconstrained<U>(_: U) -> Underconstrained<U> {
    |                     - help: consider restricting this bound: `U: std::fmt::Debug`
+LL |     5u32
+   |     ---- this returned value is of type `u32`
    |
    = help: the trait `std::fmt::Debug` is not implemented for `U`
    = note: the return type of a function must have a statically known size
@@ -30,6 +32,8 @@ LL | type Underconstrained2<T: std::fmt::Debug> = impl 'static;
 ...
 LL | fn underconstrained2<U, V>(_: U, _: V) -> Underconstrained2<V> {
    |                         - help: consider restricting this bound: `V: std::fmt::Debug`
+LL |     5u32
+   |     ---- this returned value is of type `u32`
    |
    = help: the trait `std::fmt::Debug` is not implemented for `V`
    = note: the return type of a function must have a statically known size
diff --git a/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr b/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
index 14c09ade7dd..a656b20c23e 100644
--- a/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
+++ b/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL | fn ice(x: Box<dyn Iterator<Item=()>>) {
    |                                       - possibly return type missing here?
 LL |     *x
-   |     ^^ expected `()`, found trait `std::iter::Iterator`
+   |     ^^ expected `()`, found trait object `dyn std::iter::Iterator`
    |
    = note: expected unit type `()`
            found trait object `(dyn std::iter::Iterator<Item = ()> + 'static)`
diff --git a/src/test/ui/use/use-from-trait-xc.stderr b/src/test/ui/use/use-from-trait-xc.stderr
index f7438cce229..3f38a6cae7b 100644
--- a/src/test/ui/use/use-from-trait-xc.stderr
+++ b/src/test/ui/use/use-from-trait-xc.stderr
@@ -44,13 +44,25 @@ error[E0603]: struct `Foo` is private
   --> $DIR/use-from-trait-xc.rs:14:24
    |
 LL | use use_from_trait_xc::Foo::new;
-   |                        ^^^
+   |                        ^^^ this struct is private
+   |
+note: the struct `Foo` is defined here
+  --> $DIR/auxiliary/use-from-trait-xc.rs:9:1
+   |
+LL | struct Foo;
+   | ^^^^^^^^^^^
 
 error[E0603]: struct `Foo` is private
   --> $DIR/use-from-trait-xc.rs:17:24
    |
 LL | use use_from_trait_xc::Foo::C;
-   |                        ^^^
+   |                        ^^^ this struct is private
+   |
+note: the struct `Foo` is defined here
+  --> $DIR/auxiliary/use-from-trait-xc.rs:9:1
+   |
+LL | struct Foo;
+   | ^^^^^^^^^^^
 
 error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/use/use-mod/use-mod-3.stderr b/src/test/ui/use/use-mod/use-mod-3.stderr
index 0c800ec35e4..4852759286a 100644
--- a/src/test/ui/use/use-mod/use-mod-3.stderr
+++ b/src/test/ui/use/use-mod/use-mod-3.stderr
@@ -2,13 +2,25 @@ error[E0603]: module `bar` is private
   --> $DIR/use-mod-3.rs:1:10
    |
 LL | use foo::bar::{
-   |          ^^^
+   |          ^^^ this module is private
+   |
+note: the module `bar` is defined here
+  --> $DIR/use-mod-3.rs:9:5
+   |
+LL |     mod bar { pub type Bar = isize; }
+   |     ^^^^^^^
 
 error[E0603]: module `bar` is private
   --> $DIR/use-mod-3.rs:4:10
    |
 LL | use foo::bar::{
-   |          ^^^
+   |          ^^^ this module is private
+   |
+note: the module `bar` is defined here
+  --> $DIR/use-mod-3.rs:9:5
+   |
+LL |     mod bar { pub type Bar = isize; }
+   |     ^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/xcrate/xcrate-private-by-default.stderr b/src/test/ui/xcrate/xcrate-private-by-default.stderr
index da52b4249e3..842069d6135 100644
--- a/src/test/ui/xcrate/xcrate-private-by-default.stderr
+++ b/src/test/ui/xcrate/xcrate-private-by-default.stderr
@@ -2,61 +2,121 @@ error[E0603]: static `j` is private
   --> $DIR/xcrate-private-by-default.rs:23:29
    |
 LL |     static_priv_by_default::j;
-   |                             ^
+   |                             ^ this static is private
+   |
+note: the static `j` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:47:1
+   |
+LL | static j: isize = 0;
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: function `k` is private
   --> $DIR/xcrate-private-by-default.rs:25:29
    |
 LL |     static_priv_by_default::k;
-   |                             ^
+   |                             ^ this function is private
+   |
+note: the function `k` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:48:1
+   |
+LL | fn k() {}
+   | ^^^^^^
 
 error[E0603]: unit struct `l` is private
   --> $DIR/xcrate-private-by-default.rs:27:29
    |
 LL |     static_priv_by_default::l;
-   |                             ^
+   |                             ^ this unit struct is private
+   |
+note: the unit struct `l` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:49:1
+   |
+LL | struct l;
+   | ^^^^^^^^^
 
 error[E0603]: enum `m` is private
   --> $DIR/xcrate-private-by-default.rs:29:35
    |
 LL |     foo::<static_priv_by_default::m>();
-   |                                   ^
+   |                                   ^ this enum is private
+   |
+note: the enum `m` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:50:1
+   |
+LL | enum m {}
+   | ^^^^^^
 
 error[E0603]: type alias `n` is private
   --> $DIR/xcrate-private-by-default.rs:31:35
    |
 LL |     foo::<static_priv_by_default::n>();
-   |                                   ^
+   |                                   ^ this type alias is private
+   |
+note: the type alias `n` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:51:1
+   |
+LL | type n = isize;
+   | ^^^^^^^^^^^^^^^
 
 error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:35:29
    |
 LL |     static_priv_by_default::foo::a;
-   |                             ^^^
+   |                             ^^^ this module is private
+   |
+note: the module `foo` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:12:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:37:29
    |
 LL |     static_priv_by_default::foo::b;
-   |                             ^^^
+   |                             ^^^ this module is private
+   |
+note: the module `foo` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:12:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:39:29
    |
 LL |     static_priv_by_default::foo::c;
-   |                             ^^^
+   |                             ^^^ this module is private
+   |
+note: the module `foo` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:12:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:41:35
    |
 LL |     foo::<static_priv_by_default::foo::d>();
-   |                                   ^^^
+   |                                   ^^^ this module is private
+   |
+note: the module `foo` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:12:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:43:35
    |
 LL |     foo::<static_priv_by_default::foo::e>();
-   |                                   ^^^
+   |                                   ^^^ this module is private
+   |
+note: the module `foo` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:12:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error: aborting due to 10 previous errors
 
diff --git a/src/tools/clippy b/src/tools/clippy
-Subproject 920cdb59e1edf2c4cb2f266fa521f12c1b97a49
+Subproject a8d90f6a57925d204efb21b3f6d9726d6674f9b