Rollup merge of #69201 - Aaron1011:feature/permit-if-attr, r=Centril

Permit attributes on 'if' expressions

Previously, attributes on 'if' expressions (e.g. `#[attr] if true {}`)
were disallowed during parsing. This made it impossible for macros to
perform any custom handling of such attributes (e.g. stripping them
away), since a compilation error would be emitted before they ever had a
chance to run.

This PR permits attributes on 'if' expressions ('if-attrs' from here on).
Both built-in attributes (e.g. `#[allow]`, `#[cfg]`) and proc-macro attributes are supported.

We still do *not* accept attributes on 'other parts' of an if-else
chain. That is, the following code snippet still fails to parse:

```rust
if true {} #[attr] else if false {} else #[attr] if false {} #[attr]
else {}
```

Closes https://github.com/rust-lang/rust/issues/68618
This commit is contained in:
Mazdak Farrokhzad 2020-03-09 12:57:44 +01:00 committed by GitHub
commit 4ec997503c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 248 additions and 120 deletions

View File

@ -718,20 +718,11 @@ impl<'a> Parser<'a> {
expr.map(|mut expr| {
attrs.extend::<Vec<_>>(expr.attrs.into());
expr.attrs = attrs;
self.error_attr_on_if_expr(&expr);
expr
})
})
}
fn error_attr_on_if_expr(&self, expr: &Expr) {
if let (ExprKind::If(..), [a0, ..]) = (&expr.kind, &*expr.attrs) {
// Just point to the first attribute in there...
self.struct_span_err(a0.span, "attributes are not yet allowed on `if` expressions")
.emit();
}
}
fn parse_dot_or_call_expr_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
loop {
if self.eat(&token::Question) {

View File

@ -0,0 +1,37 @@
// pp-exact
#[cfg(FALSE)]
fn simple_attr() {
#[attr]
if true { }
#[allow_warnings]
if true { }
}
#[cfg(FALSE)]
fn if_else_chain() {
#[first_attr]
if true { } else if false { } else { }
}
#[cfg(FALSE)]
fn if_let() {
#[attr]
if let Some(_) = Some(true) { }
}
#[cfg(FALSE)]
fn let_attr_if() {
let _ = #[attr] if let _ = 0 { };
let _ = #[attr] if true { };
let _ = #[attr] if let _ = 0 { } else { };
let _ = #[attr] if true { } else { };
}
fn main() { }

View File

@ -0,0 +1,5 @@
#![feature(stmt_expr_attributes)]
fn main() {
let _ = #[cfg(FALSE)] if true {}; //~ ERROR removing an expression
}

View File

@ -0,0 +1,8 @@
error: removing an expression is not supported in this position
--> $DIR/bad-cfg.rs:4:13
|
LL | let _ = #[cfg(FALSE)] if true {};
| ^^^^^^^^^^^^^
error: aborting due to previous error

View File

@ -0,0 +1,12 @@
// check-pass
fn main() {
#[allow(unused_variables)]
if true {
let a = 1;
} else if false {
let b = 1;
} else {
let c = 1;
}
}

View File

@ -0,0 +1,43 @@
// check-pass
#[cfg(FALSE)]
fn simple_attr() {
#[attr] if true {}
#[allow_warnings] if true {}
}
#[cfg(FALSE)]
fn if_else_chain() {
#[first_attr] if true {
} else if false {
} else {
}
}
#[cfg(FALSE)]
fn if_let() {
#[attr] if let Some(_) = Some(true) {}
}
fn bar() {
#[cfg(FALSE)]
if true {
let x: () = true; // Should not error due to the #[cfg(FALSE)]
}
#[cfg_attr(not(unset_attr), cfg(FALSE))]
if true {
let a: () = true; // Should not error due to the applied #[cfg(FALSE)]
}
}
macro_rules! custom_macro {
($expr:expr) => {}
}
custom_macro! {
#[attr] if true {}
}
fn main() {}

View File

@ -0,0 +1,25 @@
#[cfg(FALSE)]
fn if_else_parse_error() {
if true {
} #[attr] else if false { //~ ERROR expected
}
}
#[cfg(FALSE)]
fn else_attr_ifparse_error() {
if true {
} else #[attr] if false { //~ ERROR expected
} else {
}
}
#[cfg(FALSE)]
fn else_parse_error() {
if true {
} else if false {
} #[attr] else { //~ ERROR expected
}
}
fn main() {
}

View File

