From 8f3021bd2cc49eda82ae01ac2e769a7e0fd0aa36 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 10 Dec 2019 12:41:27 -0800 Subject: [PATCH 01/19] Get active features dynamically by their `Symbol` --- src/librustc_feature/active.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 363621b3ca4..8794d830961 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -53,6 +53,18 @@ pub fn walk_feature_fields(&self, mut f: impl FnMut(&str, bool)) { $(f(stringify!($feature), self.$feature);)+ } } + + impl std::ops::Index for Features { + type Output = bool; + + fn index(&self, feature: Symbol) -> &Self::Output { + match feature { + $( sym::$feature => &self.$feature, )* + + _ => panic!("{} was not defined in `declare_features`", feature), + } + } + } }; } From 57959b2bdcd047745f3b403c25cc470c9a0889d9 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 10 Dec 2019 12:41:58 -0800 Subject: [PATCH 02/19] Add feature gate for `const_loop` --- src/librustc_feature/active.rs | 3 +++ src/libsyntax_pos/symbol.rs | 1 + 2 files changed, 4 insertions(+) diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 8794d830961..91a84f711f2 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -538,6 +538,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.42.0", Some(52000), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 92de56bd09a..6e48747da99 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, From 8f59902aad038fe32571740356844592b42a4376 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 10 Dec 2019 12:42:50 -0800 Subject: [PATCH 03/19] Put MIR checks for loops behind the feature flag --- src/librustc_mir/transform/check_consts/ops.rs | 4 ++++ src/librustc_mir/transform/qualify_min_const_fn.rs | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) 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..7d0abb5d463 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -390,8 +390,10 @@ fn check_terminator( cleanup: _, } => check_operand(tcx, cond, span, def_id, body), - TerminatorKind::FalseUnwind { .. } => { + TerminatorKind::FalseUnwind { .. } if !tcx.features().const_loop => { Err((span, "loops are not allowed in const fn".into())) }, + + TerminatorKind::FalseUnwind { .. } => Ok(()), } } From ee233c07c6bde5e4140e898be605325cdd21967e Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 10 Dec 2019 12:43:15 -0800 Subject: [PATCH 04/19] Restructue HIR const-checker to handle features with multiple gates --- src/librustc_passes/check_const.rs | 87 +++++++++++++++++++++++------- src/librustc_passes/lib.rs | 1 + 2 files changed, 69 insertions(+), 19 deletions(-) diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs index 63c6e60de79..e108dfb8173 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], + + // `for` loops desugar to a call to `FromIterator::from_iterator`, + // so they are not yet supported behind a feature flag. + _ => 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 gates = expr.required_feature_gates(); + match 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[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 gates = gates.unwrap_or(&[]); + let missing_gates: Vec<_> = gates + .iter() + .copied() + .filter(|&g| !features[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 gates.contains(&sym::const_loop) => { + let mut err = feature_err(&self.tcx.sess.parse_sess, gate, span, &msg); + err.note("`#![feature(const_loop)]` alone is not sufficient, \ + since this loop expression contains an implicit conditional"); + err.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"] From 99e132db9785ff5910c501a21f91fe4eb2ccd7ee Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 10 Dec 2019 21:10:48 -0800 Subject: [PATCH 05/19] Extend control flow basics tests with loops --- src/test/ui/consts/control-flow/basics.rs | 63 +++++++++++++++++++---- 1 file changed, 53 insertions(+), 10 deletions(-) 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)); } From 1122404be574be1120e8ba55052455c757864241 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 10 Dec 2019 21:24:46 -0800 Subject: [PATCH 06/19] Add qualif smoke tests for const loops --- .../ui/consts/control-flow/drop-failure.rs | 24 +++++++++++++++++++ .../ui/consts/control-flow/drop-success.rs | 21 ++++++++++++++++ .../control-flow/interior-mutability.rs | 16 +++++++++++++ 3 files changed, 61 insertions(+) diff --git a/src/test/ui/consts/control-flow/drop-failure.rs b/src/test/ui/consts/control-flow/drop-failure.rs index c6bea89e6e6..599ebc6243e 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,27 @@ } }; +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; + + if i > 100 { + break; + } + + some = tmp; + tmp = None; + + i += 1; + } + + some +}; + fn main() {} 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..d064041134f 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,22 @@ y }; +const Z: Option> = { + let mut z = None; + let mut i = 0; + while i < 10 { + if i == 8 { + z = Some(Cell::new(4)); + } + + 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 } From caa7c99172a858d3f00d893328446420c7b6856b Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 10 Dec 2019 21:27:53 -0800 Subject: [PATCH 07/19] Bless unrelated tests with new help message --- src/test/ui/closures/issue-52437.stderr | 7 +++++-- src/test/ui/consts/const-eval/infinite_loop.stderr | 8 ++++++-- src/test/ui/consts/const-eval/issue-52442.stderr | 7 +++++-- src/test/ui/consts/const-eval/issue-52475.stderr | 8 ++++++-- src/test/ui/consts/const-eval/issue-62272.stderr | 12 +++++++++--- src/test/ui/consts/const-labeled-break.stderr | 8 ++++++-- src/test/ui/consts/min_const_fn/loop_ice.stderr | 7 +++++-- src/test/ui/issues/issue-51714.stderr | 8 ++++++-- 8 files changed, 48 insertions(+), 17 deletions(-) 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/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`. From 332567103670935eefa347a87fb87c9153f814b9 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 10 Dec 2019 21:11:53 -0800 Subject: [PATCH 08/19] Bless modified tests --- .../consts/control-flow/drop-failure.stderr | 14 ++- .../control-flow/interior-mutability.stderr | 19 +++- .../ui/consts/control-flow/loop.both.stderr | 19 ++++ .../consts/control-flow/loop.if_match.stderr | 98 ++++++++++++----- .../ui/consts/control-flow/loop.loop_.stderr | 96 ++++++++++++++++ src/test/ui/consts/control-flow/loop.rs | 28 ++--- .../ui/consts/control-flow/loop.stock.stderr | 104 +++++++++++++----- 7 files changed, 298 insertions(+), 80 deletions(-) create mode 100644 src/test/ui/consts/control-flow/loop.both.stderr create mode 100644 src/test/ui/consts/control-flow/loop.loop_.stderr 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/interior-mutability.stderr b/src/test/ui/consts/control-flow/interior-mutability.stderr index 49e8ea3ade7..4f9c7d34c35 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:40: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:41: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:42: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..981cd01711b 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)]` are 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 From 2add77dffbf746ed95a5420f23bbaff6b3f99be5 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 10 Dec 2019 22:20:44 -0800 Subject: [PATCH 09/19] Improve message when active feature indexing panics --- src/librustc_feature/active.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 91a84f711f2..123188944b2 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -61,7 +61,7 @@ fn index(&self, feature: Symbol) -> &Self::Output { match feature { $( sym::$feature => &self.$feature, )* - _ => panic!("{} was not defined in `declare_features`", feature), + _ => panic!("`{}` was not listed in `declare_features`", feature), } } } From a8e997c819cc3cb9c70062da93809cd6f2540a0a Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 10 Dec 2019 22:24:10 -0800 Subject: [PATCH 10/19] Improve comment --- src/librustc_passes/check_const.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs index e108dfb8173..a60e005797e 100644 --- a/src/librustc_passes/check_const.rs +++ b/src/librustc_passes/check_const.rs @@ -56,8 +56,8 @@ fn required_feature_gates(self) -> Option<&'static [Symbol]> { | Self::Match(WhileLetDesugar) => &[sym::const_loop, sym::const_if_match], - // `for` loops desugar to a call to `FromIterator::from_iterator`, - // so they are not yet supported behind a feature flag. + // A `for` loop's desugaring contains a call to `FromIterator::from_iter`, + // so they are not yet allowed with `#![feature(const_loop)]`. _ => return None, }; From a2a077460b3365a95c475ce3b33fe7987c4bfa23 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 11 Dec 2019 10:09:10 -0800 Subject: [PATCH 11/19] Look for "unstable feature" error code in test Conditionals and loops now have unstable features, and `feature_err` has its own error code. I think that `feature_err` should take an error code as a parameter, but don't have the energy to make this change throughout the codebase. Also, the error code system may be torn out entirely. --- src/librustc_error_codes/error_codes/E0744.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 { From b3aecd0d55d81b73b571b961201d4da36417bf61 Mon Sep 17 00:00:00 2001 From: ecstatic-morse Date: Wed, 11 Dec 2019 10:16:12 -0800 Subject: [PATCH 12/19] Fix grammar in test description Co-Authored-By: Mazdak Farrokhzad --- src/test/ui/consts/control-flow/loop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/consts/control-flow/loop.rs b/src/test/ui/consts/control-flow/loop.rs index 981cd01711b..bc57f7568a7 100644 --- a/src/test/ui/consts/control-flow/loop.rs +++ b/src/test/ui/consts/control-flow/loop.rs @@ -1,4 +1,4 @@ -// Ensure that loops are forbidden in a const context unless `#![feature(const_loop)]` are 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. // gate-test-const_loop From 2b5ae1cb061f6599d108d9a0fc0b7b4e17abb5e7 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 11 Dec 2019 10:20:50 -0800 Subject: [PATCH 13/19] Apply suggestions from review --- src/librustc_passes/check_const.rs | 10 +++++----- src/test/ui/consts/control-flow/drop-failure.rs | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs index a60e005797e..713dd3a7c83 100644 --- a/src/librustc_passes/check_const.rs +++ b/src/librustc_passes/check_const.rs @@ -56,7 +56,7 @@ fn required_feature_gates(self) -> Option<&'static [Symbol]> { | Self::Match(WhileLetDesugar) => &[sym::const_loop, sym::const_if_match], - // A `for` loop's desugaring contains a call to `FromIterator::from_iter`, + // A `for` loop's desugaring contains a call to `IntoIterator::into_iter`, // so they are not yet allowed with `#![feature(const_loop)]`. _ => return None, }; @@ -167,10 +167,10 @@ fn const_check_violated(&self, expr: NonConstExpr, span: Span) { // 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 gates.contains(&sym::const_loop) => { - let mut err = feature_err(&self.tcx.sess.parse_sess, gate, span, &msg); - err.note("`#![feature(const_loop)]` alone is not sufficient, \ - since this loop expression contains an implicit conditional"); - err.emit(); + 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 @ ..] => { diff --git a/src/test/ui/consts/control-flow/drop-failure.rs b/src/test/ui/consts/control-flow/drop-failure.rs index 599ebc6243e..9da5546976c 100644 --- a/src/test/ui/consts/control-flow/drop-failure.rs +++ b/src/test/ui/consts/control-flow/drop-failure.rs @@ -43,6 +43,8 @@ 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; } From 80581be2c00ae9c9b24dea1c5a1465f6863564f3 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 11 Dec 2019 10:24:40 -0800 Subject: [PATCH 14/19] Replace `Index` impl with `enabled` method --- src/librustc_feature/active.rs | 8 ++------ src/librustc_passes/check_const.rs | 4 ++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 123188944b2..a4099187762 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -52,14 +52,10 @@ impl Features { pub fn walk_feature_fields(&self, mut f: impl FnMut(&str, bool)) { $(f(stringify!($feature), self.$feature);)+ } - } - impl std::ops::Index for Features { - type Output = bool; - - fn index(&self, feature: Symbol) -> &Self::Output { + pub fn enabled(&self, feature: Symbol) -> bool { match feature { - $( sym::$feature => &self.$feature, )* + $( sym::$feature => self.$feature, )* _ => panic!("`{}` was not listed in `declare_features`", feature), } diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs index 713dd3a7c83..e382d76f120 100644 --- a/src/librustc_passes/check_const.rs +++ b/src/librustc_passes/check_const.rs @@ -137,7 +137,7 @@ fn const_check_violated(&self, expr: NonConstExpr, span: Span) { let gates = expr.required_feature_gates(); match gates { // Don't emit an error if the user has enabled the requisite feature gates. - Some(gates) if gates.iter().all(|&g| features[g]) => return, + Some(gates) if gates.iter().all(|&g| features.enabled(g)) => return, // `-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 @@ -158,7 +158,7 @@ fn const_check_violated(&self, expr: NonConstExpr, span: Span) { let missing_gates: Vec<_> = gates .iter() .copied() - .filter(|&g| !features[g]) + .filter(|&g| !features.enabled(g)) .collect(); match missing_gates.as_slice() { From 34ce0ba9196df288c21907811b63603eb53809bb Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 11 Dec 2019 10:26:06 -0800 Subject: [PATCH 15/19] Use better name for local containing required feature gates --- src/librustc_passes/check_const.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs index e382d76f120..725a742382e 100644 --- a/src/librustc_passes/check_const.rs +++ b/src/librustc_passes/check_const.rs @@ -134,8 +134,8 @@ 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) { let features = self.tcx.features(); - let gates = expr.required_feature_gates(); - match gates { + 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(gates) if gates.iter().all(|&g| features.enabled(g)) => return, @@ -154,8 +154,8 @@ fn const_check_violated(&self, expr: NonConstExpr, span: Span) { .expect("`const_check_violated` may only be called inside a const context"); let msg = format!("`{}` is not allowed in a `{}`", expr.name(), const_kind); - let gates = gates.unwrap_or(&[]); - let missing_gates: Vec<_> = gates + let required_gates = required_gates.unwrap_or(&[]); + let missing_gates: Vec<_> = required_gates .iter() .copied() .filter(|&g| !features.enabled(g)) @@ -166,7 +166,7 @@ fn const_check_violated(&self, expr: NonConstExpr, span: Span) { // 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 gates.contains(&sym::const_loop) => { + &[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") From 598bed6f5124ceef83d69256d7e15ec404dda439 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 11 Dec 2019 13:09:20 -0800 Subject: [PATCH 16/19] Ensure test actually uses dataflow, not simulation --- src/test/ui/consts/control-flow/interior-mutability.rs | 4 ++++ src/test/ui/consts/control-flow/interior-mutability.stderr | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/test/ui/consts/control-flow/interior-mutability.rs b/src/test/ui/consts/control-flow/interior-mutability.rs index d064041134f..c2439f4a7bf 100644 --- a/src/test/ui/consts/control-flow/interior-mutability.rs +++ b/src/test/ui/consts/control-flow/interior-mutability.rs @@ -30,6 +30,10 @@ z = Some(Cell::new(4)); } + if i == 9 { + z = None; + } + i += 1; } z diff --git a/src/test/ui/consts/control-flow/interior-mutability.stderr b/src/test/ui/consts/control-flow/interior-mutability.stderr index 4f9c7d34c35..0977c84d12d 100644 --- a/src/test/ui/consts/control-flow/interior-mutability.stderr +++ b/src/test/ui/consts/control-flow/interior-mutability.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/interior-mutability.rs:40:26 + --> $DIR/interior-mutability.rs:44:26 | LL | let x: &'static _ = &X; | ---------- ^ creates a temporary which is freed while still in use @@ -10,7 +10,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/interior-mutability.rs:41:26 + --> $DIR/interior-mutability.rs:45:26 | LL | let y: &'static _ = &Y; | ---------- ^ creates a temporary which is freed while still in use @@ -21,7 +21,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/interior-mutability.rs:42:26 + --> $DIR/interior-mutability.rs:46:26 | LL | let z: &'static _ = &Z; | ---------- ^ creates a temporary which is freed while still in use From 029725f139c581e4484460d90d23909d7d4bebc1 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 11 Dec 2019 14:15:56 -0800 Subject: [PATCH 17/19] Use correct nightly version for feature --- src/librustc_feature/active.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index a4099187762..20357e5581a 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -535,7 +535,7 @@ pub fn set(&self, features: &mut Features, span: Span) { (active, const_mut_refs, "1.41.0", Some(57349), None), /// Allows the use of `loop` and `while` in constants. - (active, const_loop, "1.42.0", Some(52000), None), + (active, const_loop, "1.41.0", Some(52000), None), // ------------------------------------------------------------------------- // feature-group-end: actual feature gates From 0f0bfc9c2253c44fb826b057e4356bb50e9c704f Mon Sep 17 00:00:00 2001 From: ecstatic-morse Date: Thu, 12 Dec 2019 11:10:21 -0800 Subject: [PATCH 18/19] Document `Features::enabled` Co-Authored-By: Mazdak Farrokhzad --- src/librustc_feature/active.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 20357e5581a..08b65aff7c9 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -53,6 +53,9 @@ 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, )* From faa52d1cdaa8806201d56484df0c45bf550bf565 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 13 Dec 2019 10:44:38 -0800 Subject: [PATCH 19/19] Correctly mark things as `min_const_fn` --- src/librustc_mir/transform/qualify_min_const_fn.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 7d0abb5d463..e2530795749 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -390,10 +390,12 @@ fn check_terminator( cleanup: _, } => check_operand(tcx, cond, span, def_id, body), - TerminatorKind::FalseUnwind { .. } if !tcx.features().const_loop => { - Err((span, "loops are not allowed in const fn".into())) - }, + | TerminatorKind::FalseUnwind { .. } + if feature_allowed(tcx, def_id, sym::const_loop) + => Ok(()), - TerminatorKind::FalseUnwind { .. } => Ok(()), + TerminatorKind::FalseUnwind { .. } => { + Err((span, "loops are not allowed in const fn".into())) + } } }