Stabilize const_let inside const functions
This commit is contained in:
parent
3e90a12a8a
commit
4d2bed9460
12 changed files with 56 additions and 188 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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<BitSet<Local>>) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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())),
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
@ -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() {}
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue