Open nektro opened 1 year ago
Wouldn't that require that memory be allocated for the sentinel though?
no because making the array its own variable also works and so does inline for non-sentinel
pub fn main() void {
_ = foo();
}
fn foo() [:0]u8 {
var arr = [_:0]u8{};
return &arr;
}
this also runs without error
That just looks like you're returning a pointer to stack memory. This works:
const std = @import("std");
const print = std.debug.print;
pub fn main() void {
var a = "foo".*;
const b: [:0]u8 = a[0..];
b[b.len] = 3;
print("{any}\n", .{b[b.len]});
}
because the sentinel is also part of the mutable memory.
The reason this coercion is valid for non-sentinel arrays is because they're 0 bytes long - as InKryption says, that's not the case here due to the sentinel value. The var
one clearly works (well, compiles) because you're marking the array var
so the pointer isn't const
to begin with.
its technically a pointer to stack memory but the slice has a length of 0 so it should remain valid
Even when it has a length of 0, the sentinel is still there, and still requires memory. The true size of a sentinel-terminated X is always @sizeOf(T) * (len + 1)
. So your slice there is actually not truly empty, it just doesn't have any non-sentinel elements.
even still, the sentinel in this case should be able to be put in the readonly data part of an executable. &[_:0]u8{}
is semantically the same thing as ""
It can't be in read-only data, because you can still modify the sentinel:
test {
var a = "".*;
a[0] = 42;
}
because the sentinel is also part of the mutable memory.
sorry, missed that part from your earlier comment. wait what? that should definitely be safety checked imo
Addresses of temporaries are now const. https://ziglang.org/download/0.10.0/release-notes.html#Address-of-Temporaries-Now-Produces-Const-Pointers
Your code is trying to make a non const slice which won't cast from a pointer to const.
Your code is trying to make a non const slice which won't cast from a pointer to const.
They know this; the confusion is coming from sentinel arrays specifically. The expression &.{}
is actually allowed to coerce to a mutable slice (since it doesn't refer to any memory so it's safe to "mutate" any of its 0 elements), and the confusion here is coming from the fact that this doesn't apply to sentinel-terminated arrays (due to the sentinel itself being stored).
to add clarification, the thesis of this issue is that the bug is "because the sentinel is also part of the mutable memory" and attempting to write at the sentinels position should instead be Illegal Behavior.
writing over the sentinel should require [:S]T
to be casted to a []T
with slice.len + 1
or a [*]T
.
making this change would allow a zero-length sentineled slice to be stored in constant memory.
Additional discord discussion: https://discord.com/channels/605571803288698900/906306963942543370/1228084517059690628
Zig Version
0.11.0-dev.661+d88eb75a6
Steps to Reproduce and Observed Behavior
Expected Behavior
pass the same way it does for
[]u8