summaryrefslogtreecommitdiffstats
path: root/tests/ui/consts/control-flow
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
commit218caa410aa38c29984be31a5229b9fa717560ee (patch)
treec54bd55eeb6e4c508940a30e94c0032fbd45d677 /tests/ui/consts/control-flow
parentReleasing progress-linux version 1.67.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-218caa410aa38c29984be31a5229b9fa717560ee.tar.xz
rustc-218caa410aa38c29984be31a5229b9fa717560ee.zip
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/consts/control-flow')
-rw-r--r--tests/ui/consts/control-flow/assert.rs8
-rw-r--r--tests/ui/consts/control-flow/assert.stderr11
-rw-r--r--tests/ui/consts/control-flow/basics.rs82
-rw-r--r--tests/ui/consts/control-flow/drop-fail.precise.stderr15
-rw-r--r--tests/ui/consts/control-flow/drop-fail.rs62
-rw-r--r--tests/ui/consts/control-flow/drop-fail.stock.stderr39
-rw-r--r--tests/ui/consts/control-flow/drop-pass.rs46
-rw-r--r--tests/ui/consts/control-flow/drop-precise.rs18
-rw-r--r--tests/ui/consts/control-flow/exhaustive-c-like-enum-match.rs29
-rw-r--r--tests/ui/consts/control-flow/feature-gate-const-if-match.rs96
-rw-r--r--tests/ui/consts/control-flow/interior-mutability.rs43
-rw-r--r--tests/ui/consts/control-flow/interior-mutability.stderr35
-rw-r--r--tests/ui/consts/control-flow/issue-46843.rs16
-rw-r--r--tests/ui/consts/control-flow/issue-46843.stderr11
-rw-r--r--tests/ui/consts/control-flow/issue-50577.rs6
-rw-r--r--tests/ui/consts/control-flow/issue-50577.stderr13
-rw-r--r--tests/ui/consts/control-flow/loop.rs89
-rw-r--r--tests/ui/consts/control-flow/loop.stderr25
-rw-r--r--tests/ui/consts/control-flow/short-circuit-let.rs36
-rw-r--r--tests/ui/consts/control-flow/short-circuit.rs12
-rw-r--r--tests/ui/consts/control-flow/single_variant_match_ice.rs25
-rw-r--r--tests/ui/consts/control-flow/try.rs10
-rw-r--r--tests/ui/consts/control-flow/try.stderr12
23 files changed, 739 insertions, 0 deletions
diff --git a/tests/ui/consts/control-flow/assert.rs b/tests/ui/consts/control-flow/assert.rs
new file mode 100644
index 000000000..9d17f65b9
--- /dev/null
+++ b/tests/ui/consts/control-flow/assert.rs
@@ -0,0 +1,8 @@
+// Test that `assert` works in consts.
+
+const _: () = assert!(true);
+
+const _: () = assert!(false);
+//~^ ERROR evaluation of constant value failed
+
+fn main() {}
diff --git a/tests/ui/consts/control-flow/assert.stderr b/tests/ui/consts/control-flow/assert.stderr
new file mode 100644
index 000000000..8b1ca183d
--- /dev/null
+++ b/tests/ui/consts/control-flow/assert.stderr
@@ -0,0 +1,11 @@
+error[E0080]: evaluation of constant value failed
+ --> $DIR/assert.rs:5:15
+ |
+LL | const _: () = assert!(false);
+ | ^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: false', $DIR/assert.rs:5:15
+ |
+ = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/control-flow/basics.rs b/tests/ui/consts/control-flow/basics.rs
new file mode 100644
index 000000000..02e5501f1
--- /dev/null
+++ b/tests/ui/consts/control-flow/basics.rs
@@ -0,0 +1,82 @@
+// Test basic functionality of control flow in a const context.
+
+// run-pass
+
+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)
+}
+
+const fn fib(n: u64) -> u64 {
+ if n == 0 {
+ return 0;
+ }
+
+ let mut fib = (0, 1);
+ let mut i = 1;
+ while i < n {
+ fib = (fib.1, fib.0 + fib.1);
+ i += 1;
+ }
+
+ fib.1
+}
+
+const fn is_prime(n: u64) -> bool {
+ if n % 2 == 0 {
+ return false;
+ }
+
+ let mut div = 3;
+ loop {
+ if n % div == 0 {
+ return false;
+ }
+
+ if div * div > n {
+ return true;
+ }
+
+ div += 2;
+ }
+}
+
+macro_rules! const_assert {
+ ($expr:expr) => {
+ const _: () = assert!($expr);
+ assert!($expr);
+ }
+}
+
+fn main() {
+ const_assert!(abs_diff(4, 5) == abs_diff(5, 4));
+ const_assert!(ABS_DIFF == abs_diff(5, 4));
+
+ const_assert!(gcd(48, 18) == 6);
+ const_assert!(gcd(18, 48) == 6);
+
+ const_assert!(fib(2) == 1);
+ const_assert!(fib(8) == 21);
+
+ const_assert!(is_prime(113));
+ const_assert!(!is_prime(117));
+}
diff --git a/tests/ui/consts/control-flow/drop-fail.precise.stderr b/tests/ui/consts/control-flow/drop-fail.precise.stderr
new file mode 100644
index 000000000..93b5f257e
--- /dev/null
+++ b/tests/ui/consts/control-flow/drop-fail.precise.stderr
@@ -0,0 +1,15 @@
+error[E0493]: destructor of `Option<Vec<i32>>` cannot be evaluated at compile-time
+ --> $DIR/drop-fail.rs:8:9
+ |
+LL | let x = Some(Vec::new());
+ | ^ the destructor for this type cannot be evaluated in constants
+
+error[E0493]: destructor of `Option<Vec<i32>>` cannot be evaluated at compile-time
+ --> $DIR/drop-fail.rs:39:9
+ |
+LL | let mut tmp = None;
+ | ^^^^^^^ the destructor for this type cannot be evaluated in constants
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0493`.
diff --git a/tests/ui/consts/control-flow/drop-fail.rs b/tests/ui/consts/control-flow/drop-fail.rs
new file mode 100644
index 000000000..41341f312
--- /dev/null
+++ b/tests/ui/consts/control-flow/drop-fail.rs
@@ -0,0 +1,62 @@
+// revisions: stock precise
+
+#![cfg_attr(precise, feature(const_precise_live_drops))]
+
+// `x` is *not* always moved into the final value and may be dropped inside the initializer.
+const _: Option<Vec<i32>> = {
+ let y: Option<Vec<i32>> = None;
+ let x = Some(Vec::new());
+ //[stock,precise]~^ ERROR destructor of
+
+ 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(),);
+ //[stock]~^ ERROR destructor of
+
+ vec_tuple.0
+};
+
+// This applies to single-field enum variants as well.
+const _: Vec<i32> = {
+ let x: Result<_, Vec<i32>> = Ok(Vec::new());
+ //[stock]~^ ERROR destructor of
+
+ match x {
+ Ok(x) | Err(x) => x,
+ }
+};
+
+const _: Option<Vec<i32>> = {
+ let mut some = Some(Vec::new());
+ let mut tmp = None;
+ //[stock,precise]~^ ERROR destructor of
+
+ let mut i = 0;
+ while i < 10 {
+ tmp = some;
+ some = None;
+
+ // We can escape the loop with `Some` still in `tmp`,
+ // which would require that it be dropped at the end of the block.
+ if i > 100 {
+ break;
+ }
+
+ some = tmp;
+ tmp = None;
+
+ i += 1;
+ }
+
+ some
+};
+
+fn main() {}
diff --git a/tests/ui/consts/control-flow/drop-fail.stock.stderr b/tests/ui/consts/control-flow/drop-fail.stock.stderr
new file mode 100644
index 000000000..2cc856802
--- /dev/null
+++ b/tests/ui/consts/control-flow/drop-fail.stock.stderr
@@ -0,0 +1,39 @@
+error[E0493]: destructor of `Option<Vec<i32>>` cannot be evaluated at compile-time
+ --> $DIR/drop-fail.rs:8:9
+ |
+LL | let x = Some(Vec::new());
+ | ^ the destructor for this type cannot be evaluated in constants
+...
+LL | };
+ | - value is dropped here
+
+error[E0493]: destructor of `(Vec<i32>,)` cannot be evaluated at compile-time
+ --> $DIR/drop-fail.rs:21:9
+ |
+LL | let vec_tuple = (Vec::new(),);
+ | ^^^^^^^^^ the destructor for this type cannot be evaluated in constants
+...
+LL | };
+ | - value is dropped here
+
+error[E0493]: destructor of `Result<Vec<i32>, Vec<i32>>` cannot be evaluated at compile-time
+ --> $DIR/drop-fail.rs:29:9
+ |
+LL | let x: Result<_, Vec<i32>> = Ok(Vec::new());
+ | ^ the destructor for this type cannot be evaluated in constants
+...
+LL | };
+ | - value is dropped here
+
+error[E0493]: destructor of `Option<Vec<i32>>` cannot be evaluated at compile-time
+ --> $DIR/drop-fail.rs:39:9
+ |
+LL | let mut tmp = None;
+ | ^^^^^^^ the destructor for this type cannot be evaluated in constants
+...
+LL | };
+ | - value is dropped here
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0493`.
diff --git a/tests/ui/consts/control-flow/drop-pass.rs b/tests/ui/consts/control-flow/drop-pass.rs
new file mode 100644
index 000000000..2a6d12768
--- /dev/null
+++ b/tests/ui/consts/control-flow/drop-pass.rs
@@ -0,0 +1,46 @@
+// run-pass
+// revisions: stock precise
+
+#![allow(unused)]
+#![cfg_attr(precise, feature(const_precise_live_drops))]
+
+// `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,
+ }
+};
+
+const _: Option<Vec<i32>> = {
+ let mut some = Some(Vec::new());
+ let mut tmp = None;
+
+ let mut i = 0;
+ while i < 10 {
+ tmp = some;
+ some = None;
+
+ // We can never exit the loop with `Some` in `tmp`.
+
+ some = tmp;
+ tmp = None;
+
+ i += 1;
+ }
+
+ some
+};
+
+fn main() {}
diff --git a/tests/ui/consts/control-flow/drop-precise.rs b/tests/ui/consts/control-flow/drop-precise.rs
new file mode 100644
index 000000000..4ecc5ef78
--- /dev/null
+++ b/tests/ui/consts/control-flow/drop-precise.rs
@@ -0,0 +1,18 @@
+// run-pass
+// gate-test-const_precise_live_drops
+
+#![feature(const_precise_live_drops)]
+
+const _: Vec<i32> = {
+ let vec_tuple = (Vec::new(),);
+ vec_tuple.0
+};
+
+const _: Vec<i32> = {
+ let x: Result<_, Vec<i32>> = Ok(Vec::new());
+ match x {
+ Ok(x) | Err(x) => x,
+ }
+};
+
+fn main() {}
diff --git a/tests/ui/consts/control-flow/exhaustive-c-like-enum-match.rs b/tests/ui/consts/control-flow/exhaustive-c-like-enum-match.rs
new file mode 100644
index 000000000..4320133df
--- /dev/null
+++ b/tests/ui/consts/control-flow/exhaustive-c-like-enum-match.rs
@@ -0,0 +1,29 @@
+// Test for <https://github.com/rust-lang/rust/issues/66756>
+
+// check-pass
+
+enum E {
+ A,
+ B,
+ C
+}
+
+const fn f(e: E) {
+ match e {
+ E::A => {}
+ E::B => {}
+ E::C => {}
+ }
+}
+
+const fn g(e: E) -> usize {
+ match e {
+ _ => 0
+ }
+}
+
+fn main() {
+ const X: usize = g(E::C);
+ assert_eq!(X, 0);
+ assert_eq!(g(E::A), 0);
+}
diff --git a/tests/ui/consts/control-flow/feature-gate-const-if-match.rs b/tests/ui/consts/control-flow/feature-gate-const-if-match.rs
new file mode 100644
index 000000000..cb66bc753
--- /dev/null
+++ b/tests/ui/consts/control-flow/feature-gate-const-if-match.rs
@@ -0,0 +1,96 @@
+// check-pass
+
+const _: i32 = if true { 5 } else { 6 };
+
+const _: i32 = if let Some(true) = Some(false) { 0 } else { 1 };
+
+const _: i32 = match 1 {
+ 2 => 3,
+ 4 => 5,
+ _ => 0,
+};
+
+static FOO: i32 = {
+ let x = if true { 0 } else { 1 };
+ let x = match x {
+ 0 => 1,
+ _ => 0,
+ };
+ if let Some(x) = Some(x) { x } else { 1 }
+};
+
+static mut BAR: i32 = {
+ let x = if true { 0 } else { 1 };
+ let x = match x {
+ 0 => 1,
+ _ => 0,
+ };
+ if let Some(x) = Some(x) { x } else { 1 }
+};
+
+const fn if_() -> i32 {
+ if true { 5 } else { 6 }
+}
+
+const fn if_let(a: Option<bool>) -> i32 {
+ if let Some(true) = a { 0 } else { 1 }
+}
+
+const fn match_(i: i32) -> i32 {
+ match i {
+ i if i > 10 => i,
+ 1 => 2,
+ _ => 0,
+ }
+}
+
+pub trait Foo {
+ const IF: i32 = if true { 5 } else { 6 };
+ const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 };
+ const MATCH: i32 = match 0 {
+ 1 => 2,
+ _ => 0,
+ };
+}
+
+impl Foo for () {
+ const IF: i32 = if true { 5 } else { 6 };
+ const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 };
+ const MATCH: i32 = match 0 {
+ 1 => 2,
+ _ => 0,
+ };
+}
+
+fn non_const_outside() {
+ const fn 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 }
+ }
+}
+
+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 }
+ }
+}
+
+fn main() {
+ let _ = [0; {
+ let x = if false { 0 } else { 1 };
+ let x = match x {
+ 0 => 1,
+ _ => 0,
+ };
+ if let Some(x) = Some(x) { x } else { 1 }
+ }];
+}
diff --git a/tests/ui/consts/control-flow/interior-mutability.rs b/tests/ui/consts/control-flow/interior-mutability.rs
new file mode 100644
index 000000000..a6d44237b
--- /dev/null
+++ b/tests/ui/consts/control-flow/interior-mutability.rs
@@ -0,0 +1,43 @@
+// Ensure that *any* assignment to the return place of a value with interior mutability
+// disqualifies it from promotion.
+
+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
+};
+
+const Z: Option<Cell<i32>> = {
+ let mut z = None;
+ let mut i = 0;
+ while i < 10 {
+ if i == 8 {
+ z = Some(Cell::new(4));
+ }
+
+ if i == 9 {
+ z = None;
+ }
+
+ i += 1;
+ }
+ z
+};
+
+fn main() {
+ let x: &'static _ = &X; //~ ERROR temporary value dropped while borrowed
+ let y: &'static _ = &Y; //~ ERROR temporary value dropped while borrowed
+ let z: &'static _ = &Z; //~ ERROR temporary value dropped while borrowed
+}
diff --git a/tests/ui/consts/control-flow/interior-mutability.stderr b/tests/ui/consts/control-flow/interior-mutability.stderr
new file mode 100644
index 000000000..db2ffb91b
--- /dev/null
+++ b/tests/ui/consts/control-flow/interior-mutability.stderr
@@ -0,0 +1,35 @@
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/interior-mutability.rs:40:26
+ |
+LL | let x: &'static _ = &X;
+ | ---------- ^ creates a temporary value 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[E0716]: temporary value dropped while borrowed
+ --> $DIR/interior-mutability.rs:41:26
+ |
+LL | let y: &'static _ = &Y;
+ | ---------- ^ creates a temporary value which is freed while still in use
+ | |
+ | type annotation requires that borrow lasts for `'static`
+LL | let z: &'static _ = &Z;
+LL | }
+ | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/interior-mutability.rs:42:26
+ |
+LL | let z: &'static _ = &Z;
+ | ---------- ^ creates a temporary value 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 3 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/tests/ui/consts/control-flow/issue-46843.rs b/tests/ui/consts/control-flow/issue-46843.rs
new file mode 100644
index 000000000..ddddc8505
--- /dev/null
+++ b/tests/ui/consts/control-flow/issue-46843.rs
@@ -0,0 +1,16 @@
+enum Thing {
+ This,
+ That,
+}
+
+fn non_const() -> Thing {
+ Thing::This
+}
+
+pub const Q: i32 = match non_const() {
+ //~^ ERROR cannot call non-const fn
+ Thing::This => 1,
+ Thing::That => 0
+};
+
+fn main() {}
diff --git a/tests/ui/consts/control-flow/issue-46843.stderr b/tests/ui/consts/control-flow/issue-46843.stderr
new file mode 100644
index 000000000..66227f61e
--- /dev/null
+++ b/tests/ui/consts/control-flow/issue-46843.stderr
@@ -0,0 +1,11 @@
+error[E0015]: cannot call non-const fn `non_const` in constants
+ --> $DIR/issue-46843.rs:10:26
+ |
+LL | pub const Q: i32 = match non_const() {
+ | ^^^^^^^^^^^
+ |
+ = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/control-flow/issue-50577.rs b/tests/ui/consts/control-flow/issue-50577.rs
new file mode 100644
index 000000000..beb9a44fc
--- /dev/null
+++ b/tests/ui/consts/control-flow/issue-50577.rs
@@ -0,0 +1,6 @@
+fn main() {
+ enum Foo {
+ Drop = assert_eq!(1, 1),
+ //~^ ERROR `if` may be missing an `else` clause
+ }
+}
diff --git a/tests/ui/consts/control-flow/issue-50577.stderr b/tests/ui/consts/control-flow/issue-50577.stderr
new file mode 100644
index 000000000..a931c89f4
--- /dev/null
+++ b/tests/ui/consts/control-flow/issue-50577.stderr
@@ -0,0 +1,13 @@
+error[E0317]: `if` may be missing an `else` clause
+ --> $DIR/issue-50577.rs:3:16
+ |
+LL | Drop = assert_eq!(1, 1),
+ | ^^^^^^^^^^^^^^^^ expected `isize`, found `()`
+ |
+ = note: `if` expressions without `else` evaluate to `()`
+ = help: consider adding an `else` block that evaluates to the expected type
+ = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0317`.
diff --git a/tests/ui/consts/control-flow/loop.rs b/tests/ui/consts/control-flow/loop.rs
new file mode 100644
index 000000000..2b8561a26
--- /dev/null
+++ b/tests/ui/consts/control-flow/loop.rs
@@ -0,0 +1,89 @@
+const _: () = loop { break (); };
+
+static FOO: i32 = loop { break 4; };
+
+const fn foo() {
+ loop {}
+}
+
+pub trait Foo {
+ const BAR: i32 = loop { break 4; };
+}
+
+impl Foo for () {
+ const BAR: i32 = loop { break 4; };
+}
+
+fn non_const_outside() {
+ const fn const_inside() {
+ loop {}
+ }
+}
+
+const fn const_outside() {
+ fn non_const_inside() {
+ loop {}
+ }
+}
+
+fn main() {
+ let x = [0; {
+ while false {}
+ 4
+ }];
+}
+
+const _: i32 = {
+ let mut x = 0;
+
+ while x < 4 {
+ x += 1;
+ }
+
+ while x < 8 {
+ x += 1;
+ }
+
+ x
+};
+
+const _: i32 = {
+ let mut x = 0;
+
+ for i in 0..4 { //~ ERROR `for` is not allowed in a `const`
+ x += i;
+ }
+
+ for i in 0..4 { //~ ERROR `for` is not allowed in a `const`
+ x += i;
+ }
+
+ x
+};
+
+const _: i32 = {
+ let mut x = 0;
+
+ loop {
+ x += 1;
+ if x == 4 {
+ break;
+ }
+ }
+
+ loop {
+ x += 1;
+ if x == 8 {
+ break;
+ }
+ }
+
+ x
+};
+
+const _: i32 = {
+ let mut x = 0;
+ while let None = Some(x) { }
+ while let None = Some(x) { }
+ x
+};
diff --git a/tests/ui/consts/control-flow/loop.stderr b/tests/ui/consts/control-flow/loop.stderr
new file mode 100644
index 000000000..5f6ad8c10
--- /dev/null
+++ b/tests/ui/consts/control-flow/loop.stderr
@@ -0,0 +1,25 @@
+error[E0658]: `for` is not allowed in a `const`
+ --> $DIR/loop.rs:53:5
+ |
+LL | / for i in 0..4 {
+LL | | x += i;
+LL | | }
+ | |_____^
+ |
+ = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
+ = help: add `#![feature(const_for)]` to the crate attributes to enable
+
+error[E0658]: `for` is not allowed in a `const`
+ --> $DIR/loop.rs:57:5
+ |
+LL | / for i in 0..4 {
+LL | | x += i;
+LL | | }
+ | |_____^
+ |
+ = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
+ = help: add `#![feature(const_for)]` 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/tests/ui/consts/control-flow/short-circuit-let.rs b/tests/ui/consts/control-flow/short-circuit-let.rs
new file mode 100644
index 000000000..8a58d06ac
--- /dev/null
+++ b/tests/ui/consts/control-flow/short-circuit-let.rs
@@ -0,0 +1,36 @@
+// `&&` and `||` were previously forbidden in constants alongside let bindings.
+
+// run-pass
+
+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/tests/ui/consts/control-flow/short-circuit.rs b/tests/ui/consts/control-flow/short-circuit.rs
new file mode 100644
index 000000000..6abe10785
--- /dev/null
+++ b/tests/ui/consts/control-flow/short-circuit.rs
@@ -0,0 +1,12 @@
+// run-pass
+
+// Test that both `&&` and `||` actually short-circuit.
+// Formerly, both sides were evaluated unconditionally
+
+const TRUE: bool = true || panic!();
+const FALSE: bool = false && panic!();
+
+fn main() {
+ assert!(TRUE);
+ assert!(!FALSE);
+}
diff --git a/tests/ui/consts/control-flow/single_variant_match_ice.rs b/tests/ui/consts/control-flow/single_variant_match_ice.rs
new file mode 100644
index 000000000..b59be00ff
--- /dev/null
+++ b/tests/ui/consts/control-flow/single_variant_match_ice.rs
@@ -0,0 +1,25 @@
+// check-pass
+
+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/tests/ui/consts/control-flow/try.rs b/tests/ui/consts/control-flow/try.rs
new file mode 100644
index 000000000..7d85a412b
--- /dev/null
+++ b/tests/ui/consts/control-flow/try.rs
@@ -0,0 +1,10 @@
+// The `?` operator is still not const-evaluatable because it calls `From::from` on the error
+// variant.
+
+const fn opt() -> Option<i32> {
+ let x = Some(2);
+ x?; //~ ERROR `?` is not allowed in a `const fn`
+ None
+}
+
+fn main() {}
diff --git a/tests/ui/consts/control-flow/try.stderr b/tests/ui/consts/control-flow/try.stderr
new file mode 100644
index 000000000..5aeec8fbf
--- /dev/null
+++ b/tests/ui/consts/control-flow/try.stderr
@@ -0,0 +1,12 @@
+error[E0658]: `?` is not allowed in a `const fn`
+ --> $DIR/try.rs:6:5
+ |
+LL | x?;
+ | ^^
+ |
+ = note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information
+ = help: add `#![feature(const_try)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.