about summary refs log tree commit diff
path: root/src/test/ui/consts/control-flow
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/consts/control-flow')
-rw-r--r--src/test/ui/consts/control-flow/assert.both.stderr13
-rw-r--r--src/test/ui/consts/control-flow/assert.if_match.stderr23
-rw-r--r--src/test/ui/consts/control-flow/assert.panic.stderr21
-rw-r--r--src/test/ui/consts/control-flow/assert.rs17
-rw-r--r--src/test/ui/consts/control-flow/assert.stock.stderr21
-rw-r--r--src/test/ui/consts/control-flow/basics.rs43
-rw-r--r--src/test/ui/consts/control-flow/drop-failure.rs35
-rw-r--r--src/test/ui/consts/control-flow/drop-failure.stderr21
-rw-r--r--src/test/ui/consts/control-flow/drop-success.rs24
-rw-r--r--src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr14
-rw-r--r--src/test/ui/consts/control-flow/feature-gate-const-if-match.rs118
-rw-r--r--src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr249
-rw-r--r--src/test/ui/consts/control-flow/interior-mutability.rs27
-rw-r--r--src/test/ui/consts/control-flow/interior-mutability.stderr24
-rw-r--r--src/test/ui/consts/control-flow/issue-46843.if_match.stderr9
-rw-r--r--src/test/ui/consts/control-flow/issue-46843.rs18
-rw-r--r--src/test/ui/consts/control-flow/issue-46843.stock.stderr18
-rw-r--r--src/test/ui/consts/control-flow/issue-50577.if_match.stderr16
-rw-r--r--src/test/ui/consts/control-flow/issue-50577.rs13
-rw-r--r--src/test/ui/consts/control-flow/issue-50577.stock.stderr47
-rw-r--r--src/test/ui/consts/control-flow/loop.if_match.stderr111
-rw-r--r--src/test/ui/consts/control-flow/loop.rs97
-rw-r--r--src/test/ui/consts/control-flow/loop.stock.stderr134
-rw-r--r--src/test/ui/consts/control-flow/short-circuit-let.rs39
-rw-r--r--src/test/ui/consts/control-flow/short-circuit.if_match.stderr8
-rw-r--r--src/test/ui/consts/control-flow/short-circuit.rs14
-rw-r--r--src/test/ui/consts/control-flow/short-circuit.stock.stderr23
-rw-r--r--src/test/ui/consts/control-flow/single_variant_match_ice.rs27
-rw-r--r--src/test/ui/consts/control-flow/try.rs12
-rw-r--r--src/test/ui/consts/control-flow/try.stderr9
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`.