-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix various aspects around let
bindings inside const functions
#56160
Changes from 1 commit
4d2bed9
dba5ba0
df2123c
52b67b1
ef38afc
59c6c49
7ec3c10
d62bcad
507ea97
75ce28a
d8ece18
866664c
8937faa
16d2a92
ac47bd7
25d1c07
172b428
42e5317
9d2f97b
e6e08c6
07345f0
2cb5e3d
6ca2ad5
b678238
d815e2b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like a great place for a comment =) in particular, documenting the logic behind these rules. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Something like: Currently, without a feature gate, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We decided on not doing this dual-scheme. Instead we're poisoning constants that use short circuiting operators so they can't also have I'll remove the function and move back to checking the feature gate directly |
||
self.tcx.features().const_let || self.mode == Mode::ConstFn | ||
oli-obk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
/// 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); | ||
} | ||
|
||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,47 @@ | ||
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; | ||
| ^^ | ||
| | ||
= 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; | ||
| ^^ | ||
| | ||
= 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`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @nikomatsakis
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this is not the correct reason. The reason we add
FakeRead
is documented onFakeReadCause::ForLet
-- basically it is to ensure that we give errors in some cases where we generate more optimized IR (not just for diagnostics).