diff --git a/src/doc/unstable-book/src/language-features/const-if-match.md b/src/doc/unstable-book/src/language-features/const-if-match.md new file mode 100644 index 0000000000000..ee9cfcbd9dee2 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/const-if-match.md @@ -0,0 +1,14 @@ +# `const_if_match` + +The tracking issue for this feature is: [#49146] + +[#49146]: https://github.com/rust-lang/rust/issues/49146 + +------------------------ + +Allows for the use of conditionals (`if` and `match`) in a const context. +Const contexts include `static`, `static mut`, `const`, `const fn`, const +generics, and array initializers. Enabling this feature flag will also make +`&&` and `||` function normally in a const-context by removing the hack that +replaces them with their non-short-circuiting equivalents, `&` and `|`, in a +`const` or `static`. diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 1f605711c8a8e..64d22ae943571 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1749,6 +1749,20 @@ pub enum MatchSource { AwaitDesugar, } +impl MatchSource { + pub fn name(self) -> &'static str { + use MatchSource::*; + match self { + Normal => "match", + IfDesugar { .. } | IfLetDesugar { .. } => "if", + WhileDesugar | WhileLetDesugar => "while", + ForLoopDesugar => "for", + TryDesugar => "?", + AwaitDesugar => ".await", + } + } +} + /// The loop type that yielded an `ExprKind::Loop`. #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum LoopSource { @@ -1766,8 +1780,7 @@ impl LoopSource { pub fn name(self) -> &'static str { match self { LoopSource::Loop => "loop", - LoopSource::While => "while", - LoopSource::WhileLet => "while let", + LoopSource::While | LoopSource::WhileLet => "while", LoopSource::ForLoop => "for", } } diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index de50755616bb0..694a3fd04eeb1 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -341,9 +341,10 @@ fn make_mirror_unadjusted<'a, 'tcx>( } else { // FIXME overflow match (op.node, cx.constness) { - // FIXME(eddyb) use logical ops in constants when - // they can handle that kind of control-flow. - (hir::BinOpKind::And, hir::Constness::Const) => { + // Destroy control flow if `#![feature(const_if_match)]` is not enabled. + (hir::BinOpKind::And, hir::Constness::Const) + if !cx.tcx.features().const_if_match => + { cx.control_flow_destroyed.push(( op.span, "`&&` operator".into(), @@ -354,7 +355,9 @@ fn make_mirror_unadjusted<'a, 'tcx>( rhs: rhs.to_ref(), } } - (hir::BinOpKind::Or, hir::Constness::Const) => { + (hir::BinOpKind::Or, hir::Constness::Const) + if !cx.tcx.features().const_if_match => + { cx.control_flow_destroyed.push(( op.span, "`||` operator".into(), @@ -366,14 +369,14 @@ fn make_mirror_unadjusted<'a, 'tcx>( } } - (hir::BinOpKind::And, hir::Constness::NotConst) => { + (hir::BinOpKind::And, _) => { ExprKind::LogicalOp { op: LogicalOp::And, lhs: lhs.to_ref(), rhs: rhs.to_ref(), } } - (hir::BinOpKind::Or, hir::Constness::NotConst) => { + (hir::BinOpKind::Or, _) => { ExprKind::LogicalOp { op: LogicalOp::Or, lhs: lhs.to_ref(), diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index 80f2925193a81..acad56be60403 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -52,7 +52,11 @@ pub trait NonConstOp: std::fmt::Debug { /// A `Downcast` projection. #[derive(Debug)] pub struct Downcast; -impl NonConstOp for Downcast {} +impl NonConstOp for Downcast { + fn feature_gate(tcx: TyCtxt<'_>) -> Option { + Some(tcx.features().const_if_match) + } +} /// A function call where the callee is a pointer. #[derive(Debug)] @@ -139,6 +143,10 @@ impl NonConstOp for HeapAllocation { #[derive(Debug)] pub struct IfOrMatch; impl NonConstOp for IfOrMatch { + fn feature_gate(tcx: TyCtxt<'_>) -> Option { + Some(tcx.features().const_if_match) + } + 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 65fc7cd20439d..71f13c169d41e 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -216,7 +216,9 @@ fn check_statement( check_rvalue(tcx, body, def_id, rval, span) } - StatementKind::FakeRead(FakeReadCause::ForMatchedPlace, _) => { + | StatementKind::FakeRead(FakeReadCause::ForMatchedPlace, _) + if !tcx.features().const_if_match + => { Err((span, "loops and conditional expressions are not stable in const fn".into())) } @@ -267,9 +269,10 @@ fn check_place( while let &[ref proj_base @ .., elem] = cursor { cursor = proj_base; match elem { - ProjectionElem::Downcast(..) => { - return Err((span, "`match` or `if let` in `const fn` is unstable".into())); - } + ProjectionElem::Downcast(..) if !tcx.features().const_if_match + => return Err((span, "`match` or `if let` in `const fn` is unstable".into())), + ProjectionElem::Downcast(_symbol, _variant_index) => {} + ProjectionElem::Field(..) => { let base_ty = Place::ty_from(&place.base, &proj_base, body, tcx).ty; if let Some(def) = base_ty.ty_adt_def() { @@ -321,10 +324,19 @@ fn check_terminator( check_operand(tcx, value, span, def_id, body) }, - TerminatorKind::FalseEdges { .. } | TerminatorKind::SwitchInt { .. } => Err(( + | TerminatorKind::FalseEdges { .. } + | TerminatorKind::SwitchInt { .. } + if !tcx.features().const_if_match + => Err(( span, "loops and conditional expressions are not stable in const fn".into(), )), + + TerminatorKind::FalseEdges { .. } => Ok(()), + TerminatorKind::SwitchInt { discr, switch_ty: _, values: _, targets: _ } => { + check_operand(tcx, discr, span, def_id, body) + } + | TerminatorKind::Abort | TerminatorKind::Unreachable => { Err((span, "const fn with unreachable code is not stable".into())) } diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs index 9d37b4bdb769c..24bc088e24a70 100644 --- a/src/librustc_passes/check_const.rs +++ b/src/librustc_passes/check_const.rs @@ -11,16 +11,46 @@ use rustc::hir::def_id::DefId; use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; use rustc::hir::map::Map; use rustc::hir; -use rustc::session::Session; use rustc::ty::TyCtxt; use rustc::ty::query::Providers; use syntax::ast::Mutability; +use syntax::feature_gate::{emit_feature_err, Features, GateIssue}; use syntax::span_err; -use syntax_pos::Span; +use syntax_pos::{sym, Span}; use rustc_error_codes::*; use std::fmt; +/// An expression that is not *always* legal in a const context. +#[derive(Clone, Copy)] +enum NonConstExpr { + Loop(hir::LoopSource), + Match(hir::MatchSource), +} + +impl NonConstExpr { + fn name(self) -> &'static str { + match self { + Self::Loop(src) => src.name(), + Self::Match(src) => src.name(), + } + } + + /// 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 { + use hir::MatchSource::*; + match self { + | Self::Match(Normal) + | Self::Match(IfDesugar { .. }) + | Self::Match(IfLetDesugar { .. }) + => Some(features.const_if_match), + + _ => None, + } + } +} + #[derive(Copy, Clone)] enum ConstKind { Static, @@ -75,31 +105,51 @@ pub(crate) fn provide(providers: &mut Providers<'_>) { #[derive(Copy, Clone)] struct CheckConstVisitor<'tcx> { - sess: &'tcx Session, - hir_map: &'tcx Map<'tcx>, + tcx: TyCtxt<'tcx>, const_kind: Option, } impl<'tcx> CheckConstVisitor<'tcx> { fn new(tcx: TyCtxt<'tcx>) -> Self { CheckConstVisitor { - sess: &tcx.sess, - hir_map: tcx.hir(), + tcx, const_kind: None, } } /// Emits an error when an unsupported expression is found in a const context. - fn const_check_violated(&self, bad_op: &str, span: Span) { - if self.sess.opts.debugging_opts.unleash_the_miri_inside_of_you { - self.sess.span_warn(span, "skipping const checks"); - return; + fn const_check_violated(&self, expr: NonConstExpr, span: Span) { + match expr.is_feature_gate_enabled(self.tcx.features()) { + // Don't emit an error if the user has enabled the requisite feature gates. + Some(true) => return, + + // Users of `-Zunleash-the-miri-inside-of-you` must 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; + } + + _ => {} } let const_kind = self.const_kind .expect("`const_check_violated` may only be called inside a const context"); - span_err!(self.sess, span, E0744, "`{}` is not allowed in a `{}`", bad_op, const_kind); + 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 { .. }) + => emit_feature_err( + &self.tcx.sess.parse_sess, + sym::const_if_match, + span, + GateIssue::Language, + &msg + ), + + _ => span_err!(self.tcx.sess, span, E0744, "{}", msg), + } } /// Saves the parent `const_kind` before calling `f` and restores it afterwards. @@ -113,7 +163,7 @@ impl<'tcx> CheckConstVisitor<'tcx> { impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.hir_map) + NestedVisitorMap::OnlyBodies(&self.tcx.hir()) } fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) { @@ -122,7 +172,7 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> { } fn visit_body(&mut self, body: &'tcx hir::Body) { - let kind = ConstKind::for_body(body, self.hir_map); + let kind = ConstKind::for_body(body, self.tcx.hir()); self.recurse_into(kind, |this| hir::intravisit::walk_body(this, body)); } @@ -132,24 +182,22 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> { _ if self.const_kind.is_none() => {} hir::ExprKind::Loop(_, _, source) => { - self.const_check_violated(source.name(), e.span); + self.const_check_violated(NonConstExpr::Loop(*source), e.span); } hir::ExprKind::Match(_, _, source) => { - use hir::MatchSource::*; - - let op = match source { - Normal => Some("match"), - IfDesugar { .. } | IfLetDesugar { .. } => Some("if"), - TryDesugar => Some("?"), - AwaitDesugar => Some(".await"), - + let non_const_expr = match source { // These are handled by `ExprKind::Loop` above. - WhileDesugar | WhileLetDesugar | ForLoopDesugar => None, + | hir::MatchSource::WhileDesugar + | hir::MatchSource::WhileLetDesugar + | hir::MatchSource::ForLoopDesugar + => None, + + _ => Some(NonConstExpr::Match(*source)), }; - if let Some(op) = op { - self.const_check_violated(op, e.span); + if let Some(expr) = non_const_expr { + self.const_check_violated(expr, e.span); } } diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index bd029514a9524..fa0ab90c702b9 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -529,6 +529,9 @@ declare_features! ( /// Allows using the `#[register_attr]` attribute. (active, register_tool, "1.41.0", Some(66079), None), + /// Allows the use of `if` and `match` in constants. + (active, const_if_match, "1.41.0", Some(49146), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 23ee972529a70..d20d520ac5578 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -203,6 +203,7 @@ symbols! { const_fn, const_fn_union, const_generics, + const_if_match, const_indexing, const_in_array_repeat_expressions, const_let, diff --git a/src/test/ui/borrowck/issue-64453.stderr b/src/test/ui/borrowck/issue-64453.stderr index f437880a1655f..0b66426aa2a0f 100644 --- a/src/test/ui/borrowck/issue-64453.stderr +++ b/src/test/ui/borrowck/issue-64453.stderr @@ -1,11 +1,13 @@ -error[E0744]: `match` is not allowed in a `static` +error[E0658]: `match` is not allowed in a `static` --> $DIR/issue-64453.rs:4:31 | LL | static settings_dir: String = format!(""); | ^^^^^^^^^^^ | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: 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/const-eval/infinite_loop.stderr b/src/test/ui/consts/const-eval/infinite_loop.stderr index 2af6af95c5565..de2624d7f7acf 100644 --- a/src/test/ui/consts/const-eval/infinite_loop.stderr +++ b/src/test/ui/consts/const-eval/infinite_loop.stderr @@ -9,11 +9,14 @@ LL | | LL | | } | |_________^ -error[E0744]: `if` is not allowed in a `const` +error[E0658]: `if` is not allowed in a `const` --> $DIR/infinite_loop.rs:9:17 | LL | n = if n % 2 == 0 { n/2 } else { 3*n + 1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable warning: Constant evaluating a complex constant, this might take some time --> $DIR/infinite_loop.rs:4:18 @@ -36,5 +39,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, E0744. +Some errors have detailed explanations: E0080, E0658, E0744. For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/match-test-ptr-null.stderr b/src/test/ui/consts/const-eval/match-test-ptr-null.stderr index 587dca4c1f279..d1ad2261dc259 100644 --- a/src/test/ui/consts/const-eval/match-test-ptr-null.stderr +++ b/src/test/ui/consts/const-eval/match-test-ptr-null.stderr @@ -1,4 +1,4 @@ -error[E0744]: `match` is not allowed in a `const` +error[E0658]: `match` is not allowed in a `const` --> $DIR/match-test-ptr-null.rs:6:9 | LL | / match &1 as *const i32 as usize { @@ -9,6 +9,9 @@ LL | | 0 => 42, LL | | n => n, 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]: casting pointers to integers in constants is unstable --> $DIR/match-test-ptr-null.rs:6:15 @@ -27,5 +30,5 @@ LL | match &1 as *const i32 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-if.rs b/src/test/ui/consts/const-if.rs deleted file mode 100644 index 94cce60453dcc..0000000000000 --- a/src/test/ui/consts/const-if.rs +++ /dev/null @@ -1,21 +0,0 @@ -const _: i32 = if true { //~ ERROR `if` is not allowed in a `const` - 5 -} else { - 6 -}; - -const _: i32 = match 1 { //~ ERROR `match` is not allowed in a `const` - 2 => 3, - 4 => 5, - _ => 0, -}; - -const fn foo() -> i32 { - if true { 5 } else { 6 } //~ ERROR `if` is not allowed in a `const fn` -} - -const fn bar() -> i32 { - match 0 { 1 => 2, _ => 0 } //~ ERROR `match` is not allowed in a `const fn` -} - -fn main() {} diff --git a/src/test/ui/consts/const-if.stderr b/src/test/ui/consts/const-if.stderr deleted file mode 100644 index 6fb2a0e150190..0000000000000 --- a/src/test/ui/consts/const-if.stderr +++ /dev/null @@ -1,37 +0,0 @@ -error[E0744]: `if` is not allowed in a `const` - --> $DIR/const-if.rs:1:16 - | -LL | const _: i32 = if true { - | ________________^ -LL | | 5 -LL | | } else { -LL | | 6 -LL | | }; - | |_^ - -error[E0744]: `match` is not allowed in a `const` - --> $DIR/const-if.rs:7:16 - | -LL | const _: i32 = match 1 { - | ________________^ -LL | | 2 => 3, -LL | | 4 => 5, -LL | | _ => 0, -LL | | }; - | |_^ - -error[E0744]: `if` is not allowed in a `const fn` - --> $DIR/const-if.rs:14:5 - | -LL | if true { 5 } else { 6 } - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0744]: `match` is not allowed in a `const fn` - --> $DIR/const-if.rs:18:5 - | -LL | match 0 { 1 => 2, _ => 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0744`. diff --git a/src/test/ui/consts/const-loop.rs b/src/test/ui/consts/const-loop.rs deleted file mode 100644 index b0fe5e320f4a6..0000000000000 --- a/src/test/ui/consts/const-loop.rs +++ /dev/null @@ -1,90 +0,0 @@ -const _: () = loop {}; //~ ERROR `loop` is not allowed in a `const` - -static FOO: i32 = loop { break 4; }; //~ ERROR `loop` is not allowed in a `static` - -const fn foo() { - loop {} //~ ERROR `loop` is not allowed in a `const fn` -} - -pub trait Foo { - const BAR: i32 = loop { break 4; }; //~ ERROR `loop` is not allowed in a `const` -} - -impl Foo for () { - const BAR: i32 = loop { break 4; }; //~ ERROR `loop` is not allowed in a `const` -} - -fn non_const_outside() { - const fn const_inside() { - loop {} //~ ERROR `loop` is not allowed in a `const fn` - } -} - -const fn const_outside() { - fn non_const_inside() { - loop {} - } -} - -fn main() { - let x = [0; { - while false {} - //~^ ERROR `while` is not allowed in a `const` - 4 - }]; -} - -const _: i32 = { - let mut x = 0; - - while x < 4 { //~ ERROR `while` is not allowed in a `const` - x += 1; - } - - while x < 8 { //~ ERROR `while` is not allowed in a `const` - x += 1; - } - - x -}; - -const _: i32 = { - let mut x = 0; - - for i in 0..4 { //~ ERROR `for` is not allowed in a `const` - x += i; - } - - for i in 0..4 { //~ ERROR `for` is not allowed in a `const` - x += i; - } - - x -}; - -const _: i32 = { - let mut x = 0; - - loop { //~ ERROR `loop` is not allowed in a `const` - x += 1; - if x == 4 { //~ ERROR `if` is not allowed in a `const` - break; - } - } - - loop { //~ ERROR `loop` is not allowed in a `const` - x += 1; - if x == 8 { //~ ERROR `if` is not allowed in a `const` - break; - } - } - - x -}; - -const _: i32 = { - let mut x = 0; - while let None = Some(x) { } //~ ERROR `while let` is not allowed in a `const` - while let None = Some(x) { } //~ ERROR `while let` is not allowed in a `const` - x -}; diff --git a/src/test/ui/consts/const-match-pattern-arm.stderr b/src/test/ui/consts/const-match-pattern-arm.stderr index 57ef349a377fd..4e7713f1422eb 100644 --- a/src/test/ui/consts/const-match-pattern-arm.stderr +++ b/src/test/ui/consts/const-match-pattern-arm.stderr @@ -1,4 +1,4 @@ -error[E0744]: `match` is not allowed in a `const` +error[E0658]: `match` is not allowed in a `const` --> $DIR/const-match-pattern-arm.rs:3:17 | LL | const x: bool = match Some(true) { @@ -7,8 +7,11 @@ LL | | Some(value) => true, LL | | _ => false 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]: `match` is not allowed in a `const` +error[E0658]: `match` is not allowed in a `const` --> $DIR/const-match-pattern-arm.rs:9:5 | LL | / match Some(true) { @@ -16,7 +19,10 @@ LL | | Some(value) => true, LL | | _ => false LL | | } | |_____^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable error: aborting due to 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/control-flow/assert.both.stderr b/src/test/ui/consts/control-flow/assert.both.stderr new file mode 100644 index 0000000000000..44769175f0ee9 --- /dev/null +++ b/src/test/ui/consts/control-flow/assert.both.stderr @@ -0,0 +1,13 @@ +error: any use of this value will cause an error + --> $DIR/assert.rs:12:15 + | +LL | const _: () = assert!(false); + | --------------^^^^^^^^^^^^^^- + | | + | the evaluated program panicked at 'assertion failed: false', $DIR/assert.rs:12:15 + | + = note: `#[deny(const_err)]` on by default + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/consts/control-flow/assert.if_match.stderr b/src/test/ui/consts/control-flow/assert.if_match.stderr new file mode 100644 index 0000000000000..9c8963f6c7b28 --- /dev/null +++ b/src/test/ui/consts/control-flow/assert.if_match.stderr @@ -0,0 +1,23 @@ +error[E0658]: panicking in constants is unstable + --> $DIR/assert.rs:8:15 + | +LL | const _: () = assert!(true); + | ^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/51999 + = help: add `#![feature(const_panic)]` to the crate attributes to enable + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error[E0658]: panicking in constants is unstable + --> $DIR/assert.rs:12:15 + | +LL | const _: () = assert!(false); + | ^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/51999 + = help: add `#![feature(const_panic)]` to the crate attributes to enable + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/control-flow/assert.panic.stderr b/src/test/ui/consts/control-flow/assert.panic.stderr new file mode 100644 index 0000000000000..11550bf801ab0 --- /dev/null +++ b/src/test/ui/consts/control-flow/assert.panic.stderr @@ -0,0 +1,21 @@ +error[E0658]: `if` is not allowed in a `const` + --> $DIR/assert.rs:8:15 + | +LL | const _: () = assert!(true); + | ^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/assert.rs:12:15 + | +LL | const _: () = assert!(false); + | ^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/control-flow/assert.rs b/src/test/ui/consts/control-flow/assert.rs new file mode 100644 index 0000000000000..2da42d5084bc1 --- /dev/null +++ b/src/test/ui/consts/control-flow/assert.rs @@ -0,0 +1,17 @@ +// Test that `assert` works only when both `const_if_match` and `const_panic` are enabled. + +// revisions: stock if_match panic both + +#![cfg_attr(any(both, if_match), feature(const_if_match))] +#![cfg_attr(any(both, panic), feature(const_panic))] + +const _: () = assert!(true); +//[stock,panic]~^ ERROR `if` is not allowed in a `const` +//[if_match]~^^ ERROR panicking in constants is unstable + +const _: () = assert!(false); +//[stock,panic]~^ ERROR `if` is not allowed in a `const` +//[if_match]~^^ ERROR panicking in constants is unstable +//[both]~^^^ ERROR any use of this value will cause an error + +fn main() {} diff --git a/src/test/ui/consts/control-flow/assert.stock.stderr b/src/test/ui/consts/control-flow/assert.stock.stderr new file mode 100644 index 0000000000000..11550bf801ab0 --- /dev/null +++ b/src/test/ui/consts/control-flow/assert.stock.stderr @@ -0,0 +1,21 @@ +error[E0658]: `if` is not allowed in a `const` + --> $DIR/assert.rs:8:15 + | +LL | const _: () = assert!(true); + | ^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/assert.rs:12:15 + | +LL | const _: () = assert!(false); + | ^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/control-flow/basics.rs b/src/test/ui/consts/control-flow/basics.rs new file mode 100644 index 0000000000000..8bd1929956fd3 --- /dev/null +++ b/src/test/ui/consts/control-flow/basics.rs @@ -0,0 +1,43 @@ +// Test basic functionality of `if` and `match` in a const context. + +// run-pass + +#![feature(const_panic)] +#![feature(const_if_match)] + +const X: u32 = 4; +const Y: u32 = 5; + +const ABS_DIFF: u32 = if X < Y { + Y - X +} else { + X - Y +}; + +const fn abs_diff(a: u32, b: u32) -> u32 { + match (a, b) { + (big, little) if big > little => big - little, + (little, big) => big - little, + } +} + +const fn gcd(a: u32, b: u32) -> u32 { + if b == 0 { + return a; + } + + gcd(b, a % b) +} + +fn main() { + const _: () = assert!(abs_diff(4, 5) == abs_diff(5, 4)); + assert_eq!(abs_diff(4, 5), abs_diff(5, 4)); + + const _: () = assert!(ABS_DIFF == abs_diff(5, 4)); + assert_eq!(ABS_DIFF, abs_diff(5, 4)); + + const _: () = assert!(gcd(48, 18) == 6); + const _: () = assert!(gcd(18, 48) == 6); + assert_eq!(gcd(48, 18), 6); + assert_eq!(gcd(18, 48), 6); +} diff --git a/src/test/ui/consts/control-flow/drop-failure.rs b/src/test/ui/consts/control-flow/drop-failure.rs new file mode 100644 index 0000000000000..c6bea89e6e6f7 --- /dev/null +++ b/src/test/ui/consts/control-flow/drop-failure.rs @@ -0,0 +1,35 @@ +#![feature(const_if_match)] + +// `x` is *not* always moved into the final value may be dropped inside the initializer. +const _: Option> = { + let y: Option> = None; + let x = Some(Vec::new()); + //~^ ERROR destructors cannot be evaluated at compile-time + + if true { + x + } else { + y + } +}; + +// We only clear `NeedsDrop` if a local is moved from in entirely. This is a shortcoming of the +// existing analysis. +const _: Vec = { + let vec_tuple = (Vec::new(),); + //~^ ERROR destructors cannot be evaluated at compile-time + + vec_tuple.0 +}; + +// This applies to single-field enum variants as well. +const _: Vec = { + let x: Result<_, Vec> = Ok(Vec::new()); + //~^ ERROR destructors cannot be evaluated at compile-time + + match x { + Ok(x) | Err(x) => x, + } +}; + +fn main() {} diff --git a/src/test/ui/consts/control-flow/drop-failure.stderr b/src/test/ui/consts/control-flow/drop-failure.stderr new file mode 100644 index 0000000000000..35ceb3b277084 --- /dev/null +++ b/src/test/ui/consts/control-flow/drop-failure.stderr @@ -0,0 +1,21 @@ +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/drop-failure.rs:6:9 + | +LL | let x = Some(Vec::new()); + | ^ constants cannot evaluate destructors + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/drop-failure.rs:19:9 + | +LL | let vec_tuple = (Vec::new(),); + | ^^^^^^^^^ constants cannot evaluate destructors + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/drop-failure.rs:27:9 + | +LL | let x: Result<_, Vec> = Ok(Vec::new()); + | ^ constants cannot evaluate destructors + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0493`. diff --git a/src/test/ui/consts/control-flow/drop-success.rs b/src/test/ui/consts/control-flow/drop-success.rs new file mode 100644 index 0000000000000..92b3f6ec92eb5 --- /dev/null +++ b/src/test/ui/consts/control-flow/drop-success.rs @@ -0,0 +1,24 @@ +// run-pass + +#![feature(const_if_match)] + +// `x` is always moved into the final value and is not dropped inside the initializer. +const _: Option> = { + let y: Option> = None; + let x = Some(Vec::new()); + + if true { + x + } else { + x + } +}; + +const _: Option> = { + let x = Some(Vec::new()); + match () { + () => x, + } +}; + +fn main() {} diff --git a/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr b/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr new file mode 100644 index 0000000000000..21e3f2af15ad6 --- /dev/null +++ b/src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr @@ -0,0 +1,14 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/feature-gate-const-if-match.rs:108:1 + | +LL | / fn main() { +LL | | let _ = [0; { +LL | | let x = if false { 0 } else { 1 }; +LL | | +... | +LL | | }]; +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs b/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs new file mode 100644 index 0000000000000..00576d50ac66b --- /dev/null +++ b/src/test/ui/consts/control-flow/feature-gate-const-if-match.rs @@ -0,0 +1,118 @@ +// Ensure that `if`, `if let` and `match` are only allowed in the various const contexts when +// `#![feature(const_if_match)]` is enabled. When the feature gate is removed, the `#[rustc_error]` +// on `main` should be removed and this test converted to `check-pass`. + +// revisions: stock if_match + +#![feature(rustc_attrs)] +#![cfg_attr(if_match, feature(const_if_match))] + +const _: i32 = if true { //[stock]~ ERROR `if` is not allowed in a `const` + 5 +} else { + 6 +}; + +const _: i32 = if let Some(true) = Some(false) { //[stock]~ ERROR `if` is not allowed in a `const` + 0 +} else { + 1 +}; + +const _: i32 = match 1 { //[stock]~ ERROR `match` is not allowed in a `const` + 2 => 3, + 4 => 5, + _ => 0, +}; + +static FOO: i32 = { + let x = if true { 0 } else { 1 }; + //[stock]~^ ERROR `if` is not allowed in a `static` + let x = match x { 0 => 1, _ => 0 }; + //[stock]~^ ERROR `match` is not allowed in a `static` + if let Some(x) = Some(x) { x } else { 1 } + //[stock]~^ ERROR `if` is not allowed in a `static` +}; + +static mut BAR: i32 = { + let x = if true { 0 } else { 1 }; + //[stock]~^ ERROR `if` is not allowed in a `static mut` + let x = match x { 0 => 1, _ => 0 }; + //[stock]~^ ERROR `match` is not allowed in a `static mut` + if let Some(x) = Some(x) { x } else { 1 } + //[stock]~^ ERROR `if` is not allowed in a `static mut` +}; + +const fn if_() -> i32 { + if true { 5 } else { 6 } //[stock]~ ERROR `if` is not allowed in a `const fn` +} + +const fn if_let(a: Option) -> i32 { + if let Some(true) = a { //[stock]~ ERROR `if` is not allowed in a `const fn` + 0 + } else { + 1 + } +} + +const fn match_(i: i32) -> i32 { + match i { //[stock]~ ERROR `match` is not allowed in a `const fn` + i if i > 10 => i, + 1 => 2, + _ => 0 + } +} + +pub trait Foo { + const IF: i32 = if true { 5 } else { 6 }; + //[stock]~^ ERROR `if` is not allowed in a `const` + + const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 }; + //[stock]~^ ERROR `if` is not allowed in a `const` + + const MATCH: i32 = match 0 { 1 => 2, _ => 0 }; + //[stock]~^ ERROR `match` is not allowed in a `const` +} + +impl Foo for () { + const IF: i32 = if true { 5 } else { 6 }; + //[stock]~^ ERROR `if` is not allowed in a `const` + + const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 }; + //[stock]~^ ERROR `if` is not allowed in a `const` + + const MATCH: i32 = match 0 { 1 => 2, _ => 0 }; + //[stock]~^ ERROR `match` is not allowed in a `const` +} + +fn non_const_outside() { + const fn const_inside(y: bool) -> i32 { + let x = if y { 0 } else { 1 }; + //[stock]~^ ERROR `if` is not allowed in a `const fn` + let x = match x { 0 => 1, _ => 0 }; + //[stock]~^ ERROR `match` is not allowed in a `const fn` + if let Some(x) = Some(x) { x } else { 1 } + //[stock]~^ ERROR `if` is not allowed in a `const fn` + } +} + +const fn const_outside() { + fn non_const_inside(y: bool) -> i32 { + let x = if y { 0 } else { 1 }; + let x = match x { 0 => 1, _ => 0 }; + if let Some(x) = Some(x) { x } else { 1 } + } +} + +#[rustc_error] +fn main() { //[if_match]~ ERROR fatal error triggered by #[rustc_error] + let _ = [0; { + let x = if false { 0 } else { 1 }; + //[stock]~^ ERROR `if` is not allowed in a `const` + let x = match x { 0 => 1, _ => 0 }; + //[stock]~^ ERROR `match` is not allowed in a `const` + if let Some(x) = Some(x) { x } else { 1 } + //[stock]~^ ERROR `if` is not allowed in a `const` + //[stock]~| ERROR constant contains unimplemented expression type + }]; +} diff --git a/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr b/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr new file mode 100644 index 0000000000000..d3c6a51923ffb --- /dev/null +++ b/src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr @@ -0,0 +1,249 @@ +error[E0658]: `if` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:10:16 + | +LL | const _: i32 = if true { + | ________________^ +LL | | 5 +LL | | } else { +LL | | 6 +LL | | }; + | |_^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:16:16 + | +LL | const _: i32 = if let Some(true) = Some(false) { + | ________________^ +LL | | 0 +LL | | } else { +LL | | 1 +LL | | }; + | |_^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `match` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:22:16 + | +LL | const _: i32 = match 1 { + | ________________^ +LL | | 2 => 3, +LL | | 4 => 5, +LL | | _ => 0, +LL | | }; + | |_^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `static` + --> $DIR/feature-gate-const-if-match.rs:29:13 + | +LL | let x = if true { 0 } else { 1 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `match` is not allowed in a `static` + --> $DIR/feature-gate-const-if-match.rs:31:13 + | +LL | let x = match x { 0 => 1, _ => 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `static` + --> $DIR/feature-gate-const-if-match.rs:33:5 + | +LL | if let Some(x) = Some(x) { x } else { 1 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `static mut` + --> $DIR/feature-gate-const-if-match.rs:38:13 + | +LL | let x = if true { 0 } else { 1 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `match` is not allowed in a `static mut` + --> $DIR/feature-gate-const-if-match.rs:40:13 + | +LL | let x = match x { 0 => 1, _ => 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `static mut` + --> $DIR/feature-gate-const-if-match.rs:42:5 + | +LL | if let Some(x) = Some(x) { x } else { 1 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const fn` + --> $DIR/feature-gate-const-if-match.rs:47:5 + | +LL | if true { 5 } else { 6 } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const fn` + --> $DIR/feature-gate-const-if-match.rs:51:5 + | +LL | / if let Some(true) = a { +LL | | 0 +LL | | } else { +LL | | 1 +LL | | } + | |_____^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `match` is not allowed in a `const fn` + --> $DIR/feature-gate-const-if-match.rs:59:5 + | +LL | / match i { +LL | | i if i > 10 => i, +LL | | 1 => 2, +LL | | _ => 0 +LL | | } + | |_____^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const fn` + --> $DIR/feature-gate-const-if-match.rs:90:17 + | +LL | let x = if y { 0 } else { 1 }; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `match` is not allowed in a `const fn` + --> $DIR/feature-gate-const-if-match.rs:92:17 + | +LL | let x = match x { 0 => 1, _ => 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const fn` + --> $DIR/feature-gate-const-if-match.rs:94:9 + | +LL | if let Some(x) = Some(x) { x } else { 1 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:110:17 + | +LL | let x = if false { 0 } else { 1 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `match` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:112:17 + | +LL | let x = match x { 0 => 1, _ => 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:114:9 + | +LL | if let Some(x) = Some(x) { x } else { 1 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:67:21 + | +LL | const IF: i32 = if true { 5 } else { 6 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:70:25 + | +LL | const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `match` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:73:24 + | +LL | const MATCH: i32 = match 0 { 1 => 2, _ => 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:78:21 + | +LL | const IF: i32 = if true { 5 } else { 6 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:81:25 + | +LL | const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0658]: `match` is not allowed in a `const` + --> $DIR/feature-gate-const-if-match.rs:84:24 + | +LL | const MATCH: i32 = match 0 { 1 => 2, _ => 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0019]: constant contains unimplemented expression type + --> $DIR/feature-gate-const-if-match.rs:114:21 + | +LL | if let Some(x) = Some(x) { x } else { 1 } + | ^ + +error: aborting due to 25 previous errors + +Some errors have detailed explanations: E0019, E0658. +For more information about an error, try `rustc --explain E0019`. diff --git a/src/test/ui/consts/control-flow/interior-mutability.rs b/src/test/ui/consts/control-flow/interior-mutability.rs new file mode 100644 index 0000000000000..fcced75fcb047 --- /dev/null +++ b/src/test/ui/consts/control-flow/interior-mutability.rs @@ -0,0 +1,27 @@ +// Ensure that *any* assignment to the return place of a value with interior mutability +// disqualifies it from promotion. + +#![feature(const_if_match)] + +use std::cell::Cell; + +const X: Option> = { + let mut x = None; + if false { + x = Some(Cell::new(4)); + } + x +}; + +const Y: Option> = { + let mut y = Some(Cell::new(4)); + if true { + y = None; + } + y +}; + +fn main() { + let x: &'static _ = &X; //~ ERROR temporary value dropped while borrowed + let y: &'static _ = &Y; //~ ERROR temporary value dropped while borrowed +} diff --git a/src/test/ui/consts/control-flow/interior-mutability.stderr b/src/test/ui/consts/control-flow/interior-mutability.stderr new file mode 100644 index 0000000000000..49e8ea3ade7ba --- /dev/null +++ b/src/test/ui/consts/control-flow/interior-mutability.stderr @@ -0,0 +1,24 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/interior-mutability.rs:25:26 + | +LL | let x: &'static _ = &X; + | ---------- ^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | let y: &'static _ = &Y; +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/interior-mutability.rs:26:26 + | +LL | let y: &'static _ = &Y; + | ---------- ^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/src/test/ui/consts/control-flow/issue-46843.if_match.stderr b/src/test/ui/consts/control-flow/issue-46843.if_match.stderr new file mode 100644 index 0000000000000..4c64d7dee8c01 --- /dev/null +++ b/src/test/ui/consts/control-flow/issue-46843.if_match.stderr @@ -0,0 +1,9 @@ +error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants + --> $DIR/issue-46843.rs:11:26 + | +LL | pub const Q: i32 = match non_const() { + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/consts/control-flow/issue-46843.rs b/src/test/ui/consts/control-flow/issue-46843.rs new file mode 100644 index 0000000000000..1fc91015ffa70 --- /dev/null +++ b/src/test/ui/consts/control-flow/issue-46843.rs @@ -0,0 +1,18 @@ +// revisions: stock if_match + +#![cfg_attr(if_match, feature(const_if_match))] + +enum Thing { This, That } + +fn non_const() -> Thing { + Thing::This +} + +pub const Q: i32 = match non_const() { + //[stock]~^ ERROR `match` is not allowed in a `const` + //[if_match]~^^ ERROR calls in constants are limited to constant functions + Thing::This => 1, + Thing::That => 0 +}; + +fn main() {} diff --git a/src/test/ui/consts/control-flow/issue-46843.stock.stderr b/src/test/ui/consts/control-flow/issue-46843.stock.stderr new file mode 100644 index 0000000000000..b6f38f8ed95e1 --- /dev/null +++ b/src/test/ui/consts/control-flow/issue-46843.stock.stderr @@ -0,0 +1,18 @@ +error[E0658]: `match` is not allowed in a `const` + --> $DIR/issue-46843.rs:11:20 + | +LL | pub const Q: i32 = match non_const() { + | ____________________^ +LL | | +LL | | +LL | | Thing::This => 1, +LL | | Thing::That => 0 +LL | | }; + | |_^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/control-flow/issue-50577.if_match.stderr b/src/test/ui/consts/control-flow/issue-50577.if_match.stderr new file mode 100644 index 0000000000000..79572c417024f --- /dev/null +++ b/src/test/ui/consts/control-flow/issue-50577.if_match.stderr @@ -0,0 +1,16 @@ +error[E0317]: if may be missing an else clause + --> $DIR/issue-50577.rs:7:16 + | +LL | Drop = assert_eq!(1, 1) + | ^^^^^^^^^^^^^^^^ + | | + | expected `()`, found `isize` + | found here + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0317`. diff --git a/src/test/ui/consts/control-flow/issue-50577.rs b/src/test/ui/consts/control-flow/issue-50577.rs new file mode 100644 index 0000000000000..7906ec4dc68c7 --- /dev/null +++ b/src/test/ui/consts/control-flow/issue-50577.rs @@ -0,0 +1,13 @@ +// revisions: stock if_match + +#![cfg_attr(if_match, feature(const_if_match))] + +fn main() { + enum Foo { + Drop = assert_eq!(1, 1) + //[stock,if_match]~^ ERROR if may be missing an else clause + //[stock]~^^ ERROR `match` is not allowed in a `const` + //[stock]~| ERROR `match` is not allowed in a `const` + //[stock]~| ERROR `if` is not allowed in a `const` + } +} diff --git a/src/test/ui/issues/issue-50577.stderr b/src/test/ui/consts/control-flow/issue-50577.stock.stderr similarity index 61% rename from src/test/ui/issues/issue-50577.stderr rename to src/test/ui/consts/control-flow/issue-50577.stock.stderr index 0a150fbf53a0c..13b50954292ea 100644 --- a/src/test/ui/issues/issue-50577.stderr +++ b/src/test/ui/consts/control-flow/issue-50577.stock.stderr @@ -1,29 +1,35 @@ -error[E0744]: `match` is not allowed in a `const` - --> $DIR/issue-50577.rs:3:16 +error[E0658]: `match` is not allowed in a `const` + --> $DIR/issue-50577.rs:7:16 | LL | Drop = assert_eq!(1, 1) | ^^^^^^^^^^^^^^^^ | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error[E0744]: `if` is not allowed in a `const` - --> $DIR/issue-50577.rs:3:16 +error[E0658]: `if` is not allowed in a `const` + --> $DIR/issue-50577.rs:7:16 | LL | Drop = assert_eq!(1, 1) | ^^^^^^^^^^^^^^^^ | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error[E0744]: `match` is not allowed in a `const` - --> $DIR/issue-50577.rs:3:16 +error[E0658]: `match` is not allowed in a `const` + --> $DIR/issue-50577.rs:7:16 | LL | Drop = assert_eq!(1, 1) | ^^^^^^^^^^^^^^^^ | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0317]: if may be missing an else clause - --> $DIR/issue-50577.rs:3:16 + --> $DIR/issue-50577.rs:7:16 | LL | Drop = assert_eq!(1, 1) | ^^^^^^^^^^^^^^^^ @@ -37,5 +43,5 @@ LL | Drop = assert_eq!(1, 1) error: aborting due to 4 previous errors -Some errors have detailed explanations: E0317, E0744. +Some errors have detailed explanations: E0317, E0658. For more information about an error, try `rustc --explain E0317`. diff --git a/src/test/ui/consts/const-loop.stderr b/src/test/ui/consts/control-flow/loop.if_match.stderr similarity index 67% rename from src/test/ui/consts/const-loop.stderr rename to src/test/ui/consts/control-flow/loop.if_match.stderr index 2c96d18175983..15b9eb028611e 100644 --- a/src/test/ui/consts/const-loop.stderr +++ b/src/test/ui/consts/control-flow/loop.if_match.stderr @@ -1,35 +1,35 @@ error[E0744]: `loop` is not allowed in a `const` - --> $DIR/const-loop.rs:1:15 + --> $DIR/loop.rs:8:15 | LL | const _: () = loop {}; | ^^^^^^^ error[E0744]: `loop` is not allowed in a `static` - --> $DIR/const-loop.rs:3:19 + --> $DIR/loop.rs:10:19 | LL | static FOO: i32 = loop { break 4; }; | ^^^^^^^^^^^^^^^^^ error[E0744]: `loop` is not allowed in a `const fn` - --> $DIR/const-loop.rs:6:5 + --> $DIR/loop.rs:13:5 | LL | loop {} | ^^^^^^^ error[E0744]: `loop` is not allowed in a `const fn` - --> $DIR/const-loop.rs:19:9 + --> $DIR/loop.rs:26:9 | LL | loop {} | ^^^^^^^ error[E0744]: `while` is not allowed in a `const` - --> $DIR/const-loop.rs:31:9 + --> $DIR/loop.rs:38:9 | LL | while false {} | ^^^^^^^^^^^^^^ error[E0744]: `while` is not allowed in a `const` - --> $DIR/const-loop.rs:40:5 + --> $DIR/loop.rs:47:5 | LL | / while x < 4 { LL | | x += 1; @@ -37,7 +37,7 @@ LL | | } | |_____^ error[E0744]: `while` is not allowed in a `const` - --> $DIR/const-loop.rs:44:5 + --> $DIR/loop.rs:51:5 | LL | / while x < 8 { LL | | x += 1; @@ -45,7 +45,7 @@ LL | | } | |_____^ error[E0744]: `for` is not allowed in a `const` - --> $DIR/const-loop.rs:54:5 + --> $DIR/loop.rs:61:5 | LL | / for i in 0..4 { LL | | x += i; @@ -53,7 +53,7 @@ LL | | } | |_____^ error[E0744]: `for` is not allowed in a `const` - --> $DIR/const-loop.rs:58:5 + --> $DIR/loop.rs:65:5 | LL | / for i in 0..4 { LL | | x += i; @@ -61,7 +61,7 @@ LL | | } | |_____^ error[E0744]: `loop` is not allowed in a `const` - --> $DIR/const-loop.rs:68:5 + --> $DIR/loop.rs:75:5 | LL | / loop { LL | | x += 1; @@ -71,16 +71,8 @@ LL | | } LL | | } | |_____^ -error[E0744]: `if` is not allowed in a `const` - --> $DIR/const-loop.rs:70:9 - | -LL | / if x == 4 { -LL | | break; -LL | | } - | |_________^ - error[E0744]: `loop` is not allowed in a `const` - --> $DIR/const-loop.rs:75:5 + --> $DIR/loop.rs:82:5 | LL | / loop { LL | | x += 1; @@ -90,38 +82,30 @@ LL | | } LL | | } | |_____^ -error[E0744]: `if` is not allowed in a `const` - --> $DIR/const-loop.rs:77:9 - | -LL | / if x == 8 { -LL | | break; -LL | | } - | |_________^ - -error[E0744]: `while let` is not allowed in a `const` - --> $DIR/const-loop.rs:87:5 +error[E0744]: `while` is not allowed in a `const` + --> $DIR/loop.rs:94:5 | LL | while let None = Some(x) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0744]: `while let` is not allowed in a `const` - --> $DIR/const-loop.rs:88:5 +error[E0744]: `while` is not allowed in a `const` + --> $DIR/loop.rs:95:5 | LL | while let None = Some(x) { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0744]: `loop` is not allowed in a `const` - --> $DIR/const-loop.rs:10:22 + --> $DIR/loop.rs:17:22 | LL | const BAR: i32 = loop { break 4; }; | ^^^^^^^^^^^^^^^^^ error[E0744]: `loop` is not allowed in a `const` - --> $DIR/const-loop.rs:14:22 + --> $DIR/loop.rs:21:22 | LL | const BAR: i32 = loop { break 4; }; | ^^^^^^^^^^^^^^^^^ -error: aborting due to 17 previous errors +error: aborting due to 15 previous errors For more information about this error, try `rustc --explain E0744`. diff --git a/src/test/ui/consts/control-flow/loop.rs b/src/test/ui/consts/control-flow/loop.rs new file mode 100644 index 0000000000000..4be341f2d3846 --- /dev/null +++ b/src/test/ui/consts/control-flow/loop.rs @@ -0,0 +1,97 @@ +// Ensure that all loops are forbidden in a const context, even if `#![feature(const_if_match)]` is +// enabled. + +// revisions: stock if_match + +#![cfg_attr(if_match, feature(const_if_match))] + +const _: () = loop {}; //[stock,if_match]~ ERROR `loop` is not allowed in a `const` + +static FOO: i32 = loop { break 4; }; //[stock,if_match]~ ERROR `loop` is not allowed in a `static` + +const fn foo() { + loop {} //[stock,if_match]~ ERROR `loop` is not allowed in a `const fn` +} + +pub trait Foo { + const BAR: i32 = loop { break 4; }; //[stock,if_match]~ ERROR `loop` is not allowed in a `const` +} + +impl Foo for () { + const BAR: i32 = loop { break 4; }; //[stock,if_match]~ ERROR `loop` is not allowed in a `const` +} + +fn non_const_outside() { + const fn const_inside() { + loop {} //[stock,if_match]~ ERROR `loop` is not allowed in a `const fn` + } +} + +const fn const_outside() { + fn non_const_inside() { + loop {} + } +} + +fn main() { + let x = [0; { + while false {} + //[stock,if_match]~^ ERROR `while` is not allowed in a `const` + 4 + }]; +} + +const _: i32 = { + let mut x = 0; + + while x < 4 { //[stock,if_match]~ ERROR `while` is not allowed in a `const` + x += 1; + } + + while x < 8 { //[stock,if_match]~ ERROR `while` is not allowed in a `const` + x += 1; + } + + x +}; + +const _: i32 = { + let mut x = 0; + + for i in 0..4 { //[stock,if_match]~ ERROR `for` is not allowed in a `const` + x += i; + } + + for i in 0..4 { //[stock,if_match]~ ERROR `for` is not allowed in a `const` + x += i; + } + + x +}; + +const _: i32 = { + let mut x = 0; + + loop { //[stock,if_match]~ ERROR `loop` is not allowed in a `const` + x += 1; + if x == 4 { //[stock]~ ERROR `if` is not allowed in a `const` + break; + } + } + + loop { //[stock,if_match]~ ERROR `loop` is not allowed in a `const` + x += 1; + if x == 8 { //[stock]~ ERROR `if` is not allowed in a `const` + break; + } + } + + x +}; + +const _: i32 = { + let mut x = 0; + while let None = Some(x) { } //[stock,if_match]~ ERROR `while` is not allowed in a `const` + while let None = Some(x) { } //[stock,if_match]~ ERROR `while` is not allowed in a `const` + x +}; diff --git a/src/test/ui/consts/control-flow/loop.stock.stderr b/src/test/ui/consts/control-flow/loop.stock.stderr new file mode 100644 index 0000000000000..bb651d23179f7 --- /dev/null +++ b/src/test/ui/consts/control-flow/loop.stock.stderr @@ -0,0 +1,134 @@ +error[E0744]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:8:15 + | +LL | const _: () = loop {}; + | ^^^^^^^ + +error[E0744]: `loop` is not allowed in a `static` + --> $DIR/loop.rs:10:19 + | +LL | static FOO: i32 = loop { break 4; }; + | ^^^^^^^^^^^^^^^^^ + +error[E0744]: `loop` is not allowed in a `const fn` + --> $DIR/loop.rs:13:5 + | +LL | loop {} + | ^^^^^^^ + +error[E0744]: `loop` is not allowed in a `const fn` + --> $DIR/loop.rs:26:9 + | +LL | loop {} + | ^^^^^^^ + +error[E0744]: `while` is not allowed in a `const` + --> $DIR/loop.rs:38:9 + | +LL | while false {} + | ^^^^^^^^^^^^^^ + +error[E0744]: `while` is not allowed in a `const` + --> $DIR/loop.rs:47:5 + | +LL | / while x < 4 { +LL | | x += 1; +LL | | } + | |_____^ + +error[E0744]: `while` is not allowed in a `const` + --> $DIR/loop.rs:51:5 + | +LL | / while x < 8 { +LL | | x += 1; +LL | | } + | |_____^ + +error[E0744]: `for` is not allowed in a `const` + --> $DIR/loop.rs:61:5 + | +LL | / for i in 0..4 { +LL | | x += i; +LL | | } + | |_____^ + +error[E0744]: `for` is not allowed in a `const` + --> $DIR/loop.rs:65:5 + | +LL | / for i in 0..4 { +LL | | x += i; +LL | | } + | |_____^ + +error[E0744]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:75:5 + | +LL | / loop { +LL | | x += 1; +LL | | if x == 4 { +LL | | break; +LL | | } +LL | | } + | |_____^ + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/loop.rs:77:9 + | +LL | / if x == 4 { +LL | | break; +LL | | } + | |_________^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0744]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:82:5 + | +LL | / loop { +LL | | x += 1; +LL | | if x == 8 { +LL | | break; +LL | | } +LL | | } + | |_____^ + +error[E0658]: `if` is not allowed in a `const` + --> $DIR/loop.rs:84:9 + | +LL | / if x == 8 { +LL | | break; +LL | | } + | |_________^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable + +error[E0744]: `while` is not allowed in a `const` + --> $DIR/loop.rs:94:5 + | +LL | while let None = Some(x) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0744]: `while` is not allowed in a `const` + --> $DIR/loop.rs:95:5 + | +LL | while let None = Some(x) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0744]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:17:22 + | +LL | const BAR: i32 = loop { break 4; }; + | ^^^^^^^^^^^^^^^^^ + +error[E0744]: `loop` is not allowed in a `const` + --> $DIR/loop.rs:21:22 + | +LL | const BAR: i32 = loop { break 4; }; + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 17 previous errors + +Some errors have detailed explanations: E0658, E0744. +For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/control-flow/short-circuit-let.rs b/src/test/ui/consts/control-flow/short-circuit-let.rs new file mode 100644 index 0000000000000..8cee2a54f56d3 --- /dev/null +++ b/src/test/ui/consts/control-flow/short-circuit-let.rs @@ -0,0 +1,39 @@ +// `&&` and `||` were previously forbidden in constants alongside let bindings. + +// run-pass + +#![feature(const_if_match)] +#![feature(const_panic)] + +const X: i32 = { + let mut x = 0; + let _ = true && { x = 1; false }; + x +}; + +const Y: bool = { + let x = true && false || true; + x +}; + +const fn truthy() -> bool { + let x = true || return false; + x +} + +const fn falsy() -> bool { + let x = true && return false; + x +} + +fn main() { + const _: () = assert!(Y); + assert!(Y); + + const _: () = assert!(X == 1); + assert_eq!(X, 1); + + const _: () = assert!(truthy()); + const _: () = assert!(!falsy()); + assert!(truthy() && !falsy()); +} diff --git a/src/test/ui/consts/control-flow/short-circuit.if_match.stderr b/src/test/ui/consts/control-flow/short-circuit.if_match.stderr new file mode 100644 index 0000000000000..f6ba28e7b7246 --- /dev/null +++ b/src/test/ui/consts/control-flow/short-circuit.if_match.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/short-circuit.rs:14:1 + | +LL | fn main() {} + | ^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/consts/control-flow/short-circuit.rs b/src/test/ui/consts/control-flow/short-circuit.rs new file mode 100644 index 0000000000000..f5e54a69d4a6f --- /dev/null +++ b/src/test/ui/consts/control-flow/short-circuit.rs @@ -0,0 +1,14 @@ +// Test that both `&&` and `||` actually short-circuit when the `const_if_match` feature flag is +// enabled. Without the feature flag, both sides are evaluated unconditionally. + +// revisions: stock if_match + +#![feature(rustc_attrs)] +#![feature(const_panic)] +#![cfg_attr(if_match, feature(const_if_match))] + +const _: bool = true || panic!(); //[stock]~ ERROR any use of this value will cause an error +const _: bool = false && panic!(); //[stock]~ ERROR any use of this value will cause an error + +#[rustc_error] +fn main() {} //[if_match]~ ERROR fatal error triggered by #[rustc_error] diff --git a/src/test/ui/consts/control-flow/short-circuit.stock.stderr b/src/test/ui/consts/control-flow/short-circuit.stock.stderr new file mode 100644 index 0000000000000..cf0de929593db --- /dev/null +++ b/src/test/ui/consts/control-flow/short-circuit.stock.stderr @@ -0,0 +1,23 @@ +error: any use of this value will cause an error + --> $DIR/short-circuit.rs:10:25 + | +LL | const _: bool = true || panic!(); + | ------------------------^^^^^^^^- + | | + | the evaluated program panicked at 'explicit panic', $DIR/short-circuit.rs:10:25 + | + = note: `#[deny(const_err)]` on by default + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: any use of this value will cause an error + --> $DIR/short-circuit.rs:11:26 + | +LL | const _: bool = false && panic!(); + | -------------------------^^^^^^^^- + | | + | the evaluated program panicked at 'explicit panic', $DIR/short-circuit.rs:11:26 + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/consts/control-flow/single_variant_match_ice.rs b/src/test/ui/consts/control-flow/single_variant_match_ice.rs new file mode 100644 index 0000000000000..823605ff034f1 --- /dev/null +++ b/src/test/ui/consts/control-flow/single_variant_match_ice.rs @@ -0,0 +1,27 @@ +// check-pass + +#![feature(const_if_match)] + +enum Foo { + Prob, +} + +const FOO: u32 = match Foo::Prob { + Foo::Prob => 42, +}; + +const BAR: u32 = match Foo::Prob { + x => 42, +}; + +impl Foo { + pub const fn as_val(&self) -> u8 { + use self::Foo::*; + + match *self { + Prob => 0x1, + } + } +} + +fn main() {} diff --git a/src/test/ui/consts/control-flow/try.rs b/src/test/ui/consts/control-flow/try.rs new file mode 100644 index 0000000000000..31fe09d4f6962 --- /dev/null +++ b/src/test/ui/consts/control-flow/try.rs @@ -0,0 +1,12 @@ +// The `?` operator is still not const-evaluatable because it calls `From::from` on the error +// variant. + +#![feature(const_if_match)] + +const fn opt() -> Option { + let x = Some(2); + x?; //~ ERROR `?` is not allowed in a `const fn` + None +} + +fn main() {} diff --git a/src/test/ui/consts/control-flow/try.stderr b/src/test/ui/consts/control-flow/try.stderr new file mode 100644 index 0000000000000..60a386ef6c870 --- /dev/null +++ b/src/test/ui/consts/control-flow/try.stderr @@ -0,0 +1,9 @@ +error[E0744]: `?` is not allowed in a `const fn` + --> $DIR/try.rs:8:5 + | +LL | x?; + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0744`. diff --git a/src/test/ui/consts/single_variant_match_ice.rs b/src/test/ui/consts/single_variant_match_ice.rs deleted file mode 100644 index 80a92c4c96558..0000000000000 --- a/src/test/ui/consts/single_variant_match_ice.rs +++ /dev/null @@ -1,23 +0,0 @@ -enum Foo { - Prob, -} - -const FOO: u32 = match Foo::Prob { //~ ERROR `match` is not allowed in a `const` - Foo::Prob => 42, -}; - -const BAR: u32 = match Foo::Prob { //~ ERROR `match` is not allowed in a `const` - x => 42, -}; - -impl Foo { - pub const fn as_val(&self) -> u8 { - use self::Foo::*; - - match *self { //~ ERROR `match` is not allowed in a `const fn` - Prob => 0x1, - } - } -} - -fn main() {} diff --git a/src/test/ui/consts/single_variant_match_ice.stderr b/src/test/ui/consts/single_variant_match_ice.stderr deleted file mode 100644 index 780dd0dcddf49..0000000000000 --- a/src/test/ui/consts/single_variant_match_ice.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error[E0744]: `match` is not allowed in a `const` - --> $DIR/single_variant_match_ice.rs:5:18 - | -LL | const FOO: u32 = match Foo::Prob { - | __________________^ -LL | | Foo::Prob => 42, -LL | | }; - | |_^ - -error[E0744]: `match` is not allowed in a `const` - --> $DIR/single_variant_match_ice.rs:9:18 - | -LL | const BAR: u32 = match Foo::Prob { - | __________________^ -LL | | x => 42, -LL | | }; - | |_^ - -error[E0744]: `match` is not allowed in a `const fn` - --> $DIR/single_variant_match_ice.rs:17:9 - | -LL | / match *self { -LL | | Prob => 0x1, -LL | | } - | |_________^ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0744`. diff --git a/src/test/ui/consts/miri_unleashed/enum_discriminants.rs b/src/test/ui/enum-discriminant/niche.rs similarity index 96% rename from src/test/ui/consts/miri_unleashed/enum_discriminants.rs rename to src/test/ui/enum-discriminant/niche.rs index 76d62f069f378..8d2cdf34f373e 100644 --- a/src/test/ui/consts/miri_unleashed/enum_discriminants.rs +++ b/src/test/ui/enum-discriminant/niche.rs @@ -1,8 +1,7 @@ -// compile-flags: -Zunleash-the-miri-inside-of-you -Awarnings // run-pass -// miri unleashed warnings are not useful and change frequently, so they are silenced above. #![feature(const_panic)] +#![feature(const_if_match)] //! Make sure that we read and write enum discriminants correctly for corner cases caused //! by layout optimizations. diff --git a/src/test/ui/issues/issue-46843.rs b/src/test/ui/issues/issue-46843.rs deleted file mode 100644 index e5b271367393d..0000000000000 --- a/src/test/ui/issues/issue-46843.rs +++ /dev/null @@ -1,13 +0,0 @@ -enum Thing { This, That } - -fn non_const() -> Thing { - Thing::This -} - -pub const Q: i32 = match non_const() { - //~^ ERROR `match` is not allowed in a `const` - Thing::This => 1, - Thing::That => 0 -}; - -fn main() {} diff --git a/src/test/ui/issues/issue-46843.stderr b/src/test/ui/issues/issue-46843.stderr deleted file mode 100644 index 9d5332978644e..0000000000000 --- a/src/test/ui/issues/issue-46843.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0744]: `match` is not allowed in a `const` - --> $DIR/issue-46843.rs:7:20 - | -LL | pub const Q: i32 = match non_const() { - | ____________________^ -LL | | -LL | | Thing::This => 1, -LL | | Thing::That => 0 -LL | | }; - | |_^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0744`. diff --git a/src/test/ui/issues/issue-50577.rs b/src/test/ui/issues/issue-50577.rs deleted file mode 100644 index f3f680e7b8ecd..0000000000000 --- a/src/test/ui/issues/issue-50577.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn main() { - enum Foo { - Drop = assert_eq!(1, 1) - //~^ ERROR if may be missing an else clause - //~| ERROR `match` is not allowed in a `const` - //~| ERROR `match` is not allowed in a `const` - //~| ERROR `if` is not allowed in a `const` - } -} diff --git a/src/test/ui/issues/issue-51714.rs b/src/test/ui/issues/issue-51714.rs index e0fd7ff896cd3..782037a1fe5d4 100644 --- a/src/test/ui/issues/issue-51714.rs +++ b/src/test/ui/issues/issue-51714.rs @@ -10,5 +10,5 @@ fn main() { [(); return while let Some(n) = Some(0) {}]; //~^ ERROR return statement outside of function body - //~| ERROR `while let` is not allowed in a `const` + //~| ERROR `while` is not allowed in a `const` } diff --git a/src/test/ui/issues/issue-51714.stderr b/src/test/ui/issues/issue-51714.stderr index a3b20cf97f87d..001928c3b2f31 100644 --- a/src/test/ui/issues/issue-51714.stderr +++ b/src/test/ui/issues/issue-51714.stderr @@ -1,4 +1,4 @@ -error[E0744]: `while let` is not allowed in a `const` +error[E0744]: `while` is not allowed in a `const` --> $DIR/issue-51714.rs:11:17 | LL | [(); return while let Some(n) = Some(0) {}]; diff --git a/src/test/ui/loops/loop-break-value.rs b/src/test/ui/loops/loop-break-value.rs index 8d88aefdb5185..c4fb68c02784e 100644 --- a/src/test/ui/loops/loop-break-value.rs +++ b/src/test/ui/loops/loop-break-value.rs @@ -33,19 +33,19 @@ fn main() { } while let Some(_) = Some(()) { - if break () { //~ ERROR `break` with value from a `while let` loop + if break () { //~ ERROR `break` with value from a `while` loop } } while let Some(_) = Some(()) { break None; - //~^ ERROR `break` with value from a `while let` loop + //~^ ERROR `break` with value from a `while` loop } 'while_let_loop: while let Some(_) = Some(()) { loop { break 'while_let_loop "nope"; - //~^ ERROR `break` with value from a `while let` loop + //~^ ERROR `break` with value from a `while` loop break 33; }; } diff --git a/src/test/ui/loops/loop-break-value.stderr b/src/test/ui/loops/loop-break-value.stderr index 1707a179ad0c0..1f2d81ff03f0a 100644 --- a/src/test/ui/loops/loop-break-value.stderr +++ b/src/test/ui/loops/loop-break-value.stderr @@ -28,35 +28,35 @@ help: instead, use `break` on its own without a value inside this `while` loop LL | break; | ^^^^^ -error[E0571]: `break` with value from a `while let` loop +error[E0571]: `break` with value from a `while` loop --> $DIR/loop-break-value.rs:36:12 | LL | if break () { | ^^^^^^^^ can only break with a value inside `loop` or breakable block | -help: instead, use `break` on its own without a value inside this `while let` loop +help: instead, use `break` on its own without a value inside this `while` loop | LL | if break { | ^^^^^ -error[E0571]: `break` with value from a `while let` loop +error[E0571]: `break` with value from a `while` loop --> $DIR/loop-break-value.rs:41:9 | LL | break None; | ^^^^^^^^^^ can only break with a value inside `loop` or breakable block | -help: instead, use `break` on its own without a value inside this `while let` loop +help: instead, use `break` on its own without a value inside this `while` loop | LL | break; | ^^^^^ -error[E0571]: `break` with value from a `while let` loop +error[E0571]: `break` with value from a `while` loop --> $DIR/loop-break-value.rs:47:13 | LL | break 'while_let_loop "nope"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can only break with a value inside `loop` or breakable block | -help: instead, use `break` on its own without a value inside this `while let` loop +help: instead, use `break` on its own without a value inside this `while` loop | LL | break; | ^^^^^ diff --git a/src/test/ui/return/return-match-array-const.stderr b/src/test/ui/return/return-match-array-const.stderr index 496e9208b6106..8b8e961b726d7 100644 --- a/src/test/ui/return/return-match-array-const.stderr +++ b/src/test/ui/return/return-match-array-const.stderr @@ -1,20 +1,29 @@ -error[E0744]: `match` is not allowed in a `const` +error[E0658]: `match` is not allowed in a `const` --> $DIR/return-match-array-const.rs:2:17 | LL | [(); return match 0 { n => n }]; | ^^^^^^^^^^^^^^^^^^ + | + = 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]: `match` is not allowed in a `const` +error[E0658]: `match` is not allowed in a `const` --> $DIR/return-match-array-const.rs:6:17 | LL | [(); return match 0 { 0 => 0 }]; | ^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable -error[E0744]: `match` is not allowed in a `const` +error[E0658]: `match` is not allowed in a `const` --> $DIR/return-match-array-const.rs:10:17 | LL | [(); return match () { 'a' => 0, _ => 0 }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0572]: return statement outside of function body --> $DIR/return-match-array-const.rs:2:10 @@ -36,5 +45,5 @@ LL | [(); return match () { 'a' => 0, _ => 0 }]; error: aborting due to 6 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`. diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr index 05e30a8010aa1..f24ea0505e785 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr @@ -513,23 +513,32 @@ warning: the feature `let_chains` is incomplete and may cause the compiler to cr LL | #![feature(let_chains)] // Avoid inflating `.stderr` with overzealous gates in this test. | ^^^^^^^^^^ -error[E0744]: `match` is not allowed in a `const` +error[E0658]: `match` is not allowed in a `const` --> $DIR/disallowed-positions.rs:218:17 | LL | true && let 1 = 1 | ^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable -error[E0744]: `match` is not allowed in a `const` +error[E0658]: `match` is not allowed in a `const` --> $DIR/disallowed-positions.rs:223:17 | LL | true && let 1 = 1 | ^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable -error[E0744]: `match` is not allowed in a `const` +error[E0658]: `match` is not allowed in a `const` --> $DIR/disallowed-positions.rs:228:17 | LL | true && let 1 = 1 | ^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/49146 + = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:32:8 @@ -952,5 +961,5 @@ LL | let 0 = 0?; error: aborting due to 106 previous errors -Some errors have detailed explanations: E0277, E0308, E0600, E0614, E0744. +Some errors have detailed explanations: E0277, E0308, E0600, E0614, E0658. For more information about an error, try `rustc --explain E0277`.