about summary refs log tree commit diff
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2020-07-14 13:19:22 -0700
committerGitHub <noreply@github.com>2020-07-14 13:19:22 -0700
commitbe5c7abfd6c5d366f90cf5b44543a7af2120852e (patch)
tree41bdbb37318928e26a6576bd374cfcd465ec81a2
parent353df59893f4dc249f06047dca659b5b2172063f (diff)
parent04298204ed17eeed4d23aaa45fb0db9336e6583c (diff)
downloadrust-be5c7abfd6c5d366f90cf5b44543a7af2120852e.tar.gz
rust-be5c7abfd6c5d366f90cf5b44543a7af2120852e.zip
Rollup merge of #74211 - estebank:struct-pat-as-unit, r=petrochenkov
Structured suggestion when not using struct pattern

r? @petrochenkov
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs6
-rw-r--r--src/librustc_resolve/late.rs16
-rw-r--r--src/librustc_resolve/late/diagnostics.rs68
-rw-r--r--src/test/ui/empty/empty-struct-braces-expr.stderr60
-rw-r--r--src/test/ui/empty/empty-struct-braces-pat-1.stderr16
-rw-r--r--src/test/ui/empty/empty-struct-braces-pat-2.stderr72
-rw-r--r--src/test/ui/empty/empty-struct-braces-pat-3.stderr42
-rw-r--r--src/test/ui/error-codes/E0423.stderr15
-rw-r--r--src/test/ui/issues/issue-19086.stderr2
-rw-r--r--src/test/ui/issues/issue-34334.stderr2
-rw-r--r--src/test/ui/issues/issue-63983.stderr2
-rw-r--r--src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr15
-rw-r--r--src/test/ui/namespace/namespace-mix.stderr12
-rw-r--r--src/test/ui/parser/recover-from-bad-variant.stderr2
-rw-r--r--src/test/ui/resolve/issue-18252.stderr2
-rw-r--r--src/test/ui/resolve/issue-19452.stderr4
-rw-r--r--src/test/ui/resolve/issue-39226.stderr12
-rw-r--r--src/test/ui/resolve/issue-6702.stderr2
-rw-r--r--src/test/ui/resolve/privacy-enum-ctor.stderr8
-rw-r--r--src/test/ui/resolve/privacy-struct-ctor.stderr2
-rw-r--r--src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr14
-rw-r--r--src/test/ui/suggestions/issue-61226.stderr2
-rw-r--r--src/test/ui/xcrate/xcrate-unit-struct.stderr2
23 files changed, 239 insertions, 139 deletions
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index bca65c63e91..8db27babd05 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -300,9 +300,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
     }
 
     fn insert_field_names(&mut self, def_id: DefId, field_names: Vec<Spanned<Symbol>>) {
-        if !field_names.is_empty() {
-            self.r.field_names.insert(def_id, field_names);
-        }
+        self.r.field_names.insert(def_id, field_names);
     }
 
     fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
@@ -1428,6 +1426,8 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
         let ctor_kind = CtorKind::from_ast(&variant.data);
         let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id);
         self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id));
+        // Record field names for error reporting.
+        self.insert_field_names_local(ctor_def_id, &variant.data);
 
         visit::walk_variant(self, variant);
     }
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 679f5637686..71c71fe4ce6 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -184,7 +184,7 @@ crate enum PathSource<'a> {
     // Paths in struct expressions and patterns `Path { .. }`.
     Struct,
     // Paths in tuple struct patterns `Path(..)`.
-    TupleStruct,
+    TupleStruct(Span),
     // `m::A::B` in `<T as m::A>::B::C`.
     TraitItem(Namespace),
 }
@@ -193,7 +193,7 @@ impl<'a> PathSource<'a> {
     fn namespace(self) -> Namespace {
         match self {
             PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS,
-            PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct => ValueNS,
+            PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct(_) => ValueNS,
             PathSource::TraitItem(ns) => ns,
         }
     }
@@ -204,7 +204,7 @@ impl<'a> PathSource<'a> {
             | PathSource::Expr(..)
             | PathSource::Pat
             | PathSource::Struct
-            | PathSource::TupleStruct => true,
+            | PathSource::TupleStruct(_) => true,
             PathSource::Trait(_) | PathSource::TraitItem(..) => false,
         }
     }
