about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-04-19 20:15:11 +0000
committerbors <bors@rust-lang.org>2019-04-19 20:15:11 +0000
commit8aaae4294b16b8070a52b858364f440873bfc95c (patch)
treef5a111e9d7c6f22094470312420842e9de67b423
parent130dc3e7dac132cf30272ccf4541b512828e2108 (diff)
parentaa393b0cde881c612379d90ca300396cd7ce2e96 (diff)
downloadrust-8aaae4294b16b8070a52b858364f440873bfc95c.tar.gz
rust-8aaae4294b16b8070a52b858364f440873bfc95c.zip
Auto merge of #59981 - estebank:recover-struct-lit, r=petrochenkov
Emit specific error for struct literal in conditions

Fix #59962, fix #51311.
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs4
-rw-r--r--src/librustc_resolve/diagnostics.rs161
-rw-r--r--src/libsyntax/parse/parser.rs53
-rw-r--r--src/test/ui/error-codes/E0423.rs6
-rw-r--r--src/test/ui/error-codes/E0423.stderr54
-rw-r--r--src/test/ui/parser/struct-literal-in-for.rs6
-rw-r--r--src/test/ui/parser/struct-literal-in-for.stderr41
-rw-r--r--src/test/ui/parser/struct-literal-in-if.rs6
-rw-r--r--src/test/ui/parser/struct-literal-in-if.stderr34
-rw-r--r--src/test/ui/parser/struct-literal-in-match-discriminant.rs10
-rw-r--r--src/test/ui/parser/struct-literal-in-match-discriminant.stderr47
-rw-r--r--src/test/ui/parser/struct-literal-in-while.rs7
-rw-r--r--src/test/ui/parser/struct-literal-in-while.stderr41
-rw-r--r--src/test/ui/parser/struct-literal-restrictions-in-lamda.rs7
-rw-r--r--src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr48
-rw-r--r--src/test/ui/struct-literal-variant-in-if.rs25
-rw-r--r--src/test/ui/struct-literal-variant-in-if.stderr73
17 files changed, 341 insertions, 282 deletions
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index fe39e3ae0c6..a2f6d9713f0 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -897,8 +897,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                         self.cannot_borrow_path_as_mutable(error_span, &descr, Origin::Ast)
                     }
                     BorrowViolation(euv::ClosureInvocation) => {
-                        span_bug!(err.span,
-                            "err_mutbl with a closure invocation");
+                        span_bug!(err.span, "err_mutbl with a closure invocation");
                     }
                 };
 
@@ -1096,7 +1095,6 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
             BorrowViolation(euv::MatchDiscriminant) => {
                 "cannot borrow data mutably"
             }
