about summary refs log tree commit diff
path: root/src/test/ui/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/parser')
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad-2.rs2
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad-2.stderr8
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad-3.rs2
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad-3.stderr8
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad.rs107
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad.stderr390
-rw-r--r--src/test/ui/parser/do-catch-suggests-try.rs7
-rw-r--r--src/test/ui/parser/do-catch-suggests-try.stderr17
-rw-r--r--src/test/ui/parser/issue-65257-invalid-var-decl-recovery.rs21
-rw-r--r--src/test/ui/parser/issue-65257-invalid-var-decl-recovery.stderr67
-rw-r--r--src/test/ui/parser/recover-labeled-non-block-expr.rs5
-rw-r--r--src/test/ui/parser/recover-labeled-non-block-expr.stderr17
-rw-r--r--src/test/ui/parser/recovery-attr-on-if.rs9
-rw-r--r--src/test/ui/parser/recovery-attr-on-if.stderr35
-rw-r--r--src/test/ui/parser/stmt_expr_attrs_placement.rs22
-rw-r--r--src/test/ui/parser/stmt_expr_attrs_placement.stderr10
16 files changed, 722 insertions, 5 deletions
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad-2.rs b/src/test/ui/parser/attr-stmt-expr-attr-bad-2.rs
new file mode 100644
index 00000000000..e5ac59ae463
--- /dev/null
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad-2.rs
@@ -0,0 +1,2 @@
+#[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
+//~^ ERROR unexpected token: `#`
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad-2.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad-2.stderr
new file mode 100644
index 00000000000..ca1043250ba
--- /dev/null
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad-2.stderr
@@ -0,0 +1,8 @@
+error: unexpected token: `#`
+  --> $DIR/attr-stmt-expr-attr-bad-2.rs:1:34
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
+   |                                  ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad-3.rs b/src/test/ui/parser/attr-stmt-expr-attr-bad-3.rs
new file mode 100644
index 00000000000..7dc71af52f4
--- /dev/null
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad-3.rs
@@ -0,0 +1,2 @@
+#[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
+//~^ ERROR unexpected token: `#`
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad-3.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad-3.stderr
new file mode 100644
index 00000000000..ab9366d042a
--- /dev/null
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad-3.stderr
@@ -0,0 +1,8 @@
+error: unexpected token: `#`
+  --> $DIR/attr-stmt-expr-attr-bad-3.rs:1:34
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
+   |                                  ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
new file mode 100644
index 00000000000..ef10010ed0e
--- /dev/null
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
@@ -0,0 +1,107 @@
+fn main() {}
+
+#[cfg(FALSE)] fn e() { let _ = box #![attr] 0; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = [#[attr]]; }
+//~^ ERROR expected expression, found `]`
+#[cfg(FALSE)] fn e() { let _ = foo#[attr](); }
+//~^ ERROR expected one of
+#[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
+//~^ ERROR an inner attribute is not permitted in this context
+//~| ERROR expected expression, found `)`
+#[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
+//~^ ERROR an inner attribute is not permitted in this context
+//~| ERROR expected expression, found `)`
+#[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = !#![attr] 0; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = -#![attr] 0; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = x #![attr] as Y; }
+//~^ ERROR expected one of
+#[cfg(FALSE)] fn e() { let _ = || #![attr] foo; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = #[attr] ..#[attr] 0; }
+//~^ ERROR expected expression, found `..`
+#[cfg(FALSE)] fn e() { let _ = #[attr] ..; }
+//~^ ERROR expected expression, found `..`
+#[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = #[attr] if 0 {}; }
+//~^ ERROR attributes are not yet allowed on `if` expressions
+#[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
+//~^ ERROR expected `{`, found `#`
+#[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; }
+//~^ ERROR expected one of
+#[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
+//~^ ERROR expected `{`, found `#`
+#[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
+//~^ ERROR attributes are not yet allowed on `if` expressions
+//~| ERROR expected `{`, found `#`
+#[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
+//~^ ERROR expected `{`, found `#`
+#[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = #[attr] if let _ = 0 {}; }
+//~^ ERROR attributes are not yet allowed on `if` expressions
+#[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
+//~^ ERROR expected `{`, found `#`
+#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
+//~^ ERROR expected one of
+#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
+//~^ ERROR expected `{`, found `#`
+#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
+//~^ ERROR an inner attribute is not permitted in this context
+#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
+//~^ ERROR attributes are not yet allowed on `if` expressions
+//~| ERROR expected `{`, found `#`
+#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
+//~^ ERROR expected `{`, found `#`
+#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
+//~^ ERROR an inner attribute is not permitted in this context
+
+#[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
+//~^ ERROR an inner attribute is not permitted following an outer attribute
+#[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
+//~^ ERROR an inner attribute is not permitted following an outer attribute
+#[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
+//~^ ERROR an inner attribute is not permitted following an outer attribute
+#[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
+//~^ ERROR an inner attribute is not permitted following an outer attribute
+#[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
+//~^ ERROR an inner attribute is not permitted following an outer attribute
+
+// FIXME: Allow attributes in pattern constexprs?
+// note: requires parens in patterns to allow disambiguation
+
+#[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
+//~^ ERROR `X..=` range patterns are not supported
+//~| ERROR expected one of `=>`, `if`, or `|`, found `#`
+#[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
+//~^ ERROR `X..=` range patterns are not supported
+//~| ERROR expected one of `=>`, `if`, or `|`, found `#`
+#[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
+//~^ ERROR unexpected token: `#`
+#[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
+//~^ ERROR `X..=` range patterns are not supported
+//~| ERROR expected one of `=>`, `if`, or `|`, found `#`
+
+// make sure we don't catch this bug again...
+#[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } }
+//~^ ERROR expected statement after outer attribute
+#[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } }
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
new file mode 100644
index 00000000000..9a0d3176714
--- /dev/null
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
@@ -0,0 +1,390 @@
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:3:36
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = box #![attr] 0; }
+   |                                    ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: expected expression, found `]`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:5:40
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = [#[attr]]; }
+   |                                        ^ expected expression
+
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:7:35
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = foo#[attr](); }
+   |                                   ^ expected one of 7 possible tokens
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:9:36
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
+   |                                    ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: expected expression, found `)`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:9:44
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
+   |                                            ^ expected expression
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:12:38
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
+   |                                      ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: expected expression, found `)`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:12:46
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
+   |                                              ^ expected expression
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:15:36
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; }
+   |                                    ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:17:33
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = !#![attr] 0; }
+   |                                 ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:19:33
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = -#![attr] 0; }
+   |                                 ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:21:34
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = x #![attr] as Y; }
+   |                                  ^ expected one of 7 possible tokens
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:23:35
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] foo; }
+   |                                   ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:25:40
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; }
+   |                                        ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:27:35
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; }
+   |                                   ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:29:40
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; }
+   |                                        ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: expected expression, found `..`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:31:40
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..#[attr] 0; }
+   |                                        ^^ expected expression
+
+error: expected expression, found `..`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:33:40
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..; }
+   |                                        ^^ expected expression
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:35:41
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; }
+   |                                         ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:37:45
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
+   |                                             ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: attributes are not yet allowed on `if` expressions
+  --> $DIR/attr-stmt-expr-attr-bad.rs:39:32
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if 0 {}; }
+   |                                ^^^^^^^
+
+error: expected `{`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:41:37
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
+   |                                --   ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                |    |
+   |                                |    expected `{`
+   |                                this `if` statement has a condition, but no block
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:43:38
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
+   |                                      ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:45:40
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; }
+   |                                        ^ expected one of `.`, `;`, `?`, `else`, or an operator
+
+error: expected `{`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:47:45
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
+   |                                             ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                             |
+   |                                             expected `{`
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:49:46
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
+   |                                              ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: attributes are not yet allowed on `if` expressions
+  --> $DIR/attr-stmt-expr-attr-bad.rs:51:45
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
+   |                                             ^^^^^^^
+
+error: expected `{`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:51:45
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
+   |                                             ^       -------- help: try placing this code inside a block: `{ if 0 {}; }`
+   |                                             |
+   |                                             expected `{`
+
+error: expected `{`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:54:50
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
+   |                                             --   ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                             |    |
+   |                                             |    expected `{`
+   |                                             this `if` statement has a condition, but no block
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:56:51
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
+   |                                                   ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: attributes are not yet allowed on `if` expressions
+  --> $DIR/attr-stmt-expr-attr-bad.rs:58:32
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if let _ = 0 {}; }
+   |                                ^^^^^^^
+
+error: expected `{`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:60:45
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
+   |                                --           ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                |            |
+   |                                |            expected `{`
+   |                                this `if` statement has a condition, but no block
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:62:46
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
+   |                                              ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:64:48
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
+   |                                                ^ expected one of `.`, `;`, `?`, `else`, or an operator
+
+error: expected `{`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:66:53
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
+   |                                                     ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                                     |
+   |                                                     expected `{`
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:68:54
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
+   |                                                      ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: attributes are not yet allowed on `if` expressions
+  --> $DIR/attr-stmt-expr-attr-bad.rs:70:53
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
+   |                                                     ^^^^^^^
+
+error: expected `{`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:70:53
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
+   |                                                     ^       ---------------- help: try placing this code inside a block: `{ if let _ = 0 {}; }`
+   |                                                     |
+   |                                                     expected `{`
+
+error: expected `{`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:73:66
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
+   |                                                     --           ^       --- help: try placing this code inside a block: `{ {}; }`
+   |                                                     |            |
+   |                                                     |            expected `{`
+   |                                                     this `if` statement has a condition, but no block
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/attr-stmt-expr-attr-bad.rs:75:67
+   |
+LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
+   |                                                                   ^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted following an outer attribute
+  --> $DIR/attr-stmt-expr-attr-bad.rs:78:32
+   |
+LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
+   |                        ------- ^^^^^^^^ not permitted following an outer attibute
+   |                        |
+   |                        previous outer attribute
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted following an outer attribute
+  --> $DIR/attr-stmt-expr-attr-bad.rs:80:32
+   |
+LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
+   |                        ------- ^^^^^^^^ not permitted following an outer attibute
+   |                        |
+   |                        previous outer attribute
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted following an outer attribute
+  --> $DIR/attr-stmt-expr-attr-bad.rs:82:32
+   |
+LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
+   |                        ------- ^^^^^^^^ not permitted following an outer attibute
+   |                        |
+   |                        previous outer attribute
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted following an outer attribute
+  --> $DIR/attr-stmt-expr-attr-bad.rs:84:32
+   |
+LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
+   |                        ------- ^^^^^^^^ not permitted following an outer attibute
+   |                        |
+   |                        previous outer attribute
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: an inner attribute is not permitted following an outer attribute
+  --> $DIR/attr-stmt-expr-attr-bad.rs:86:32
+   |
+LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
+   |                        ------- ^^^^^^^^ not permitted following an outer attibute
+   |                        |
+   |                        previous outer attribute
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: `X..=` range patterns are not supported
+  --> $DIR/attr-stmt-expr-attr-bad.rs:92:34
+   |
+LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
+   |                                  ^^^^ help: try using the maximum value for the type: `0..=MAX`
+
+error: expected one of `=>`, `if`, or `|`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:92:38
+   |
+LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
+   |                                      ^ expected one of `=>`, `if`, or `|`
+
+error: `X..=` range patterns are not supported
+  --> $DIR/attr-stmt-expr-attr-bad.rs:95:34
+   |
+LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
+   |                                  ^^^^ help: try using the maximum value for the type: `0..=MAX`
+
+error: expected one of `=>`, `if`, or `|`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:95:38
+   |
+LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
+   |                                      ^ expected one of `=>`, `if`, or `|`
+
+error: unexpected token: `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:98:39
+   |
+LL | #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
+   |                                       ^
+
+error: `X..=` range patterns are not supported
+  --> $DIR/attr-stmt-expr-attr-bad.rs:100:34
+   |
+LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
+   |                                  ^^^^ help: try using the maximum value for the type: `0..=MAX`
+
+error: expected one of `=>`, `if`, or `|`, found `#`
+  --> $DIR/attr-stmt-expr-attr-bad.rs:100:38
+   |
+LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
+   |                                      ^ expected one of `=>`, `if`, or `|`
+
+error: expected statement after outer attribute
+  --> $DIR/attr-stmt-expr-attr-bad.rs:105:44
+   |
+LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } }
+   |                                            ^
+
+error: aborting due to 52 previous errors
+
diff --git a/src/test/ui/parser/do-catch-suggests-try.rs b/src/test/ui/parser/do-catch-suggests-try.rs
index d805ab75882..f64568d06e9 100644
--- a/src/test/ui/parser/do-catch-suggests-try.rs
+++ b/src/test/ui/parser/do-catch-suggests-try.rs
@@ -1,5 +1,10 @@
+#![feature(try_blocks)]
+
 fn main() {
     let _: Option<()> = do catch {};
     //~^ ERROR found removed `do catch` syntax
-    //~^^ HELP following RFC #2388, the new non-placeholder syntax is `try`
+    //~| replace with the new syntax
+    //~| following RFC #2388, the new non-placeholder syntax is `try`
+
+    let _recovery_witness: () = 1; //~ ERROR mismatched types
 }