@ -0,0 +1,27 @@
error: expected expression, found keyword `else`
--> $DIR/else-attrs.rs:4:15
|
LL | } #[attr] else if false {
| ^^^^ expected expression
error: expected `{`, found `#`
--> $DIR/else-attrs.rs:11:12
|
LL | } else #[attr] if false {
| ^ expected `{`
|
help: try placing this code inside a block
|
LL | } else #[attr] { if false {
LL | } else {
LL | } }
|
error: expected expression, found keyword `else`
--> $DIR/else-attrs.rs:20:15
|
LL | } #[attr] else {
| ^^^^ expected expression
error: aborting due to 3 previous errors

View File

@ -0,0 +1,15 @@
// run-pass
fn main() {
let x = 1;
#[cfg(FALSE)]
if false {
x = 2;
} else if true {
x = 3;
} else {
x = 4;
}
assert_eq!(x, 1);
}

View File

@ -0,0 +1,13 @@
// check-pass
#![feature(let_chains)] //~ WARN the feature `let_chains` is incomplete
#[cfg(FALSE)]
fn foo() {
#[attr]
if let Some(_) = Some(true) && let Ok(_) = Ok(1) {
} else if let Some(false) = Some(true) {
}
}
fn main() {}

View File

@ -0,0 +1,8 @@
warning: the feature `let_chains` is incomplete and may cause the compiler to crash
--> $DIR/let-chains-attr.rs:3:12
|
LL | #![feature(let_chains)]
| ^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default

View File

@ -0,0 +1,6 @@
fn main() {
let _ = #[deny(warnings)] if true { //~ ERROR attributes on expressions
} else if false {
} else {
};
}

View File

@ -0,0 +1,12 @@
error[E0658]: attributes on expressions are experimental
--> $DIR/stmt-expr-gated.rs:2:13
|
LL | let _ = #[deny(warnings)] if true {
| ^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -38,8 +38,6 @@ fn main() {}
//~^ 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]}; }
@ -51,14 +49,11 @@ fn main() {}
#[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 `#`
//~^ 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]}; }
@ -70,8 +65,7 @@ fn main() {}
#[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 `#`
//~^ 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]}; }

View File

