about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndy Russell <arussell123@gmail.com>2019-01-09 14:11:00 -0500
committerAndy Russell <arussell123@gmail.com>2019-01-09 14:11:00 -0500
commit404ad50d148af4ea388861d1f9a45dd9f5c43ef7 (patch)
tree816e61b92ec36ccfdbb9dcb55c2915bcf34bb3e0
parentb8c8f0bdf62728198696cab7d00a8fdc3ee381d3 (diff)
downloadrust-404ad50d148af4ea388861d1f9a45dd9f5c43ef7.tar.gz
rust-404ad50d148af4ea388861d1f9a45dd9f5c43ef7.zip
clarify resolve typo suggestion
Include the kind of the binding that we're suggesting, and use a
structured suggestion.
-rw-r--r--src/librustc/hir/def.rs3
-rw-r--r--src/librustc_resolve/lib.rs86
-rw-r--r--src/librustc_resolve/macros.rs1
-rw-r--r--src/test/ui/associated-types/associated-types-eq-1.stderr2
-rw-r--r--src/test/ui/empty/empty-struct-braces-expr.stderr8
-rw-r--r--src/test/ui/empty/empty-struct-braces-pat-1.stderr2
-rw-r--r--src/test/ui/empty/empty-struct-braces-pat-2.stderr8
-rw-r--r--src/test/ui/empty/empty-struct-braces-pat-3.stderr4
-rw-r--r--src/test/ui/empty/empty-struct-tuple-pat.stderr2
-rw-r--r--src/test/ui/empty/empty-struct-unit-pat.stderr12
-rw-r--r--src/test/ui/error-codes/E0423.stderr2
-rw-r--r--src/test/ui/error-festival.stderr2
-rw-r--r--src/test/ui/glob-resolve1.stderr18
-rw-r--r--src/test/ui/issues/issue-10200.stderr2
-rw-r--r--src/test/ui/issues/issue-17546.stderr26
-rw-r--r--src/test/ui/issues/issue-31845.stderr2
-rw-r--r--src/test/ui/issues/issue-32004.stderr2
-rw-r--r--src/test/ui/issues/issue-32086.stderr4
-rw-r--r--src/test/ui/issues/issue-46332.stderr2
-rw-r--r--src/test/ui/issues/issue-7607-1.stderr2
-rw-r--r--src/test/ui/namespace/namespace-mix.stderr34
-rw-r--r--src/test/ui/pattern/pattern-error-continue.stderr2
-rw-r--r--src/test/ui/privacy/privacy-ns1.stderr24
-rw-r--r--src/test/ui/privacy/privacy-ns2.stderr12
-rw-r--r--src/test/ui/proc-macro/lints_in_proc_macros.rs3
-rw-r--r--src/test/ui/proc-macro/lints_in_proc_macros.stderr2
-rw-r--r--src/test/ui/proc-macro/parent-source-spans.stderr6
-rw-r--r--src/test/ui/resolve/issue-39226.stderr2
-rw-r--r--src/test/ui/resolve/issue-5035.stderr2
-rw-r--r--src/test/ui/resolve/levenshtein.stderr14
-rw-r--r--src/test/ui/resolve/privacy-enum-ctor.stderr34
-rw-r--r--src/test/ui/resolve/privacy-struct-ctor.stderr7
-rw-r--r--src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr10
-rw-r--r--src/test/ui/resolve/tuple-struct-alias.stderr4
-rw-r--r--src/test/ui/span/typo-suggestion.stderr2
-rw-r--r--src/test/ui/span/visibility-ty-params.stderr2
-rw-r--r--src/test/ui/structs/struct-fields-shorthand-unresolved.stderr2
-rw-r--r--src/test/ui/traits/trait-impl-for-module.stderr2
-rw-r--r--src/test/ui/ufcs/ufcs-partially-resolved.stderr14
-rw-r--r--src/test/ui/ui-testing-optout.stderr6
40 files changed, 249 insertions, 125 deletions
diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs
index 20ec620a281..9909c5d94ef 100644
--- a/src/librustc/hir/def.rs
+++ b/src/librustc/hir/def.rs
@@ -284,7 +284,7 @@ impl Def {
         }
     }
 
-    /// A human readable kind name
+    /// A human readable name for the def kind ("function", "module", etc.).
     pub fn kind_name(&self) -> &'static str {
         match *self {
             Def::Fn(..) => "function",
@@ -324,6 +324,7 @@ impl Def {
         }
     }
 
