From f63b88c761f935d9b2c220a1b4e3abf0c0681c69 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sat, 15 Feb 2020 19:04:20 -0500 Subject: [PATCH 01/11] 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]`) 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 {} ``` --- src/librustc_parse/parser/expr.rs | 9 ------ src/test/pretty/if-attr.rs | 28 +++++++++++++++++ src/test/ui/parser/attr-stmt-expr-attr-bad.rs | 10 ++---- .../ui/parser/if-attrs/cfg-false-if-attr.rs | 31 +++++++++++++++++++ src/test/ui/parser/if-attrs/else-attrs.rs | 25 +++++++++++++++ src/test/ui/parser/if-attrs/else-attrs.stderr | 27 ++++++++++++++++ .../ui/parser/if-attrs/let-chains-attr.rs | 13 ++++++++ .../ui/parser/if-attrs/let-chains-attr.stderr | 8 +++++ src/test/ui/parser/recovery-attr-on-if.rs | 2 -- src/test/ui/parser/recovery-attr-on-if.stderr | 18 ++--------- 10 files changed, 137 insertions(+), 34 deletions(-) create mode 100644 src/test/pretty/if-attr.rs create mode 100644 src/test/ui/parser/if-attrs/cfg-false-if-attr.rs create mode 100644 src/test/ui/parser/if-attrs/else-attrs.rs create mode 100644 src/test/ui/parser/if-attrs/else-attrs.stderr create mode 100644 src/test/ui/parser/if-attrs/let-chains-attr.rs create mode 100644 src/test/ui/parser/if-attrs/let-chains-attr.stderr diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 18ddd23588e..f31686afd1a 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -665,20 +665,11 @@ impl<'a> Parser<'a> { expr.map(|mut expr| { attrs.extend::>(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, lo: Span) -> PResult<'a, P> { loop { if self.eat(&token::Question) { diff --git a/src/test/pretty/if-attr.rs b/src/test/pretty/if-attr.rs new file mode 100644 index 00000000000..463476737a9 --- /dev/null +++ b/src/test/pretty/if-attr.rs @@ -0,0 +1,28 @@ +// 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) { } +} + + +fn main() { } diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs index 118bff8144c..f3980a59648 100644 --- a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs +++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs @@ -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]}; } diff --git a/src/test/ui/parser/if-attrs/cfg-false-if-attr.rs b/src/test/ui/parser/if-attrs/cfg-false-if-attr.rs new file mode 100644 index 00000000000..2932ec1a231 --- /dev/null +++ b/src/test/ui/parser/if-attrs/cfg-false-if-attr.rs @@ -0,0 +1,31 @@ +// 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) {} +} + +macro_rules! custom_macro { + ($expr:expr) => {} +} + +custom_macro! { + #[attr] if true {} +} + + +fn main() {} diff --git a/src/test/ui/parser/if-attrs/else-attrs.rs b/src/test/ui/parser/if-attrs/else-attrs.rs new file mode 100644 index 00000000000..4394b2100c1 --- /dev/null +++ b/src/test/ui/parser/if-attrs/else-attrs.rs @@ -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() { +} diff --git a/src/test/ui/parser/if-attrs/else-attrs.stderr b/src/test/ui/parser/if-attrs/else-attrs.stderr new file mode 100644 index 00000000000..af25b6abc0a --- /dev/null +++ b/src/test/ui/parser/if-attrs/else-attrs.stderr @@ -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 + diff --git a/src/test/ui/parser/if-attrs/let-chains-attr.rs b/src/test/ui/parser/if-attrs/let-chains-attr.rs new file mode 100644 index 00000000000..5237a9ff396 --- /dev/null +++ b/src/test/ui/parser/if-attrs/let-chains-attr.rs @@ -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() {} diff --git a/src/test/ui/parser/if-attrs/let-chains-attr.stderr b/src/test/ui/parser/if-attrs/let-chains-attr.stderr new file mode 100644 index 00000000000..a6c91bb9203 --- /dev/null +++ b/src/test/ui/parser/if-attrs/let-chains-attr.stderr @@ -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 + diff --git a/src/test/ui/parser/recovery-attr-on-if.rs b/src/test/ui/parser/recovery-attr-on-if.rs index 0d1f5be7b49..b4fb25ec8d3 100644 --- a/src/test/ui/parser/recovery-attr-on-if.rs +++ b/src/test/ui/parser/recovery-attr-on-if.rs @@ -1,9 +1,7 @@ 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 index a02846827c9..cbf2714a1a1 100644 --- a/src/test/ui/parser/recovery-attr-on-if.stderr +++ b/src/test/ui/parser/recovery-attr-on-if.stderr @@ -1,17 +1,5 @@ -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 + --> $DIR/recovery-attr-on-if.rs:4:7 | LL | #[attr] if true {}; | ^^^^ @@ -23,13 +11,13 @@ LL | #[attr] if true {}; | ^^^^ error[E0308]: mismatched types - --> $DIR/recovery-attr-on-if.rs:8:33 + --> $DIR/recovery-attr-on-if.rs:6:33 | LL | let _recovery_witness: () = 0; | -- ^ expected `()`, found integer | | | expected due to this -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. From e912d9d7ecd9d326affd18f7b133dafb72ee8896 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sat, 15 Feb 2020 19:13:36 -0500 Subject: [PATCH 02/11] Test #[allow(unused)] on `if` expression --- src/test/ui/parser/if-attrs/builtin-if-attr.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/test/ui/parser/if-attrs/builtin-if-attr.rs diff --git a/src/test/ui/parser/if-attrs/builtin-if-attr.rs b/src/test/ui/parser/if-attrs/builtin-if-attr.rs new file mode 100644 index 00000000000..7e290661501 --- /dev/null +++ b/src/test/ui/parser/if-attrs/builtin-if-attr.rs @@ -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; + } +} From e9ec47bb70810f972e6565d496120b0b00f261f0 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 19 Feb 2020 10:45:21 -0500 Subject: [PATCH 03/11] Test that stmt_expr_attrs properly gates if-attrs --- src/test/ui/parser/if-attrs/stmt-expr-gated.rs | 6 ++++++ src/test/ui/parser/if-attrs/stmt-expr-gated.stderr | 12 ++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 src/test/ui/parser/if-attrs/stmt-expr-gated.rs create mode 100644 src/test/ui/parser/if-attrs/stmt-expr-gated.stderr diff --git a/src/test/ui/parser/if-attrs/stmt-expr-gated.rs b/src/test/ui/parser/if-attrs/stmt-expr-gated.rs new file mode 100644 index 00000000000..38599c8e67c --- /dev/null +++ b/src/test/ui/parser/if-attrs/stmt-expr-gated.rs @@ -0,0 +1,6 @@ +fn main() { + let _ = #[deny(warnings)] if true { //~ ERROR attributes on expressions + } else if false { + } else { + }; +} diff --git a/src/test/ui/parser/if-attrs/stmt-expr-gated.stderr b/src/test/ui/parser/if-attrs/stmt-expr-gated.stderr new file mode 100644 index 00000000000..47dac39a9ae --- /dev/null +++ b/src/test/ui/parser/if-attrs/stmt-expr-gated.stderr @@ -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 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`. From 9a299e4e210ff91ec59bf9f09bdb402196e02bd5 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 19 Feb 2020 10:47:27 -0500 Subject: [PATCH 04/11] Test trying to cfg-remove an `if` expression --- src/test/ui/parser/if-attrs/bad-cfg.rs | 5 +++++ src/test/ui/parser/if-attrs/bad-cfg.stderr | 8 ++++++++ 2 files changed, 13 insertions(+) create mode 100644 src/test/ui/parser/if-attrs/bad-cfg.rs create mode 100644 src/test/ui/parser/if-attrs/bad-cfg.stderr diff --git a/src/test/ui/parser/if-attrs/bad-cfg.rs b/src/test/ui/parser/if-attrs/bad-cfg.rs new file mode 100644 index 00000000000..3f84929a00e --- /dev/null +++ b/src/test/ui/parser/if-attrs/bad-cfg.rs @@ -0,0 +1,5 @@ +#![feature(stmt_expr_attributes)] + +fn main() { + let _ = #[cfg(FALSE)] if true {}; //~ ERROR removing an expression +} diff --git a/src/test/ui/parser/if-attrs/bad-cfg.stderr b/src/test/ui/parser/if-attrs/bad-cfg.stderr new file mode 100644 index 00000000000..8a2890886a1 --- /dev/null +++ b/src/test/ui/parser/if-attrs/bad-cfg.stderr @@ -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 + From b00f6745c4df0e979dd53dcbf43ededf5728e349 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 19 Feb 2020 10:48:13 -0500 Subject: [PATCH 05/11] Remove recovery test --- src/test/ui/parser/recovery-attr-on-if.rs | 7 ------ src/test/ui/parser/recovery-attr-on-if.stderr | 23 ------------------- 2 files changed, 30 deletions(-) delete mode 100644 src/test/ui/parser/recovery-attr-on-if.rs delete mode 100644 src/test/ui/parser/recovery-attr-on-if.stderr diff --git a/src/test/ui/parser/recovery-attr-on-if.rs b/src/test/ui/parser/recovery-attr-on-if.rs deleted file mode 100644 index b4fb25ec8d3..00000000000 --- a/src/test/ui/parser/recovery-attr-on-if.rs +++ /dev/null @@ -1,7 +0,0 @@ -fn main() { - #[attr] if true {}; - //~^ ERROR cannot find attribute - #[attr] if true {}; - //~^ ERROR cannot find attribute - 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 deleted file mode 100644 index cbf2714a1a1..00000000000 --- a/src/test/ui/parser/recovery-attr-on-if.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error: cannot find attribute `attr` in this scope - --> $DIR/recovery-attr-on-if.rs:4: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:6:33 - | -LL | let _recovery_witness: () = 0; - | -- ^ expected `()`, found integer - | | - | expected due to this - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0308`. From e11cdfdae48f8793c618834227114bcb5a6d57bd Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 19 Feb 2020 10:49:34 -0500 Subject: [PATCH 06/11] Add run-pass test suggested by @joshtriplett --- src/test/ui/parser/if-attrs/gate-whole-expr.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/test/ui/parser/if-attrs/gate-whole-expr.rs diff --git a/src/test/ui/parser/if-attrs/gate-whole-expr.rs b/src/test/ui/parser/if-attrs/gate-whole-expr.rs new file mode 100644 index 00000000000..efce28e1d5b --- /dev/null +++ b/src/test/ui/parser/if-attrs/gate-whole-expr.rs @@ -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); +} From 7f19358c9ef51a130e0177d327eaac5adc6d73ad Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 19 Feb 2020 10:50:03 -0500 Subject: [PATCH 07/11] Move if-attr tests to their own directory --- src/test/ui/{parser => }/if-attrs/bad-cfg.rs | 0 src/test/ui/{parser => }/if-attrs/bad-cfg.stderr | 0 src/test/ui/{parser => }/if-attrs/builtin-if-attr.rs | 0 src/test/ui/{parser => }/if-attrs/cfg-false-if-attr.rs | 0 src/test/ui/{parser => }/if-attrs/else-attrs.rs | 0 src/test/ui/{parser => }/if-attrs/else-attrs.stderr | 0 src/test/ui/{parser => }/if-attrs/gate-whole-expr.rs | 0 src/test/ui/{parser => }/if-attrs/let-chains-attr.rs | 0 src/test/ui/{parser => }/if-attrs/let-chains-attr.stderr | 0 src/test/ui/{parser => }/if-attrs/stmt-expr-gated.rs | 0 src/test/ui/{parser => }/if-attrs/stmt-expr-gated.stderr | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{parser => }/if-attrs/bad-cfg.rs (100%) rename src/test/ui/{parser => }/if-attrs/bad-cfg.stderr (100%) rename src/test/ui/{parser => }/if-attrs/builtin-if-attr.rs (100%) rename src/test/ui/{parser => }/if-attrs/cfg-false-if-attr.rs (100%) rename src/test/ui/{parser => }/if-attrs/else-attrs.rs (100%) rename src/test/ui/{parser => }/if-attrs/else-attrs.stderr (100%) rename src/test/ui/{parser => }/if-attrs/gate-whole-expr.rs (100%) rename src/test/ui/{parser => }/if-attrs/let-chains-attr.rs (100%) rename src/test/ui/{parser => }/if-attrs/let-chains-attr.stderr (100%) rename src/test/ui/{parser => }/if-attrs/stmt-expr-gated.rs (100%) rename src/test/ui/{parser => }/if-attrs/stmt-expr-gated.stderr (100%) diff --git a/src/test/ui/parser/if-attrs/bad-cfg.rs b/src/test/ui/if-attrs/bad-cfg.rs similarity index 100% rename from src/test/ui/parser/if-attrs/bad-cfg.rs rename to src/test/ui/if-attrs/bad-cfg.rs diff --git a/src/test/ui/parser/if-attrs/bad-cfg.stderr b/src/test/ui/if-attrs/bad-cfg.stderr similarity index 100% rename from src/test/ui/parser/if-attrs/bad-cfg.stderr rename to src/test/ui/if-attrs/bad-cfg.stderr diff --git a/src/test/ui/parser/if-attrs/builtin-if-attr.rs b/src/test/ui/if-attrs/builtin-if-attr.rs similarity index 100% rename from src/test/ui/parser/if-attrs/builtin-if-attr.rs rename to src/test/ui/if-attrs/builtin-if-attr.rs diff --git a/src/test/ui/parser/if-attrs/cfg-false-if-attr.rs b/src/test/ui/if-attrs/cfg-false-if-attr.rs similarity index 100% rename from src/test/ui/parser/if-attrs/cfg-false-if-attr.rs rename to src/test/ui/if-attrs/cfg-false-if-attr.rs diff --git a/src/test/ui/parser/if-attrs/else-attrs.rs b/src/test/ui/if-attrs/else-attrs.rs similarity index 100% rename from src/test/ui/parser/if-attrs/else-attrs.rs rename to src/test/ui/if-attrs/else-attrs.rs diff --git a/src/test/ui/parser/if-attrs/else-attrs.stderr b/src/test/ui/if-attrs/else-attrs.stderr similarity index 100% rename from src/test/ui/parser/if-attrs/else-attrs.stderr rename to src/test/ui/if-attrs/else-attrs.stderr diff --git a/src/test/ui/parser/if-attrs/gate-whole-expr.rs b/src/test/ui/if-attrs/gate-whole-expr.rs similarity index 100% rename from src/test/ui/parser/if-attrs/gate-whole-expr.rs rename to src/test/ui/if-attrs/gate-whole-expr.rs diff --git a/src/test/ui/parser/if-attrs/let-chains-attr.rs b/src/test/ui/if-attrs/let-chains-attr.rs similarity index 100% rename from src/test/ui/parser/if-attrs/let-chains-attr.rs rename to src/test/ui/if-attrs/let-chains-attr.rs diff --git a/src/test/ui/parser/if-attrs/let-chains-attr.stderr b/src/test/ui/if-attrs/let-chains-attr.stderr similarity index 100% rename from src/test/ui/parser/if-attrs/let-chains-attr.stderr rename to src/test/ui/if-attrs/let-chains-attr.stderr diff --git a/src/test/ui/parser/if-attrs/stmt-expr-gated.rs b/src/test/ui/if-attrs/stmt-expr-gated.rs similarity index 100% rename from src/test/ui/parser/if-attrs/stmt-expr-gated.rs rename to src/test/ui/if-attrs/stmt-expr-gated.rs diff --git a/src/test/ui/parser/if-attrs/stmt-expr-gated.stderr b/src/test/ui/if-attrs/stmt-expr-gated.stderr similarity index 100% rename from src/test/ui/parser/if-attrs/stmt-expr-gated.stderr rename to src/test/ui/if-attrs/stmt-expr-gated.stderr From 1b681d6652bacce6b741ca66725f25b9afb16bc8 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 19 Feb 2020 11:01:51 -0500 Subject: [PATCH 08/11] Test that cfg-gated if-exprs are not type-checked --- src/test/ui/if-attrs/cfg-false-if-attr.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/ui/if-attrs/cfg-false-if-attr.rs b/src/test/ui/if-attrs/cfg-false-if-attr.rs index 2932ec1a231..1f77a1bb342 100644 --- a/src/test/ui/if-attrs/cfg-false-if-attr.rs +++ b/src/test/ui/if-attrs/cfg-false-if-attr.rs @@ -19,6 +19,18 @@ 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) => {} } From 37c2c38aeb0d50f7b956200c698bc59fce6e7181 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 19 Feb 2020 11:05:31 -0500 Subject: [PATCH 09/11] Extent pretty-print test --- src/test/pretty/if-attr.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/pretty/if-attr.rs b/src/test/pretty/if-attr.rs index 463476737a9..652604fc7f3 100644 --- a/src/test/pretty/if-attr.rs +++ b/src/test/pretty/if-attr.rs @@ -24,5 +24,14 @@ fn if_let() { 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() { } From 66b152cf9fd53b27027c66378a73404b92c6e35b Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 19 Feb 2020 11:36:04 -0500 Subject: [PATCH 10/11] Fix tabs --- src/test/ui/if-attrs/gate-whole-expr.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/test/ui/if-attrs/gate-whole-expr.rs b/src/test/ui/if-attrs/gate-whole-expr.rs index efce28e1d5b..63772d54b53 100644 --- a/src/test/ui/if-attrs/gate-whole-expr.rs +++ b/src/test/ui/if-attrs/gate-whole-expr.rs @@ -1,15 +1,15 @@ // run-pass fn main() { - let x = 1; + let x = 1; - #[cfg(FALSE)] - if false { - x = 2; - } else if true { - x = 3; - } else { - x = 4; - } - assert_eq!(x, 1); + #[cfg(FALSE)] + if false { + x = 2; + } else if true { + x = 3; + } else { + x = 4; + } + assert_eq!(x, 1); } From e50fd5a3dc587b5b970b6b969eff7e8547dede70 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 4 Mar 2020 16:54:16 -0500 Subject: [PATCH 11/11] Update stderr --- .../ui/parser/attr-stmt-expr-attr-bad.stderr | 94 +++++++------------ 1 file changed, 35 insertions(+), 59 deletions(-) diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr index b03db85422d..3cc3a455c12 100644 --- a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr +++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr @@ -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 attibute @@ -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 attibute @@ -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 attibute @@ -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 attibute @@ -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 attibute @@ -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`.