提交 4d2bed94 编写于 作者: O Oliver Scherer

Stabilize `const_let` inside const functions

上级 3e90a12a
......@@ -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 @@ fn assign(&mut self, dest: &Place<'tcx>, location: Location) {
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 @@ fn assign(&mut self, dest: &Place<'tcx>, location: Location) {
}
}
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 @@ fn qualify_const(&mut self) -> (Qualif, Lrc<BitSet<Local>>) {
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 @@ fn visit_local(&mut self,
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 @@ fn visit_assign(&mut self,
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() {}
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[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
error: aborting due to 3 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() {}
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`.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册