+    /// An English article for the def.
     pub fn article(&self) -> &'static str {
         match *self {
             Def::AssociatedTy(..) | Def::AssociatedConst(..) | Def::AssociatedExistential(..) |
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index cf949b62a63..a622a1a9a11 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -120,6 +120,16 @@ struct BindingError {
     target: BTreeSet<Span>,
 }
 
+struct TypoSuggestion {
+    candidate: Symbol,
+
+    /// The kind of the binding ("crate", "module", etc.)
+    kind: &'static str,
+
+    /// An appropriate article to refer to the binding ("a", "an", etc.)
+    article: &'static str,
+}
+
 impl PartialOrd for BindingError {
     fn partial_cmp(&self, other: &BindingError) -> Option<cmp::Ordering> {
         Some(self.cmp(other))
@@ -1448,7 +1458,7 @@ impl PrimitiveTypeTable {
     }
 }
 
-#[derive(Default, Clone)]
+#[derive(Debug, Default, Clone)]
 pub struct ExternPreludeEntry<'a> {
     extern_crate_item: Option<&'a NameBinding<'a>>,
     pub introduced_by_item: bool,
@@ -3277,8 +3287,19 @@ impl<'a> Resolver<'a> {
             let mut levenshtein_worked = false;
 
             // Try Levenshtein algorithm.
-            if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected, span) {
-                err.span_label(ident_span, format!("did you mean `{}`?", candidate));
+            let suggestion = this.lookup_typo_candidate(path, ns, is_expected, span);
+            if let Some(suggestion) = suggestion {
+                let msg = format!(
+                    "{} {} with a similar name exists",
+                    suggestion.article, suggestion.kind
+                );
+                err.span_suggestion_with_applicability(
+                    ident_span,
+                    &msg,
+                    suggestion.candidate.to_string(),
+                    Applicability::MaybeIncorrect,
+                );
+
                 levenshtein_worked = true;
             }
 
@@ -4162,19 +4183,25 @@ impl<'a> Resolver<'a> {
         None
     }
 
-    fn lookup_typo_candidate<FilterFn>(&mut self,
-                                       path: &[Segment],
-                                       ns: Namespace,
-                                       filter_fn: FilterFn,
-                                       span: Span)
-                                       -> Option<Symbol>
-        where FilterFn: Fn(Def) -> bool
+    fn lookup_typo_candidate<FilterFn>(
+        &mut self,
+        path: &[Segment],
+        ns: Namespace,
+        filter_fn: FilterFn,
+        span: Span,
+    ) -> Option<TypoSuggestion>
+    where
+        FilterFn: Fn(Def) -> bool,
     {
-        let add_module_candidates = |module: Module, names: &mut Vec<Name>| {
+        let add_module_candidates = |module: Module, names: &mut Vec<TypoSuggestion>| {
             for (&(ident, _), resolution) in module.resolutions.borrow().iter() {
                 if let Some(binding) = resolution.borrow().binding {
                     if filter_fn(binding.def()) {
-                        names.push(ident.name);
+                        names.push(TypoSuggestion {
+                            candidate: ident.name,
+                            article: binding.def().article(),
+                            kind: binding.def().kind_name(),
+                        });
                     }
                 }
             }
@@ -4188,7 +4215,11 @@ impl<'a> Resolver<'a> {
                 // Locals and type parameters
                 for (ident, def) in &rib.bindings {
                     if filter_fn(*def) {
-                        names.push(ident.name);
+                        names.push(TypoSuggestion {
+                            candidate: ident.name,
+                            article: def.article(),
+                            kind: def.kind_name(),
+                        });
                     }
                 }
                 // Items in scope
@@ -4201,7 +4232,13 @@ impl<'a> Resolver<'a> {
                     } else {
                         // Items from the prelude
                         if !module.no_implicit_prelude {
-                            names.extend(self.extern_prelude.iter().map(|(ident, _)| ident.name));
+                            names.extend(self.extern_prelude.iter().map(|(ident, _)| {
+                                TypoSuggestion {
+                                    candidate: ident.name,
+                                    article: "a",
+                                    kind: "crate",
+                                }
+                            }));
                             if let Some(prelude) = self.prelude {
                                 add_module_candidates(prelude, &mut names);
                             }
@@ -4213,7 +4250,13 @@ impl<'a> Resolver<'a> {
             // Add primitive types to the mix
             if filter_fn(Def::PrimTy(Bool)) {
                 names.extend(
-                    self.primitive_type_table.primitive_types.iter().map(|(name, _)| name)
+                    self.primitive_type_table.primitive_types.iter().map(|(name, _)| {
+                        TypoSuggestion {
+                            candidate: *name,
+                            article: "a",
+                            kind: "primitive type",
+                        }
+                    })
                 )
             }
         } else {
@@ -4230,9 +4273,16 @@ impl<'a> Resolver<'a> {
 
         let name = path[path.len() - 1].ident.name;
         // Make sure error reporting is deterministic.
-        names.sort_by_cached_key(|name| name.as_str());
-        match find_best_match_for_name(names.iter(), &name.as_str(), None) {
-            Some(found) if found != name => Some(found),
+        names.sort_by_cached_key(|suggestion| suggestion.candidate.as_str());
+
+        match find_best_match_for_name(
+            names.iter().map(|suggestion| &suggestion.candidate),
+            &name.as_str(),
+            None,
+        ) {
+            Some(found) if found != name => names
+                .into_iter()
+                .find(|suggestion| suggestion.candidate == found),
             _ => None,
         }
     }
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index e5e6c7a994b..7aa2ba48435 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -1002,6 +1002,7 @@ impl<'a> Resolver<'a> {
             };
             let ident = Ident::new(Symbol::intern(name), span);
             self.lookup_typo_candidate(&[Segment::from_ident(ident)], MacroNS, is_macro, span)
+                .map(|suggestion| suggestion.candidate)
         });
 
         if let Some(suggestion) = suggestion {
diff --git a/src/test/ui/associated-types/associated-types-eq-1.stderr b/src/test/ui/associated-types/associated-types-eq-1.stderr
index a517bf86a87..0935d6ae3e6 100644
--- a/src/test/ui/associated-types/associated-types-eq-1.stderr
+++ b/src/test/ui/associated-types/associated-types-eq-1.stderr
@@ -2,7 +2,7 @@ error[E0412]: cannot find type `A` in this scope
   --> $DIR/associated-types-eq-1.rs:10:12
    |
 LL |     let _: A = x.boo(); //~ ERROR cannot find type `A` in this scope
-   |            ^ did you mean `I`?
+   |            ^ help: a type parameter with a similar name exists: `I`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr
index d3e1cebd26f..e595e0ccb92 100644
--- a/src/test/ui/empty/empty-struct-braces-expr.stderr
+++ b/src/test/ui/empty/empty-struct-braces-expr.stderr
@@ -4,8 +4,8 @@ error[E0423]: expected value, found struct `Empty1`
 LL |     let e1 = Empty1; //~ ERROR expected value, found struct `Empty1`
    |              ^^^^^^
    |              |
-   |              did you mean `XEmpty2`?
    |              did you mean `Empty1 { /* fields */ }`?
+   |              help: a unit struct with a similar name exists: `XEmpty2`
 
 error[E0423]: expected function, found struct `Empty1`
   --> $DIR/empty-struct-braces-expr.rs:16:14
@@ -13,8 +13,8 @@ error[E0423]: expected function, found struct `Empty1`
 LL |     let e1 = Empty1(); //~ ERROR expected function, found struct `Empty1`
    |              ^^^^^^
    |              |
-   |              did you mean `XEmpty2`?
    |              did you mean `Empty1 { /* fields */ }`?
+   |              help: a unit struct with a similar name exists: `XEmpty2`
 
 error[E0423]: expected value, found struct variant `E::Empty3`
   --> $DIR/empty-struct-braces-expr.rs:17:14
@@ -34,8 +34,8 @@ error[E0423]: expected value, found struct `XEmpty1`
 LL |     let xe1 = XEmpty1; //~ ERROR expected value, found struct `XEmpty1`
    |               ^^^^^^^
    |               |
-   |               did you mean `XEmpty2`?
    |               did you mean `XEmpty1 { /* fields */ }`?
+   |               help: a unit struct with a similar name exists: `XEmpty2`
 
 error[E0423]: expected function, found struct `XEmpty1`
   --> $DIR/empty-struct-braces-expr.rs:21:15
@@ -43,8 +43,8 @@ error[E0423]: expected function, found struct `XEmpty1`
 LL |     let xe1 = XEmpty1(); //~ ERROR expected function, found struct `XEmpty1`
    |               ^^^^^^^
    |               |
-   |               did you mean `XEmpty2`?
    |               did you mean `XEmpty1 { /* fields */ }`?
+   |               help: a unit struct with a similar name exists: `XEmpty2`
 
 error[E0599]: no variant named `Empty3` found for type `empty_struct::XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:22:19
diff --git a/src/test/ui/empty/empty-struct-braces-pat-1.stderr b/src/test/ui/empty/empty-struct-braces-pat-1.stderr
index f43262574fb..6c361c70344 100644
--- a/src/test/ui/empty/empty-struct-braces-pat-1.stderr
+++ b/src/test/ui/empty/empty-struct-braces-pat-1.stderr
@@ -10,7 +10,7 @@ error[E0532]: expected unit struct/variant or constant, found struct variant `XE
 LL |         XE::XEmpty3 => ()
    |         ^^^^-------
    |         |   |
-   |         |   did you mean `XEmpty4`?
+   |         |   help: a unit variant with a similar name exists: `XEmpty4`
    |         did you mean `XE::XEmpty3 { /* fields */ }`?
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/empty/empty-struct-braces-pat-2.stderr b/src/test/ui/empty/empty-struct-braces-pat-2.stderr
index 8c55b2119f1..fc2ed79bb2e 100644
--- a/src/test/ui/empty/empty-struct-braces-pat-2.stderr
+++ b/src/test/ui/empty/empty-struct-braces-pat-2.stderr
@@ -4,8 +4,8 @@ error[E0532]: expected tuple struct/variant, found struct `Empty1`
 LL |         Empty1() => () //~ ERROR expected tuple struct/variant, found struct `Empty1`
    |         ^^^^^^
    |         |
-   |         did you mean `XEmpty6`?
    |         did you mean `Empty1 { /* fields */ }`?
+   |         help: a tuple struct with a similar name exists: `XEmpty6`
 
 error[E0532]: expected tuple struct/variant, found struct `XEmpty1`
   --> $DIR/empty-struct-braces-pat-2.rs:18:9
@@ -13,8 +13,8 @@ error[E0532]: expected tuple struct/variant, found struct `XEmpty1`
 LL |         XEmpty1() => () //~ ERROR expected tuple struct/variant, found struct `XEmpty1`
    |         ^^^^^^^
    |         |
-   |         did you mean `XEmpty6`?
    |         did you mean `XEmpty1 { /* fields */ }`?
+   |         help: a tuple struct with a similar name exists: `XEmpty6`
 
 error[E0532]: expected tuple struct/variant, found struct `Empty1`
   --> $DIR/empty-struct-braces-pat-2.rs:21:9
@@ -22,8 +22,8 @@ error[E0532]: expected tuple struct/variant, found struct `Empty1`
 LL |         Empty1(..) => () //~ ERROR expected tuple struct/variant, found struct `Empty1`
    |         ^^^^^^
    |         |
-   |         did you mean `XEmpty6`?
    |         did you mean `Empty1 { /* fields */ }`?
+   |         help: a tuple struct with a similar name exists: `XEmpty6`
 
 error[E0532]: expected tuple struct/variant, found struct `XEmpty1`
   --> $DIR/empty-struct-braces-pat-2.rs:24:9
@@ -31,8 +31,8 @@ error[E0532]: expected tuple struct/variant, found struct `XEmpty1`
 LL |         XEmpty1(..) => () //~ ERROR expected tuple struct/variant, found struct `XEmpty1`
    |         ^^^^^^^
    |         |
-   |         did you mean `XEmpty6`?
    |         did you mean `XEmpty1 { /* fields */ }`?
+   |         help: a tuple struct with a similar name exists: `XEmpty6`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/empty/empty-struct-braces-pat-3.stderr b/src/test/ui/empty/empty-struct-braces-pat-3.stderr
index 17670cb0bd6..af8731b5f05 100644
--- a/src/test/ui/empty/empty-struct-braces-pat-3.stderr
+++ b/src/test/ui/empty/empty-struct-braces-pat-3.stderr
@@ -10,7 +10,7 @@ error[E0532]: expected tuple struct/variant, found struct variant `XE::XEmpty3`
 LL |         XE::XEmpty3() => ()
    |         ^^^^-------
    |         |   |
-   |         |   did you mean `XEmpty5`?
+   |         |   help: a tuple variant with a similar name exists: `XEmpty5`
    |         did you mean `XE::XEmpty3 { /* fields */ }`?
 
 error[E0532]: expected tuple struct/variant, found struct variant `E::Empty3`
@@ -25,7 +25,7 @@ error[E0532]: expected tuple struct/variant, found struct variant `XE::XEmpty3`
 LL |         XE::XEmpty3(..) => ()
    |         ^^^^-------
    |         |   |
-   |         |   did you mean `XEmpty5`?
+   |         |   help: a tuple variant with a similar name exists: `XEmpty5`
    |         did you mean `XE::XEmpty3 { /* fields */ }`?
 
 error: aborting due to 4 previous errors
diff --git a/src/test/ui/empty/empty-struct-tuple-pat.stderr b/src/test/ui/empty/empty-struct-tuple-pat.stderr
index 4cb869e64a5..f92c4e5c463 100644
--- a/src/test/ui/empty/empty-struct-tuple-pat.stderr
+++ b/src/test/ui/empty/empty-struct-tuple-pat.stderr
@@ -28,7 +28,7 @@ error[E0532]: expected unit struct/variant or constant, found tuple variant `XE:
 LL |         XE::XEmpty5 => (),
    |         ^^^^-------
    |             |
-   |             did you mean `XEmpty4`?
+   |             help: a unit variant with a similar name exists: `XEmpty4`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/empty/empty-struct-unit-pat.stderr b/src/test/ui/empty/empty-struct-unit-pat.stderr
index 3711bd6dcb7..e62246562be 100644
--- a/src/test/ui/empty/empty-struct-unit-pat.stderr
+++ b/src/test/ui/empty/empty-struct-unit-pat.stderr
@@ -2,25 +2,25 @@ error[E0532]: expected tuple struct/variant, found unit struct `Empty2`
   --> $DIR/empty-struct-unit-pat.rs:21:9
    |
 LL |         Empty2() => () //~ ERROR expected tuple struct/variant, found unit struct `Empty2`
-   |         ^^^^^^ did you mean `XEmpty6`?
+   |         ^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
 
 error[E0532]: expected tuple struct/variant, found unit struct `XEmpty2`
   --> $DIR/empty-struct-unit-pat.rs:24:9
    |
 LL |         XEmpty2() => () //~ ERROR expected tuple struct/variant, found unit struct `XEmpty2`
-   |         ^^^^^^^ did you mean `XEmpty6`?
+   |         ^^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
 
 error[E0532]: expected tuple struct/variant, found unit struct `Empty2`
   --> $DIR/empty-struct-unit-pat.rs:27:9
    |
 LL |         Empty2(..) => () //~ ERROR expected tuple struct/variant, found unit struct `Empty2`
-   |         ^^^^^^ did you mean `XEmpty6`?
+   |         ^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
 
 error[E0532]: expected tuple struct/variant, found unit struct `XEmpty2`
   --> $DIR/empty-struct-unit-pat.rs:30:9
    |
 LL |         XEmpty2(..) => () //~ ERROR expected tuple struct/variant, found unit struct `XEmpty2`
-   |         ^^^^^^^ did you mean `XEmpty6`?
+   |         ^^^^^^^ help: a tuple struct with a similar name exists: `XEmpty6`
 
 error[E0532]: expected tuple struct/variant, found unit variant `E::Empty4`
   --> $DIR/empty-struct-unit-pat.rs:34:9
@@ -34,7 +34,7 @@ error[E0532]: expected tuple struct/variant, found unit variant `XE::XEmpty4`
 LL |         XE::XEmpty4() => (),
    |         ^^^^-------
    |             |
-   |             did you mean `XEmpty5`?
+   |             help: a tuple variant with a similar name exists: `XEmpty5`
 
 error[E0532]: expected tuple struct/variant, found unit variant `E::Empty4`
   --> $DIR/empty-struct-unit-pat.rs:42:9
@@ -48,7 +48,7 @@ error[E0532]: expected tuple struct/variant, found unit variant `XE::XEmpty4`
 LL |         XE::XEmpty4(..) => (),
    |         ^^^^-------
    |             |
-   |             did you mean `XEmpty5`?
+   |             help: a tuple variant with a similar name exists: `XEmpty5`
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr
index df9ed631a1c..c422a1e7957 100644
--- a/src/test/ui/error-codes/E0423.stderr
+++ b/src/test/ui/error-codes/E0423.stderr
@@ -22,8 +22,8 @@ error[E0423]: expected function, found struct `Foo`
 LL |     let f = Foo(); //~ ERROR E0423
    |             ^^^
    |             |
-   |             did you mean `foo`?
    |             did you mean `Foo { /* fields */ }`?
+   |             help: a function with a similar name exists: `foo`
 
 error[E0423]: expected value, found struct `S`
   --> $DIR/E0423.rs:12:32
diff --git a/src/test/ui/error-festival.stderr b/src/test/ui/error-festival.stderr
index 2a482722169..946319a1edf 100644
--- a/src/test/ui/error-festival.stderr
+++ b/src/test/ui/error-festival.stderr
@@ -2,7 +2,7 @@ error[E0425]: cannot find value `y` in this scope
   --> $DIR/error-festival.rs:14:5
    |
 LL |     y = 2;
-   |     ^ did you mean `x`?
+   |     ^ help: a local variable with a similar name exists: `x`
 
 error[E0603]: constant `FOO` is private
   --> $DIR/error-festival.rs:22:10
diff --git a/src/test/ui/glob-resolve1.stderr b/src/test/ui/glob-resolve1.stderr
index 899ffbf0d09..10a57aa6ca6 100644
--- a/src/test/ui/glob-resolve1.stderr
+++ b/src/test/ui/glob-resolve1.stderr
@@ -47,7 +47,11 @@ error[E0412]: cannot find type `A` in this scope
   --> $DIR/glob-resolve1.rs:28:11
    |
 LL |     foo::<A>(); //~ ERROR: cannot find type `A` in this scope
-   |           ^ did you mean `B`?
+   |           ^
+help: an enum with a similar name exists
+   |
+LL |     foo::<B>(); //~ ERROR: cannot find type `A` in this scope
+   |           ^
 help: possible candidate is found in another module, you can import it into scope
    |
 LL | use bar::A;
@@ -57,7 +61,11 @@ error[E0412]: cannot find type `C` in this scope
   --> $DIR/glob-resolve1.rs:29:11
    |
 LL |     foo::<C>(); //~ ERROR: cannot find type `C` in this scope
-   |           ^ did you mean `B`?
+   |           ^
+help: an enum with a similar name exists
+   |
+LL |     foo::<B>(); //~ ERROR: cannot find type `C` in this scope
+   |           ^
 help: possible candidate is found in another module, you can import it into scope
    |
 LL | use bar::C;
@@ -67,7 +75,11 @@ error[E0412]: cannot find type `D` in this scope
   --> $DIR/glob-resolve1.rs:30:11
    |
 LL |     foo::<D>(); //~ ERROR: cannot find type `D` in this scope
-   |           ^ did you mean `B`?
+   |           ^
+help: an enum with a similar name exists
+   |
+LL |     foo::<B>(); //~ ERROR: cannot find type `D` in this scope
+   |           ^
 help: possible candidate is found in another module, you can import it into scope
    |
 LL | use bar::D;
diff --git a/src/test/ui/issues/issue-10200.stderr b/src/test/ui/issues/issue-10200.stderr
index 78e601568f1..ac1ad118a71 100644
--- a/src/test/ui/issues/issue-10200.stderr
+++ b/src/test/ui/issues/issue-10200.stderr
@@ -2,7 +2,7 @@ error[E0532]: expected tuple struct/variant, found function `foo`
   --> $DIR/issue-10200.rs:6:9
    |
 LL |         foo(x) //~ ERROR expected tuple struct/variant, found function `foo`
-   |         ^^^ did you mean `Foo`?
+   |         ^^^ help: a tuple struct with a similar name exists: `Foo`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17546.stderr b/src/test/ui/issues/issue-17546.stderr
index 4f2c6cfc4bb..1fbb229ed98 100644
--- a/src/test/ui/issues/issue-17546.stderr
+++ b/src/test/ui/issues/issue-17546.stderr
@@ -2,10 +2,15 @@ error[E0573]: expected type, found variant `NoResult`
   --> $DIR/issue-17546.rs:12:17
    |
 LL |     fn new() -> NoResult<MyEnum, String> {
-   |                 --------^^^^^^^^^^^^^^^^
-   |                 |
-   |                 did you mean `Result`?
-   |                 help: try using the variant's enum: `foo::MyEnum`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using the variant's enum
+   |
+LL |     fn new() -> foo::MyEnum {
+   |                 ^^^^^^^^^^^
+help: an enum with a similar name exists
+   |
+LL |     fn new() -> Result<MyEnum, String> {
+   |                 ^^^^^^
 
 error[E0573]: expected type, found variant `Result`
   --> $DIR/issue-17546.rs:22:17
@@ -45,10 +50,15 @@ error[E0573]: expected type, found variant `NoResult`
   --> $DIR/issue-17546.rs:33:15
    |
 LL | fn newer() -> NoResult<foo::MyEnum, String> {
-   |               --------^^^^^^^^^^^^^^^^^^^^^
-   |               |
-   |               did you mean `Result`?
-   |               help: try using the variant's enum: `foo::MyEnum`
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using the variant's enum
+   |
+LL | fn newer() -> foo::MyEnum {
+   |               ^^^^^^^^^^^
+help: an enum with a similar name exists
+   |
+LL | fn newer() -> Result<foo::MyEnum, String> {
+   |               ^^^^^^
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issues/issue-31845.stderr b/src/test/ui/issues/issue-31845.stderr
index d04a884a933..7ee1a41a387 100644
--- a/src/test/ui/issues/issue-31845.stderr
+++ b/src/test/ui/issues/issue-31845.stderr
@@ -2,7 +2,7 @@ error[E0425]: cannot find function `g` in this scope
   --> $DIR/issue-31845.rs:7:12
    |
 LL |            g(); //~ ERROR cannot find function `g` in this scope
-   |            ^ did you mean `h`?
+   |            ^ help: a function with a similar name exists: `h`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-32004.stderr b/src/test/ui/issues/issue-32004.stderr
index 04cd27b8bdb..f8c418b25a0 100644
--- a/src/test/ui/issues/issue-32004.stderr
+++ b/src/test/ui/issues/issue-32004.stderr
@@ -4,7 +4,7 @@ error[E0532]: expected unit struct/variant or constant, found tuple variant `Foo
 LL |         Foo::Bar => {}
    |         ^^^^^---
    |              |
-   |              did you mean `Baz`?
+   |              help: a unit variant with a similar name exists: `Baz`
 
 error[E0532]: expected tuple struct/variant, found unit struct `S`
   --> $DIR/issue-32004.rs:16:9
diff --git a/src/test/ui/issues/issue-32086.stderr b/src/test/ui/issues/issue-32086.stderr
index 98a6200cdae..bb2cc7c101b 100644
--- a/src/test/ui/issues/issue-32086.stderr
+++ b/src/test/ui/issues/issue-32086.stderr
@@ -2,13 +2,13 @@ error[E0532]: expected tuple struct/variant, found constant `C`
   --> $DIR/issue-32086.rs:5:9
    |
 LL |     let C(a) = S(11); //~ ERROR expected tuple struct/variant, found constant `C`
-   |         ^ did you mean `S`?
+   |         ^ help: a tuple struct with a similar name exists: `S`
 
 error[E0532]: expected tuple struct/variant, found constant `C`
   --> $DIR/issue-32086.rs:6:9
    |
 LL |     let C(..) = S(11); //~ ERROR expected tuple struct/variant, found constant `C`
-   |         ^ did you mean `S`?
+   |         ^ help: a tuple struct with a similar name exists: `S`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-46332.stderr b/src/test/ui/issues/issue-46332.stderr
index 785deb77ef7..812a50000d1 100644
--- a/src/test/ui/issues/issue-46332.stderr
+++ b/src/test/ui/issues/issue-46332.stderr
@@ -2,7 +2,7 @@ error[E0422]: cannot find struct, variant or union type `TyUInt` in this scope
   --> $DIR/issue-46332.rs:9:5
    |
 LL |     TyUInt {};
-   |     ^^^^^^ did you mean `TyUint`?
+   |     ^^^^^^ help: a struct with a similar name exists: `TyUint`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-7607-1.stderr b/src/test/ui/issues/issue-7607-1.stderr
index ffe03f521e0..aa0a6c761bf 100644
--- a/src/test/ui/issues/issue-7607-1.stderr
+++ b/src/test/ui/issues/issue-7607-1.stderr
@@ -2,7 +2,7 @@ error[E0412]: cannot find type `Fo` in this scope
   --> $DIR/issue-7607-1.rs:5:6
    |
 LL | impl Fo { //~ ERROR cannot find type `Fo` in this scope
-   |      ^^ did you mean `Fn`?
+   |      ^^ help: a trait with a similar name exists: `Fn`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr
index 18d426979fa..5ebb40e75b3 100644
--- a/src/test/ui/namespace/namespace-mix.stderr
+++ b/src/test/ui/namespace/namespace-mix.stderr
@@ -2,11 +2,13 @@ error[E0423]: expected value, found type alias `m1::S`
   --> $DIR/namespace-mix.rs:34:11
    |
 LL |     check(m1::S); //~ ERROR expected value, found type alias `m1::S`
-   |           ^^^^-
-   |               |
-   |               did you mean `TS`?
+   |           ^^^^^
    |
    = note: can't use a type alias as a constructor
+help: a tuple struct with a similar name exists
+   |
+LL |     check(m1::TS); //~ ERROR expected value, found type alias `m1::S`
+   |               ^^
 help: possible better candidates are found in other modules, you can import them into scope
    |
 LL | use m2::S;
@@ -18,11 +20,13 @@ error[E0423]: expected value, found type alias `xm1::S`
   --> $DIR/namespace-mix.rs:40:11
    |
 LL |     check(xm1::S); //~ ERROR expected value, found type alias `xm1::S`
-   |           ^^^^^-
-   |                |
-   |                did you mean `TS`?
+   |           ^^^^^^
    |
    = note: can't use a type alias as a constructor
+help: a tuple struct with a similar name exists
+   |
+LL |     check(xm1::TS); //~ ERROR expected value, found type alias `xm1::S`
+   |                ^^
 help: possible better candidates are found in other modules, you can import them into scope
    |
 LL | use m2::S;
@@ -34,10 +38,11 @@ error[E0423]: expected value, found struct variant `m7::V`
   --> $DIR/namespace-mix.rs:100:11
    |
 LL |     check(m7::V); //~ ERROR expected value, found struct variant `m7::V`
-   |           ^^^^-
-   |           |   |
-   |           |   did you mean `TV`?
-   |           did you mean `m7::V { /* fields */ }`?
+   |           ^^^^^ did you mean `m7::V { /* fields */ }`?
+help: a tuple variant with a similar name exists
+   |
+LL |     check(m7::TV); //~ ERROR expected value, found struct variant `m7::V`
+   |               ^^
 help: possible better candidates are found in other modules, you can import them into scope
    |
 LL | use m8::V;
@@ -49,10 +54,11 @@ error[E0423]: expected value, found struct variant `xm7::V`
   --> $DIR/namespace-mix.rs:106:11
    |
 LL |     check(xm7::V); //~ ERROR expected value, found struct variant `xm7::V`
-   |           ^^^^^-
-   |           |    |
-   |           |    did you mean `TV`?
-   |           did you mean `xm7::V { /* fields */ }`?
+   |           ^^^^^^ did you mean `xm7::V { /* fields */ }`?
+help: a tuple variant with a similar name exists
+   |
+LL |     check(xm7::TV); //~ ERROR expected value, found struct variant `xm7::V`
+   |                ^^
 help: possible better candidates are found in other modules, you can import them into scope
    |
 LL | use m8::V;
diff --git a/src/test/ui/pattern/pattern-error-continue.stderr b/src/test/ui/pattern/pattern-error-continue.stderr
index c17d4b70f0b..88de7577341 100644
--- a/src/test/ui/pattern/pattern-error-continue.stderr
+++ b/src/test/ui/pattern/pattern-error-continue.stderr
@@ -10,7 +10,7 @@ error[E0532]: expected tuple struct/variant, found unit variant `A::D`
 LL |         A::D(_) => (),       //~ ERROR expected tuple struct/variant, found unit variant `A::D`
    |         ^^^-
    |            |
-   |            did you mean `B`?
+   |            help: a tuple variant with a similar name exists: `B`
 
 error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields
   --> $DIR/pattern-error-continue.rs:17:9
diff --git a/src/test/ui/privacy/privacy-ns1.stderr b/src/test/ui/privacy/privacy-ns1.stderr
index e778b6ec350..6ba2dbe41a2 100644
--- a/src/test/ui/privacy/privacy-ns1.stderr
+++ b/src/test/ui/privacy/privacy-ns1.stderr
@@ -2,7 +2,11 @@ error[E0423]: expected function, found trait `Bar`
   --> $DIR/privacy-ns1.rs:20:5
    |
 LL |     Bar();  //~ ERROR expected function, found trait `Bar`
-   |     ^^^ did you mean `Baz`?
+   |     ^^^
+help: a unit struct with a similar name exists
+   |
+LL |     Baz();  //~ ERROR expected function, found trait `Bar`
+   |     ^^^
 help: possible better candidates are found in other modules, you can import them into scope
    |
 LL | use foo1::Bar;
@@ -16,7 +20,11 @@ error[E0573]: expected type, found function `Bar`
   --> $DIR/privacy-ns1.rs:35:17
    |
 LL |     let _x: Box<Bar>;  //~ ERROR expected type, found function `Bar`
-   |                 ^^^ did you mean `Baz`?
+   |                 ^^^
+help: a struct with a similar name exists
+   |
+LL |     let _x: Box<Baz>;  //~ ERROR expected type, found function `Bar`
+   |                 ^^^
 help: possible better candidates are found in other modules, you can import them into scope
    |
 LL | use foo1::Bar;
@@ -30,7 +38,11 @@ error[E0425]: cannot find function `Bar` in this scope
   --> $DIR/privacy-ns1.rs:50:5
    |
 LL |     Bar();  //~ ERROR cannot find function `Bar` in this scope
-   |     ^^^ did you mean `Baz`?
+   |     ^^^
+help: a unit struct with a similar name exists
+   |
+LL |     Baz();  //~ ERROR cannot find function `Bar` in this scope
+   |     ^^^
 help: possible candidates are found in other modules, you can import them into scope
    |
 LL | use foo1::Bar;
@@ -44,7 +56,11 @@ error[E0412]: cannot find type `Bar` in this scope
   --> $DIR/privacy-ns1.rs:51:17
    |
 LL |     let _x: Box<Bar>;  //~ ERROR cannot find type `Bar` in this scope
-   |                 ^^^ did you mean `Baz`?
+   |                 ^^^
+help: a struct with a similar name exists
+   |
+LL |     let _x: Box<Baz>;  //~ ERROR cannot find type `Bar` in this scope
+   |                 ^^^
 help: possible candidates are found in other modules, you can import them into scope
    |
 LL | use foo1::Bar;
diff --git a/src/test/ui/privacy/privacy-ns2.stderr b/src/test/ui/privacy/privacy-ns2.stderr
index 74f86677789..0012072ed11 100644
--- a/src/test/ui/privacy/privacy-ns2.stderr
+++ b/src/test/ui/privacy/privacy-ns2.stderr
@@ -16,7 +16,11 @@ error[E0423]: expected function, found trait `Bar`
   --> $DIR/privacy-ns2.rs:26:5
    |
 LL |     Bar(); //~ ERROR expected function, found trait `Bar`
-   |     ^^^ did you mean `Baz`?
+   |     ^^^
+help: a unit struct with a similar name exists
+   |
+LL |     Baz(); //~ ERROR expected function, found trait `Bar`
+   |     ^^^
 help: possible better candidates are found in other modules, you can import them into scope
    |
 LL | use foo1::Bar;
@@ -44,7 +48,11 @@ error[E0573]: expected type, found function `Bar`
   --> $DIR/privacy-ns2.rs:47:17
    |
 LL |     let _x: Box<Bar>; //~ ERROR expected type, found function `Bar`
-   |                 ^^^ did you mean `Baz`?
+   |                 ^^^
+help: a struct with a similar name exists
+   |
+LL |     let _x: Box<Baz>; //~ ERROR expected type, found function `Bar`
+   |                 ^^^
 help: possible better candidates are found in other modules, you can import them into scope
    |
 LL | use foo1::Bar;
diff --git a/src/test/ui/proc-macro/lints_in_proc_macros.rs b/src/test/ui/proc-macro/lints_in_proc_macros.rs
index 8f76cc48c4f..8d2957ef5da 100644
--- a/src/test/ui/proc-macro/lints_in_proc_macros.rs
+++ b/src/test/ui/proc-macro/lints_in_proc_macros.rs
@@ -11,6 +11,7 @@ fn main() {
     let foobar = 42;
     bang_proc_macro2!();
     //~^ ERROR cannot find value `foobar2` in this scope
-    //~^^ did you mean `foobar`?
+    //~| HELP a local variable with a similar name exists
+    //~| SUGGESTION foobar
     println!("{}", x);
 }
diff --git a/src/test/ui/proc-macro/lints_in_proc_macros.stderr b/src/test/ui/proc-macro/lints_in_proc_macros.stderr
index c10a8a0ffa6..2d97cd700be 100644
--- a/src/test/ui/proc-macro/lints_in_proc_macros.stderr
+++ b/src/test/ui/proc-macro/lints_in_proc_macros.stderr
@@ -2,7 +2,7 @@ error[E0425]: cannot find value `foobar2` in this scope
   --> $DIR/lints_in_proc_macros.rs:12:5
    |
 LL |     bang_proc_macro2!();
-   |     ^^^^^^^^^^^^^^^^^^^^ did you mean `foobar`?
+   |     ^^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `foobar`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/proc-macro/parent-source-spans.stderr b/src/test/ui/proc-macro/parent-source-spans.stderr
index a8ee325b41d..423122539c8 100644
--- a/src/test/ui/proc-macro/parent-source-spans.stderr
+++ b/src/test/ui/proc-macro/parent-source-spans.stderr
@@ -128,7 +128,7 @@ error[E0425]: cannot find value `ok` in this scope
   --> $DIR/parent-source-spans.rs:30:5
    |
 LL |     parent_source_spans!($($tokens)*);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `Ok`?
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok`
 ...
 LL |     one!("hello", "world");
    |     ----------------------- in this macro invocation
@@ -137,7 +137,7 @@ error[E0425]: cannot find value `ok` in this scope
   --> $DIR/parent-source-spans.rs:30:5
    |
 LL |     parent_source_spans!($($tokens)*);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `Ok`?
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok`
 ...
 LL |     two!("yay", "rust");
    |     -------------------- in this macro invocation
@@ -146,7 +146,7 @@ error[E0425]: cannot find value `ok` in this scope
   --> $DIR/parent-source-spans.rs:30:5
    |
 LL |     parent_source_spans!($($tokens)*);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `Ok`?
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok`
 ...
 LL |     three!("hip", "hop");
    |     --------------------- in this macro invocation
diff --git a/src/test/ui/resolve/issue-39226.stderr b/src/test/ui/resolve/issue-39226.stderr
index 3a93928aef9..c97fb4db6be 100644
--- a/src/test/ui/resolve/issue-39226.stderr
+++ b/src/test/ui/resolve/issue-39226.stderr
@@ -4,8 +4,8 @@ error[E0423]: expected value, found struct `Handle`
 LL |         handle: Handle
    |                 ^^^^^^
    |                 |
-   |                 did you mean `handle`?
    |                 did you mean `Handle { /* fields */ }`?
+   |                 help: a local variable with a similar name exists: `handle`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/issue-5035.stderr b/src/test/ui/resolve/issue-5035.stderr
index 39216c6ec0c..57ad5f22f4c 100644
--- a/src/test/ui/resolve/issue-5035.stderr
+++ b/src/test/ui/resolve/issue-5035.stderr
@@ -10,8 +10,8 @@ error[E0404]: expected trait, found type alias `K`
 LL | impl K for isize {} //~ ERROR expected trait, found type alias `K`
    |      ^
    |      |
-   |      did you mean `I`?
    |      type aliases cannot be used as traits
+   |      help: a trait with a similar name exists: `I`
    |
    = note: did you mean to use a trait alias?
 
diff --git a/src/test/ui/resolve/levenshtein.stderr b/src/test/ui/resolve/levenshtein.stderr
index df075d15d7f..cddfe4e7ff5 100644
--- a/src/test/ui/resolve/levenshtein.stderr
+++ b/src/test/ui/resolve/levenshtein.stderr
@@ -2,19 +2,19 @@ error[E0412]: cannot find type `esize` in this scope
   --> $DIR/levenshtein.rs:5:11
    |
 LL | fn foo(c: esize) {} // Misspelled primitive type name.
-   |           ^^^^^ did you mean `isize`?
+   |           ^^^^^ help: a primitive type with a similar name exists: `isize`
 
 error[E0412]: cannot find type `Baz` in this scope
   --> $DIR/levenshtein.rs:10:10
    |
 LL | type A = Baz; // Misspelled type name.
-   |          ^^^ did you mean `Bar`?
+   |          ^^^ help: an enum with a similar name exists: `Bar`
 
 error[E0412]: cannot find type `Opiton` in this scope
   --> $DIR/levenshtein.rs:12:10
    |
 LL | type B = Opiton<u8>; // Misspelled type name from the prelude.
-   |          ^^^^^^ did you mean `Option`?
+   |          ^^^^^^ help: an enum with a similar name exists: `Option`
 
 error[E0412]: cannot find type `Baz` in this scope
   --> $DIR/levenshtein.rs:16:14
@@ -26,25 +26,25 @@ error[E0425]: cannot find value `MAXITEM` in this scope
   --> $DIR/levenshtein.rs:24:20
    |
 LL |     let v = [0u32; MAXITEM]; // Misspelled constant name.
-   |                    ^^^^^^^ did you mean `MAX_ITEM`?
+   |                    ^^^^^^^ help: a constant with a similar name exists: `MAX_ITEM`
 
 error[E0425]: cannot find function `foobar` in this scope
   --> $DIR/levenshtein.rs:26:5
    |
 LL |     foobar(); // Misspelled function name.
-   |     ^^^^^^ did you mean `foo_bar`?
+   |     ^^^^^^ help: a function with a similar name exists: `foo_bar`
 
 error[E0412]: cannot find type `first` in module `m`
   --> $DIR/levenshtein.rs:28:15
    |
 LL |     let b: m::first = m::second; // Misspelled item in module.
-   |               ^^^^^ did you mean `First`?
+   |               ^^^^^ help: a struct with a similar name exists: `First`
 
 error[E0425]: cannot find value `second` in module `m`
   --> $DIR/levenshtein.rs:28:26
    |
 LL |     let b: m::first = m::second; // Misspelled item in module.
-   |                          ^^^^^^ did you mean `Second`?
+   |                          ^^^^^^ help: a unit struct with a similar name exists: `Second`
 
 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 71b1ec46247..01f0941282e 100644
--- a/src/test/ui/resolve/privacy-enum-ctor.stderr
+++ b/src/test/ui/resolve/privacy-enum-ctor.stderr
@@ -13,7 +13,7 @@ error[E0423]: expected value, found enum `Z`
   --> $DIR/privacy-enum-ctor.rs:25:9
    |
 LL |         Z;
-   |         ^ did you mean `f`?
+   |         ^ help: a function with a similar name exists: `f`
    |
    = note: did you mean to use one of the following variants?
            - `m::Z::Fn`
@@ -30,14 +30,16 @@ error[E0423]: expected value, found enum `m::E`
   --> $DIR/privacy-enum-ctor.rs:41:16
    |
 LL |     let _: E = m::E;
-   |                ^^^-
-   |                   |
-   |                   did you mean `f`?
+   |                ^^^^
    |
    = note: did you mean to use one of the following variants?
            - `E::Fn`
            - `E::Struct`
            - `E::Unit`
+help: a function with a similar name exists
+   |
+LL |     let _: E = m::f;
+   |                   ^
 help: possible better candidates are found in other modules, you can import them into scope
    |
 LL | use std::f32::consts::E;
@@ -78,7 +80,11 @@ error[E0412]: cannot find type `Z` in this scope
   --> $DIR/privacy-enum-ctor.rs:57:12
    |
 LL |     let _: Z = m::n::Z;
-   |            ^ did you mean `E`?
+   |            ^
+help: an enum with a similar name exists
+   |
+LL |     let _: E = m::n::Z;
+   |            ^
 help: possible candidate is found in another module, you can import it into scope
    |
 LL | use m::n::Z;
@@ -99,7 +105,11 @@ error[E0412]: cannot find type `Z` in this scope
   --> $DIR/privacy-enum-ctor.rs:61:12
    |
 LL |     let _: Z = m::n::Z::Fn;
-   |            ^ did you mean `E`?
+   |            ^
+help: an enum with a similar name exists
+   |
+LL |     let _: E = m::n::Z::Fn;
+   |            ^
 help: possible candidate is found in another module, you can import it into scope
    |
 LL | use m::n::Z;
@@ -109,7 +119,11 @@ error[E0412]: cannot find type `Z` in this scope
   --> $DIR/privacy-enum-ctor.rs:64:12
    |
 LL |     let _: Z = m::n::Z::Struct;
-   |            ^ did you mean `E`?
+   |            ^
+help: an enum with a similar name exists
+   |
+LL |     let _: E = m::n::Z::Struct;
+   |            ^
 help: possible candidate is found in another module, you can import it into scope
    |
 LL | use m::n::Z;
@@ -125,7 +139,11 @@ error[E0412]: cannot find type `Z` in this scope
   --> $DIR/privacy-enum-ctor.rs:68:12
    |
 LL |     let _: Z = m::n::Z::Unit {};
-   |            ^ did you mean `E`?
+   |            ^
+help: an enum with a similar name exists
+   |
+LL |     let _: E = m::n::Z::Unit {};
+   |            ^
 help: possible candidate is found in another module, you can import it into scope
    |
 LL | use m::n::Z;
diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr
index edb7a672edd..44ecf6b97bf 100644
--- a/src/test/ui/resolve/privacy-struct-ctor.stderr
+++ b/src/test/ui/resolve/privacy-struct-ctor.stderr
@@ -2,10 +2,11 @@ error[E0423]: expected value, found struct `Z`
   --> $DIR/privacy-struct-ctor.rs:20:9
    |
 LL |         Z;
+   |         ^ constructor is not visible here due to private fields
+help: a tuple struct with a similar name exists
+   |
+LL |         S;
    |         ^
-   |         |
-   |         did you mean `S`?
-   |         constructor is not visible here due to private fields
 help: possible better candidate is found in another module, you can import it into scope
    |
 LL |     use m::n::Z;
diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
index 157b4cc79df..8a9426bfee8 100644
--- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
+++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
@@ -28,7 +28,7 @@ error[E0423]: expected value, found module `a::b`
 LL |     a::b.J
    |     ^^^---
    |     |  |
-   |     |  did you mean `I`?
+   |     |  help: a constant with a similar name exists: `I`
    |     did you mean `a::b::J`?
 
 error[E0423]: expected value, found module `a`
@@ -45,7 +45,7 @@ error[E0423]: expected value, found module `a::b`
 LL |     v.push(a::b);
    |            ^^^-
    |               |
-   |               did you mean `I`?
+   |               help: a constant with a similar name exists: `I`
 
 error[E0423]: expected value, found module `a::b`
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:45:5
@@ -53,7 +53,7 @@ error[E0423]: expected value, found module `a::b`
 LL |     a::b.f()
    |     ^^^-----
    |     |  |
-   |     |  did you mean `I`?
+   |     |  help: a constant with a similar name exists: `I`
    |     did you mean `a::b::f(...)`?
 
 error[E0423]: expected value, found module `a::b`
@@ -62,7 +62,7 @@ error[E0423]: expected value, found module `a::b`
 LL |     a::b
    |     ^^^-
    |        |
-   |        did you mean `I`?
+   |        help: a constant with a similar name exists: `I`
 
 error[E0423]: expected function, found module `a::b`
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:55:5
@@ -70,7 +70,7 @@ error[E0423]: expected function, found module `a::b`
 LL |     a::b()
    |     ^^^-
    |        |
-   |        did you mean `I`?
+   |        help: a constant with a similar name exists: `I`
 
 error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/resolve/tuple-struct-alias.stderr b/src/test/ui/resolve/tuple-struct-alias.stderr
index 6338c340c23..f299aa40a31 100644
--- a/src/test/ui/resolve/tuple-struct-alias.stderr
+++ b/src/test/ui/resolve/tuple-struct-alias.stderr
@@ -2,7 +2,7 @@ error[E0423]: expected function, found type alias `A`
   --> $DIR/tuple-struct-alias.rs:5:13
    |
 LL |     let s = A(0, 1); //~ ERROR expected function
-   |             ^ did you mean `S`?
+   |             ^ help: a tuple struct with a similar name exists: `S`
    |
    = note: can't use a type alias as a constructor
 
@@ -10,7 +10,7 @@ error[E0532]: expected tuple struct/variant, found type alias `A`
   --> $DIR/tuple-struct-alias.rs:7:9
    |
 LL |         A(..) => {} //~ ERROR expected tuple struct/variant
-   |         ^ did you mean `S`?
+   |         ^ help: a tuple struct with a similar name exists: `S`
    |
    = note: can't use a type alias as a constructor
 
diff --git a/src/test/ui/span/typo-suggestion.stderr b/src/test/ui/span/typo-suggestion.stderr
index 5c564f7dd74..7b12c4430ed 100644
--- a/src/test/ui/span/typo-suggestion.stderr
+++ b/src/test/ui/span/typo-suggestion.stderr
@@ -8,7 +8,7 @@ error[E0425]: cannot find value `fob` in this scope
   --> $DIR/typo-suggestion.rs:8:26
    |
 LL |     println!("Hello {}", fob); //~ ERROR cannot find value
-   |                          ^^^ did you mean `foo`?
+   |                          ^^^ help: a local variable with a similar name exists: `foo`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/visibility-ty-params.stderr b/src/test/ui/span/visibility-ty-params.stderr
index 1fb54df1570..d7914528f46 100644
--- a/src/test/ui/span/visibility-ty-params.stderr
+++ b/src/test/ui/span/visibility-ty-params.stderr
@@ -16,7 +16,7 @@ error[E0577]: expected module, found struct `S`
 LL | m!{ S<u8> } //~ ERROR unexpected generic arguments in path
    |     -^^^^
    |     |
-   |     did you mean `m`?
+   |     help: a module with a similar name exists: `m`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/structs/struct-fields-shorthand-unresolved.stderr b/src/test/ui/structs/struct-fields-shorthand-unresolved.stderr
index 0fcaac55fd6..37ec6c0f015 100644
--- a/src/test/ui/structs/struct-fields-shorthand-unresolved.stderr
+++ b/src/test/ui/structs/struct-fields-shorthand-unresolved.stderr
@@ -2,7 +2,7 @@ error[E0425]: cannot find value `y` in this scope
   --> $DIR/struct-fields-shorthand-unresolved.rs:10:9
    |
 LL |         y //~ ERROR cannot find value `y` in this scope
-   |         ^ did you mean `x`?
+   |         ^ help: a local variable with a similar name exists: `x`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/trait-impl-for-module.stderr b/src/test/ui/traits/trait-impl-for-module.stderr
index 3f9407e6835..99da4b7c87a 100644
--- a/src/test/ui/traits/trait-impl-for-module.stderr
+++ b/src/test/ui/traits/trait-impl-for-module.stderr
@@ -2,7 +2,7 @@ error[E0573]: expected type, found module `a`
   --> $DIR/trait-impl-for-module.rs:7:12
    |
 LL | impl A for a { //~ ERROR expected type, found module
-   |            ^ did you mean `A`?
+   |            ^ help: a trait with a similar name exists: `A`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.stderr b/src/test/ui/ufcs/ufcs-partially-resolved.stderr
index a576fdde117..3cd1cac71fa 100644
--- a/src/test/ui/ufcs/ufcs-partially-resolved.stderr
+++ b/src/test/ui/ufcs/ufcs-partially-resolved.stderr
@@ -14,7 +14,7 @@ error[E0576]: cannot find associated type `N` in trait `Tr`
   --> $DIR/ufcs-partially-resolved.rs:19:24
    |
 LL |     let _: <u8 as Tr>::N; //~ ERROR cannot find associated type `N` in trait `Tr`
-   |                        ^ did you mean `Y`?
+   |                        ^ help: an associated type with a similar name exists: `Y`
 
 error[E0576]: cannot find associated type `N` in enum `E`
   --> $DIR/ufcs-partially-resolved.rs:20:23
@@ -32,7 +32,7 @@ error[E0576]: cannot find method or associated constant `N` in trait `Tr`
   --> $DIR/ufcs-partially-resolved.rs:22:17
    |
 LL |     <u8 as Tr>::N; //~ ERROR cannot find method or associated constant `N` in trait `Tr`
-   |                 ^ did you mean `Y`?
+   |                 ^ help: a method with a similar name exists: `Y`
 
 error[E0576]: cannot find method or associated constant `N` in enum `E`
   --> $DIR/ufcs-partially-resolved.rs:23:16
@@ -62,7 +62,7 @@ error[E0576]: cannot find associated type `N` in trait `Tr`
   --> $DIR/ufcs-partially-resolved.rs:30:24
    |
 LL |     let _: <u8 as Tr>::N::NN; //~ ERROR cannot find associated type `N` in trait `Tr`
-   |                        ^ did you mean `Y`?
+   |                        ^ help: an associated type with a similar name exists: `Y`
 
 error[E0576]: cannot find associated type `N` in enum `E`
   --> $DIR/ufcs-partially-resolved.rs:31:23
@@ -80,7 +80,7 @@ error[E0576]: cannot find associated type `N` in trait `Tr`
   --> $DIR/ufcs-partially-resolved.rs:33:17
    |
 LL |     <u8 as Tr>::N::NN; //~ ERROR cannot find associated type `N` in trait `Tr`
-   |                 ^ did you mean `Y`?
+   |                 ^ help: an associated type with a similar name exists: `Y`
 
 error[E0576]: cannot find associated type `N` in enum `E`
   --> $DIR/ufcs-partially-resolved.rs:34:16
@@ -160,7 +160,7 @@ error[E0575]: expected associated type, found method `Dr::Z`
 LL |     let _: <u8 as Dr>::Z; //~ ERROR expected associated type, found method `Dr::Z`
    |            ^^^^^^^^^^^^-
    |                        |
-   |                        did you mean `X`?
+   |                        help: an associated type with a similar name exists: `X`
 
 error[E0575]: expected method or associated constant, found associated type `Dr::X`
   --> $DIR/ufcs-partially-resolved.rs:53:5
@@ -168,7 +168,7 @@ error[E0575]: expected method or associated constant, found associated type `Dr:
 LL |     <u8 as Dr>::X; //~ ERROR expected method or associated constant, found associated type `Dr::X`
    |     ^^^^^^^^^^^^-
    |                 |
-   |                 did you mean `Z`?
+   |                 help: a method with a similar name exists: `Z`
    |
    = note: can't use a type alias as a constructor
 
@@ -178,7 +178,7 @@ error[E0575]: expected associated type, found method `Dr::Z`
 LL |     let _: <u8 as Dr>::Z::N; //~ ERROR expected associated type, found method `Dr::Z`
    |            ^^^^^^^^^^^^-^^^
    |                        |
-   |                        did you mean `X`?
+   |                        help: an associated type with a similar name exists: `X`
 
 error[E0223]: ambiguous associated type
   --> $DIR/ufcs-partially-resolved.rs:36:12
diff --git a/src/test/ui/ui-testing-optout.stderr b/src/test/ui/ui-testing-optout.stderr
index 3233715d325..5a662e0ea89 100644
--- a/src/test/ui/ui-testing-optout.stderr
+++ b/src/test/ui/ui-testing-optout.stderr
@@ -2,19 +2,19 @@ error[E0412]: cannot find type `B` in this scope
  --> $DIR/ui-testing-optout.rs:4:10
   |
 4 | type A = B; //~ ERROR
-  |          ^ did you mean `A`?
+  |          ^ help: a type alias with a similar name exists: `A`
 
 error[E0412]: cannot find type `D` in this scope
   --> $DIR/ui-testing-optout.rs:10:10
    |
 10 | type C = D; //~ ERROR
-   |          ^ did you mean `A`?
+   |          ^ help: a type alias with a similar name exists: `A`
 
 error[E0412]: cannot find type `F` in this scope
   --> $DIR/ui-testing-optout.rs:95:10
    |
 95 | type E = F; //~ ERROR
-   |          ^ did you mean `A`?
+   |          ^ help: a type alias with a similar name exists: `A`
 
 error: aborting due to 3 previous errors