zig
zig copied to clipboard
Assertion failed at analyze.cpp:605 in get_pointer_to_type_extra2
zig version 0.5.0+e491b2f5a
Small reproducible:
const Foo = struct {
bar: i32,
// Mistake is that it should be *c_void
// ZIG FAILS WITH:
// Assertion failed at /deps/zig/src/analyze.cpp:605 in get_pointer_to_type_extra2. This is a bug in the Zig compiler.
pub fn unbox(pointer: *void) *Foo {
return @ptrCast(*Foo, @alignCast(@alignOf(Foo), pointer));
}
};
pub fn main() anyerror!void {
var foo: Foo = .{ .bar = 42 };
var userdata = @ptrCast(*c_void, &foo);
var foo2 = Foo.unbox(userdata);
}
Compilation fails with:
Assertion failed at /deps/zig/src/analyze.cpp:605 in get_pointer_to_type_extra2. This is a bug in the Zig compiler.
Duplicate of #3610 (the stack trace is slightly different as some compiler internals have changed since then).
Two questions arise:
- What should
@alignCast
do for zero-sized types? - Is
*void
a valid type? Unlikec_void
the child type has no alignment and no size and it's gonna trip so many assertions throughout the compiler.
What should
@alignCast
do for zero-sized types?
Related: #4016
Easy question first:
Is
*void
a valid type? Unlikec_void
the child type has no alignment and no size and it's gonna trip so many assertions throughout the compiler.
Yes, *void
should be handled the same as *u0
.
What should
@alignCast
do for zero-sized types?
Currently the language defines pointers to 0-bit types to also be 0-bit types, e.g. they have no actual address. @ptrToInt
on a pointer to 0-bit is a compile error.
I think the answer to how this should behave can be derived by thinking about what @alignOf(ZeroBitType)
should be. Which is 0. Because a zero bit type does not even require 1-byte alignment, no alignment is required.
So *void
guarantees no alignment, not even 1 byte alignment. This would make @alignCast
a compile error if casting to a non-zero-bit type, e.g. Foo
in this example.
However it would work fine if both types were 0-bit. And it would work the other way: @alignCast
from a non-zero-bit type to a zero-bit-type.
As far as implementing this in the compiler goes, there is a footgun to look out for, which is that 0
is currently a special value which has the meaning of "ABI alignment". We also need to adjust this when implementing #3802.
Ran into this issue myself in a slightly different way with another weird 0 bit type case partially due to a bug on my part, but I felt I'd add it here in case it is useful. Not exactly sure where in the standard library the issue is coming from, but the code that caused it is essentially this:
const std = @import("std");
pub fn main() !void {
try std.testing.allocator.alignedAlloc(type, 1, 1);
}
Of course if I took @alignOf(type)
to get a proper alignment it'd inform me that there's no valid alignment for it, but I was accidentally passing some other alignment in this instance which generated that code and resulted in a compiler assertion just the same (running on 0.10.0-dev.3050+e05487746
):
zig-git/src/zig/src/stage1/analyze.cpp:620 in get_pointer_to_type_extra2. This is a bug in the Zig compiler.
No longer relevant with #6706