-
             BorrowViolation(euv::ClosureInvocation) => {
                 is_closure = true;
                 "closure invocation"
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 9b02f98164f..c89c222ad57 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -240,6 +240,56 @@ impl<'a> Resolver<'a> {
         (err, candidates)
     }
 
+    fn followed_by_brace(&self, span: Span) -> (bool, Option<(Span, String)>) {
+        // HACK(estebank): find a better way to figure out that this was a
+        // parser issue where a struct literal is being used on an expression
+        // where a brace being opened means a block is being started. Look
+        // ahead for the next text to see if `span` is followed by a `{`.
+        let sm = self.session.source_map();
+        let mut sp = span;
+        loop {
+            sp = sm.next_point(sp);
+            match sm.span_to_snippet(sp) {
+                Ok(ref snippet) => {
+                    if snippet.chars().any(|c| { !c.is_whitespace() }) {
+                        break;
+                    }
+                }
+                _ => break,
+            }
+        }
+        let followed_by_brace = match sm.span_to_snippet(sp) {
+            Ok(ref snippet) if snippet == "{" => true,
+            _ => false,
+        };
+        // In case this could be a struct literal that needs to be surrounded
+        // by parenthesis, find the appropriate span.
+        let mut i = 0;
+        let mut closing_brace = None;
+        loop {
+            sp = sm.next_point(sp);
+            match sm.span_to_snippet(sp) {
+                Ok(ref snippet) => {
+                    if snippet == "}" {
+                        let sp = span.to(sp);
+                        if let Ok(snippet) = sm.span_to_snippet(sp) {
+                            closing_brace = Some((sp, snippet));
+                        }
+                        break;
+                    }
+                }
+                _ => break,
+            }
+            i += 1;
+            // The bigger the span, the more likely we're incorrect --
+            // bound it to 100 chars long.
+            if i > 100 {
+                break;
+            }
+        }
+        return (followed_by_brace, closing_brace)
+    }
+
     /// Provides context-dependent help for errors reported by the `smart_resolve_path_fragment`
     /// function.
     /// Returns `true` if able to provide context-dependent help.
@@ -278,6 +328,39 @@ impl<'a> Resolver<'a> {
             _ => false,
         };
 
+        let mut bad_struct_syntax_suggestion = || {
+            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(None) if followed_by_brace == true => {
+                    if let Some((sp, snippet)) = closing_brace {
+                        err.span_suggestion(
+                            sp,
+                            "surround the struct literal with parenthesis",
+                            format!("({})", snippet),
+                            Applicability::MaybeIncorrect,
+                        );
+                    } else {
+                        err.span_label(
+                            span,  // Note the parenthesis surrounding the suggestion below
+                            format!("did you mean `({} {{ /* fields */ }})`?", path_str),
+                        );
+                    }
+                    suggested = true;
+                },
+                _ => {}
+            }
+            if !suggested {
+                err.span_label(
+                    span,
+                    format!("did you mean `{} {{ /* fields */ }}`?", path_str),
+                );
+            }
+        };
+
         match (def, source) {
             (Def::Macro(..), _) => {
                 err.span_suggestion(
@@ -331,87 +414,13 @@ impl<'a> Resolver<'a> {
                         );
                     }
                 } else {
-                    // HACK(estebank): find a better way to figure out that this was a
-                    // parser issue where a struct literal is being used on an expression
-                    // where a brace being opened means a block is being started. Look
-                    // ahead for the next text to see if `span` is followed by a `{`.
-                    let sm = self.session.source_map();
-                    let mut sp = span;
-                    loop {
-                        sp = sm.next_point(sp);
-                        match sm.span_to_snippet(sp) {
-                            Ok(ref snippet) => {
-                                if snippet.chars().any(|c| { !c.is_whitespace() }) {
-                                    break;
-                                }
-                            }
-                            _ => break,
-                        }
-                    }
-                    let followed_by_brace = match sm.span_to_snippet(sp) {
-                        Ok(ref snippet) if snippet == "{" => true,
-                        _ => false,
-                    };
-                    // In case this could be a struct literal that needs to be surrounded
-                    // by parenthesis, find the appropriate span.
-                    let mut i = 0;
-                    let mut closing_brace = None;
-                    loop {
-                        sp = sm.next_point(sp);
-                        match sm.span_to_snippet(sp) {
-                            Ok(ref snippet) => {
-                                if snippet == "}" {
-                                    let sp = span.to(sp);
-                                    if let Ok(snippet) = sm.span_to_snippet(sp) {
-                                        closing_brace = Some((sp, snippet));
-                                    }
-                                    break;
-                                }
-                            }
-                            _ => break,
-                        }
-                        i += 1;
-                        // The bigger the span, the more likely we're incorrect --
-                        // bound it to 100 chars long.
-                        if i > 100 {
-                            break;
-                        }
-                    }
-                    match source {
-                        PathSource::Expr(Some(parent)) => if !path_sep(err, &parent) {
-                            err.span_label(
-                                span,
-                                format!("did you mean `{} {{ /* fields */ }}`?", path_str),
-                            );
-                        }
-                        PathSource::Expr(None) if followed_by_brace == true => {
-                            if let Some((sp, snippet)) = closing_brace {
-                                err.span_suggestion(
-                                    sp,
-                                    "surround the struct literal with parenthesis",
-                                    format!("({})", snippet),
-                                    Applicability::MaybeIncorrect,
-                                );
-                            } else {
-                                err.span_label(
-                                    span,
-                                    format!("did you mean `({} {{ /* fields */ }})`?", path_str),
-                                );
-                            }
-                        },
-                        _ => {
-                            err.span_label(
-                                span,
-                                format!("did you mean `{} {{ /* fields */ }}`?", path_str),
-                            );
-                        },
-                    }
+                    bad_struct_syntax_suggestion();
                 }
             }
             (Def::Union(..), _) |
             (Def::Variant(..), _) |
             (Def::Ctor(_, _, CtorKind::Fictive), _) if ns == ValueNS => {
-                err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?", path_str));
+                bad_struct_syntax_suggestion();
             }
             (Def::SelfTy(..), _) if ns == ValueNS => {
                 err.span_label(span, fallback_label);
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index a5adb37f745..8feab373e71 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2855,11 +2855,13 @@ impl<'a> Parser<'a> {
                         let (delim, tts) = self.expect_delimited_token_tree()?;
                         hi = self.prev_span;
                         ex = ExprKind::Mac(respan(lo.to(hi), Mac_ { path, tts, delim }));
-                    } else if self.check(&token::OpenDelim(token::Brace)) &&
-                              !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL) {
-                        // This is a struct literal, unless we're prohibited
-                        // from parsing struct literals here.
-                        return self.parse_struct_expr(lo, path, attrs);
+                    } else if self.check(&token::OpenDelim(token::Brace)) {
+                        if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) {
+                            return expr;
+                        } else {
+                            hi = path.span;
+                            ex = ExprKind::Path(None, path);
+                        }
                     } else {
                         hi = path.span;
                         ex = ExprKind::Path(None, path);
@@ -2902,6 +2904,47 @@ impl<'a> Parser<'a> {
         self.maybe_recover_from_bad_qpath(expr, true)
     }
 
+    fn maybe_parse_struct_expr(
+        &mut self,
+        lo: Span,
+        path: &ast::Path,
+        attrs: &ThinVec<Attribute>,
+    ) -> Option<PResult<'a, P<Expr>>> {
+        let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
+        let certainly_not_a_block = || self.look_ahead(1, |t| t.is_ident()) && (
+            // `{ ident, ` cannot start a block
+            self.look_ahead(2, |t| t == &token::Comma) ||
+            self.look_ahead(2, |t| t == &token::Colon) && (
+                // `{ ident: token, ` cannot start a block
+                self.look_ahead(4, |t| t == &token::Comma) ||
+                // `{ ident: ` cannot start a block unless it's a type ascription `ident: Type`
+                self.look_ahead(3, |t| !t.can_begin_type())
+            )
+        );
+
+        if struct_allowed || certainly_not_a_block() {
+            // This is a struct literal, but we don't can't accept them here
+            let expr = self.parse_struct_expr(lo, path.clone(), attrs.clone());
+            if let (Ok(expr), false) = (&expr, struct_allowed) {
+                let mut err = self.diagnostic().struct_span_err(
+                    expr.span,
+                    "struct literals are not allowed here",
+                );
+                err.multipart_suggestion(
+                    "surround the struct literal with parenthesis",
+                    vec![
+                        (lo.shrink_to_lo(), "(".to_string()),
+                        (expr.span.shrink_to_hi(), ")".to_string()),
+                    ],
+                    Applicability::MachineApplicable,
+                );
+                err.emit();
+            }
+            return Some(expr);
+        }
+        None
+    }
+
     fn parse_struct_expr(&mut self, lo: Span, pth: ast::Path, mut attrs: ThinVec<Attribute>)
                          -> PResult<'a, P<Expr>> {
         let struct_sp = lo.to(self.prev_span);
diff --git a/src/test/ui/error-codes/E0423.rs b/src/test/ui/error-codes/E0423.rs
index 2b26808d4bd..5080a5e0599 100644
--- a/src/test/ui/error-codes/E0423.rs
+++ b/src/test/ui/error-codes/E0423.rs
@@ -10,8 +10,7 @@ fn bar() {
     struct T {}
 
     if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
-    //~^ ERROR E0423
-    //~|  expected type, found `1`
+    //~^ ERROR struct literals are not allowed here
     if T {} == T {} { println!("Ok"); }
     //~^ ERROR E0423
     //~| ERROR expected expression, found `==`
@@ -19,6 +18,5 @@ fn bar() {
 
 fn foo() {
     for _ in std::ops::Range { start: 0, end: 10 } {}
-    //~^ ERROR E0423
-    //~| ERROR expected type, found `0`
+    //~^ ERROR struct literals are not allowed here
 }
diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr
index b0ef4e1b254..5cb7121a0d1 100644
--- a/src/test/ui/error-codes/E0423.stderr
+++ b/src/test/ui/error-codes/E0423.stderr
@@ -1,36 +1,28 @@
-error: expected type, found `1`
-  --> $DIR/E0423.rs:12:39
+error: struct literals are not allowed here
+  --> $DIR/E0423.rs:12:32
    |
 LL |     if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
-   |                                       ^ expecting a type here because of type ascription
-   |
-   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
-note: this expression expects an ascribed type after the colon
-  --> $DIR/E0423.rs:12:36
+   |                                ^^^^^^^^^^^^^^^^
+help: surround the struct literal with parenthesis
    |
-LL |     if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
-   |                                    ^
-   = help: this might be indicative of a syntax error elsewhere
+LL |     if let S { x: _x, y: 2 } = (S { x: 1, y: 2 }) { println!("Ok"); }
+   |                                ^                ^
 
 error: expected expression, found `==`
-  --> $DIR/E0423.rs:15:13
+  --> $DIR/E0423.rs:14:13
    |
 LL |     if T {} == T {} { println!("Ok"); }
    |             ^^ expected expression
 
-error: expected type, found `0`
-  --> $DIR/E0423.rs:21:39
+error: struct literals are not allowed here
+  --> $DIR/E0423.rs:20:14
    |
 LL |     for _ in std::ops::Range { start: 0, end: 10 } {}
-   |                                       ^ expecting a type here because of type ascription
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: surround the struct literal with parenthesis
    |
-   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
-note: this expression expects an ascribed type after the colon
-  --> $DIR/E0423.rs:21:32
-   |
-LL |     for _ in std::ops::Range { start: 0, end: 10 } {}
-   |                                ^^^^^
-   = help: this might be indicative of a syntax error elsewhere
+LL |     for _ in (std::ops::Range { start: 0, end: 10 }) {}
+   |              ^                                     ^
 
 error[E0423]: expected function, found struct `Foo`
   --> $DIR/E0423.rs:4:13
@@ -41,30 +33,14 @@ LL |     let f = 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
-   |
-LL |     if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
-   |                                ^---------------
-   |                                |
-   |                                help: surround the struct literal with parenthesis: `(S { x: 1, y: 2 })`
-
 error[E0423]: expected value, found struct `T`
-  --> $DIR/E0423.rs:15:8
+  --> $DIR/E0423.rs:14:8
    |
 LL |     if T {} == T {} { println!("Ok"); }
    |        ^---
    |        |
    |        help: surround the struct literal with parenthesis: `(T {})`
 
-error[E0423]: expected value, found struct `std::ops::Range`
-  --> $DIR/E0423.rs:21:14
-   |
-LL |     for _ in std::ops::Range { start: 0, end: 10 } {}
-   |              ^^^^^^^^^^^^^^^----------------------
-   |              |
-   |              help: surround the struct literal with parenthesis: `(std::ops::Range { start: 0, end: 10 })`
-
-error: aborting due to 7 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/parser/struct-literal-in-for.rs b/src/test/ui/parser/struct-literal-in-for.rs
index 526b5e75c45..3227ae37bfd 100644
--- a/src/test/ui/parser/struct-literal-in-for.rs
+++ b/src/test/ui/parser/struct-literal-in-for.rs
@@ -9,9 +9,9 @@ impl Foo {
 }
 
 fn main() {
-    for x in Foo { //~ ERROR expected value, found struct `Foo`
-        x: 3    //~ ERROR expected type, found `3`
-    }.hi() { //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
+    for x in Foo { //~ ERROR struct literals are not allowed here
+        x: 3       //~^ ERROR `bool` is not an iterator
+    }.hi() {
         println!("yo");
     }
 }
diff --git a/src/test/ui/parser/struct-literal-in-for.stderr b/src/test/ui/parser/struct-literal-in-for.stderr
index 07f2e41ac4f..3c3f6e7f032 100644
--- a/src/test/ui/parser/struct-literal-in-for.stderr
+++ b/src/test/ui/parser/struct-literal-in-for.stderr
@@ -1,29 +1,30 @@
-error: expected type, found `3`
-  --> $DIR/struct-literal-in-for.rs:13:12
-   |
-LL |         x: 3
-   |            ^ expecting a type here because of type ascription
+error: struct literals are not allowed here
+  --> $DIR/struct-literal-in-for.rs:12:14
    |
-   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
-note: this expression expects an ascribed type after the colon
-  --> $DIR/struct-literal-in-for.rs:13:9
+LL |       for x in Foo {
+   |  ______________^
+LL | |         x: 3
+LL | |     }.hi() {
+   | |_____^
+help: surround the struct literal with parenthesis
    |
+LL |     for x in (Foo {
 LL |         x: 3
-   |         ^
-   = help: this might be indicative of a syntax error elsewhere
-
-error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
-  --> $DIR/struct-literal-in-for.rs:14:12
+LL |     }).hi() {
    |
-LL |     }.hi() {
-   |            ^ expected one of `.`, `;`, `?`, `}`, or an operator here
 
-error[E0423]: expected value, found struct `Foo`
+error[E0277]: `bool` is not an iterator
   --> $DIR/struct-literal-in-for.rs:12:14
    |
-LL |     for x in Foo {
-   |              ^^^ did you mean `(Foo { /* fields */ })`?
+LL |       for x in Foo {
+   |  ______________^
+LL | |         x: 3
+LL | |     }.hi() {
+   | |__________^ `bool` is not an iterator
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `bool`
+   = note: required by `std::iter::IntoIterator::into_iter`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0423`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/parser/struct-literal-in-if.rs b/src/test/ui/parser/struct-literal-in-if.rs
index 362a71c577f..2ce2c8f1899 100644
--- a/src/test/ui/parser/struct-literal-in-if.rs
+++ b/src/test/ui/parser/struct-literal-in-if.rs
@@ -9,9 +9,9 @@ impl Foo {
 }
 
 fn main() {
-    if Foo { //~ ERROR expected value, found struct `Foo`
-        x: 3    //~ ERROR expected type, found `3`
-    }.hi() { //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
+    if Foo { //~ ERROR struct literals are not allowed here
+        x: 3
+    }.hi() {
         println!("yo");
     }
 }
diff --git a/src/test/ui/parser/struct-literal-in-if.stderr b/src/test/ui/parser/struct-literal-in-if.stderr
index 3dd61e74f12..851c495abb4 100644
--- a/src/test/ui/parser/struct-literal-in-if.stderr
+++ b/src/test/ui/parser/struct-literal-in-if.stderr
@@ -1,29 +1,17 @@
-error: expected type, found `3`
-  --> $DIR/struct-literal-in-if.rs:13:12
-   |
-LL |         x: 3
-   |            ^ expecting a type here because of type ascription
+error: struct literals are not allowed here
+  --> $DIR/struct-literal-in-if.rs:12:8
    |
-   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
-note: this expression expects an ascribed type after the colon
-  --> $DIR/struct-literal-in-if.rs:13:9
+LL |       if Foo {
+   |  ________^
+LL | |         x: 3
+LL | |     }.hi() {
+   | |_____^
+help: surround the struct literal with parenthesis
    |
+LL |     if (Foo {
 LL |         x: 3
-   |         ^
-   = help: this might be indicative of a syntax error elsewhere
-
-error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
-  --> $DIR/struct-literal-in-if.rs:14:12
-   |
-LL |     }.hi() {
-   |            ^ expected one of `.`, `;`, `?`, `}`, or an operator here
-
-error[E0423]: expected value, found struct `Foo`
-  --> $DIR/struct-literal-in-if.rs:12:8
+LL |     }).hi() {
    |
-LL |     if Foo {
-   |        ^^^ did you mean `(Foo { /* fields */ })`?
 
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/parser/struct-literal-in-match-discriminant.rs b/src/test/ui/parser/struct-literal-in-match-discriminant.rs
index 35a11090351..ce132df5a88 100644
--- a/src/test/ui/parser/struct-literal-in-match-discriminant.rs
+++ b/src/test/ui/parser/struct-literal-in-match-discriminant.rs
@@ -3,11 +3,11 @@ struct Foo {
 }
 
 fn main() {
-    match Foo { //~ ERROR expected value, found struct `Foo`
-        x: 3    //~ ERROR expected one of `=>`, `@`, `if`, or `|`, found `:`
+    match Foo { //~ ERROR struct literals are not allowed here
+        x: 3
     } {
-        Foo { //~ ERROR mismatched types
-            x: x //~ ERROR cannot find value `x` in this scope
-        } => {} //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `=>`
+        Foo {
+            x: x
+        } => {}
     }
 }
diff --git a/src/test/ui/parser/struct-literal-in-match-discriminant.stderr b/src/test/ui/parser/struct-literal-in-match-discriminant.stderr
index d061591e510..0058e8981cd 100644
--- a/src/test/ui/parser/struct-literal-in-match-discriminant.stderr
+++ b/src/test/ui/parser/struct-literal-in-match-discriminant.stderr
@@ -1,42 +1,17 @@
-error: expected one of `=>`, `@`, `if`, or `|`, found `:`
-  --> $DIR/struct-literal-in-match-discriminant.rs:7:10
-   |
-LL |         x: 3
-   |          ^ expected one of `=>`, `@`, `if`, or `|` here
-
-error: expected one of `.`, `;`, `?`, `}`, or an operator, found `=>`
-  --> $DIR/struct-literal-in-match-discriminant.rs:11:11
-   |
-LL |         } => {}
-   |           ^^ expected one of `.`, `;`, `?`, `}`, or an operator here
-
-error[E0423]: expected value, found struct `Foo`
+error: struct literals are not allowed here
   --> $DIR/struct-literal-in-match-discriminant.rs:6:11
    |
-LL |     match Foo {
-   |           ^^^ did you mean `(Foo { /* fields */ })`?
-
-error[E0425]: cannot find value `x` in this scope
-  --> $DIR/struct-literal-in-match-discriminant.rs:10:16
-   |
-LL |             x: x
-   |                ^ not found in this scope
-
-error[E0308]: mismatched types
-  --> $DIR/struct-literal-in-match-discriminant.rs:9:9
+LL |       match Foo {
+   |  ___________^
+LL | |         x: 3
+LL | |     } {
+   | |_____^
+help: surround the struct literal with parenthesis
    |
-LL |   fn main() {
-   |             - expected `()` because of default return type
-...
-LL | /         Foo {
-LL | |             x: x
-LL | |         } => {}
-   | |_________^ expected (), found struct `Foo`
+LL |     match (Foo {
+LL |         x: 3
+LL |     }) {
    |
-   = note: expected type `()`
-              found type `Foo`
 
-error: aborting due to 5 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0308, E0423, E0425.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/struct-literal-in-while.rs b/src/test/ui/parser/struct-literal-in-while.rs
index 561cdcea089..5000ce85b7f 100644
--- a/src/test/ui/parser/struct-literal-in-while.rs
+++ b/src/test/ui/parser/struct-literal-in-while.rs
@@ -9,10 +9,9 @@ impl Foo {
 }
 
 fn main() {
-    while Foo { //~ ERROR expected value, found struct `Foo`
-        x: 3    //~ ERROR expected type, found `3`
-    }.hi() { //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
-             //~| ERROR no method named `hi` found for type `()` in the current scope
+    while Foo { //~ ERROR struct literals are not allowed here
+        x: 3
+    }.hi() {
         println!("yo");
     }
 }
diff --git a/src/test/ui/parser/struct-literal-in-while.stderr b/src/test/ui/parser/struct-literal-in-while.stderr
index c07975331f8..9959a57be85 100644
--- a/src/test/ui/parser/struct-literal-in-while.stderr
+++ b/src/test/ui/parser/struct-literal-in-while.stderr
@@ -1,36 +1,17 @@
-error: expected type, found `3`
-  --> $DIR/struct-literal-in-while.rs:13:12
-   |
-LL |         x: 3
-   |            ^ expecting a type here because of type ascription
+error: struct literals are not allowed here
+  --> $DIR/struct-literal-in-while.rs:12:11
    |
-   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
-note: this expression expects an ascribed type after the colon
-  --> $DIR/struct-literal-in-while.rs:13:9
+LL |       while Foo {
+   |  ___________^
+LL | |         x: 3
+LL | |     }.hi() {
+   | |_____^
+help: surround the struct literal with parenthesis
    |
+LL |     while (Foo {
 LL |         x: 3
-   |         ^
-   = help: this might be indicative of a syntax error elsewhere
-
-error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
-  --> $DIR/struct-literal-in-while.rs:14:12
-   |
-LL |     }.hi() {
-   |            ^ expected one of `.`, `;`, `?`, `}`, or an operator here
-
-error[E0423]: expected value, found struct `Foo`
-  --> $DIR/struct-literal-in-while.rs:12:11
-   |
-LL |     while Foo {
-   |           ^^^ did you mean `(Foo { /* fields */ })`?
-
-error[E0599]: no method named `hi` found for type `()` in the current scope
-  --> $DIR/struct-literal-in-while.rs:14:7
+LL |     }).hi() {
    |
-LL |     }.hi() {
-   |       ^^
 
-error: aborting due to 4 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0423, E0599.
-For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/parser/struct-literal-restrictions-in-lamda.rs b/src/test/ui/parser/struct-literal-restrictions-in-lamda.rs
index e5049082ab0..e185153dcf6 100644
--- a/src/test/ui/parser/struct-literal-restrictions-in-lamda.rs
+++ b/src/test/ui/parser/struct-literal-restrictions-in-lamda.rs
@@ -9,10 +9,9 @@ impl Foo {
 }
 
 fn main() {
-    while || Foo { //~ ERROR expected value, found struct `Foo`
-        x: 3    //~ ERROR expected type, found `3`
-    }.hi() { //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
-             //~| ERROR no method named `hi` found for type `()` in the current scope
+    while || Foo { //~ ERROR struct literals are not allowed here
+        x: 3       //~^ ERROR mismatched types
+    }.hi() {
         println!("yo");
     }
 }
diff --git a/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr b/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr
index 977875dd938..81f7a91ddb3 100644
--- a/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr
+++ b/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr
@@ -1,36 +1,30 @@
-error: expected type, found `3`
-  --> $DIR/struct-literal-restrictions-in-lamda.rs:13:12
-   |
-LL |         x: 3
-   |            ^ expecting a type here because of type ascription
+error: struct literals are not allowed here
+  --> $DIR/struct-literal-restrictions-in-lamda.rs:12:14
    |
-   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
-note: this expression expects an ascribed type after the colon
-  --> $DIR/struct-literal-restrictions-in-lamda.rs:13:9
+LL |       while || Foo {
+   |  ______________^
+LL | |         x: 3
+LL | |     }.hi() {
+   | |_____^
+help: surround the struct literal with parenthesis
    |
+LL |     while || (Foo {
 LL |         x: 3
-   |         ^
-   = help: this might be indicative of a syntax error elsewhere
-
-error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
-  --> $DIR/struct-literal-restrictions-in-lamda.rs:14:12
+LL |     }).hi() {
    |
-LL |     }.hi() {
-   |            ^ expected one of `.`, `;`, `?`, `}`, or an operator here
 
-error[E0423]: expected value, found struct `Foo`
-  --> $DIR/struct-literal-restrictions-in-lamda.rs:12:14
+error[E0308]: mismatched types
+  --> $DIR/struct-literal-restrictions-in-lamda.rs:12:11
    |
-LL |     while || Foo {
-   |              ^^^ did you mean `(Foo { /* fields */ })`?
-
-error[E0599]: no method named `hi` found for type `()` in the current scope
-  --> $DIR/struct-literal-restrictions-in-lamda.rs:14:7
+LL |       while || Foo {
+   |  ___________^
+LL | |         x: 3
+LL | |     }.hi() {
+   | |__________^ expected bool, found closure
    |
-LL |     }.hi() {
-   |       ^^
+   = note: expected type `bool`
+              found type `[closure@$DIR/struct-literal-restrictions-in-lamda.rs:12:11: 14:11]`
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0423, E0599.
-For more information about an error, try `rustc --explain E0423`.
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/struct-literal-variant-in-if.rs b/src/test/ui/struct-literal-variant-in-if.rs
new file mode 100644
index 00000000000..4ef8effaf1f
--- /dev/null
+++ b/src/test/ui/struct-literal-variant-in-if.rs
@@ -0,0 +1,25 @@
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+enum E {
+    V { field: bool },
+    I { field1: bool, field2: usize },
+    J { field: isize },
+    K { field: &'static str},
+}
+fn test_E(x: E) {
+    let field = true;
+    if x == E::V { field } {}
+    //~^ ERROR expected value, found struct variant `E::V`
+    //~| ERROR mismatched types
+    if x == E::I { field1: true, field2: 42 } {}
+    //~^ ERROR struct literals are not allowed here
+    if x == E::V { field: false } {}
+    //~^ ERROR struct literals are not allowed here
+    if x == E::J { field: -42 } {}
+    //~^ ERROR struct literals are not allowed here
+    if x == E::K { field: "" } {}
+    //~^ ERROR struct literals are not allowed here
+    let y: usize = ();
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/struct-literal-variant-in-if.stderr b/src/test/ui/struct-literal-variant-in-if.stderr
new file mode 100644
index 00000000000..55f23baea7a
--- /dev/null
+++ b/src/test/ui/struct-literal-variant-in-if.stderr
@@ -0,0 +1,73 @@
+error: struct literals are not allowed here
+  --> $DIR/struct-literal-variant-in-if.rs:13:13
+   |
+LL |     if x == E::I { field1: true, field2: 42 } {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: surround the struct literal with parenthesis
+   |
+LL |     if x == (E::I { field1: true, field2: 42 }) {}
+   |             ^                                 ^
+
+error: struct literals are not allowed here
+  --> $DIR/struct-literal-variant-in-if.rs:15:13
+   |
+LL |     if x == E::V { field: false } {}
+   |             ^^^^^^^^^^^^^^^^^^^^^
+help: surround the struct literal with parenthesis
+   |
+LL |     if x == (E::V { field: false }) {}
+   |             ^                     ^
+
+error: struct literals are not allowed here
+  --> $DIR/struct-literal-variant-in-if.rs:17:13
+   |
+LL |     if x == E::J { field: -42 } {}
+   |             ^^^^^^^^^^^^^^^^^^^
+help: surround the struct literal with parenthesis
+   |
+LL |     if x == (E::J { field: -42 }) {}
+   |             ^                   ^
+
+error: struct literals are not allowed here
+  --> $DIR/struct-literal-variant-in-if.rs:19:13
+   |
+LL |     if x == E::K { field: "" } {}
+   |             ^^^^^^^^^^^^^^^^^^
+help: surround the struct literal with parenthesis
+   |
+LL |     if x == (E::K { field: "" }) {}
+   |             ^                  ^
+
+error[E0423]: expected value, found struct variant `E::V`
+  --> $DIR/struct-literal-variant-in-if.rs:10:13
+   |
+LL |     if x == E::V { field } {}
+   |             ^^^^----------
+   |             |
+   |             help: surround the struct literal with parenthesis: `(E::V { field })`
+
+error[E0308]: mismatched types
+  --> $DIR/struct-literal-variant-in-if.rs:10:20
+   |
+LL | fn test_E(x: E) {
+   |                 - help: try adding a return type: `-> bool`
+LL |     let field = true;
+LL |     if x == E::V { field } {}
+   |                    ^^^^^ expected (), found bool
+   |
+   = note: expected type `()`
+              found type `bool`
+
+error[E0308]: mismatched types
+  --> $DIR/struct-literal-variant-in-if.rs:21:20
+   |
+LL |     let y: usize = ();
+   |                    ^^ expected usize, found ()
+   |
+   = note: expected type `usize`
+              found type `()`
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0308, E0423.
+For more information about an error, try `rustc --explain E0308`.