Skip to content

Union with type that has optional field causes segfault in compiler #1995

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ghost opened this issue Feb 22, 2019 · 5 comments
Closed

Union with type that has optional field causes segfault in compiler #1995

ghost opened this issue Feb 22, 2019 · 5 comments
Labels
bug Observed behavior contradicts documented or intended behavior
Milestone

Comments

@ghost
Copy link

ghost commented Feb 22, 2019

If an union has a type with an optional type then the compiler with crash with segfault.
Example code (stripped down from larger project):

const LhsExpr = struct {
    rhsExpr: ?AstObject
};

const AstObject = union {
    lhsExpr: LhsExpr
};

test "crash" {
    const lhsExpr = LhsExpr {
        .rhsExpr = null
    };

    const obj = AstObject {
        .lhsExpr = lhsExpr
    };
}

The compiler crashes because it fails to allocate at src/analyze.cpp:2293 (resolve_union_type) because union_type->data.unionation.gen_field_count is 0

@andrewrk andrewrk added this to the 0.4.0 milestone Feb 22, 2019
@andrewrk andrewrk added the bug Observed behavior contradicts documented or intended behavior label Feb 22, 2019
@andrewrk
Copy link
Member

Thanks for the stripped down example.

@ghost
Copy link
Author

ghost commented Feb 22, 2019

I see now that it's not supposed to work (but still not supposed to crash of course) because there is a recursive dependency (LhsExpr depends on a non-pointer type of AstObject and AstObject depends on a non-pointer type of LhsExpr).
So this works and doesn't crash:

const std = @import("std");

pub const LhsExpr = struct {
    rhsExpr: ?AstObject
};

pub const AstObject = union {
    lhsExpr: *LhsExpr
};

test "crash" {
    var lhsExpr = try std.debug.global_allocator.create(LhsExpr);
    const astObj = AstObject {
        .lhsExpr = lhsExpr
    };
}

however this does crash:

const std = @import("std");

pub const LhsExpr = struct {
    rhsExpr: ?AstObject
};

pub const AstObject = union {
    lhsExpr: *LhsExpr
};

test "crash" {
    const alignment = @alignOf(AstObject);
}

on the other hand @alignOf(LhsExpr) doesn't crash

@daurnimator
Copy link
Contributor

I think this might be a dupe of #1735

@andrewrk
Copy link
Member

andrewrk commented Apr 4, 2019

Proposal to fix this: #2174

@andrewrk
Copy link
Member

Now it gives this:

/home/andy/dev/zig/build/test.zig:1:17: error: struct 'LhsExpr' depends on itself
const LhsExpr = struct {
                ^
/home/andy/dev/zig/build/test.zig:5:5: note: while checking this field
    lhsExpr: LhsExpr,
    ^
/home/andy/dev/zig/build/test.zig:2:5: note: while checking this field
    rhsExpr: ?AstObject,
    ^
/home/andy/dev/zig/build/test.zig:8:30: note: referenced here
    const lhsExpr = LhsExpr{ .rhsExpr = null };
                             ^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior
Projects
None yet
Development

No branches or pull requests

2 participants