Make it so that var assignments to constant values are semantically visible despite being var, can still be observed at comptime. this allows it to be semantically inlined.
var x: int = 2;
var s: struct { item: int } = .{ item: 2 };
let print = @js("console").log;
print(s.item);
should lower to this Air:
Air for <fn() -> void, decl ''>
X #0 = block {
S #1 = js_global_ref console
S #2 = field(#1, log)
X #3 = call(#2, [
<float, 2>
])
}
Examples of clobbers
var x: int = 2;
if @js("Math").random() > 0.5 {
x = 3; // analysis of this assignment clobbers the `x` .memory location
}
var s: struct { item: int } = .{ item: 2 };
let print = @js("console").log;
print(s.item); // no optimization
// this assignment un-clobbers the memory location
// it is now known at comptime
x = 4;
print(x); // inlined 4
I add the optimization tag to this issue, but it will be of sema and it will be a semantic change to how var and assignments work. This means future code with comptime functions can take advantage of this behavior.
fn doSomethingAtComptime(comptime x: int) { ... }
var x = 3;
if build_config.should_x_be_four {
x = 4;
}
doSomethingAtComptime(x);
In this snippet, we will expect no errors unless build_config.should_x_be_four is not known at compile time. we will get the error on x saying it is not known at compile time. Previously, x is not comptime because it was using var, but now we can point directly at x = 4 being a clobber in a runtime branch. If we want to be very specific in the error, we could trace the clobber back to the runtime branch and show that in the error message.
I think this should be reasonably easy to implement, and it will open the door to more semantic optimizations.
Milestone: 0.3.0.
Just got structs to visualize what this currently looks like
Air for <fn() -> void, decl ''>
X #0 = block {
S #1 = memory(<int32, 2>, type: int32)
S #2 = struct_init(struct { item: int32 }, {
item: #1
}
S #3 = memory(#2, type: struct { item: int32 })
S #4 = js_global_ref console
S #5 = field_opaque(#4, log)
S #6 = field_struct(#3, item)
X #7 = call(#5, [
#6
])
}