zig icon indicating copy to clipboard operation
zig copied to clipboard

Unexpected results with `@typeInfo` on `anyerror!noreturn`

Open wooster0 opened this issue 1 year ago • 2 comments

Zig Version

0.11.0-dev.3704+729a051e9

Steps to Reproduce and Observed Behavior

fn main() anyerror!noreturn {
    return error.a;
}

test {
    switch (@typeInfo(@typeInfo(@TypeOf(main)).Fn.return_type.?)) {
        .ErrorUnion => {
            const result = main() catch undefined;
            // see for yourself: @compileLog(@TypeOf(result));
            switch (@TypeOf(result)) {
                noreturn => return error.expected,
                else => return error.unexpected,
            }
        },
        else => return error.unexpected,
    }
}
$ zig test x.zig
Test [1/1] test_0... FAIL (unexpected)
/home/wooster/Desktop/zig/x.zig:12:25: 0x20ebf7 in test_0 (test)
                else => return error.unexpected,
                        ^

Expected Behavior

Replace all occurrences of noreturn with something else like u8:

$ zig test x.zig
Test [1/1] test_0... FAIL (expected)
/home/wooster/Desktop/zig/x.zig:11:23: 0x20ec17 in test_0 (test)
                u8 => return error.expected,
                      ^

As a result of this bug, this program can be zig run:

pub fn main() !noreturn {
    return error.a;
}
$ zig run x.zig
error: a
/home/wooster/Desktop/zig/x.zig:20:5: 0x20b008 in main (x)
    return error.a;
    ^

But I expect https://github.com/ziglang/zig/blob/a72d634b731952ee227d026c27e83c5702dcea4a/lib/std/start.zig#L623 to be hit.

wooster0 avatar Jun 20 '23 06:06 wooster0

The type of (_!noreturn) catch _ is noreturn. Drive-by opinion: The compiler should actually issue a compile error once analysis reaches the instantiation of a value of type noreturn (in this case via coercion from undefined), since that is a semantic error: noreturn means "guaranteed to never be instantiated".

Compare with a more explicitly annotated version:

const result = main() catch
  @as(noreturn, block: { //we guarantee this expression diverts control flow, not providing a value
    break :block undefined; //we break the guarantee (provide a value without diverting control flow) - this is compile-time checkable illegal behavior
  });

(Alternatively it could also translate the expression to a call to @panic("instantiated noreturn"), but compile errors > runtime crashes.)

rohlem avatar Jun 20 '23 12:06 rohlem

See #13807 and #15909

Vexu avatar Jun 20 '23 16:06 Vexu