zig icon indicating copy to clipboard operation
zig copied to clipboard

Assertion failed at analyze.cpp:605 in get_pointer_to_type_extra2

Open dsego opened this issue 5 years ago • 4 comments

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.

dsego avatar Jan 20 '20 13:01 dsego

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? Unlike c_void the child type has no alignment and no size and it's gonna trip so many assertions throughout the compiler.

LemonBoy avatar Jan 20 '20 15:01 LemonBoy

What should @alignCast do for zero-sized types?

Related: #4016

daurnimator avatar Jan 20 '20 15:01 daurnimator

Easy question first:

Is *void a valid type? Unlike c_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.

andrewrk avatar Jan 28 '20 22:01 andrewrk

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.

presentfactory avatar Jul 26 '22 06:07 presentfactory

No longer relevant with #6706

Vexu avatar Dec 30 '22 20:12 Vexu