Firstly, I should note that this is specifically about comptime-mutable memory - i.e. comptime var
, not comptime-known const
s. But yes, as of that change, one admittedly slightly irritating thing is constructing strings with type []const u8
at comptime. This code will no longer work:
pub fn main() void {
var runtime_var: []const u8 = undefined;
runtime_var = comptime getString();
}
fn getString() []const u8 {
return comptime str: {
var str: [5]u8 = undefined;
str = "hello".*;
break :str &str;
};
}
This fails because the slice returned at comptime from getString
references str
, which is a comptime var
. Of course, in this situation it could just be const
, but in many cases you’ll want var
to construct the string in a loop or something. The solution to this is to copy your finalized data into a const
, e.g.:
fn getString() []const u8 {
return comptime str: {
var str: [5]u8 = undefined;
str = "hello".*;
const final = str;
break :str &final;
}
}
You can see in the PR that I’ve had to make this change in a couple places in std. I will freely admit that this is a little annoying, but it serves to resolve some serious soundness issues with comptime var
– if a pointer to one is permitted to become runtime-known like today, there are some major footguns:
- A load from such a pointer has different behavior if performed at runtime vs comptime. A comptime load will get the current value of the
comptime var
at the time of analysis, while a runtime load will get its “final” value which is lowered into the binary. - If any reference to such memory becomes runtime-known with a mutable type, there is a trivial issue: you cannot legally mutate that pointer, but the type system cannot enforce this. We could theoretically resolve this by const-ifying all such pointers, but this is a bit tricky implementation-wise and could lead to some incredibly unintuitive compile errors, so it makes sense to stop you from doing it at all.
If you have any specific code example which you’d like to ask about, feel free – I can tell you whether it will still work, and if not, point to how to could be made to compile.