diff --git a/src/test/ui/parser/do-catch-suggests-try.stderr b/src/test/ui/parser/do-catch-suggests-try.stderr
index e151d4cf8a6..cd8907b7eac 100644
--- a/src/test/ui/parser/do-catch-suggests-try.stderr
+++ b/src/test/ui/parser/do-catch-suggests-try.stderr
@@ -1,10 +1,19 @@
 error: found removed `do catch` syntax
-  --> $DIR/do-catch-suggests-try.rs:2:25
+  --> $DIR/do-catch-suggests-try.rs:4:25
    |
 LL |     let _: Option<()> = do catch {};
-   |                         ^^
+   |                         ^^^^^^^^ help: replace with the new syntax: `try`
    |
-   = help: following RFC #2388, the new non-placeholder syntax is `try`
+   = note: following RFC #2388, the new non-placeholder syntax is `try`
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/do-catch-suggests-try.rs:9:33
+   |
+LL |     let _recovery_witness: () = 1;
+   |                            --   ^ expected `()`, found integer
+   |                            |
+   |                            expected due to this
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.rs b/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.rs
new file mode 100644
index 00000000000..c1826f8caae
--- /dev/null
+++ b/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.rs
@@ -0,0 +1,21 @@
+fn main() {
+    auto n = 0;//~ ERROR invalid variable declaration
+    //~^ HELP write `let` instead of `auto` to introduce a new variable
+    auto m;//~ ERROR invalid variable declaration
+    //~^ HELP write `let` instead of `auto` to introduce a new variable
+    m = 0;
+
+    var n = 0;//~ ERROR invalid variable declaration
+    //~^ HELP write `let` instead of `var` to introduce a new variable
+    var m;//~ ERROR invalid variable declaration
+    //~^ HELP write `let` instead of `var` to introduce a new variable
+    m = 0;
+
+    mut n = 0;//~ ERROR invalid variable declaration
+    //~^ HELP missing keyword
+    mut var;//~ ERROR invalid variable declaration
+    //~^ HELP missing keyword
+    var = 0;
+
+    let _recovery_witness: () = 0; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.stderr b/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.stderr
new file mode 100644
index 00000000000..ad72dd30542
--- /dev/null
+++ b/src/test/ui/parser/issue-65257-invalid-var-decl-recovery.stderr
@@ -0,0 +1,67 @@
+error: invalid variable declaration
+  --> $DIR/issue-65257-invalid-var-decl-recovery.rs:2:5
+   |
+LL |     auto n = 0;
+   |     ^^^^
+   |
+help: write `let` instead of `auto` to introduce a new variable
+   |
+LL |     let n = 0;
+   |     ^^^
+
+error: invalid variable declaration
+  --> $DIR/issue-65257-invalid-var-decl-recovery.rs:4:5
+   |
+LL |     auto m;
+   |     ^^^^
+   |
+help: write `let` instead of `auto` to introduce a new variable
+   |
+LL |     let m;
+   |     ^^^
+
+error: invalid variable declaration
+  --> $DIR/issue-65257-invalid-var-decl-recovery.rs:8:5
+   |
+LL |     var n = 0;
+   |     ^^^
+   |
+help: write `let` instead of `var` to introduce a new variable
+   |
+LL |     let n = 0;
+   |     ^^^
+
+error: invalid variable declaration
+  --> $DIR/issue-65257-invalid-var-decl-recovery.rs:10:5
+   |
+LL |     var m;
+   |     ^^^
+   |
+help: write `let` instead of `var` to introduce a new variable
+   |
+LL |     let m;
+   |     ^^^
+
+error: invalid variable declaration
+  --> $DIR/issue-65257-invalid-var-decl-recovery.rs:14:5
+   |
+LL |     mut n = 0;
+   |     ^^^ help: missing keyword: `let mut`
+
+error: invalid variable declaration
+  --> $DIR/issue-65257-invalid-var-decl-recovery.rs:16:5
+   |
+LL |     mut var;
+   |     ^^^ help: missing keyword: `let mut`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-65257-invalid-var-decl-recovery.rs:20:33
+   |
+LL |     let _recovery_witness: () = 0;
+   |                            --   ^ expected `()`, found integer
+   |                            |
+   |                            expected due to this
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/recover-labeled-non-block-expr.rs b/src/test/ui/parser/recover-labeled-non-block-expr.rs
new file mode 100644
index 00000000000..be92170acf0
--- /dev/null
+++ b/src/test/ui/parser/recover-labeled-non-block-expr.rs
@@ -0,0 +1,5 @@
+fn main() {
+    'label: 1 + 1; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
+
+    let _recovery_witness: () = 0; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/parser/recover-labeled-non-block-expr.stderr b/src/test/ui/parser/recover-labeled-non-block-expr.stderr
new file mode 100644
index 00000000000..771a915288c
--- /dev/null
+++ b/src/test/ui/parser/recover-labeled-non-block-expr.stderr
@@ -0,0 +1,17 @@
+error: expected `while`, `for`, `loop` or `{` after a label
+  --> $DIR/recover-labeled-non-block-expr.rs:2:13
+   |
+LL |     'label: 1 + 1;
+   |             ^ expected `while`, `for`, `loop` or `{` after a label
+
+error[E0308]: mismatched types
+  --> $DIR/recover-labeled-non-block-expr.rs:4:33
+   |
+LL |     let _recovery_witness: () = 0;
+   |                            --   ^ expected `()`, found integer
+   |                            |
+   |                            expected due to this
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/recovery-attr-on-if.rs b/src/test/ui/parser/recovery-attr-on-if.rs
new file mode 100644
index 00000000000..0d1f5be7b49
--- /dev/null
+++ b/src/test/ui/parser/recovery-attr-on-if.rs
@@ -0,0 +1,9 @@
+fn main() {
+    #[attr] if true {};
+    //~^ ERROR cannot find attribute
+    //~| ERROR attributes are not yet allowed on `if` expressions
+    #[attr] if true {};
+    //~^ ERROR cannot find attribute
+    //~| ERROR attributes are not yet allowed on `if` expressions
+    let _recovery_witness: () = 0; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/parser/recovery-attr-on-if.stderr b/src/test/ui/parser/recovery-attr-on-if.stderr
new file mode 100644
index 00000000000..a02846827c9
--- /dev/null
+++ b/src/test/ui/parser/recovery-attr-on-if.stderr
@@ -0,0 +1,35 @@
+error: attributes are not yet allowed on `if` expressions
+  --> $DIR/recovery-attr-on-if.rs:2:5
+   |
+LL |     #[attr] if true {};
+   |     ^^^^^^^
+
+error: attributes are not yet allowed on `if` expressions
+  --> $DIR/recovery-attr-on-if.rs:5:5
+   |
+LL |     #[attr] if true {};
+   |     ^^^^^^^
+
+error: cannot find attribute `attr` in this scope
+  --> $DIR/recovery-attr-on-if.rs:5:7
+   |
+LL |     #[attr] if true {};
+   |       ^^^^
+
+error: cannot find attribute `attr` in this scope
+  --> $DIR/recovery-attr-on-if.rs:2:7
+   |
+LL |     #[attr] if true {};
+   |       ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/recovery-attr-on-if.rs:8:33
+   |
+LL |     let _recovery_witness: () = 0;
+   |                            --   ^ expected `()`, found integer
+   |                            |
+   |                            expected due to this
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/stmt_expr_attrs_placement.rs b/src/test/ui/parser/stmt_expr_attrs_placement.rs
new file mode 100644
index 00000000000..b8a794f4b92
--- /dev/null
+++ b/src/test/ui/parser/stmt_expr_attrs_placement.rs
@@ -0,0 +1,22 @@
+#![feature(stmt_expr_attributes)]
+
+// Test that various placements of the inner attribute are parsed correctly,
+// or not.
+
+fn main() {
+    let a = #![allow(warnings)] (1, 2);
+    //~^ ERROR an inner attribute is not permitted in this context
+
+    let b = (#![allow(warnings)] 1, 2);
+
+    let c = {
+        #![allow(warnings)]
+        (#![allow(warnings)] 1, 2)
+    };
+
+    let d = {
+        #![allow(warnings)]
+        let e = (#![allow(warnings)] 1, 2);
+        e
+    };
+}
diff --git a/src/test/ui/parser/stmt_expr_attrs_placement.stderr b/src/test/ui/parser/stmt_expr_attrs_placement.stderr
new file mode 100644
index 00000000000..1886a0f9ba0
--- /dev/null
+++ b/src/test/ui/parser/stmt_expr_attrs_placement.stderr
@@ -0,0 +1,10 @@
+error: an inner attribute is not permitted in this context
+  --> $DIR/stmt_expr_attrs_placement.rs:7:13
+   |
+LL |     let a = #![allow(warnings)] (1, 2);
+   |             ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+
+error: aborting due to previous error
+