@@ -215,7 +215,7 @@ impl<'a> PathSource<'a> {
             PathSource::Trait(_) => "trait",
             PathSource::Pat => "unit struct, unit variant or constant",
             PathSource::Struct => "struct, variant or union type",
-            PathSource::TupleStruct => "tuple struct or tuple variant",
+            PathSource::TupleStruct(_) => "tuple struct or tuple variant",
             PathSource::TraitItem(ns) => match ns {
                 TypeNS => "associated type",
                 ValueNS => "method or associated constant",
@@ -301,7 +301,7 @@ impl<'a> PathSource<'a> {
                 | Res::SelfCtor(..) => true,
                 _ => false,
             },
-            PathSource::TupleStruct => match res {
+            PathSource::TupleStruct(_) => match res {
                 Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Res::SelfCtor(..) => true,
                 _ => false,
             },
@@ -336,8 +336,8 @@ impl<'a> PathSource<'a> {
             (PathSource::Struct, false) => error_code!(E0422),
             (PathSource::Expr(..), true) => error_code!(E0423),
             (PathSource::Expr(..), false) => error_code!(E0425),
-            (PathSource::Pat | PathSource::TupleStruct, true) => error_code!(E0532),
-            (PathSource::Pat | PathSource::TupleStruct, false) => error_code!(E0531),
+            (PathSource::Pat | PathSource::TupleStruct(_), true) => error_code!(E0532),
+            (PathSource::Pat | PathSource::TupleStruct(_), false) => error_code!(E0531),
             (PathSource::TraitItem(..), true) => error_code!(E0575),
             (PathSource::TraitItem(..), false) => error_code!(E0576),
         }
@@ -1483,7 +1483,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                     self.r.record_partial_res(pat.id, PartialRes::new(res));
                 }
                 PatKind::TupleStruct(ref path, ..) => {
-                    self.smart_resolve_path(pat.id, None, path, PathSource::TupleStruct);
+                    self.smart_resolve_path(pat.id, None, path, PathSource::TupleStruct(pat.span));
                 }
                 PatKind::Path(ref qself, ref path) => {
                     self.smart_resolve_path(pat.id, qself.as_ref(), path, PathSource::Pat);
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index fc41ce5d535..918b5941a79 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -480,10 +480,12 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
 
         let mut bad_struct_syntax_suggestion = |def_id: DefId| {
             let (followed_by_brace, closing_brace) = self.followed_by_brace(span);
-            let mut suggested = false;
+
             match source {
-                PathSource::Expr(Some(parent)) => {
-                    suggested = path_sep(err, &parent);
+                PathSource::Expr(Some(
+                    parent @ Expr { kind: ExprKind::Field(..) | ExprKind::MethodCall(..), .. },
+                )) => {
+                    path_sep(err, &parent);
                 }
                 PathSource::Expr(None) if followed_by_brace => {
                     if let Some(sp) = closing_brace {
@@ -505,15 +507,56 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
                             ),
                         );
                     }
-                    suggested = true;
                 }
-                _ => {}
-            }
-            if !suggested {
-                if let Some(span) = self.r.opt_span(def_id) {
-                    err.span_label(span, &format!("`{}` defined here", path_str));
+                PathSource::Expr(
+                    None | Some(Expr { kind: ExprKind::Call(..) | ExprKind::Path(..), .. }),
+                )
+                | PathSource::TupleStruct(_)
+                | PathSource::Pat => {
+                    let span = match &source {
+                        PathSource::Expr(Some(Expr {
+                            span, kind: ExprKind::Call(_, _), ..
+                        }))
+                        | PathSource::TupleStruct(span) => {
+                            // We want the main underline to cover the suggested code as well for
+                            // cleaner output.
+                            err.set_span(*span);
+                            *span
+                        }
+                        _ => span,
+                    };
+                    if let Some(span) = self.r.opt_span(def_id) {
+                        err.span_label(span, &format!("`{}` defined here", path_str));
+                    }
+                    let (tail, descr, applicability) = match source {
+                        PathSource::Pat | PathSource::TupleStruct(_) => {
+                            ("", "pattern", Applicability::MachineApplicable)
+                        }
+                        _ => (": val", "literal", Applicability::HasPlaceholders),
+                    };
+                    let (fields, applicability) = match self.r.field_names.get(&def_id) {
+                        Some(fields) => (
+                            fields
+                                .iter()
+                                .map(|f| format!("{}{}", f.node, tail))
+                                .collect::<Vec<String>>()
+                                .join(", "),
+                            applicability,
+                        ),
+                        None => ("/* fields */".to_string(), Applicability::HasPlaceholders),
+                    };
+                    let pad = match self.r.field_names.get(&def_id) {
+                        Some(fields) if fields.is_empty() => "",
+                        _ => " ",
+                    };
+                    err.span_suggestion(
+                        span,
+                        &format!("use struct {} syntax instead", descr),
+                        format!("{} {{{pad}{}{pad}}}", path_str, fields, pad = pad),
+                        applicability,
+                    );
                 }
-                err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?", path_str));
+                _ => {}
             }
         };
 
@@ -546,7 +589,10 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
                     return false;
                 }
             }
-            (Res::Def(DefKind::Enum, def_id), PathSource::TupleStruct | PathSource::Expr(..)) => {
+            (
+                Res::Def(DefKind::Enum, def_id),
+                PathSource::TupleStruct(_) | PathSource::Expr(..),
+            ) => {
                 if let Some(variants) = self.collect_enum_variants(def_id) {
                     if !variants.is_empty() {
                         let msg = if variants.len() == 1 {
diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr
index 9da3a5f5bdb..c0ba9716fb0 100644
--- a/src/test/ui/empty/empty-struct-braces-expr.stderr
+++ b/src/test/ui/empty/empty-struct-braces-expr.stderr
@@ -6,14 +6,20 @@ LL | struct Empty1 {}
 ...
 LL |     let e1 = Empty1;
    |              ^^^^^^
-   |              |
-   |              did you mean `Empty1 { /* fields */ }`?
-   |              help: a unit struct with a similar name exists: `XEmpty2`
    | 
   ::: $DIR/auxiliary/empty-struct.rs:2:1
    |
 LL | pub struct XEmpty2;
    | ------------------- similarly named unit struct `XEmpty2` defined here
+   |
+help: a unit struct with a similar name exists
+   |
+LL |     let e1 = XEmpty2;
+   |              ^^^^^^^
+help: use struct literal syntax instead
+   |
+LL |     let e1 = Empty1 {};
+   |              ^^^^^^^^^
 
 error[E0423]: expected function, tuple struct or tuple variant, found struct `Empty1`
   --> $DIR/empty-struct-braces-expr.rs:16:14
@@ -22,15 +28,16 @@ LL | struct Empty1 {}
    | ---------------- `Empty1` defined here
 ...
 LL |     let e1 = Empty1();
-   |              ^^^^^^
-   |              |
-   |              did you mean `Empty1 { /* fields */ }`?
-   |              help: a unit struct with a similar name exists: `XEmpty2`
-   | 
-  ::: $DIR/auxiliary/empty-struct.rs:2:1
+   |              ^^^^^^^^
    |
-LL | pub struct XEmpty2;
-   | ------------------- similarly named unit struct `XEmpty2` defined here
+help: a unit struct with a similar name exists
+   |
+LL |     let e1 = XEmpty2();
+   |              ^^^^^^^
+help: use struct literal syntax instead
+   |
+LL |     let e1 = Empty1 {};
+   |              ^^^^^^^^^
 
 error[E0423]: expected value, found struct variant `E::Empty3`
   --> $DIR/empty-struct-braces-expr.rs:18:14
@@ -39,7 +46,7 @@ LL |     Empty3 {}
    |     --------- `E::Empty3` defined here
 ...
 LL |     let e3 = E::Empty3;
-   |              ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`?
+   |              ^^^^^^^^^ help: use struct literal syntax instead: `E::Empty3 {}`
 
 error[E0423]: expected function, tuple struct or tuple variant, found struct variant `E::Empty3`
   --> $DIR/empty-struct-braces-expr.rs:19:14
@@ -48,35 +55,42 @@ LL |     Empty3 {}
    |     --------- `E::Empty3` defined here
 ...
 LL |     let e3 = E::Empty3();
-   |              ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`?
+   |              ^^^^^^^^^^^ help: use struct literal syntax instead: `E::Empty3 {}`
 
 error[E0423]: expected value, found struct `XEmpty1`
   --> $DIR/empty-struct-braces-expr.rs:22:15
    |
 LL |     let xe1 = XEmpty1;
    |               ^^^^^^^
-   |               |
-   |               did you mean `XEmpty1 { /* fields */ }`?
-   |               help: a unit struct with a similar name exists: `XEmpty2`
    | 
   ::: $DIR/auxiliary/empty-struct.rs:2:1
    |
 LL | pub struct XEmpty2;
    | ------------------- similarly named unit struct `XEmpty2` defined here
+   |
+help: a unit struct with a similar name exists
+   |
+LL |     let xe1 = XEmpty2;
+   |               ^^^^^^^
+help: use struct literal syntax instead
+   |
+LL |     let xe1 = XEmpty1 {};
+   |               ^^^^^^^^^^
 
 error[E0423]: expected function, tuple struct or tuple variant, found struct `XEmpty1`
   --> $DIR/empty-struct-braces-expr.rs:23:15
    |
 LL |     let xe1 = XEmpty1();
+   |               ^^^^^^^^^
+   |
+help: a unit struct with a similar name exists
+   |
+LL |     let xe1 = XEmpty2();
    |               ^^^^^^^
-   |               |
-   |               did you mean `XEmpty1 { /* fields */ }`?
-   |               help: a unit struct with a similar name exists: `XEmpty2`
-   | 
-  ::: $DIR/auxiliary/empty-struct.rs:2:1
+help: use struct literal syntax instead
    |
-LL | pub struct XEmpty2;
-   | ------------------- similarly named unit struct `XEmpty2` defined here
+LL |     let xe1 = XEmpty1 {};
+   |               ^^^^^^^^^^
 
 error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:25: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 0ff21c91b78..b027c82f7dd 100644
--- a/src/test/ui/empty/empty-struct-braces-pat-1.stderr
+++ b/src/test/ui/empty/empty-struct-braces-pat-1.stderr
@@ -5,21 +5,27 @@ LL |     Empty3 {}
    |     --------- `E::Empty3` defined here
 ...
 LL |         E::Empty3 => ()
-   |         ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`?
+   |         ^^^^^^^^^ help: use struct pattern syntax instead: `E::Empty3 {}`
 
 error[E0532]: expected unit struct, unit variant or constant, found struct variant `XE::XEmpty3`
   --> $DIR/empty-struct-braces-pat-1.rs:31:9
    |
 LL |         XE::XEmpty3 => ()
-   |         ^^^^-------
-   |         |   |
-   |         |   help: a unit variant with a similar name exists: `XEmpty4`
-   |         did you mean `XE::XEmpty3 { /* fields */ }`?
+   |         ^^^^^^^^^^^
    | 
   ::: $DIR/auxiliary/empty-struct.rs:7:5
    |
 LL |     XEmpty4,
    |     ------- similarly named unit variant `XEmpty4` defined here
+   |
+help: a unit variant with a similar name exists
+   |
+LL |         XE::XEmpty4 => ()
+   |             ^^^^^^^
+help: use struct pattern syntax instead
+   |
+LL |         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 80c29db8d9b..a53b88db7d1 100644
--- a/src/test/ui/empty/empty-struct-braces-pat-2.stderr
+++ b/src/test/ui/empty/empty-struct-braces-pat-2.stderr
@@ -5,29 +5,31 @@ LL | struct Empty1 {}
    | ---------------- `Empty1` defined here
 ...
 LL |         Empty1() => ()
-   |         ^^^^^^
-   |         |
-   |         did you mean `Empty1 { /* fields */ }`?
-   |         help: a tuple struct with a similar name exists: `XEmpty6`
-   | 
-  ::: $DIR/auxiliary/empty-struct.rs:3:1
-   |
-LL | pub struct XEmpty6();
-   | --------------------- similarly named tuple struct `XEmpty6` defined here
+   |         ^^^^^^^^
+   |
+help: a tuple struct with a similar name exists
+   |
+LL |         XEmpty6() => ()
+   |         ^^^^^^^
+help: use struct pattern syntax instead
+   |
+LL |         Empty1 {} => ()
+   |         ^^^^^^^^^
 
 error[E0532]: expected tuple struct or tuple variant, found struct `XEmpty1`
   --> $DIR/empty-struct-braces-pat-2.rs:18:9
    |
 LL |         XEmpty1() => ()
+   |         ^^^^^^^^^
+   |
+help: a tuple struct with a similar name exists
+   |
+LL |         XEmpty6() => ()
    |         ^^^^^^^
-   |         |
-   |         did you mean `XEmpty1 { /* fields */ }`?
-   |         help: a tuple struct with a similar name exists: `XEmpty6`
-   | 
-  ::: $DIR/auxiliary/empty-struct.rs:3:1
-   |
-LL | pub struct XEmpty6();
-   | --------------------- similarly named tuple struct `XEmpty6` defined here
+help: use struct pattern syntax instead
+   |
+LL |         XEmpty1 {} => ()
+   |         ^^^^^^^^^^
 
 error[E0532]: expected tuple struct or tuple variant, found struct `Empty1`
   --> $DIR/empty-struct-braces-pat-2.rs:21:9
@@ -36,29 +38,31 @@ LL | struct Empty1 {}
    | ---------------- `Empty1` defined here
 ...
 LL |         Empty1(..) => ()
-   |         ^^^^^^
-   |         |
-   |         did you mean `Empty1 { /* fields */ }`?
-   |         help: a tuple struct with a similar name exists: `XEmpty6`
-   | 
-  ::: $DIR/auxiliary/empty-struct.rs:3:1
-   |
-LL | pub struct XEmpty6();
-   | --------------------- similarly named tuple struct `XEmpty6` defined here
+   |         ^^^^^^^^^^
+   |
+help: a tuple struct with a similar name exists
+   |
+LL |         XEmpty6(..) => ()
+   |         ^^^^^^^
+help: use struct pattern syntax instead
+   |
+LL |         Empty1 {} => ()
+   |         ^^^^^^^^^
 
 error[E0532]: expected tuple struct or tuple variant, found struct `XEmpty1`
   --> $DIR/empty-struct-braces-pat-2.rs:24:9
    |
 LL |         XEmpty1(..) => ()
+   |         ^^^^^^^^^^^
+   |
+help: a tuple struct with a similar name exists
+   |
+LL |         XEmpty6(..) => ()
    |         ^^^^^^^
-   |         |
-   |         did you mean `XEmpty1 { /* fields */ }`?
-   |         help: a tuple struct with a similar name exists: `XEmpty6`
-   | 
-  ::: $DIR/auxiliary/empty-struct.rs:3:1
-   |
-LL | pub struct XEmpty6();
-   | --------------------- similarly named tuple struct `XEmpty6` defined here
+help: use struct pattern syntax instead
+   |
+LL |         XEmpty1 {} => ()
+   |         ^^^^^^^^^^
 
 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 05439b39ea3..93ace3eccef 100644
--- a/src/test/ui/empty/empty-struct-braces-pat-3.stderr
+++ b/src/test/ui/empty/empty-struct-braces-pat-3.stderr
@@ -5,21 +5,22 @@ LL |     Empty3 {}
    |     --------- `E::Empty3` defined here
 ...
 LL |         E::Empty3() => ()
-   |         ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`?
+   |         ^^^^^^^^^^^ help: use struct pattern syntax instead: `E::Empty3 {}`
 
 error[E0532]: expected tuple struct or tuple variant, found struct variant `XE::XEmpty3`
   --> $DIR/empty-struct-braces-pat-3.rs:21:9
    |
 LL |         XE::XEmpty3() => ()
-   |         ^^^^-------
-   |         |   |
-   |         |   help: a tuple variant with a similar name exists: `XEmpty5`
-   |         did you mean `XE::XEmpty3 { /* fields */ }`?
-   | 
-  ::: $DIR/auxiliary/empty-struct.rs:8:5
-   |
-LL |     XEmpty5(),
-   |     --------- similarly named tuple variant `XEmpty5` defined here
+   |         ^^^^^^^^^^^^^
+   |
+help: a tuple variant with a similar name exists
+   |
+LL |         XE::XEmpty5() => ()
+   |             ^^^^^^^
+help: use struct pattern syntax instead
+   |
+LL |         XE::XEmpty3 { /* fields */ } => ()
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0532]: expected tuple struct or tuple variant, found struct variant `E::Empty3`
   --> $DIR/empty-struct-braces-pat-3.rs:25:9
@@ -28,21 +29,22 @@ LL |     Empty3 {}
    |     --------- `E::Empty3` defined here
 ...
 LL |         E::Empty3(..) => ()
-   |         ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`?
+   |         ^^^^^^^^^^^^^ help: use struct pattern syntax instead: `E::Empty3 {}`
 
 error[E0532]: expected tuple struct or tuple variant, found struct variant `XE::XEmpty3`
   --> $DIR/empty-struct-braces-pat-3.rs:29:9
    |
 LL |         XE::XEmpty3(..) => ()
-   |         ^^^^-------
-   |         |   |
-   |         |   help: a tuple variant with a similar name exists: `XEmpty5`
-   |         did you mean `XE::XEmpty3 { /* fields */ }`?
-   | 
-  ::: $DIR/auxiliary/empty-struct.rs:8:5
-   |
-LL |     XEmpty5(),
-   |     --------- similarly named tuple variant `XEmpty5` defined here
+   |         ^^^^^^^^^^^^^^^
+   |
+help: a tuple variant with a similar name exists
+   |
+LL |         XE::XEmpty5(..) => ()
+   |             ^^^^^^^
+help: use struct pattern syntax instead
+   |
+LL |         XE::XEmpty3 { /* fields */ } => ()
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr
index d4860394259..077367de9d8 100644
--- a/src/test/ui/error-codes/E0423.stderr
+++ b/src/test/ui/error-codes/E0423.stderr
@@ -33,13 +33,16 @@ LL |     struct Foo { a: bool };
    |     ---------------------- `Foo` defined here
 LL | 
 LL |     let f = Foo();
+   |             ^^^^^
+   |
+help: a function with a similar name exists
+   |
+LL |     let f = foo();
    |             ^^^
-   |             |
-   |             did you mean `Foo { /* fields */ }`?
-   |             help: a function with a similar name exists (notice the capitalization): `foo`
-...
-LL | fn foo() {
-   | -------- similarly named function `foo` defined here
+help: use struct literal syntax instead
+   |
+LL |     let f = Foo { a: val };
+   |             ^^^^^^^^^^^^^^
 
 error[E0423]: expected value, found struct `T`
   --> $DIR/E0423.rs:14:8
diff --git a/src/test/ui/issues/issue-19086.stderr b/src/test/ui/issues/issue-19086.stderr
index 27992da0ebd..a54f1008e4b 100644
--- a/src/test/ui/issues/issue-19086.stderr
+++ b/src/test/ui/issues/issue-19086.stderr
@@ -5,7 +5,7 @@ LL |     FooB { x: i32, y: i32 }
    |     ----------------------- `FooB` defined here
 ...
 LL |         FooB(a, b) => println!("{} {}", a, b),
-   |         ^^^^ did you mean `FooB { /* fields */ }`?
+   |         ^^^^^^^^^^ help: use struct pattern syntax instead: `FooB { x, y }`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr
index c68b271807b..5f157f6e3c0 100644
--- a/src/test/ui/issues/issue-34334.stderr
+++ b/src/test/ui/issues/issue-34334.stderr
@@ -23,7 +23,7 @@ error[E0423]: expected value, found struct `Vec`
   --> $DIR/issue-34334.rs:2:13
    |
 LL |     let sr: Vec<(u32, _, _) = vec![];
-   |             ^^^ did you mean `Vec { /* fields */ }`?
+   |             ^^^ help: use struct literal syntax instead: `Vec { buf: val, len: val }`
 
 error[E0308]: mismatched types
   --> $DIR/issue-34334.rs:2:31
diff --git a/src/test/ui/issues/issue-63983.stderr b/src/test/ui/issues/issue-63983.stderr
index e54466faedd..771a5c285af 100644
--- a/src/test/ui/issues/issue-63983.stderr
+++ b/src/test/ui/issues/issue-63983.stderr
@@ -14,7 +14,7 @@ LL |     Struct{ s: i32 },
    |     ---------------- `MyEnum::Struct` defined here
 ...
 LL |         MyEnum::Struct => "",
-   |         ^^^^^^^^^^^^^^ did you mean `MyEnum::Struct { /* fields */ }`?
+   |         ^^^^^^^^^^^^^^ help: use struct pattern syntax instead: `MyEnum::Struct { s }`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr b/src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr
index 44e5d38abbc..12053d8a129 100644
--- a/src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr
+++ b/src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr
@@ -5,11 +5,16 @@ LL | struct X {}
    | ----------- `X` defined here
 LL | 
 LL | const Y: X = X("ö");
-   | -------------^------
-   | |            |
-   | |            did you mean `X { /* fields */ }`?
-   | |            help: a constant with a similar name exists: `Y`
-   | similarly named constant `Y` defined here
+   |              ^^^^^^
+   |
+help: a constant with a similar name exists
+   |
+LL | const Y: X = Y("ö");
+   |              ^
+help: use struct literal syntax instead
+   |
+LL | const Y: X = X {};
+   |              ^^^^
 
 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 ee730910ee4..636789c9cc3 100644
--- a/src/test/ui/namespace/namespace-mix.stderr
+++ b/src/test/ui/namespace/namespace-mix.stderr
@@ -51,12 +51,16 @@ LL |         TV(),
    |         ---- similarly named tuple variant `TV` defined here
 ...
 LL |     check(m7::V);
-   |           ^^^^^ did you mean `m7::V { /* fields */ }`?
+   |           ^^^^^
    |
 help: a tuple variant with a similar name exists
    |
 LL |     check(m7::TV);
    |               ^^
+help: use struct literal syntax instead
+   |
+LL |     check(m7::V {});
+   |           ^^^^^^^^
 help: consider importing one of these items instead
    |
 LL | use m8::V;
@@ -68,7 +72,7 @@ error[E0423]: expected value, found struct variant `xm7::V`
   --> $DIR/namespace-mix.rs:106:11
    |
 LL |     check(xm7::V);
-   |           ^^^^^^ did you mean `xm7::V { /* fields */ }`?
+   |           ^^^^^^
    | 
   ::: $DIR/auxiliary/namespace-mix.rs:7:9
    |
@@ -79,6 +83,10 @@ help: a tuple variant with a similar name exists
    |
 LL |     check(xm7::TV);
    |                ^^
+help: use struct literal syntax instead
+   |
+LL |     check(xm7::V { /* fields */ });
+   |           ^^^^^^^^^^^^^^^^^^^^^^^
 help: consider importing one of these items instead
    |
 LL | use m8::V;
diff --git a/src/test/ui/parser/recover-from-bad-variant.stderr b/src/test/ui/parser/recover-from-bad-variant.stderr
index 0272326c7bc..6986d966d69 100644
--- a/src/test/ui/parser/recover-from-bad-variant.stderr
+++ b/src/test/ui/parser/recover-from-bad-variant.stderr
@@ -16,7 +16,7 @@ LL |     Foo { a: usize, b: usize },
    |     -------------------------- `Enum::Foo` defined here
 ...
 LL |         Enum::Foo(a, b) => {}
-   |         ^^^^^^^^^ did you mean `Enum::Foo { /* fields */ }`?
+   |         ^^^^^^^^^^^^^^^ help: use struct pattern syntax instead: `Enum::Foo { a, b }`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/resolve/issue-18252.stderr b/src/test/ui/resolve/issue-18252.stderr
index 39b44449810..13e7a59732d 100644
--- a/src/test/ui/resolve/issue-18252.stderr
+++ b/src/test/ui/resolve/issue-18252.stderr
@@ -5,7 +5,7 @@ LL |     Variant { x: usize }
    |     -------------------- `Foo::Variant` defined here
 ...
 LL |     let f = Foo::Variant(42);
-   |             ^^^^^^^^^^^^ did you mean `Foo::Variant { /* fields */ }`?
+   |             ^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `Foo::Variant { x: val }`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/issue-19452.stderr b/src/test/ui/resolve/issue-19452.stderr
index 4d20f158026..d1690d4eef7 100644
--- a/src/test/ui/resolve/issue-19452.stderr
+++ b/src/test/ui/resolve/issue-19452.stderr
@@ -5,13 +5,13 @@ LL |     Madoka { age: u32 }
    |     ------------------- `Homura::Madoka` defined here
 ...
 LL |     let homura = Homura::Madoka;
-   |                  ^^^^^^^^^^^^^^ did you mean `Homura::Madoka { /* fields */ }`?
+   |                  ^^^^^^^^^^^^^^ help: use struct literal syntax instead: `Homura::Madoka { age: val }`
 
 error[E0423]: expected value, found struct variant `issue_19452_aux::Homura::Madoka`
   --> $DIR/issue-19452.rs:13:18
    |
 LL |     let homura = issue_19452_aux::Homura::Madoka;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `issue_19452_aux::Homura::Madoka { /* fields */ }`?
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `issue_19452_aux::Homura::Madoka { /* fields */ }`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/resolve/issue-39226.stderr b/src/test/ui/resolve/issue-39226.stderr
index d9a28e63dce..c9b9aeb45ba 100644
--- a/src/test/ui/resolve/issue-39226.stderr
+++ b/src/test/ui/resolve/issue-39226.stderr
@@ -6,9 +6,15 @@ LL | struct Handle {}
 ...
 LL |         handle: Handle
    |                 ^^^^^^
-   |                 |
-   |                 did you mean `Handle { /* fields */ }`?
-   |                 help: a local variable with a similar name exists: `handle`
+   |
+help: a local variable with a similar name exists
+   |
+LL |         handle: handle
+   |                 ^^^^^^
+help: use struct literal syntax instead
+   |
+LL |         handle: Handle {}
+   |                 ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/issue-6702.stderr b/src/test/ui/resolve/issue-6702.stderr
index 252d50c70f8..a118f94191d 100644
--- a/src/test/ui/resolve/issue-6702.stderr
+++ b/src/test/ui/resolve/issue-6702.stderr
@@ -7,7 +7,7 @@ LL | | }
    | |_- `Monster` defined here
 ...
 LL |       let _m = Monster();
-   |                ^^^^^^^ did you mean `Monster { /* fields */ }`?
+   |                ^^^^^^^^^ help: use struct literal syntax instead: `Monster { damage: val }`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr
index 16baa6c9b62..3904a00dde1 100644
--- a/src/test/ui/resolve/privacy-enum-ctor.stderr
+++ b/src/test/ui/resolve/privacy-enum-ctor.stderr
@@ -44,7 +44,7 @@ LL | |             },
    | |_____________- `Z::Struct` defined here
 ...
 LL |           let _: Z = Z::Struct;
-   |                      ^^^^^^^^^ did you mean `Z::Struct { /* fields */ }`?
+   |                      ^^^^^^^^^ help: use struct literal syntax instead: `Z::Struct { s: val }`
 
 error[E0423]: expected value, found enum `m::E`
   --> $DIR/privacy-enum-ctor.rs:41:16
@@ -83,7 +83,7 @@ LL | |         },
    | |_________- `m::E::Struct` defined here
 ...
 LL |       let _: E = m::E::Struct;
-   |                  ^^^^^^^^^^^^ did you mean `m::E::Struct { /* fields */ }`?
+   |                  ^^^^^^^^^^^^ help: use struct literal syntax instead: `m::E::Struct { s: val }`
 
 error[E0423]: expected value, found enum `E`
   --> $DIR/privacy-enum-ctor.rs:49:16
@@ -115,7 +115,7 @@ LL | |         },
    | |_________- `E::Struct` defined here
 ...
 LL |       let _: E = E::Struct;
-   |                  ^^^^^^^^^ did you mean `E::Struct { /* fields */ }`?
+   |                  ^^^^^^^^^ help: use struct literal syntax instead: `E::Struct { s: val }`
 
 error[E0412]: cannot find type `Z` in this scope
   --> $DIR/privacy-enum-ctor.rs:57:12
@@ -195,7 +195,7 @@ LL | |             },
    | |_____________- `m::n::Z::Struct` defined here
 ...
 LL |       let _: Z = m::n::Z::Struct;
-   |                  ^^^^^^^^^^^^^^^ did you mean `m::n::Z::Struct { /* fields */ }`?
+   |                  ^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `m::n::Z::Struct { s: val }`
 
 error[E0412]: cannot find type `Z` in this scope
   --> $DIR/privacy-enum-ctor.rs:68:12
diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr
index e0305b129a8..a72f69cf1cd 100644
--- a/src/test/ui/resolve/privacy-struct-ctor.stderr
+++ b/src/test/ui/resolve/privacy-struct-ctor.stderr
@@ -25,7 +25,7 @@ LL | |     }
    | |_____- `S2` defined here
 ...
 LL |       S2;
-   |       ^^ did you mean `S2 { /* fields */ }`?
+   |       ^^ help: use struct literal syntax instead: `S2 { s: val }`
 
 error[E0423]: expected value, found struct `xcrate::S`
   --> $DIR/privacy-struct-ctor.rs:43:5
diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
index b03bea1eddb..45309486db4 100644
--- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
+++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
@@ -7,10 +7,16 @@ LL |     B { a: usize },
    |     -------------- `E::B` defined here
 ...
 LL |     let _: E = E::B;
-   |                ^^^-
-   |                |  |
-   |                |  help: a tuple variant with a similar name exists: `A`
-   |                did you mean `E::B { /* fields */ }`?
+   |                ^^^^
+   |
+help: a tuple variant with a similar name exists
+   |
+LL |     let _: E = E::A;
+   |                   ^
+help: use struct literal syntax instead
+   |
+LL |     let _: E = E::B { a: val };
+   |                ^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/fn-or-tuple-struct-without-args.rs:29:20
diff --git a/src/test/ui/suggestions/issue-61226.stderr b/src/test/ui/suggestions/issue-61226.stderr
index fbcfba6653f..7f6f082d7a8 100644
--- a/src/test/ui/suggestions/issue-61226.stderr
+++ b/src/test/ui/suggestions/issue-61226.stderr
@@ -5,7 +5,7 @@ LL | struct X {}
    | ----------- `X` defined here
 LL | fn main() {
 LL |     vec![X]; //…
-   |          ^ did you mean `X { /* fields */ }`?
+   |          ^ help: use struct literal syntax instead: `X {}`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/xcrate/xcrate-unit-struct.stderr b/src/test/ui/xcrate/xcrate-unit-struct.stderr
index e4a4b9c5806..813d5d4fdb1 100644
--- a/src/test/ui/xcrate/xcrate-unit-struct.stderr
+++ b/src/test/ui/xcrate/xcrate-unit-struct.stderr
@@ -2,7 +2,7 @@ error[E0423]: expected value, found struct `xcrate_unit_struct::StructWithFields
   --> $DIR/xcrate-unit-struct.rs:9:13
    |
 LL |     let _ = xcrate_unit_struct::StructWithFields;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `xcrate_unit_struct::StructWithFields { /* fields */ }`?
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `xcrate_unit_struct::StructWithFields { foo: val }`
 
 error: aborting due to previous error