diff --git a/src/librustc_error_codes/error_codes/E0744.md b/src/librustc_error_codes/error_codes/E0744.md index b299102fd69..602fbc50a71 100644 --- a/src/librustc_error_codes/error_codes/E0744.md +++ b/src/librustc_error_codes/error_codes/E0744.md @@ -3,7 +3,7 @@ Control-flow expressions are not allowed inside a const context. At the moment, `if` and `match`, as well as the looping constructs `for`, `while`, and `loop`, are forbidden inside a `const`, `static`, or `const fn`. -```compile_fail,E0744 +```compile_fail,E0658 const _: i32 = { let mut x = 0; loop { diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 1e3413b32f0..a386cbf56af 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -52,6 +52,17 @@ impl Features { pub fn walk_feature_fields(&self, mut f: impl FnMut(&str, bool)) { $(f(stringify!($feature), self.$feature);)+ } + + /// Is the given feature enabled? + /// + /// Panics if the symbol doesn't correspond to a declared feature. + pub fn enabled(&self, feature: Symbol) -> bool { + match feature { + $( sym::$feature => self.$feature, )* + + _ => panic!("`{}` was not listed in `declare_features`", feature), + } + } } }; } @@ -525,6 +536,9 @@ pub fn set(&self, features: &mut Features, span: Span) { /// Allows using `&mut` in constant functions. (active, const_mut_refs, "1.41.0", Some(57349), None), + /// Allows the use of `loop` and `while` in constants. + (active, const_loop, "1.41.0", Some(52000), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index 393ae9442a1..3df60993d9a 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -170,6 +170,10 @@ fn emit_error(&self, item: &Item<'_, '_>, span: Span) { #[derive(Debug)] pub struct Loop; impl NonConstOp for Loop { + fn feature_gate(tcx: TyCtxt<'_>) -> Option { + Some(tcx.features().const_loop) + } + fn emit_error(&self, item: &Item<'_, '_>, span: Span) { // This should be caught by the HIR const-checker. item.tcx.sess.delay_span_bug( diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 1c95155e7ff..e2530795749 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -390,8 +390,12 @@ fn check_terminator( cleanup: _, } => check_operand(tcx, cond, span, def_id, body), + | TerminatorKind::FalseUnwind { .. } + if feature_allowed(tcx, def_id, sym::const_loop) + => Ok(()), + TerminatorKind::FalseUnwind { .. } => { Err((span, "loops are not allowed in const fn".into())) - }, + } } } diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs index 63c6e60de79..725a742382e 100644 --- a/src/librustc_passes/check_const.rs +++ b/src/librustc_passes/check_const.rs @@ -13,11 +13,11 @@ use rustc::hir; use rustc::ty::TyCtxt; use rustc::ty::query::Providers; -use rustc_feature::Features; +use rustc::session::config::nightly_options; use syntax::ast::Mutability; use syntax::feature_gate::feature_err; use syntax::span_err; -use syntax_pos::{sym, Span}; +use syntax_pos::{sym, Span, Symbol}; use rustc_error_codes::*; use std::fmt; @@ -37,18 +37,31 @@ fn name(self) -> &'static str { } } - /// Returns `true` if all feature gates required to enable this expression are turned on, or - /// `None` if there is no feature gate corresponding to this expression. - fn is_feature_gate_enabled(self, features: &Features) -> Option { + fn required_feature_gates(self) -> Option<&'static [Symbol]> { use hir::MatchSource::*; - match self { + use hir::LoopSource::*; + + let gates: &[_] = match self { | Self::Match(Normal) | Self::Match(IfDesugar { .. }) | Self::Match(IfLetDesugar { .. }) - => Some(features.const_if_match), + => &[sym::const_if_match], - _ => None, - } + | Self::Loop(Loop) + => &[sym::const_loop], + + | Self::Loop(While) + | Self::Loop(WhileLet) + | Self::Match(WhileDesugar) + | Self::Match(WhileLetDesugar) + => &[sym::const_loop, sym::const_if_match], + + // A `for` loop's desugaring contains a call to `IntoIterator::into_iter`, + // so they are not yet allowed with `#![feature(const_loop)]`. + _ => return None, + }; + + Some(gates) } } @@ -120,11 +133,15 @@ fn new(tcx: TyCtxt<'tcx>) -> Self { /// Emits an error when an unsupported expression is found in a const context. fn const_check_violated(&self, expr: NonConstExpr, span: Span) { - match expr.is_feature_gate_enabled(self.tcx.features()) { + let features = self.tcx.features(); + let required_gates = expr.required_feature_gates(); + match required_gates { // Don't emit an error if the user has enabled the requisite feature gates. - Some(true) => return, + Some(gates) if gates.iter().all(|&g| features.enabled(g)) => return, - // Users of `-Zunleash-the-miri-inside-of-you` must use feature gates when possible. + // `-Zunleash-the-miri-inside-of-you` only works for expressions that don't have a + // corresponding feature gate. This encourages nightly users to use feature gates when + // possible. None if self.tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you => { self.tcx.sess.span_warn(span, "skipping const checks"); return; @@ -135,15 +152,47 @@ fn const_check_violated(&self, expr: NonConstExpr, span: Span) { let const_kind = self.const_kind .expect("`const_check_violated` may only be called inside a const context"); - let msg = format!("`{}` is not allowed in a `{}`", expr.name(), const_kind); - match expr { - | NonConstExpr::Match(hir::MatchSource::Normal) - | NonConstExpr::Match(hir::MatchSource::IfDesugar { .. }) - | NonConstExpr::Match(hir::MatchSource::IfLetDesugar { .. }) - => feature_err(&self.tcx.sess.parse_sess, sym::const_if_match, span, &msg).emit(), - _ => span_err!(self.tcx.sess, span, E0744, "{}", msg), + let required_gates = required_gates.unwrap_or(&[]); + let missing_gates: Vec<_> = required_gates + .iter() + .copied() + .filter(|&g| !features.enabled(g)) + .collect(); + + match missing_gates.as_slice() { + &[] => span_err!(self.tcx.sess, span, E0744, "{}", msg), + + // If the user enabled `#![feature(const_loop)]` but not `#![feature(const_if_match)]`, + // explain why their `while` loop is being rejected. + &[gate @ sym::const_if_match] if required_gates.contains(&sym::const_loop) => { + feature_err(&self.tcx.sess.parse_sess, gate, span, &msg) + .note("`#![feature(const_loop)]` alone is not sufficient, \ + since this loop expression contains an implicit conditional") + .emit(); + } + + &[missing_primary, ref missing_secondary @ ..] => { + let mut err = feature_err(&self.tcx.sess.parse_sess, missing_primary, span, &msg); + + // If multiple feature gates would be required to enable this expression, include + // them as help messages. Don't emit a separate error for each missing feature gate. + // + // FIXME(ecstaticmorse): Maybe this could be incorporated into `feature_err`? This + // is a pretty narrow case, however. + if nightly_options::is_nightly_build() { + for gate in missing_secondary { + let note = format!( + "add `#![feature({})]` to the crate attributes to enable", + gate, + ); + err.help(¬e); + } + } + + err.emit(); + } } } diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 81f06a14d95..f01867f32c6 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -8,6 +8,7 @@ #![feature(in_band_lifetimes)] #![feature(nll)] +#![feature(slice_patterns)] #![recursion_limit="256"] diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index c7e4182de6b..ae34064c926 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -213,6 +213,7 @@ const_indexing, const_in_array_repeat_expressions, const_let, + const_loop, const_mut_refs, const_panic, const_raw_ptr_deref, diff --git a/src/test/ui/closures/issue-52437.stderr b/src/test/ui/closures/issue-52437.stderr index b4b40336aa9..4d13a80e4cc 100644 --- a/src/test/ui/closures/issue-52437.stderr +++ b/src/test/ui/closures/issue-52437.stderr @@ -4,11 +4,14 @@ error: invalid label name `'static` LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize] | ^^^^^^^ -error[E0744]: `loop` is not allowed in a `const` +error[E0658]: `loop` is not allowed in a `const` --> $DIR/issue-52437.rs:2:13 | LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize] | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable error[E0282]: type annotations needed --> $DIR/issue-52437.rs:2:30 @@ -18,5 +21,5 @@ LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize] error: aborting due to 3 previous errors -Some errors have detailed explanations: E0282, E0744. +Some errors have detailed explanations: E0282, E0658. For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/consts/const-eval/infinite_loop.stderr b/src/test/ui/consts/const-eval/infinite_loop.stderr index de2624d7f7a..ed3c66db2cd 100644 --- a/src/test/ui/consts/const-eval/infinite_loop.stderr +++ b/src/test/ui/consts/const-eval/infinite_loop.stderr @@ -1,4 +1,4 @@ -error[E0744]: `while` is not allowed in a `const` +error[E0658]: `while` is not allowed in a `const` --> $DIR/infinite_loop.rs:7:9 | LL | / while n != 0 { @@ -8,6 +8,10 @@ LL | | LL | | LL | | } | |_________^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable + = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `const` --> $DIR/infinite_loop.rs:9:17 @@ -39,5 +43,5 @@ LL | n = if n % 2 == 0 { n/2 } else { 3*n + 1 }; error: aborting due to 3 previous errors -Some errors have detailed explanations: E0080, E0658, E0744. +Some errors have detailed explanations: E0080, E0658. For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/issue-52442.stderr b/src/test/ui/consts/const-eval/issue-52442.stderr index fa2272f8d63..c8ac4b1a762 100644 --- a/src/test/ui/consts/const-eval/issue-52442.stderr +++ b/src/test/ui/consts/const-eval/issue-52442.stderr @@ -1,8 +1,11 @@ -error[E0744]: `loop` is not allowed in a `const` +error[E0658]: `loop` is not allowed in a `const` --> $DIR/issue-52442.rs:2:14 | LL | [(); { &loop { break } as *const _ as usize } ]; | ^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable error[E0658]: casting pointers to integers in constants is unstable --> $DIR/issue-52442.rs:2:13 @@ -21,5 +24,5 @@ LL | [(); { &loop { break } as *const _ as usize } ]; error: aborting due to 3 previous errors -Some errors have detailed explanations: E0080, E0658, E0744. +Some errors have detailed explanations: E0080, E0658. For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/issue-52475.stderr b/src/test/ui/consts/const-eval/issue-52475.stderr index b8267f495de..7c0c735f9a4 100644 --- a/src/test/ui/consts/const-eval/issue-52475.stderr +++ b/src/test/ui/consts/const-eval/issue-52475.stderr @@ -1,4 +1,4 @@ -error[E0744]: `while` is not allowed in a `const` +error[E0658]: `while` is not allowed in a `const` --> $DIR/issue-52475.rs:6:9 | LL | / while n < 5 { @@ -7,6 +7,10 @@ LL | | n = (n + 1) % 5; LL | | x = &0; // Materialize a new AllocId LL | | } | |_________^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable + = help: add `#![feature(const_if_match)]` to the crate attributes to enable warning: Constant evaluating a complex constant, this might take some time --> $DIR/issue-52475.rs:2:18 @@ -29,5 +33,5 @@ LL | n = (n + 1) % 5; error: aborting due to 2 previous errors -Some errors have detailed explanations: E0080, E0744. +Some errors have detailed explanations: E0080, E0658. For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/issue-62272.stderr b/src/test/ui/consts/const-eval/issue-62272.stderr index 573d04f5e47..a02bbe557cf 100644 --- a/src/test/ui/consts/const-eval/issue-62272.stderr +++ b/src/test/ui/consts/const-eval/issue-62272.stderr @@ -1,15 +1,21 @@ -error[E0744]: `loop` is not allowed in a `const` +error[E0658]: `loop` is not allowed in a `const` --> $DIR/issue-62272.rs:7:17 | LL | const FOO: () = loop { break; }; | ^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0744]: `loop` is not allowed in a `const` +error[E0658]: `loop` is not allowed in a `const` --> $DIR/issue-62272.rs:10:20 | LL | [FOO; { let x; loop { x = 5; break; } x }]; | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0744`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/const-labeled-break.stderr b/src/test/ui/consts/const-labeled-break.stderr index ec32386439f..1282008fb63 100644 --- a/src/test/ui/consts/const-labeled-break.stderr +++ b/src/test/ui/consts/const-labeled-break.stderr @@ -1,9 +1,13 @@ -error[E0744]: `while` is not allowed in a `const` +error[E0658]: `while` is not allowed in a `const` --> $DIR/const-labeled-break.rs:10:19 | LL | const CRASH: () = 'a: while break 'a {}; | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable + = 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 E0744`. +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 index b9ff0409158..a53293743d5 100644 --- a/src/test/ui/consts/control-flow/basics.rs +++ b/src/test/ui/consts/control-flow/basics.rs @@ -1,9 +1,10 @@ -// Test basic functionality of `if` and `match` in a const context. +// Test basic functionality of control flow in a const context. // run-pass #![feature(const_panic)] #![feature(const_if_match)] +#![feature(const_loop)] #![feature(const_fn)] const X: u32 = 4; @@ -30,15 +31,57 @@ const fn gcd(a: u32, b: u32) -> u32 { 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 fn fib(n: u64) -> u64 { + if n == 0 { + return 0; + } - const _: () = assert!(ABS_DIFF == abs_diff(5, 4)); - assert_eq!(ABS_DIFF, abs_diff(5, 4)); + let mut fib = (0, 1); + let mut i = 1; + while i < n { + fib = (fib.1, fib.0 + fib.1); + i += 1; + } - const _: () = assert!(gcd(48, 18) == 6); - const _: () = assert!(gcd(18, 48) == 6); - assert_eq!(gcd(48, 18), 6); - assert_eq!(gcd(18, 48), 6); + 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/src/test/ui/consts/control-flow/drop-failure.rs b/src/test/ui/consts/control-flow/drop-failure.rs index c6bea89e6e6..9da5546976c 100644 --- a/src/test/ui/consts/control-flow/drop-failure.rs +++ b/src/test/ui/consts/control-flow/drop-failure.rs @@ -1,4 +1,5 @@ #![feature(const_if_match)] +#![feature(const_loop)] // `x` is *not* always moved into the final value may be dropped inside the initializer. const _: Option> = { @@ -32,4 +33,29 @@ } }; +const _: Option> = { + let mut some = Some(Vec::new()); + let mut tmp = None; + //~^ ERROR destructors cannot be evaluated at compile-time + + 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/src/test/ui/consts/control-flow/drop-failure.stderr b/src/test/ui/consts/control-flow/drop-failure.stderr index 35ceb3b2770..3eec3a929a0 100644 --- a/src/test/ui/consts/control-flow/drop-failure.stderr +++ b/src/test/ui/consts/control-flow/drop-failure.stderr @@ -1,21 +1,27 @@ error[E0493]: destructors cannot be evaluated at compile-time - --> $DIR/drop-failure.rs:6:9 + --> $DIR/drop-failure.rs:7: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 + --> $DIR/drop-failure.rs:20: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 + --> $DIR/drop-failure.rs:28:9 | LL | let x: Result<_, Vec> = Ok(Vec::new()); | ^ constants cannot evaluate destructors -error: aborting due to 3 previous errors +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/drop-failure.rs:38:9 + | +LL | let mut tmp = None; + | ^^^^^^^ constants cannot evaluate destructors + +error: aborting due to 4 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 index 92b3f6ec92e..185d6b63996 100644 --- a/src/test/ui/consts/control-flow/drop-success.rs +++ b/src/test/ui/consts/control-flow/drop-success.rs @@ -1,6 +1,7 @@ // run-pass #![feature(const_if_match)] +#![feature(const_loop)] // `x` is always moved into the final value and is not dropped inside the initializer. const _: Option> = { @@ -21,4 +22,24 @@ } }; +const _: Option> = { + 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/src/test/ui/consts/control-flow/interior-mutability.rs b/src/test/ui/consts/control-flow/interior-mutability.rs index fcced75fcb0..c2439f4a7bf 100644 --- a/src/test/ui/consts/control-flow/interior-mutability.rs +++ b/src/test/ui/consts/control-flow/interior-mutability.rs @@ -2,6 +2,7 @@ // disqualifies it from promotion. #![feature(const_if_match)] +#![feature(const_loop)] use std::cell::Cell; @@ -21,7 +22,26 @@ y }; +const Z: Option> = { + 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/src/test/ui/consts/control-flow/interior-mutability.stderr b/src/test/ui/consts/control-flow/interior-mutability.stderr index 49e8ea3ade7..0977c84d12d 100644 --- a/src/test/ui/consts/control-flow/interior-mutability.stderr +++ b/src/test/ui/consts/control-flow/interior-mutability.stderr @@ -1,24 +1,35 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/interior-mutability.rs:25:26 + --> $DIR/interior-mutability.rs:44: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 + --> $DIR/interior-mutability.rs:45: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 | 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:46:26 + | +LL | let z: &'static _ = &Z; + | ---------- ^ 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 +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0716`. diff --git a/src/test/ui/consts/control-flow/loop.both.stderr b/src/test/ui/consts/control-flow/loop.both.stderr new file mode 100644 index 00000000000..71d96b216f9 --- /dev/null +++ b/src/test/ui/consts/control-flow/loop.both.stderr @@ -0,0 +1,19 @@ +error[E0744]: `for` is not allowed in a `const` + --> $DIR/loop.rs:63:5 + | +LL | / for i in 0..4 { +LL | | x += i; +LL | | } + | |_____^ + +error[E0744]: `for` is not allowed in a `const` + --> $DIR/loop.rs:67:5 + | +LL | / for i in 0..4 { +LL | | x += i; +LL | | } + | |_____^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0744`. diff --git a/src/test/ui/consts/control-flow/loop.if_match.stderr b/src/test/ui/consts/control-flow/loop.if_match.stderr index 15b9eb02861..e01081638ec 100644 --- a/src/test/ui/consts/control-flow/loop.if_match.stderr +++ b/src/test/ui/consts/control-flow/loop.if_match.stderr @@ -1,51 +1,72 @@ -error[E0744]: `loop` is not allowed in a `const` - --> $DIR/loop.rs:8:15 +error[E0658]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:10:15 | LL | const _: () = loop {}; | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0744]: `loop` is not allowed in a `static` - --> $DIR/loop.rs:10:19 +error[E0658]: `loop` is not allowed in a `static` + --> $DIR/loop.rs:12:19 | LL | static FOO: i32 = loop { break 4; }; | ^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0744]: `loop` is not allowed in a `const fn` - --> $DIR/loop.rs:13:5 +error[E0658]: `loop` is not allowed in a `const fn` + --> $DIR/loop.rs:15:5 | LL | loop {} | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0744]: `loop` is not allowed in a `const fn` - --> $DIR/loop.rs:26:9 +error[E0658]: `loop` is not allowed in a `const fn` + --> $DIR/loop.rs:28:9 | LL | loop {} | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0744]: `while` is not allowed in a `const` - --> $DIR/loop.rs:38:9 +error[E0658]: `while` is not allowed in a `const` + --> $DIR/loop.rs:40:9 | LL | while false {} | ^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0744]: `while` is not allowed in a `const` - --> $DIR/loop.rs:47:5 +error[E0658]: `while` is not allowed in a `const` + --> $DIR/loop.rs:49:5 | LL | / while x < 4 { LL | | x += 1; LL | | } | |_____^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0744]: `while` is not allowed in a `const` - --> $DIR/loop.rs:51:5 +error[E0658]: `while` is not allowed in a `const` + --> $DIR/loop.rs:53:5 | LL | / while x < 8 { LL | | x += 1; LL | | } | |_____^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable error[E0744]: `for` is not allowed in a `const` - --> $DIR/loop.rs:61:5 + --> $DIR/loop.rs:63:5 | LL | / for i in 0..4 { LL | | x += i; @@ -53,15 +74,15 @@ LL | | } | |_____^ error[E0744]: `for` is not allowed in a `const` - --> $DIR/loop.rs:65:5 + --> $DIR/loop.rs:67: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 +error[E0658]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:77:5 | LL | / loop { LL | | x += 1; @@ -70,9 +91,12 @@ LL | | break; LL | | } LL | | } | |_____^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0744]: `loop` is not allowed in a `const` - --> $DIR/loop.rs:82:5 +error[E0658]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:84:5 | LL | / loop { LL | | x += 1; @@ -81,31 +105,47 @@ LL | | break; LL | | } LL | | } | |_____^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0744]: `while` is not allowed in a `const` - --> $DIR/loop.rs:94:5 +error[E0658]: `while` is not allowed in a `const` + --> $DIR/loop.rs:96:5 | LL | while let None = Some(x) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0744]: `while` is not allowed in a `const` - --> $DIR/loop.rs:95:5 +error[E0658]: `while` is not allowed in a `const` + --> $DIR/loop.rs:97:5 | LL | while let None = Some(x) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0744]: `loop` is not allowed in a `const` - --> $DIR/loop.rs:17:22 +error[E0658]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:19:22 | LL | const BAR: i32 = loop { break 4; }; | ^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0744]: `loop` is not allowed in a `const` - --> $DIR/loop.rs:21:22 +error[E0658]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:23:22 | LL | const BAR: i32 = loop { break 4; }; | ^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable error: aborting due to 15 previous errors -For more information about this error, try `rustc --explain E0744`. +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/loop.loop_.stderr b/src/test/ui/consts/control-flow/loop.loop_.stderr new file mode 100644 index 00000000000..cf871c9a78c --- /dev/null +++ b/src/test/ui/consts/control-flow/loop.loop_.stderr @@ -0,0 +1,96 @@ +error[E0658]: `while` is not allowed in a `const` + --> $DIR/loop.rs:40:9 + | +LL | while 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 + = note: `#![feature(const_loop)]` alone is not sufficient, since this loop expression contains an implicit conditional + +error[E0658]: `while` is not allowed in a `const` + --> $DIR/loop.rs:49:5 + | +LL | / while x < 4 { +LL | | x += 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 + = note: `#![feature(const_loop)]` alone is not sufficient, since this loop expression contains an implicit conditional + +error[E0658]: `while` is not allowed in a `const` + --> $DIR/loop.rs:53:5 + | +LL | / while x < 8 { +LL | | x += 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 + = note: `#![feature(const_loop)]` alone is not sufficient, since this loop expression contains an implicit conditional + +error[E0744]: `for` is not allowed in a `const` + --> $DIR/loop.rs:63:5 + | +LL | / for i in 0..4 { +LL | | x += i; +LL | | } + | |_____^ + +error[E0744]: `for` is not allowed in a `const` + --> $DIR/loop.rs:67:5 + | +LL | / for i in 0..4 { +LL | | x += i; +LL | | } + | |_____^ + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/loop.rs:79: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[E0658]: `if` is not allowed in a `const` + --> $DIR/loop.rs:86: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[E0658]: `while` is not allowed in a `const` + --> $DIR/loop.rs:96:5 + | +LL | while let None = Some(x) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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: `#![feature(const_loop)]` alone is not sufficient, since this loop expression contains an implicit conditional + +error[E0658]: `while` is not allowed in a `const` + --> $DIR/loop.rs:97:5 + | +LL | while let None = Some(x) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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: `#![feature(const_loop)]` alone is not sufficient, since this loop expression contains an implicit conditional + +error: aborting due to 9 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/loop.rs b/src/test/ui/consts/control-flow/loop.rs index 4be341f2d38..bc57f7568a7 100644 --- a/src/test/ui/consts/control-flow/loop.rs +++ b/src/test/ui/consts/control-flow/loop.rs @@ -1,9 +1,11 @@ -// Ensure that all loops are forbidden in a const context, even if `#![feature(const_if_match)]` is -// enabled. +// Ensure that loops are forbidden in a const context unless `#![feature(const_loop)]` is enabled. +// `while` loops require `#![feature(const_if_match)]` to be enabled as well. -// revisions: stock if_match +// gate-test-const_loop +// revisions: stock if_match loop_ both -#![cfg_attr(if_match, feature(const_if_match))] +#![cfg_attr(any(both, if_match), feature(const_if_match))] +#![cfg_attr(any(both, loop_), feature(const_loop))] const _: () = loop {}; //[stock,if_match]~ ERROR `loop` is not allowed in a `const` @@ -36,7 +38,7 @@ fn non_const_inside() { fn main() { let x = [0; { while false {} - //[stock,if_match]~^ ERROR `while` is not allowed in a `const` + //[stock,if_match,loop_]~^ ERROR `while` is not allowed in a `const` 4 }]; } @@ -44,11 +46,11 @@ fn main() { const _: i32 = { let mut x = 0; - while x < 4 { //[stock,if_match]~ ERROR `while` is not allowed in a `const` + while x < 4 { //[stock,if_match,loop_]~ ERROR `while` is not allowed in a `const` x += 1; } - while x < 8 { //[stock,if_match]~ ERROR `while` is not allowed in a `const` + while x < 8 { //[stock,if_match,loop_]~ ERROR `while` is not allowed in a `const` x += 1; } @@ -58,11 +60,11 @@ fn main() { const _: i32 = { let mut x = 0; - for i in 0..4 { //[stock,if_match]~ ERROR `for` is not allowed in a `const` + for i in 0..4 { //[stock,if_match,loop_,both]~ 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` + for i in 0..4 { //[stock,if_match,loop_,both]~ ERROR `for` is not allowed in a `const` x += i; } @@ -74,14 +76,14 @@ fn main() { 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` + if x == 4 { //[stock,loop_]~ 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` + if x == 8 { //[stock,loop_]~ ERROR `if` is not allowed in a `const` break; } } @@ -91,7 +93,7 @@ fn main() { 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` + while let None = Some(x) { } //[stock,if_match,loop_]~ ERROR `while` is not allowed in a `const` + while let None = Some(x) { } //[stock,if_match,loop_]~ 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 index bb651d23179..e3687cf12ac 100644 --- a/src/test/ui/consts/control-flow/loop.stock.stderr +++ b/src/test/ui/consts/control-flow/loop.stock.stderr @@ -1,51 +1,75 @@ -error[E0744]: `loop` is not allowed in a `const` - --> $DIR/loop.rs:8:15 +error[E0658]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:10:15 | LL | const _: () = loop {}; | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0744]: `loop` is not allowed in a `static` - --> $DIR/loop.rs:10:19 +error[E0658]: `loop` is not allowed in a `static` + --> $DIR/loop.rs:12:19 | LL | static FOO: i32 = loop { break 4; }; | ^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0744]: `loop` is not allowed in a `const fn` - --> $DIR/loop.rs:13:5 +error[E0658]: `loop` is not allowed in a `const fn` + --> $DIR/loop.rs:15:5 | LL | loop {} | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0744]: `loop` is not allowed in a `const fn` - --> $DIR/loop.rs:26:9 +error[E0658]: `loop` is not allowed in a `const fn` + --> $DIR/loop.rs:28:9 | LL | loop {} | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0744]: `while` is not allowed in a `const` - --> $DIR/loop.rs:38:9 +error[E0658]: `while` is not allowed in a `const` + --> $DIR/loop.rs:40:9 | LL | while false {} | ^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable + = help: add `#![feature(const_if_match)]` to the crate attributes to enable -error[E0744]: `while` is not allowed in a `const` - --> $DIR/loop.rs:47:5 +error[E0658]: `while` is not allowed in a `const` + --> $DIR/loop.rs:49:5 | LL | / while x < 4 { LL | | x += 1; LL | | } | |_____^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable + = help: add `#![feature(const_if_match)]` to the crate attributes to enable -error[E0744]: `while` is not allowed in a `const` - --> $DIR/loop.rs:51:5 +error[E0658]: `while` is not allowed in a `const` + --> $DIR/loop.rs:53:5 | LL | / while x < 8 { LL | | x += 1; LL | | } | |_____^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable + = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0744]: `for` is not allowed in a `const` - --> $DIR/loop.rs:61:5 + --> $DIR/loop.rs:63:5 | LL | / for i in 0..4 { LL | | x += i; @@ -53,15 +77,15 @@ LL | | } | |_____^ error[E0744]: `for` is not allowed in a `const` - --> $DIR/loop.rs:65:5 + --> $DIR/loop.rs:67: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 +error[E0658]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:77:5 | LL | / loop { LL | | x += 1; @@ -70,9 +94,12 @@ LL | | break; LL | | } LL | | } | |_____^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `const` - --> $DIR/loop.rs:77:9 + --> $DIR/loop.rs:79:9 | LL | / if x == 4 { LL | | break; @@ -82,8 +109,8 @@ 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 +error[E0658]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:84:5 | LL | / loop { LL | | x += 1; @@ -92,9 +119,12 @@ LL | | break; LL | | } LL | | } | |_____^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `const` - --> $DIR/loop.rs:84:9 + --> $DIR/loop.rs:86:9 | LL | / if x == 8 { LL | | break; @@ -104,29 +134,43 @@ 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 +error[E0658]: `while` is not allowed in a `const` + --> $DIR/loop.rs:96:5 | LL | while let None = Some(x) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable + = help: add `#![feature(const_if_match)]` to the crate attributes to enable -error[E0744]: `while` is not allowed in a `const` - --> $DIR/loop.rs:95:5 +error[E0658]: `while` is not allowed in a `const` + --> $DIR/loop.rs:97:5 | LL | while let None = Some(x) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable + = help: add `#![feature(const_if_match)]` to the crate attributes to enable -error[E0744]: `loop` is not allowed in a `const` - --> $DIR/loop.rs:17:22 +error[E0658]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:19:22 | LL | const BAR: i32 = loop { break 4; }; | ^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0744]: `loop` is not allowed in a `const` - --> $DIR/loop.rs:21:22 +error[E0658]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:23:22 | LL | const BAR: i32 = loop { break 4; }; | ^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable error: aborting due to 17 previous errors diff --git a/src/test/ui/consts/min_const_fn/loop_ice.stderr b/src/test/ui/consts/min_const_fn/loop_ice.stderr index 87db65fbb7d..58d1d421133 100644 --- a/src/test/ui/consts/min_const_fn/loop_ice.stderr +++ b/src/test/ui/consts/min_const_fn/loop_ice.stderr @@ -1,9 +1,12 @@ -error[E0744]: `loop` is not allowed in a `const fn` +error[E0658]: `loop` is not allowed in a `const fn` --> $DIR/loop_ice.rs:2:5 | LL | loop {} | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable error: aborting due to previous error -For more information about this error, try `rustc --explain E0744`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-51714.stderr b/src/test/ui/issues/issue-51714.stderr index 001928c3b2f..c3b880200f8 100644 --- a/src/test/ui/issues/issue-51714.stderr +++ b/src/test/ui/issues/issue-51714.stderr @@ -1,8 +1,12 @@ -error[E0744]: `while` is not allowed in a `const` +error[E0658]: `while` is not allowed in a `const` --> $DIR/issue-51714.rs:11:17 | LL | [(); return while let Some(n) = Some(0) {}]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/52000 + = help: add `#![feature(const_loop)]` to the crate attributes to enable + = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0572]: return statement outside of function body --> $DIR/issue-51714.rs:2:14 @@ -30,5 +34,5 @@ LL | [(); return while let Some(n) = Some(0) {}]; error: aborting due to 5 previous errors -Some errors have detailed explanations: E0572, E0744. +Some errors have detailed explanations: E0572, E0658. For more information about an error, try `rustc --explain E0572`.