@ -136,14 +136,8 @@ 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:41:32
|
LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if 0 {}; }
| ^^^^^^^
error: expected `{`, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:43:37
--> $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: `{ {}; }`
@ -152,7 +146,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
| this `if` expression has a condition, but no block
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:45:38
--> $DIR/attr-stmt-expr-attr-bad.rs:43:38
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
| ^^^^^^^^
@ -160,13 +154,13 @@ 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:47:40
--> $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:49:45
--> $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: `{ {}; }`
@ -174,21 +168,15 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
| expected `{`
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:51:46
--> $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:53:45
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
| ^^^^^^^
error: expected `{`, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:53:45
--> $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 {}; }`
@ -196,7 +184,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
| expected `{`
error: expected `{`, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:56:50
--> $DIR/attr-stmt-expr-attr-bad.rs:53:50
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
| -- ^ --- help: try placing this code inside a block: `{ {}; }`
@ -205,21 +193,15 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
| this `if` expression has a condition, but no block
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:58:51
--> $DIR/attr-stmt-expr-attr-bad.rs:55: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:60:32
|
LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if let _ = 0 {}; }
| ^^^^^^^
error: expected `{`, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:62:45
--> $DIR/attr-stmt-expr-attr-bad.rs:57:45
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
| -- ^ --- help: try placing this code inside a block: `{ {}; }`
@ -228,7 +210,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
| this `if` expression has a condition, but no block
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:64:46
--> $DIR/attr-stmt-expr-attr-bad.rs:59:46
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
| ^^^^^^^^
@ -236,13 +218,13 @@ 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:66:48
--> $DIR/attr-stmt-expr-attr-bad.rs:61: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:68:53
--> $DIR/attr-stmt-expr-attr-bad.rs:63:53
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
| ^ --- help: try placing this code inside a block: `{ {}; }`
@ -250,21 +232,15 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
| expected `{`
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:70:54
--> $DIR/attr-stmt-expr-attr-bad.rs:65: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:72: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:72:53
--> $DIR/attr-stmt-expr-attr-bad.rs:67: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 {}; }`
@ -272,7 +248,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}
| expected `{`
error: expected `{`, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:75:66
--> $DIR/attr-stmt-expr-attr-bad.rs:69:66
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
| -- ^ --- help: try placing this code inside a block: `{ {}; }`
@ -281,7 +257,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}
| this `if` expression has a condition, but no block
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:77:67
--> $DIR/attr-stmt-expr-attr-bad.rs:71:67
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
| ^^^^^^^^
@ -289,7 +265,7 @@ 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:80:32
--> $DIR/attr-stmt-expr-attr-bad.rs:74:32
|
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
| ------- ^^^^^^^^ not permitted following an outer attribute
@ -299,7 +275,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 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 following an outer attribute
--> $DIR/attr-stmt-expr-attr-bad.rs:82:32
--> $DIR/attr-stmt-expr-attr-bad.rs:76:32
|
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
| ------- ^^^^^^^^ not permitted following an outer attribute
@ -309,7 +285,7 @@ LL | #[cfg(FALSE)] fn s() { #[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 following an outer attribute
--> $DIR/attr-stmt-expr-attr-bad.rs:84:32
--> $DIR/attr-stmt-expr-attr-bad.rs:78:32
|
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
| ------- ^^^^^^^^ not permitted following an outer attribute
@ -319,7 +295,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![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 following an outer attribute
--> $DIR/attr-stmt-expr-attr-bad.rs:86:32
--> $DIR/attr-stmt-expr-attr-bad.rs:80:32
|
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
| ------- ^^^^^^^^ not permitted following an outer attribute
@ -329,7 +305,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![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 following an outer attribute
--> $DIR/attr-stmt-expr-attr-bad.rs:88:32
--> $DIR/attr-stmt-expr-attr-bad.rs:82:32
|
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
| ------- ^^^^^^^^ not permitted following an outer attribute
@ -339,7 +315,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![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[E0586]: inclusive range with no end
--> $DIR/attr-stmt-expr-attr-bad.rs:94:35
--> $DIR/attr-stmt-expr-attr-bad.rs:88:35
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
| ^^^ help: use `..` instead
@ -347,13 +323,13 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error: expected one of `=>`, `if`, or `|`, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:94:38
--> $DIR/attr-stmt-expr-attr-bad.rs:88:38
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
| ^ expected one of `=>`, `if`, or `|`
error[E0586]: inclusive range with no end
--> $DIR/attr-stmt-expr-attr-bad.rs:97:35
--> $DIR/attr-stmt-expr-attr-bad.rs:91:35
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
| ^^^ help: use `..` instead
@ -361,19 +337,19 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error: expected one of `=>`, `if`, or `|`, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:97:38
--> $DIR/attr-stmt-expr-attr-bad.rs:91: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:100:39
--> $DIR/attr-stmt-expr-attr-bad.rs:94:39
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
| ^
error[E0586]: inclusive range with no end
--> $DIR/attr-stmt-expr-attr-bad.rs:102:35
--> $DIR/attr-stmt-expr-attr-bad.rs:96:35
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
| ^^^ help: use `..` instead
@ -381,47 +357,47 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error: expected one of `=>`, `if`, or `|`, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:102:38
--> $DIR/attr-stmt-expr-attr-bad.rs:96:38
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
| ^ expected one of `=>`, `if`, or `|`
error: unexpected token: `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:106:34
--> $DIR/attr-stmt-expr-attr-bad.rs:100:34
|
LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
| ^
error: expected one of `.`, `;`, `?`, or an operator, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:106:34
--> $DIR/attr-stmt-expr-attr-bad.rs:100:34
|
LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
| ^ expected one of `.`, `;`, `?`, or an operator
error: unexpected token: `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:109:34
--> $DIR/attr-stmt-expr-attr-bad.rs:103:34
|
LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
| ^
error: expected one of `.`, `;`, `?`, or an operator, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:109:34
--> $DIR/attr-stmt-expr-attr-bad.rs:103:34
|
LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
| ^ expected one of `.`, `;`, `?`, or an operator
error: expected statement after outer attribute
--> $DIR/attr-stmt-expr-attr-bad.rs:114:37
--> $DIR/attr-stmt-expr-attr-bad.rs:108:37
|
LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } }
| ^^^^^^^
error: expected statement after outer attribute
--> $DIR/attr-stmt-expr-attr-bad.rs:116:37
--> $DIR/attr-stmt-expr-attr-bad.rs:110:37
|
LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } }
| ^^^^^^^
error: aborting due to 57 previous errors
error: aborting due to 53 previous errors
For more information about this error, try `rustc --explain E0586`.

View File

@ -1,9 +0,0 @@
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
}

View File

@ -1,35 +0,0 @@
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`.