diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 368f83eb6112..2607f5fd08b4 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1748,6 +1748,8 @@ pub enum StatementKind<'tcx> { /// (e.g. inspecting constants and discriminant values), and the /// kind of pattern it comes from. This is in order to adapt potential /// error messages to these specific patterns. + /// + /// Note that this also is emitted for regular `let` bindings to aid destructuring diagnostics FakeRead(FakeReadCause, Place<'tcx>), /// Write the discriminant for a variant to the enum Place. diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 09fe7b14c797..61e79990f922 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -243,7 +243,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { return; } - if self.tcx.features().const_let { + if self.const_let_allowed() { let mut dest = dest; let index = loop { match dest { @@ -320,6 +320,10 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { } } + fn const_let_allowed(&self) -> bool { + self.tcx.features().const_let || self.mode == Mode::ConstFn + } + /// Qualify a whole const, static initializer or const fn. fn qualify_const(&mut self) -> (Qualif, Lrc>) { debug!("qualifying {} {:?}", self.mode, self.def_id); @@ -357,7 +361,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { TerminatorKind::FalseUnwind { .. } => None, TerminatorKind::Return => { - if !self.tcx.features().const_let { + if !self.const_let_allowed() { // Check for unused values. This usually means // there are extra statements in the AST. for temp in mir.temps_iter() { @@ -464,7 +468,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { LocalKind::ReturnPointer => { self.not_const(); } - LocalKind::Var if !self.tcx.features().const_let => { + LocalKind::Var if !self.const_let_allowed() => { if self.mode != Mode::Fn { emit_feature_err(&self.tcx.sess.parse_sess, "const_let", self.span, GateIssue::Language, @@ -1154,48 +1158,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { debug!("visit_assign: dest={:?} rvalue={:?} location={:?}", dest, rvalue, location); self.visit_rvalue(rvalue, location); - // Check the allowed const fn argument forms. - if let (Mode::ConstFn, &Place::Local(index)) = (self.mode, dest) { - if self.mir.local_kind(index) == LocalKind::Var && - self.const_fn_arg_vars.insert(index) && - !self.tcx.features().const_let { - - // Direct use of an argument is permitted. - match *rvalue { - Rvalue::Use(Operand::Copy(Place::Local(local))) | - Rvalue::Use(Operand::Move(Place::Local(local))) => { - if self.mir.local_kind(local) == LocalKind::Arg { - return; - } - } - _ => {} - } - - // Avoid a generic error for other uses of arguments. - if self.qualif.contains(Qualif::FN_ARGUMENT) { - let decl = &self.mir.local_decls[index]; - let mut err = feature_err( - &self.tcx.sess.parse_sess, - "const_let", - decl.source_info.span, - GateIssue::Language, - "arguments of constant functions can only be immutable by-value bindings" - ); - if self.tcx.sess.teach(&err.get_code().unwrap()) { - err.note("Constant functions are not allowed to mutate anything. Thus, \ - binding to an argument with a mutable pattern is not allowed."); - err.note("Remove any mutable bindings from the argument list to fix this \ - error. In case you need to mutate the argument, try lazily \ - initializing a global variable instead of using a const fn, or \ - refactoring the code to a functional style to avoid mutation if \ - possible."); - } - err.emit(); - return; - } - } - } - self.assign(dest, location); } diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 13e134ba8592..5729775e15dc 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -64,12 +64,6 @@ pub fn is_min_const_fn( } } - for local in mir.vars_iter() { - return Err(( - mir.local_decls[local].source_info.span, - "local variables in const fn are unstable".into(), - )); - } for local in &mir.local_decls { check_ty(tcx, local.ty, local.source_info.span)?; } @@ -229,7 +223,7 @@ fn check_statement( check_rvalue(tcx, mir, rval, span) } - StatementKind::FakeRead(..) => Err((span, "match in const fn is unstable".into())), + StatementKind::FakeRead(_, place) => check_place(tcx, mir, place, span, PlaceMode::Read), // just an assignment StatementKind::SetDiscriminant { .. } => Ok(()), @@ -270,15 +264,8 @@ fn check_place( mode: PlaceMode, ) -> McfResult { match place { - Place::Local(l) => match mode { - PlaceMode::Assign => match mir.local_kind(*l) { - LocalKind::Temp | LocalKind::ReturnPointer => Ok(()), - LocalKind::Arg | LocalKind::Var => { - Err((span, "assignments in const fn are unstable".into())) - } - }, - PlaceMode::Read => Ok(()), - }, + // assignments to locals, arguments, temporaries or the return slot are fine + Place::Local(_) => Ok(()), // promoteds are always fine, they are essentially constants Place::Promoted(_) => Ok(()), Place::Static(_) => Err((span, "cannot access `static` items in const fn".into())), diff --git a/src/test/ui/consts/const-fn-destructuring-arg.rs b/src/test/ui/consts/const-fn-destructuring-arg.rs index fce1688716d3..8aa6871fa758 100644 --- a/src/test/ui/consts/const-fn-destructuring-arg.rs +++ b/src/test/ui/consts/const-fn-destructuring-arg.rs @@ -8,20 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// test that certain things are disallowed in constant functions +// compile-pass -#![feature(const_fn)] - -// no destructuring -const fn i(( - a, - //~^ ERROR arguments of constant functions can only be immutable by-value bindings - b - //~^ ERROR arguments of constant functions can only be immutable by-value bindings - ): (u32, u32)) -> u32 { +const fn i((a, b): (u32, u32)) -> u32 { a + b - //~^ ERROR let bindings in constant functions are unstable - //~| ERROR let bindings in constant functions are unstable } fn main() {} diff --git a/src/test/ui/consts/const-fn-destructuring-arg.stderr b/src/test/ui/consts/const-fn-destructuring-arg.stderr deleted file mode 100644 index 029d63a7720a..000000000000 --- a/src/test/ui/consts/const-fn-destructuring-arg.stderr +++ /dev/null @@ -1,35 +0,0 @@ -error[E0658]: arguments of constant functions can only be immutable by-value bindings (see issue #48821) - --> $DIR/const-fn-destructuring-arg.rs:17:13 - | -LL | a, - | ^ - | - = help: add #![feature(const_let)] to the crate attributes to enable - -error[E0658]: arguments of constant functions can only be immutable by-value bindings (see issue #48821) - --> $DIR/const-fn-destructuring-arg.rs:19:13 - | -LL | b - | ^ - | - = help: add #![feature(const_let)] to the crate attributes to enable - -error[E0658]: let bindings in constant functions are unstable (see issue #48821) - --> $DIR/const-fn-destructuring-arg.rs:22:5 - | -LL | a + b - | ^ - | - = help: add #![feature(const_let)] to the crate attributes to enable - -error[E0658]: let bindings in constant functions are unstable (see issue #48821) - --> $DIR/const-fn-destructuring-arg.rs:22:9 - | -LL | a + b - | ^ - | - = help: add #![feature(const_let)] to the crate attributes to enable - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/const-fn-not-safe-for-const.rs b/src/test/ui/consts/const-fn-not-safe-for-const.rs index 30a738a83a3b..aee5539980c6 100644 --- a/src/test/ui/consts/const-fn-not-safe-for-const.rs +++ b/src/test/ui/consts/const-fn-not-safe-for-const.rs @@ -38,14 +38,8 @@ const fn get_Y_addr() -> &'static u32 { const fn get() -> u32 { let x = 22; - //~^ ERROR let bindings in constant functions are unstable - //~| ERROR statements in constant functions are unstable let y = 44; - //~^ ERROR let bindings in constant functions are unstable - //~| ERROR statements in constant functions are unstable x + y - //~^ ERROR let bindings in constant functions are unstable - //~| ERROR let bindings in constant functions are unstable } fn main() {} diff --git a/src/test/ui/consts/const-fn-not-safe-for-const.stderr b/src/test/ui/consts/const-fn-not-safe-for-const.stderr index 613670acc932..90a7314b7d1f 100644 --- a/src/test/ui/consts/const-fn-not-safe-for-const.stderr +++ b/src/test/ui/consts/const-fn-not-safe-for-const.stderr @@ -16,55 +16,7 @@ error[E0013]: constant functions cannot refer to statics, use a constant instead LL | &Y | ^^ -error[E0658]: let bindings in constant functions are unstable (see issue #48821) - --> $DIR/const-fn-not-safe-for-const.rs:40:13 - | -LL | let x = 22; - | ^^ - | - = help: add #![feature(const_let)] to the crate attributes to enable +error: aborting due to 3 previous errors -error[E0658]: statements in constant functions are unstable (see issue #48821) - --> $DIR/const-fn-not-safe-for-const.rs:40:13 - | -LL | let x = 22; - | ^^ - | - = help: add #![feature(const_let)] to the crate attributes to enable - -error[E0658]: let bindings in constant functions are unstable (see issue #48821) - --> $DIR/const-fn-not-safe-for-const.rs:43:13 - | -LL | let y = 44; - | ^^ - | - = help: add #![feature(const_let)] to the crate attributes to enable - -error[E0658]: statements in constant functions are unstable (see issue #48821) - --> $DIR/const-fn-not-safe-for-const.rs:43:13 - | -LL | let y = 44; - | ^^ - | - = help: add #![feature(const_let)] to the crate attributes to enable - -error[E0658]: let bindings in constant functions are unstable (see issue #48821) - --> $DIR/const-fn-not-safe-for-const.rs:46:5 - | -LL | x + y - | ^ - | - = help: add #![feature(const_let)] to the crate attributes to enable - -error[E0658]: let bindings in constant functions are unstable (see issue #48821) - --> $DIR/const-fn-not-safe-for-const.rs:46:9 - | -LL | x + y - | ^ - | - = help: add #![feature(const_let)] to the crate attributes to enable - -error: aborting due to 9 previous errors - -Some errors occurred: E0013, E0015, E0658. +Some errors occurred: E0013, E0015. For more information about an error, try `rustc --explain E0013`. diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr index f43befb37c13..39adf088642b 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr @@ -112,12 +112,6 @@ error: `if`, `match`, `&&` and `||` are not stable in const fn LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn | ^^^^^^^^^^^ -error: local variables in const fn are unstable - --> $DIR/min_const_fn.rs:109:34 - | -LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable - | ^ - error: `if`, `match`, `&&` and `||` are not stable in const fn --> $DIR/min_const_fn.rs:110:44 | @@ -221,7 +215,7 @@ error: function pointers in const fn are unstable LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo } | ^^^^ -error: aborting due to 35 previous errors +error: aborting due to 34 previous errors Some errors occurred: E0493, E0515. For more information about an error, try `rustc --explain E0493`. diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs index 0dba3a7de537..80db24006ec3 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs @@ -106,7 +106,7 @@ const fn foo30_2(x: *mut u32) -> usize { x as usize } const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } } //~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn -const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable +const fn foo30_6() -> bool { let x = true; x } const fn foo36(a: bool, b: bool) -> bool { a && b } //~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn const fn foo37(a: bool, b: bool) -> bool { a || b } diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index bcb9be6e5485..530282cfea92 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -112,12 +112,6 @@ error: `if`, `match`, `&&` and `||` are not stable in const fn LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn | ^^^^^^^^^^^ -error: local variables in const fn are unstable - --> $DIR/min_const_fn.rs:109:34 - | -LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable - | ^ - error: `if`, `match`, `&&` and `||` are not stable in const fn --> $DIR/min_const_fn.rs:110:44 | @@ -208,6 +202,6 @@ error: function pointers in const fn are unstable LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo } | ^^^^ -error: aborting due to 35 previous errors +error: aborting due to 34 previous errors For more information about this error, try `rustc --explain E0493`. diff --git a/src/test/ui/feature-gates/feature-gate-const_let.rs b/src/test/ui/feature-gates/feature-gate-const_let.rs index 05d02e62bc87..aad251a205e9 100644 --- a/src/test/ui/feature-gates/feature-gate-const_let.rs +++ b/src/test/ui/feature-gates/feature-gate-const_let.rs @@ -10,13 +10,13 @@ // Test use of const let without feature gate. -#![feature(const_fn)] - -const fn foo() -> usize { +const FOO: usize = { + //~^ ERROR statements in constants are unstable + //~| ERROR: let bindings in constants are unstable let x = 42; - //~^ ERROR statements in constant functions are unstable - //~| ERROR: let bindings in constant functions are unstable + //~^ ERROR statements in constants are unstable + //~| ERROR: let bindings in constants are unstable 42 -} +}; fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-const_let.stderr b/src/test/ui/feature-gates/feature-gate-const_let.stderr index 6a7f6255678f..4fab6ec540eb 100644 --- a/src/test/ui/feature-gates/feature-gate-const_let.stderr +++ b/src/test/ui/feature-gates/feature-gate-const_let.stderr @@ -1,4 +1,4 @@ -error[E0658]: let bindings in constant functions are unstable (see issue #48821) +error[E0658]: let bindings in constants are unstable (see issue #48821) --> $DIR/feature-gate-const_let.rs:16:13 | LL | let x = 42; @@ -6,7 +6,7 @@ LL | let x = 42; | = help: add #![feature(const_let)] to the crate attributes to enable -error[E0658]: statements in constant functions are unstable (see issue #48821) +error[E0658]: statements in constants are unstable (see issue #48821) --> $DIR/feature-gate-const_let.rs:16:13 | LL | let x = 42; @@ -14,6 +14,34 @@ LL | let x = 42; | = help: add #![feature(const_let)] to the crate attributes to enable -error: aborting due to 2 previous errors +error[E0658]: let bindings in constants are unstable (see issue #48821) + --> $DIR/feature-gate-const_let.rs:13:1 + | +LL | / const FOO: usize = { +LL | | //~^ ERROR statements in constants are unstable +LL | | //~| ERROR: let bindings in constants are unstable +LL | | let x = 42; +... | +LL | | 42 +LL | | }; + | |__^ + | + = help: add #![feature(const_let)] to the crate attributes to enable + +error[E0658]: statements in constants are unstable (see issue #48821) + --> $DIR/feature-gate-const_let.rs:13:1 + | +LL | / const FOO: usize = { +LL | | //~^ ERROR statements in constants are unstable +LL | | //~| ERROR: let bindings in constants are unstable +LL | | let x = 42; +... | +LL | | 42 +LL | | }; + | |__^ + | + = help: add #![feature(const_let)] to the crate attributes to enable + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0658`.