This is a tracking issue for the RFC "Allow locals and destructuring in const fn" (rust-lang/rfcs#2341).
Steps:
Unresolved questions:
None.
just remove the few checks
It's a bit trickier, because rustc_mir::transform::qualify_consts needs to track local variables just like it does only temporaries right now, but it shouldn't
Also, was let in other const contexts in the RFC, i.e. const X: i32 = { let x = 2 + 3; x * x};?
@eddyb Feel free to edit the issue description =)
Also, was let in other const contexts in the RFC, i.e.
const X: i32 = { let x = 2 + 3; x * x};?
Yes, because (quoting the summary):
Allow let bindings in the body of constants and const fns. Additionally enable destructuring in let bindings and const fn arguments.
A question about the "Drawbacks" section from the original RFC:
You can create mutable locals in constants and then actually modify them. This has no real impact on the constness, as the mutation happens entirely at compile time and results in an immutable value.
Can you elaborate on this? Is this just referring to something like const foo: i32 = { let mut x = 0; x += 1; x };? That's my straightforward reading of the text, but it also seems completely expected so I'm not sure whether there's a more pernicious drawback I ought to be seeing.
Not a drawback really, but a note that this is new behaviour, because before you could never modify the same memory twice, only emulate the same program behaviour via const fn.
This works now on nightly (behind a feature gate). Please play around with this feature liberally and report any findings! Any help in documenting and pushing it over the stabilization line is appreciated.
There seems to be a bug in the current implementation. This should work, right? http://play.rust-lang.org/?gist=5009873918b2b45bfa8015d4f21bb355&version=nightly&mode=debug&edition=2015
Imo it would be fine if added behind its own feature gate. So if you're looking for something easy to do:
const_let and copy all the defining parts)Short-circuiting operators need to be fixed before stabilizing const_let. Otherwise it is possible to observe wrong results when changing a fn to const fn. #53515
I already added it to the OP ;)
The const_let feature gate does not seem to work for field assignment.
#![feature(const_let)]
struct S(i32);
const A: () = {
let mut s = S(0);
s.0 = 1;
};
fn main() {}
error[E0658]: statements in constants are unstable (see issue #48821)
--> src/main.rs:7:5
|
7 | s.0 = 1;
| ^^^^^^^
|
= help: add #![feature(const_let)] to the crate attributes to enable
It suggests adding #![feature(const_let)] even though that feature is already enabled.
We could stabilize let bindings in const fn (but not in const/static), because const functions do not have the issue that && and || short circuit (since these operations are illegal in const functions until control flow in general is allowed).
Due to backwards compatibility constraints we cannot make && and || illegal in constants and statics.
cc @Centril
@oli-obk Hmm... there are a bunch of bug reports cited in https://github.com/rust-lang/rust/issues/48821#issuecomment-425705272... we'd have to feel comfortable with the implementation before stabilizing.
However, my main question re. stabilizing is whether stabilizing let without control flow would bring much benefit without any control flow? What is it that we "unlock" by stabilizing in const fn only?
I have a fix ready for these bugs in https://github.com/rust-lang/rust/pull/56070
However, my main question re. stabilizing is whether stabilizing let without control flow would bring much benefit without any control flow? What is it that we "unlock" by stabilizing in const fn only?
You can do things like
fn bar() -> [u32; 500] {
let mut foo = [0; 500];
foo[3] = 42;
foo
}
Or just generally make your code more readable in case the return expression is very complex.
@oli-obk
I have a fix ready for these bugs in #56070
Cool. :)
Or just generally make your code more readable in case the return expression is very complex.
I somehow doubt expressions can become complex without any sort of control flow but I suppose it doesn't hurt. Clearly enough time has passed since it was landed in nightly...
Could you? prepare:
@oli-obk PS: also make sure that const fn with let bindings is well behaved when then later used in a const or static item wrt. short circuit.
also make sure that const fn with let bindings is well behaved when then later used in a const or static item wrt. short circuit.
I'm not even sure I understand. Are you asking whether calling a const fn inside a const initializer could be problematic in the presence of short circuiting operators in the initializer? I don't see how the body of the const fn can be relevant here.
@oli-obk Never mind; I was saying nonsense things. =P
Does this tracking issue include mutable references? Or is that a separate RFC/tracking issue?
Mutable references require their own full rfc imo. There are so many edge cases. I have started tracking some in https://github.com/rust-rfcs/const-eval/issues/16
Stabilization proposed: https://github.com/rust-lang/rust/pull/57175#issuecomment-450593735
Stabilized in https://github.com/rust-lang/rust/pull/57175; Documentation issue: https://github.com/rust-lang-nursery/reference/issues/506
Everything is done so closing therefore.
Most helpful comment
Stabilized in https://github.com/rust-lang/rust/pull/57175; Documentation issue: https://github.com/rust-lang-nursery/reference/issues/506
Everything is done so closing therefore.