diff options
Diffstat (limited to 'src/test/ui/consts/control-flow')
30 files changed, 1245 insertions, 0 deletions
diff --git a/src/test/ui/consts/control-flow/assert.both.stderr b/src/test/ui/consts/control-flow/assert.both.stderr new file mode 100644 index 00000000000..44769175f0e --- /dev/null +++ b/src/test/ui/consts/control-flow/assert.both.stderr @@ -0,0 +1,13 @@ +error: any use of this value will cause an error + --> $DIR/assert.rs:12:15 + | +LL | const _: () = assert!(false); + | --------------^^^^^^^^^^^^^^- + | | + | the evaluated program panicked at 'assertion failed: false', $DIR/assert.rs:12:15 + | + = note: `#[deny(const_err)]` on by default + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/consts/control-flow/assert.if_match.stderr b/src/test/ui/consts/control-flow/assert.if_match.stderr new file mode 100644 index 00000000000..9c8963f6c7b --- /dev/null +++ b/src/test/ui/consts/control-flow/assert.if_match.stderr @@ -0,0 +1,23 @@ +error[E0658]: panicking in constants is unstable + --> $DIR/assert.rs:8:15 + | +LL | const _: () = assert!(true); + | ^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/51999 + = help: add `#![feature(const_panic)]` to the crate attributes to enable + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error[E0658]: panicking in constants is unstable + --> $DIR/assert.rs:12:15 + | +LL | const _: () = assert!(false); + | ^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/51999 + = help: add `#![feature(const_panic)]` to the crate attributes to enable + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/control-flow/assert.panic.stderr b/src/test/ui/consts/control-flow/assert.panic.stderr new file mode 100644 index 00000000000..11550bf801a --- /dev/null +++ b/src/test/ui/consts/control-flow/assert.panic.stderr @@ -0,0 +1,21 @@ +error[E0658]: `if` is not allowed in a `const` + --> $DIR/assert.rs:8:15 + | +LL | const _: () = assert!(true); + | ^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/assert.rs:12:15 + | +LL | const _: () = assert!(false); + | ^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/control-flow/assert.rs b/src/test/ui/consts/control-flow/assert.rs new file mode 100644 index 00000000000..2da42d5084b --- /dev/null +++ b/src/test/ui/consts/control-flow/assert.rs @@ -0,0 +1,17 @@ +// Test that `assert` works only when both `const_if_match` and `const_panic` are enabled. + +// revisions: stock if_match panic both + +#![cfg_attr(any(both, if_match), feature(const_if_match))] +#![cfg_attr(any(both, panic), feature(const_panic))] + +const _: () = assert!(true); +//[stock,panic]~^ ERROR `if` is not allowed in a `const` +//[if_match]~^^ ERROR panicking in constants is unstable + +const _: () = assert!(false); +//[stock,panic]~^ ERROR `if` is not allowed in a `const` +//[if_match]~^^ ERROR panicking in constants is unstable +//[both]~^^^ ERROR any use of this value will cause an error + +fn main() {} diff --git a/src/test/ui/consts/control-flow/assert.stock.stderr b/src/test/ui/consts/control-flow/assert.stock.stderr new file mode 100644 index 00000000000..11550bf801a --- /dev/null +++ b/src/test/ui/consts/control-flow/assert.stock.stderr @@ -0,0 +1,21 @@ +error[E0658]: `if` is not allowed in a `const` + --> $DIR/assert.rs:8:15 + | +LL | const _: () = assert!(true); + | ^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/assert.rs:12:15 + | +LL | const _: () = assert!(false); + | ^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/control-flow/basics.rs b/src/test/ui/consts/control-flow/basics.rs new file mode 100644 index 00000000000..8bd1929956f --- /dev/null +++ b/src/test/ui/consts/control-flow/basics.rs @@ -0,0 +1,43 @@ +// Test basic functionality of `if` and `match` in a const context. + +// run-pass + +#![feature(const_panic)] +#![feature(const_if_match)] + +const X: u32 = 4; +const Y: u32 = 5; + +const ABS_DIFF: u32 = if X < Y { + Y - X +} else { + X - Y +}; + +const fn abs_diff(a: u32, b: u32) -> u32 { + match (a, b) { + (big, little) if big > little => big - little, + (little, big) => big - little, + } +} + +const fn gcd(a: u32, b: u32) -> u32 { + if b == 0 { + return a; + } + + gcd(b, a % b) +} + +fn main() { + const _: () = assert!(abs_diff(4, 5) == abs_diff(5, 4)); + assert_eq!(abs_diff(4, 5), abs_diff(5, 4)); + + const _: () = assert!(ABS_DIFF == abs_diff(5, 4)); + assert_eq!(ABS_DIFF, abs_diff(5, 4)); + + const _: () = assert!(gcd(48, 18) == 6); + const _: () = assert!(gcd(18, 48) == 6); + assert_eq!(gcd(48, 18), 6); + assert_eq!(gcd(18, 48), 6); +} diff --git a/src/test/ui/consts/control-flow/drop-failure.rs b/src/test/ui/consts/control-flow/drop-failure.rs new file mode 100644 index 00000000000..c6bea89e6e6 --- /dev/null +++ b/src/test/ui/consts/control-flow/drop-failure.rs @@ -0,0 +1,35 @@ +#![feature(const_if_match)] + +// `x` is *not* always moved into the final value may be dropped inside the initializer. +const _: Option<Vec<i32>> = { + let y: Option<Vec<i32>> = None; + let x = Some(Vec::new()); + //~^ ERROR destructors cannot be evaluated at compile-time + + if true { + x + } else { + y + } +}; + +// We only clear `NeedsDrop` if a local is moved from in entirely. This is a shortcoming of the +// existing analysis. +const _: Vec<i32> = { + let vec_tuple = (Vec::new(),); + //~^ ERROR destructors cannot be evaluated at compile-time + + vec_tuple.0 +}; + +// This applies to single-field enum variants as well. +const _: Vec<i32> = { + let x: Result<_, Vec<i32>> = Ok(Vec::new()); + //~^ ERROR destructors cannot be evaluated at compile-time + + match x { + Ok(x) | Err(x) => x, + } +}; + +fn main() {} diff --git a/src/test/ui/consts/control-flow/drop-failure.stderr b/src/test/ui/consts/control-flow/drop-failure.stderr new file mode 100644 index 00000000000..35ceb3b2770 --- /dev/null +++ b/src/test/ui/consts/control-flow/drop-failure.stderr @@ -0,0 +1,21 @@ +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/drop-failure.rs:6:9 + | +LL | let x = Some(Vec::new()); + | ^ constants cannot evaluate destructors + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/drop-failure.rs:19:9 + | +LL | let vec_tuple = (Vec::new(),); + | ^^^^^^^^^ constants cannot evaluate destructors + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/drop-failure.rs:27:9 + | +LL | let x: Result<_, Vec<i32>> = Ok(Vec::new()); + | ^ constants cannot evaluate destructors + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0493`. diff --git a/src/test/ui/consts/control-flow/drop-success.rs b/src/test/ui/consts/control-flow/drop-success.rs new file mode 100644 index 00000000000..92b3f6ec92e --- /dev/null +++ b/src/test/ui/consts/control-flow/drop-success.rs @@ -0,0 +1,24 @@ +// run-pass + +#![feature(const_if_match)] + +// `x` is always moved into the final value and is not dropped inside the initializer. +const _: Option<Vec<i32>> = { + let y: Option<Vec<i32>> = None; + let x = Some(Vec::new()); + + if true { + x + } else { + x + } +}; + +const _: Option<Vec<i32>> = { + let x = Some(Vec::new()); + match () { + () => x, + } +}; + +fn main() {} diff --git a/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr b/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr new file mode 100644 index 00000000000..21e3f2af15a --- /dev/null +++ b/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr @@ -0,0 +1,14 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/feature-gate-const-if-match.rs:108:1 + | +LL | / fn main() { +LL | | let _ = [0; { +LL | | let x = if false { 0 } else { 1 }; +LL | | +... | +LL | | }]; +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs b/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs new file mode 100644 index 00000000000..00576d50ac6 --- /dev/null +++ b/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs @@ -0,0 +1,118 @@ +// Ensure that `if`, `if let` and `match` are only allowed in the various const contexts when +// `#![feature(const_if_match)]` is enabled. When the feature gate is removed, the `#[rustc_error]` +// on `main` should be removed and this test converted to `check-pass`. + +// revisions: stock if_match + +#![feature(rustc_attrs)] +#![cfg_attr(if_match, feature(const_if_match))] + +const _: i32 = if true { //[stock]~ ERROR `if` is not allowed in a `const` + 5 +} else { + 6 +}; + +const _: i32 = if let Some(true) = Some(false) { //[stock]~ ERROR `if` is not allowed in a `const` + 0 +} else { + 1 +}; + +const _: i32 = match 1 { //[stock]~ ERROR `match` is not allowed in a `const` + 2 => 3, + 4 => 5, + _ => 0, +}; + +static FOO: i32 = { + let x = if true { 0 } else { 1 }; + //[stock]~^ ERROR `if` is not allowed in a `static` + let x = match x { 0 => 1, _ => 0 }; + //[stock]~^ ERROR `match` is not allowed in a `static` + if let Some(x) = Some(x) { x } else { 1 } + //[stock]~^ ERROR `if` is not allowed in a `static` +}; + +static mut BAR: i32 = { + let x = if true { 0 } else { 1 }; + //[stock]~^ ERROR `if` is not allowed in a `static mut` + let x = match x { 0 => 1, _ => 0 }; + //[stock]~^ ERROR `match` is not allowed in a `static mut` + if let Some(x) = Some(x) { x } else { 1 } + //[stock]~^ ERROR `if` is not allowed in a `static mut` +}; + +const fn if_() -> i32 { + if true { 5 } else { 6 } //[stock]~ ERROR `if` is not allowed in a `const fn` +} + +const fn if_let(a: Option<bool>) -> i32 { + if let Some(true) = a { //[stock]~ ERROR `if` is not allowed in a `const fn` + 0 + } else { + 1 + } +} + +const fn match_(i: i32) -> i32 { + match i { //[stock]~ ERROR `match` is not allowed in a `const fn` + i if i > 10 => i, + 1 => 2, + _ => 0 + } +} + +pub trait Foo { + const IF: i32 = if true { 5 } else { 6 }; + //[stock]~^ ERROR `if` is not allowed in a `const` + + const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 }; + //[stock]~^ ERROR `if` is not allowed in a `const` + + const MATCH: i32 = match 0 { 1 => 2, _ => 0 }; + //[stock]~^ ERROR `match` is not allowed in a `const` +} + +impl Foo for () { + const IF: i32 = if true { 5 } else { 6 }; + //[stock]~^ ERROR `if` is not allowed in a `const` + + const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 }; + //[stock]~^ ERROR `if` is not allowed in a `const` + + const MATCH: i32 = match 0 { 1 => 2, _ => 0 }; + //[stock]~^ ERROR `match` is not allowed in a `const` +} + +fn non_const_outside() { + const fn const_inside(y: bool) -> i32 { + let x = if y { 0 } else { 1 }; + //[stock]~^ ERROR `if` is not allowed in a `const fn` + let x = match x { 0 => 1, _ => 0 }; + //[stock]~^ ERROR `match` is not allowed in a `const fn` + if let Some(x) = Some(x) { x } else { 1 } + //[stock]~^ ERROR `if` is not allowed in a `const fn` + } +} + +const fn const_outside() { + fn non_const_inside(y: bool) -> i32 { + let x = if y { 0 } else { 1 }; + let x = match x { 0 => 1, _ => 0 }; + if let Some(x) = Some(x) { x } else { 1 } + } +} + +#[rustc_error] +fn main() { //[if_match]~ ERROR fatal error triggered by #[rustc_error] + let _ = [0; { + let x = if false { 0 } else { 1 }; + //[stock]~^ ERROR `if` is not allowed in a `const` + let x = match x { 0 => 1, _ => 0 }; + //[stock]~^ ERROR `match` is not allowed in a `const` + if let Some(x) = Some(x) { x } else { 1 } + //[stock]~^ ERROR `if` is not allowed in a `const` + //[stock]~| ERROR constant contains unimplemented expression type + }]; +} diff --git a/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr b/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr new file mode 100644 index 00000000000..d3c6a51923f --- /dev/null +++ b/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr @@ -0,0 +1,249 @@ +error[E0658]: `if` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:10:16 + | +LL | const _: i32 = if true { + | ________________^ +LL | | 5 +LL | | } else { +LL | | 6 +LL | | }; + | |_^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:16:16 + | +LL | const _: i32 = if let Some(true) = Some(false) { + | ________________^ +LL | | 0 +LL | | } else { +LL | | 1 +LL | | }; + | |_^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `match` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:22:16 + | +LL | const _: i32 = match 1 { + | ________________^ +LL | | 2 => 3, +LL | | 4 => 5, +LL | | _ => 0, +LL | | }; + | |_^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `static` + --> $DIR/feature-gate-const-if-match.rs:29:13 + | +LL | let x = if true { 0 } else { 1 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `match` is not allowed in a `static` + --> $DIR/feature-gate-const-if-match.rs:31:13 + | +LL | let x = match x { 0 => 1, _ => 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `static` + --> $DIR/feature-gate-const-if-match.rs:33:5 + | +LL | if let Some(x) = Some(x) { x } else { 1 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `static mut` + --> $DIR/feature-gate-const-if-match.rs:38:13 + | +LL | let x = if true { 0 } else { 1 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `match` is not allowed in a `static mut` + --> $DIR/feature-gate-const-if-match.rs:40:13 + | +LL | let x = match x { 0 => 1, _ => 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `static mut` + --> $DIR/feature-gate-const-if-match.rs:42:5 + | +LL | if let Some(x) = Some(x) { x } else { 1 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const fn` + --> $DIR/feature-gate-const-if-match.rs:47:5 + | +LL | if true { 5 } else { 6 } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const fn` + --> $DIR/feature-gate-const-if-match.rs:51:5 + | +LL | / if let Some(true) = a { +LL | | 0 +LL | | } else { +LL | | 1 +LL | | } + | |_____^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `match` is not allowed in a `const fn` + --> $DIR/feature-gate-const-if-match.rs:59:5 + | +LL | / match i { +LL | | i if i > 10 => i, +LL | | 1 => 2, +LL | | _ => 0 +LL | | } + | |_____^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const fn` + --> $DIR/feature-gate-const-if-match.rs:90:17 + | +LL | let x = if y { 0 } else { 1 }; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `match` is not allowed in a `const fn` + --> $DIR/feature-gate-const-if-match.rs:92:17 + | +LL | let x = match x { 0 => 1, _ => 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const fn` + --> $DIR/feature-gate-const-if-match.rs:94:9 + | +LL | if let Some(x) = Some(x) { x } else { 1 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:110:17 + | +LL | let x = if false { 0 } else { 1 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `match` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:112:17 + | +LL | let x = match x { 0 => 1, _ => 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:114:9 + | +LL | if let Some(x) = Some(x) { x } else { 1 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:67:21 + | +LL | const IF: i32 = if true { 5 } else { 6 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:70:25 + | +LL | const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `match` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:73:24 + | +LL | const MATCH: i32 = match 0 { 1 => 2, _ => 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:78:21 + | +LL | const IF: i32 = if true { 5 } else { 6 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:81:25 + | +LL | const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `match` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:84:24 + | +LL | const MATCH: i32 = match 0 { 1 => 2, _ => 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0019]: constant contains unimplemented expression type + --> $DIR/feature-gate-const-if-match.rs:114:21 + | +LL | if let Some(x) = Some(x) { x } else { 1 } + | ^ + +error: aborting due to 25 previous errors + +Some errors have detailed explanations: E0019, E0658. +For more information about an error, try `rustc --explain E0019`. diff --git a/src/test/ui/consts/control-flow/interior-mutability.rs b/src/test/ui/consts/control-flow/interior-mutability.rs new file mode 100644 index 00000000000..fcced75fcb0 --- /dev/null +++ b/src/test/ui/consts/control-flow/interior-mutability.rs @@ -0,0 +1,27 @@ +// Ensure that *any* assignment to the return place of a value with interior mutability +// disqualifies it from promotion. + +#![feature(const_if_match)] + +use std::cell::Cell; + +const X: Option<Cell<i32>> = { + let mut x = None; + if false { + x = Some(Cell::new(4)); + } + x +}; + +const Y: Option<Cell<i32>> = { + let mut y = Some(Cell::new(4)); + if true { + y = None; + } + y +}; + +fn main() { + let x: &'static _ = &X; //~ ERROR temporary value dropped while borrowed + let y: &'static _ = &Y; //~ ERROR temporary value dropped while borrowed +} diff --git a/src/test/ui/consts/control-flow/interior-mutability.stderr b/src/test/ui/consts/control-flow/interior-mutability.stderr new file mode 100644 index 00000000000..49e8ea3ade7 --- /dev/null +++ b/src/test/ui/consts/control-flow/interior-mutability.stderr @@ -0,0 +1,24 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/interior-mutability.rs:25:26 + | +LL | let x: &'static _ = &X; + | ---------- ^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | let y: &'static _ = &Y; +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/interior-mutability.rs:26:26 + | +LL | let y: &'static _ = &Y; + | ---------- ^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/src/test/ui/consts/control-flow/issue-46843.if_match.stderr b/src/test/ui/consts/control-flow/issue-46843.if_match.stderr new file mode 100644 index 00000000000..4c64d7dee8c --- /dev/null +++ b/src/test/ui/consts/control-flow/issue-46843.if_match.stderr @@ -0,0 +1,9 @@ +error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants + --> $DIR/issue-46843.rs:11:26 + | +LL | pub const Q: i32 = match non_const() { + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/consts/control-flow/issue-46843.rs b/src/test/ui/consts/control-flow/issue-46843.rs new file mode 100644 index 00000000000..1fc91015ffa --- /dev/null +++ b/src/test/ui/consts/control-flow/issue-46843.rs @@ -0,0 +1,18 @@ +// revisions: stock if_match + +#![cfg_attr(if_match, feature(const_if_match))] + +enum Thing { This, That } + +fn non_const() -> Thing { + Thing::This +} + +pub const Q: i32 = match non_const() { + //[stock]~^ ERROR `match` is not allowed in a `const` + //[if_match]~^^ ERROR calls in constants are limited to constant functions + Thing::This => 1, + Thing::That => 0 +}; + +fn main() {} diff --git a/src/test/ui/consts/control-flow/issue-46843.stock.stderr b/src/test/ui/consts/control-flow/issue-46843.stock.stderr new file mode 100644 index 00000000000..b6f38f8ed95 --- /dev/null +++ b/src/test/ui/consts/control-flow/issue-46843.stock.stderr @@ -0,0 +1,18 @@ +error[E0658]: `match` is not allowed in a `const` + --> $DIR/issue-46843.rs:11:20 + | +LL | pub const Q: i32 = match non_const() { + | ____________________^ +LL | | +LL | | +LL | | Thing::This => 1, +LL | | Thing::That => 0 +LL | | }; + | |_^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/control-flow/issue-50577.if_match.stderr b/src/test/ui/consts/control-flow/issue-50577.if_match.stderr new file mode 100644 index 00000000000..79572c41702 --- /dev/null +++ b/src/test/ui/consts/control-flow/issue-50577.if_match.stderr @@ -0,0 +1,16 @@ +error[E0317]: if may be missing an else clause + --> $DIR/issue-50577.rs:7:16 + | +LL | Drop = assert_eq!(1, 1) + | ^^^^^^^^^^^^^^^^ + | | + | expected `()`, found `isize` + | found here + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0317`. diff --git a/src/test/ui/consts/control-flow/issue-50577.rs b/src/test/ui/consts/control-flow/issue-50577.rs new file mode 100644 index 00000000000..7906ec4dc68 --- /dev/null +++ b/src/test/ui/consts/control-flow/issue-50577.rs @@ -0,0 +1,13 @@ +// revisions: stock if_match + +#![cfg_attr(if_match, feature(const_if_match))] + +fn main() { + enum Foo { + Drop = assert_eq!(1, 1) + //[stock,if_match]~^ ERROR if may be missing an else clause + //[stock]~^^ ERROR `match` is not allowed in a `const` + //[stock]~| ERROR `match` is not allowed in a `const` + //[stock]~| ERROR `if` is not allowed in a `const` + } +} diff --git a/src/test/ui/consts/control-flow/issue-50577.stock.stderr b/src/test/ui/consts/control-flow/issue-50577.stock.stderr new file mode 100644 index 00000000000..13b50954292 --- /dev/null +++ b/src/test/ui/consts/control-flow/issue-50577.stock.stderr @@ -0,0 +1,47 @@ +error[E0658]: `match` is not allowed in a `const` + --> $DIR/issue-50577.rs:7:16 + | +LL | Drop = assert_eq!(1, 1) + | ^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/issue-50577.rs:7:16 + | +LL | Drop = assert_eq!(1, 1) + | ^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error[E0658]: `match` is not allowed in a `const` + --> $DIR/issue-50577.rs:7:16 + | +LL | Drop = assert_eq!(1, 1) + | ^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error[E0317]: if may be missing an else clause + --> $DIR/issue-50577.rs:7:16 + | +LL | Drop = assert_eq!(1, 1) + | ^^^^^^^^^^^^^^^^ + | | + | expected `()`, found `isize` + | found here + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0317, E0658. +For more information about an error, try `rustc --explain E0317`. diff --git a/src/test/ui/consts/control-flow/loop.if_match.stderr b/src/test/ui/consts/control-flow/loop.if_match.stderr new file mode 100644 index 00000000000..15b9eb02861 --- /dev/null +++ b/src/test/ui/consts/control-flow/loop.if_match.stderr @@ -0,0 +1,111 @@ +error[E0744]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:8:15 + | +LL | const _: () = loop {}; + | ^^^^^^^ + +error[E0744]: `loop` is not allowed in a `static` + --> $DIR/loop.rs:10:19 + | +LL | static FOO: i32 = loop { break 4; }; + | ^^^^^^^^^^^^^^^^^ + +error[E0744]: `loop` is not allowed in a `const fn` + --> $DIR/loop.rs:13:5 + | +LL | loop {} + | ^^^^^^^ + +error[E0744]: `loop` is not allowed in a `const fn` + --> $DIR/loop.rs:26:9 + | +LL | loop {} + | ^^^^^^^ + +error[E0744]: `while` is not allowed in a `const` + --> $DIR/loop.rs:38:9 + | +LL | while false {} + | ^^^^^^^^^^^^^^ + +error[E0744]: `while` is not allowed in a `const` + --> $DIR/loop.rs:47:5 + | +LL | / while x < 4 { +LL | | x += 1; +LL | | } + | |_____^ + +error[E0744]: `while` is not allowed in a `const` + --> $DIR/loop.rs:51:5 + | +LL | / while x < 8 { +LL | | x += 1; +LL | | } + | |_____^ + +error[E0744]: `for` is not allowed in a `const` + --> $DIR/loop.rs:61:5 + | +LL | / for i in 0..4 { +LL | | x += i; +LL | | } + | |_____^ + +error[E0744]: `for` is not allowed in a `const` + --> $DIR/loop.rs:65:5 + | +LL | / for i in 0..4 { +LL | | x += i; +LL | | } + | |_____^ + +error[E0744]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:75:5 + | +LL | / loop { +LL | | x += 1; +LL | | if x == 4 { +LL | | break; +LL | | } +LL | | } + | |_____^ + +error[E0744]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:82:5 + | +LL | / loop { +LL | | x += 1; +LL | | if x == 8 { +LL | | break; +LL | | } +LL | | } + | |_____^ + +error[E0744]: `while` is not allowed in a `const` + --> $DIR/loop.rs:94:5 + | +LL | while let None = Some(x) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0744]: `while` is not allowed in a `const` + --> $DIR/loop.rs:95:5 + | +LL | while let None = Some(x) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0744]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:17:22 + | +LL | const BAR: i32 = loop { break 4; }; + | ^^^^^^^^^^^^^^^^^ + +error[E0744]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:21:22 + | +LL | const BAR: i32 = loop { break 4; }; + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 15 previous errors + +For more information about this error, try `rustc --explain E0744`. diff --git a/src/test/ui/consts/control-flow/loop.rs b/src/test/ui/consts/control-flow/loop.rs new file mode 100644 index 00000000000..4be341f2d38 --- /dev/null +++ b/src/test/ui/consts/control-flow/loop.rs @@ -0,0 +1,97 @@ +// Ensure that all loops are forbidden in a const context, even if `#![feature(const_if_match)]` is +// enabled. + +// revisions: stock if_match + +#![cfg_attr(if_match, feature(const_if_match))] + +const _: () = loop {}; //[stock,if_match]~ ERROR `loop` is not allowed in a `const` + +static FOO: i32 = loop { break 4; }; //[stock,if_match]~ ERROR `loop` is not allowed in a `static` + +const fn foo() { + loop {} //[stock,if_match]~ ERROR `loop` is not allowed in a `const fn` +} + +pub trait Foo { + const BAR: i32 = loop { break 4; }; //[stock,if_match]~ ERROR `loop` is not allowed in a `const` +} + +impl Foo for () { + const BAR: i32 = loop { break 4; }; //[stock,if_match]~ ERROR `loop` is not allowed in a `const` +} + +fn non_const_outside() { + const fn const_inside() { + loop {} //[stock,if_match]~ ERROR `loop` is not allowed in a `const fn` + } +} + +const fn const_outside() { + fn non_const_inside() { + loop {} + } +} + +fn main() { + let x = [0; { + while false {} + //[stock,if_match]~^ ERROR `while` is not allowed in a `const` + 4 + }]; +} + +const _: i32 = { + let mut x = 0; + + while x < 4 { //[stock,if_match]~ ERROR `while` is not allowed in a `const` + x += 1; + } + + while x < 8 { //[stock,if_match]~ ERROR `while` is not allowed in a `const` + x += 1; + } + + x +}; + +const _: i32 = { + let mut x = 0; + + for i in 0..4 { //[stock,if_match]~ ERROR `for` is not allowed in a `const` + x += i; + } + + for i in 0..4 { //[stock,if_match]~ ERROR `for` is not allowed in a `const` + x += i; + } + + x +}; + +const _: i32 = { + let mut x = 0; + + loop { //[stock,if_match]~ ERROR `loop` is not allowed in a `const` + x += 1; + if x == 4 { //[stock]~ ERROR `if` is not allowed in a `const` + break; + } + } + + loop { //[stock,if_match]~ ERROR `loop` is not allowed in a `const` + x += 1; + if x == 8 { //[stock]~ ERROR `if` is not allowed in a `const` + break; + } + } + + x +}; + +const _: i32 = { + let mut x = 0; + while let None = Some(x) { } //[stock,if_match]~ ERROR `while` is not allowed in a `const` + while let None = Some(x) { } //[stock,if_match]~ ERROR `while` is not allowed in a `const` + x +}; diff --git a/src/test/ui/consts/control-flow/loop.stock.stderr b/src/test/ui/consts/control-flow/loop.stock.stderr new file mode 100644 index 00000000000..bb651d23179 --- /dev/null +++ b/src/test/ui/consts/control-flow/loop.stock.stderr @@ -0,0 +1,134 @@ +error[E0744]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:8:15 + | +LL | const _: () = loop {}; + | ^^^^^^^ + +error[E0744]: `loop` is not allowed in a `static` + --> $DIR/loop.rs:10:19 + | +LL | static FOO: i32 = loop { break 4; }; + | ^^^^^^^^^^^^^^^^^ + +error[E0744]: `loop` is not allowed in a `const fn` + --> $DIR/loop.rs:13:5 + | +LL | loop {} + | ^^^^^^^ + +error[E0744]: `loop` is not allowed in a `const fn` + --> $DIR/loop.rs:26:9 + | +LL | loop {} + | ^^^^^^^ + +error[E0744]: `while` is not allowed in a `const` + --> $DIR/loop.rs:38:9 + | +LL | while false {} + | ^^^^^^^^^^^^^^ + +error[E0744]: `while` is not allowed in a `const` + --> $DIR/loop.rs:47:5 + | +LL | / while x < 4 { +LL | | x += 1; +LL | | } + | |_____^ + +error[E0744]: `while` is not allowed in a `const` + --> $DIR/loop.rs:51:5 + | +LL | / while x < 8 { +LL | | x += 1; +LL | | } + | |_____^ + +error[E0744]: `for` is not allowed in a `const` + --> $DIR/loop.rs:61:5 + | +LL | / for i in 0..4 { +LL | | x += i; +LL | | } + | |_____^ + +error[E0744]: `for` is not allowed in a `const` + --> $DIR/loop.rs:65:5 + | +LL | / for i in 0..4 { +LL | | x += i; +LL | | } + | |_____^ + +error[E0744]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:75:5 + | +LL | / loop { +LL | | x += 1; +LL | | if x == 4 { +LL | | break; +LL | | } +LL | | } + | |_____^ + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/loop.rs:77:9 + | +LL | / if x == 4 { +LL | | break; +LL | | } + | |_________^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0744]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:82:5 + | +LL | / loop { +LL | | x += 1; +LL | | if x == 8 { +LL | | break; +LL | | } +LL | | } + | |_____^ + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/loop.rs:84:9 + | +LL | / if x == 8 { +LL | | break; +LL | | } + | |_________^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0744]: `while` is not allowed in a `const` + --> $DIR/loop.rs:94:5 + | +LL | while let None = Some(x) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0744]: `while` is not allowed in a `const` + --> $DIR/loop.rs:95:5 + | +LL | while let None = Some(x) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0744]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:17:22 + | +LL | const BAR: i32 = loop { break 4; }; + | ^^^^^^^^^^^^^^^^^ + +error[E0744]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:21:22 + | +LL | const BAR: i32 = loop { break 4; }; + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 17 previous errors + +Some errors have detailed explanations: E0658, E0744. +For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/control-flow/short-circuit-let.rs b/src/test/ui/consts/control-flow/short-circuit-let.rs new file mode 100644 index 00000000000..8cee2a54f56 --- /dev/null +++ b/src/test/ui/consts/control-flow/short-circuit-let.rs @@ -0,0 +1,39 @@ +// `&&` and `||` were previously forbidden in constants alongside let bindings. + +// run-pass + +#![feature(const_if_match)] +#![feature(const_panic)] + +const X: i32 = { + let mut x = 0; + let _ = true && { x = 1; false }; + x +}; + +const Y: bool = { + let x = true && false || true; + x +}; + +const fn truthy() -> bool { + let x = true || return false; + x +} + +const fn falsy() -> bool { + let x = true && return false; + x +} + +fn main() { + const _: () = assert!(Y); + assert!(Y); + + const _: () = assert!(X == 1); + assert_eq!(X, 1); + + const _: () = assert!(truthy()); + const _: () = assert!(!falsy()); + assert!(truthy() && !falsy()); +} diff --git a/src/test/ui/consts/control-flow/short-circuit.if_match.stderr b/src/test/ui/consts/control-flow/short-circuit.if_match.stderr new file mode 100644 index 00000000000..f6ba28e7b72 --- /dev/null +++ b/src/test/ui/consts/control-flow/short-circuit.if_match.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/short-circuit.rs:14:1 + | +LL | fn main() {} + | ^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/consts/control-flow/short-circuit.rs b/src/test/ui/consts/control-flow/short-circuit.rs new file mode 100644 index 00000000000..f5e54a69d4a --- /dev/null +++ b/src/test/ui/consts/control-flow/short-circuit.rs @@ -0,0 +1,14 @@ +// Test that both `&&` and `||` actually short-circuit when the `const_if_match` feature flag is +// enabled. Without the feature flag, both sides are evaluated unconditionally. + +// revisions: stock if_match + +#![feature(rustc_attrs)] +#![feature(const_panic)] +#![cfg_attr(if_match, feature(const_if_match))] + +const _: bool = true || panic!(); //[stock]~ ERROR any use of this value will cause an error +const _: bool = false && panic!(); //[stock]~ ERROR any use of this value will cause an error + +#[rustc_error] +fn main() {} //[if_match]~ ERROR fatal error triggered by #[rustc_error] diff --git a/src/test/ui/consts/control-flow/short-circuit.stock.stderr b/src/test/ui/consts/control-flow/short-circuit.stock.stderr new file mode 100644 index 00000000000..cf0de929593 --- /dev/null +++ b/src/test/ui/consts/control-flow/short-circuit.stock.stderr @@ -0,0 +1,23 @@ +error: any use of this value will cause an error + --> $DIR/short-circuit.rs:10:25 + | +LL | const _: bool = true || panic!(); + | ------------------------^^^^^^^^- + | | + | the evaluated program panicked at 'explicit panic', $DIR/short-circuit.rs:10:25 + | + = note: `#[deny(const_err)]` on by default + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: any use of this value will cause an error + --> $DIR/short-circuit.rs:11:26 + | +LL | const _: bool = false && panic!(); + | -------------------------^^^^^^^^- + | | + | the evaluated program panicked at 'explicit panic', $DIR/short-circuit.rs:11:26 + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/consts/control-flow/single_variant_match_ice.rs b/src/test/ui/consts/control-flow/single_variant_match_ice.rs new file mode 100644 index 00000000000..823605ff034 --- /dev/null +++ b/src/test/ui/consts/control-flow/single_variant_match_ice.rs @@ -0,0 +1,27 @@ +// check-pass + +#![feature(const_if_match)] + +enum Foo { + Prob, +} + +const FOO: u32 = match Foo::Prob { + Foo::Prob => 42, +}; + +const BAR: u32 = match Foo::Prob { + x => 42, +}; + +impl Foo { + pub const fn as_val(&self) -> u8 { + use self::Foo::*; + + match *self { + Prob => 0x1, + } + } +} + +fn main() {} diff --git a/src/test/ui/consts/control-flow/try.rs b/src/test/ui/consts/control-flow/try.rs new file mode 100644 index 00000000000..31fe09d4f69 --- /dev/null +++ b/src/test/ui/consts/control-flow/try.rs @@ -0,0 +1,12 @@ +// The `?` operator is still not const-evaluatable because it calls `From::from` on the error +// variant. + +#![feature(const_if_match)] + +const fn opt() -> Option<i32> { + let x = Some(2); + x?; //~ ERROR `?` is not allowed in a `const fn` + None +} + +fn main() {} diff --git a/src/test/ui/consts/control-flow/try.stderr b/src/test/ui/consts/control-flow/try.stderr new file mode 100644 index 00000000000..60a386ef6c8 --- /dev/null +++ b/src/test/ui/consts/control-flow/try.stderr @@ -0,0 +1,9 @@ +error[E0744]: `?` is not allowed in a `const fn` + --> $DIR/try.rs:8:5 + | +LL | x?; + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0744`. |
