Skip to content

Commit 4d2bed9

Browse files
committed
Stabilize const_let inside const functions
1 parent 3e90a12 commit 4d2bed9

12 files changed

+56
-188
lines changed

src/librustc/mir/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1748,6 +1748,8 @@ pub enum StatementKind<'tcx> {
17481748
/// (e.g. inspecting constants and discriminant values), and the
17491749
/// kind of pattern it comes from. This is in order to adapt potential
17501750
/// error messages to these specific patterns.
1751+
///
1752+
/// Note that this also is emitted for regular `let` bindings to aid destructuring diagnostics
17511753
FakeRead(FakeReadCause, Place<'tcx>),
17521754

17531755
/// Write the discriminant for a variant to the enum Place.

src/librustc_mir/transform/qualify_consts.rs

Lines changed: 7 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
243243
return;
244244
}
245245

246-
if self.tcx.features().const_let {
246+
if self.const_let_allowed() {
247247
let mut dest = dest;
248248
let index = loop {
249249
match dest {
@@ -320,6 +320,10 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
320320
}
321321
}
322322

323+
fn const_let_allowed(&self) -> bool {
324+
self.tcx.features().const_let || self.mode == Mode::ConstFn
325+
}
326+
323327
/// Qualify a whole const, static initializer or const fn.
324328
fn qualify_const(&mut self) -> (Qualif, Lrc<BitSet<Local>>) {
325329
debug!("qualifying {} {:?}", self.mode, self.def_id);
@@ -357,7 +361,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
357361
TerminatorKind::FalseUnwind { .. } => None,
358362

359363
TerminatorKind::Return => {
360-
if !self.tcx.features().const_let {
364+
if !self.const_let_allowed() {
361365
// Check for unused values. This usually means
362366
// there are extra statements in the AST.
363367
for temp in mir.temps_iter() {
@@ -464,7 +468,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
464468
LocalKind::ReturnPointer => {
465469
self.not_const();
466470
}
467-
LocalKind::Var if !self.tcx.features().const_let => {
471+
LocalKind::Var if !self.const_let_allowed() => {
468472
if self.mode != Mode::Fn {
469473
emit_feature_err(&self.tcx.sess.parse_sess, "const_let",
470474
self.span, GateIssue::Language,
@@ -1154,48 +1158,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
11541158
debug!("visit_assign: dest={:?} rvalue={:?} location={:?}", dest, rvalue, location);
11551159
self.visit_rvalue(rvalue, location);
11561160

1157-
// Check the allowed const fn argument forms.
1158-
if let (Mode::ConstFn, &Place::Local(index)) = (self.mode, dest) {
1159-
if self.mir.local_kind(index) == LocalKind::Var &&
1160-
self.const_fn_arg_vars.insert(index) &&
1161-
!self.tcx.features().const_let {
1162-
1163-
// Direct use of an argument is permitted.
1164-
match *rvalue {
1165-
Rvalue::Use(Operand::Copy(Place::Local(local))) |
1166-
Rvalue::Use(Operand::Move(Place::Local(local))) => {
1167-
if self.mir.local_kind(local) == LocalKind::Arg {
1168-
return;
1169-
}
1170-
}
1171-
_ => {}
1172-
}
1173-
1174-
// Avoid a generic error for other uses of arguments.
1175-
if self.qualif.contains(Qualif::FN_ARGUMENT) {
1176-
let decl = &self.mir.local_decls[index];
1177-
let mut err = feature_err(
1178-
&self.tcx.sess.parse_sess,
1179-
"const_let",
1180-
decl.source_info.span,
1181-
GateIssue::Language,
1182-
"arguments of constant functions can only be immutable by-value bindings"
1183-
);
1184-
if self.tcx.sess.teach(&err.get_code().unwrap()) {
1185-
err.note("Constant functions are not allowed to mutate anything. Thus, \
1186-
binding to an argument with a mutable pattern is not allowed.");
1187-
err.note("Remove any mutable bindings from the argument list to fix this \
1188-
error. In case you need to mutate the argument, try lazily \
1189-
initializing a global variable instead of using a const fn, or \
1190-
refactoring the code to a functional style to avoid mutation if \
1191-
possible.");
1192-
}
1193-
err.emit();
1194-
return;
1195-
}
1196-
}
1197-
}
1198-
11991161
self.assign(dest, location);
12001162
}
12011163

src/librustc_mir/transform/qualify_min_const_fn.rs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,6 @@ pub fn is_min_const_fn(
6464
}
6565
}
6666

67-
for local in mir.vars_iter() {
68-
return Err((
69-
mir.local_decls[local].source_info.span,
70-
"local variables in const fn are unstable".into(),
71-
));
72-
}
7367
for local in &mir.local_decls {
7468
check_ty(tcx, local.ty, local.source_info.span)?;
7569
}
@@ -229,7 +223,7 @@ fn check_statement(
229223
check_rvalue(tcx, mir, rval, span)
230224
}
231225

232-
StatementKind::FakeRead(..) => Err((span, "match in const fn is unstable".into())),
226+
StatementKind::FakeRead(_, place) => check_place(tcx, mir, place, span, PlaceMode::Read),
233227

234228
// just an assignment
235229
StatementKind::SetDiscriminant { .. } => Ok(()),
@@ -270,15 +264,8 @@ fn check_place(
270264
mode: PlaceMode,
271265
) -> McfResult {
272266
match place {
273-
Place::Local(l) => match mode {
274-
PlaceMode::Assign => match mir.local_kind(*l) {
275-
LocalKind::Temp | LocalKind::ReturnPointer => Ok(()),
276-
LocalKind::Arg | LocalKind::Var => {
277-
Err((span, "assignments in const fn are unstable".into()))
278-
}
279-
},
280-
PlaceMode::Read => Ok(()),
281-
},
267+
// assignments to locals, arguments, temporaries or the return slot are fine
268+
Place::Local(_) => Ok(()),
282269
// promoteds are always fine, they are essentially constants
283270
Place::Promoted(_) => Ok(()),
284271
Place::Static(_) => Err((span, "cannot access `static` items in const fn".into())),

src/test/ui/consts/const-fn-destructuring-arg.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,10 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// test that certain things are disallowed in constant functions
11+
// compile-pass
1212

13-
#![feature(const_fn)]
14-
15-
// no destructuring
16-
const fn i((
17-
a,
18-
//~^ ERROR arguments of constant functions can only be immutable by-value bindings
19-
b
20-
//~^ ERROR arguments of constant functions can only be immutable by-value bindings
21-
): (u32, u32)) -> u32 {
13+
const fn i((a, b): (u32, u32)) -> u32 {
2214
a + b
23-
//~^ ERROR let bindings in constant functions are unstable
24-
//~| ERROR let bindings in constant functions are unstable
2515
}
2616

2717
fn main() {}

src/test/ui/consts/const-fn-destructuring-arg.stderr

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/test/ui/consts/const-fn-not-safe-for-const.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,8 @@ const fn get_Y_addr() -> &'static u32 {
3838

3939
const fn get() -> u32 {
4040
let x = 22;
41-
//~^ ERROR let bindings in constant functions are unstable
42-
//~| ERROR statements in constant functions are unstable
4341
let y = 44;
44-
//~^ ERROR let bindings in constant functions are unstable
45-
//~| ERROR statements in constant functions are unstable
4642
x + y
47-
//~^ ERROR let bindings in constant functions are unstable
48-
//~| ERROR let bindings in constant functions are unstable
4943
}
5044

5145
fn main() {}

src/test/ui/consts/const-fn-not-safe-for-const.stderr

Lines changed: 2 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -16,55 +16,7 @@ error[E0013]: constant functions cannot refer to statics, use a constant instead
1616
LL | &Y
1717
| ^^
1818

19-
error[E0658]: let bindings in constant functions are unstable (see issue #48821)
20-
--> $DIR/const-fn-not-safe-for-const.rs:40:13
21-
|
22-
LL | let x = 22;
23-
| ^^
24-
|
25-
= help: add #![feature(const_let)] to the crate attributes to enable
26-
27-
error[E0658]: statements in constant functions are unstable (see issue #48821)
28-
--> $DIR/const-fn-not-safe-for-const.rs:40:13
29-
|
30-
LL | let x = 22;
31-
| ^^
32-
|
33-
= help: add #![feature(const_let)] to the crate attributes to enable
34-
35-
error[E0658]: let bindings in constant functions are unstable (see issue #48821)
36-
--> $DIR/const-fn-not-safe-for-const.rs:43:13
37-
|
38-
LL | let y = 44;
39-
| ^^
40-
|
41-
= help: add #![feature(const_let)] to the crate attributes to enable
42-
43-
error[E0658]: statements in constant functions are unstable (see issue #48821)
44-
--> $DIR/const-fn-not-safe-for-const.rs:43:13
45-
|
46-
LL | let y = 44;
47-
| ^^
48-
|
49-
= help: add #![feature(const_let)] to the crate attributes to enable
50-
51-
error[E0658]: let bindings in constant functions are unstable (see issue #48821)
52-
--> $DIR/const-fn-not-safe-for-const.rs:46:5
53-
|
54-
LL | x + y
55-
| ^
56-
|
57-
= help: add #![feature(const_let)] to the crate attributes to enable
58-
59-
error[E0658]: let bindings in constant functions are unstable (see issue #48821)
60-
--> $DIR/const-fn-not-safe-for-const.rs:46:9
61-
|
62-
LL | x + y
63-
| ^
64-
|
65-
= help: add #![feature(const_let)] to the crate attributes to enable
66-
67-
error: aborting due to 9 previous errors
19+
error: aborting due to 3 previous errors
6820

69-
Some errors occurred: E0013, E0015, E0658.
21+
Some errors occurred: E0013, E0015.
7022
For more information about an error, try `rustc --explain E0013`.

src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,6 @@ error: `if`, `match`, `&&` and `||` are not stable in const fn
112112
LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
113113
| ^^^^^^^^^^^
114114

115-
error: local variables in const fn are unstable
116-
--> $DIR/min_const_fn.rs:109:34
117-
|
118-
LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
119-
| ^
120-
121115
error: `if`, `match`, `&&` and `||` are not stable in const fn
122116
--> $DIR/min_const_fn.rs:110:44
123117
|
@@ -221,7 +215,7 @@ error: function pointers in const fn are unstable
221215
LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
222216
| ^^^^
223217

224-
error: aborting due to 35 previous errors
218+
error: aborting due to 34 previous errors
225219

226220
Some errors occurred: E0493, E0515.
227221
For more information about an error, try `rustc --explain E0493`.

src/test/ui/consts/min_const_fn/min_const_fn.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ const fn foo30_2(x: *mut u32) -> usize { x as usize }
106106
const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
107107
//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
108108
const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
109-
const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
109+
const fn foo30_6() -> bool { let x = true; x }
110110
const fn foo36(a: bool, b: bool) -> bool { a && b }
111111
//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
112112
const fn foo37(a: bool, b: bool) -> bool { a || b }

src/test/ui/consts/min_const_fn/min_const_fn.stderr

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,6 @@ error: `if`, `match`, `&&` and `||` are not stable in const fn
112112
LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
113113
| ^^^^^^^^^^^
114114

115-
error: local variables in const fn are unstable
116-
--> $DIR/min_const_fn.rs:109:34
117-
|
118-
LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
119-
| ^
120-
121115
error: `if`, `match`, `&&` and `||` are not stable in const fn
122116
--> $DIR/min_const_fn.rs:110:44
123117
|
@@ -208,6 +202,6 @@ error: function pointers in const fn are unstable
208202
LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
209203
| ^^^^
210204

211-
error: aborting due to 35 previous errors
205+
error: aborting due to 34 previous errors
212206

213207
For more information about this error, try `rustc --explain E0493`.

0 commit comments

Comments
 (0)