Skip to content

Conversation

SeanTheGleaming
Copy link
Contributor

Revival of #25222, where I bungled so bad with git that I had to create a new branch, not just for the operation of the code, but for my honor.
Addresses multiple bugs in Sema/Value/Type.
To be specific:

Peer @TypeOf in a @cImport block

In a unary @TypeOf block, the current behavior regarding @cImport statements is that operands are treated as if they are outside of a @cImport block; If you use @TypeOf(@cInclude(...)) even inside of a @cImport block, this is a compile error. It seems that peer @TypeOf did not agree with this implementation. Or any implementation for that matter. It crashed the compiler by attempting to write to a @cImport buffer that didn't exist. Now the behavior is consistent with unary @TypeOf.

In practice, this turns the following code from a crash into a compile error:

const c = @cImport({
    _ = @TypeOf(@cInclude("stdlib.h"), @cInclude("stdio.h"));
});

Pass an optional sema parameter to print_value and Type.print

Some API changes were made to Value, Type, and print_value to allow for semantic analysis during the formatting of Value and Type. Resolves the TODO above Type.print.

  • Functions in print_value now take an opt_sema: ?*Sema parameter
  • Added new formatting functions to Value
    • Value.fmtValueOptSema
      • Similar to Value.fmtSema , except the sema parameter is now optional.
      • For use when Sema may or may not be available
    • Explicit depth formatting functions
      • Value.fmtDepth
        • Identical to Value.fmt, but takes an additional depth parameter
      • Value.fmtSemaDepth
        • Identical to Value.fmtSema, but takes an additional depth parameter
      • Value.fmtOptSemaDepth
        • Identical to Value.fmtOptSema, but takes an additional depth parameter
  • Type.print now takes an ?*Sema parameter
    • When provided with a nonnull value, this makes semantic analysis during the printing of types possible.
  • Added new formatting functions to Type
    • Type.fmt remains unchanged
      • Never performs semantic analysis
      • Symmetrical to Value.printValue
    • Type.fmtSema
      • Similar to Type.fmt, but accepts an additional *Sema parameter
      • May perform semantic analysis
      • For use whenever Sema is available
      • Symmetrical to Value.printValueSema
    • Type.fmtOptSema
      • Similar to Type.fmt, but accepts an additional ?*Sema parameter
      • May perform semantic analysis if the ?*Sema parameter is nonnull
      • For use when Sema may or may not be available
      • Symmetrical to Value.printValueOptSema

These changes fix the following compiler crash (and many similar crashes in the same vain):

comptime {
    var mutable: u8 = 0;
    @compileLog(@TypeOf(.{&mutable}));
}

And speaking of capturing comptime variables as default field values in anonymous struct literals...

Better checks for capturing comptime-mutable references

Previously, it was relatively simple to "hide" a comptime-mutable reference inside of a type. If you stored a comptime-mutable reference in the sentinel of an array or the default field of a struct, it was possible to create a type which contained a comptime-mutable reference. Building on that, it was possible to create structs containing these types, pointers pointing to these types, arrays with these types as children, and so on. After a thorough rework of the relevant code, this is no more!

In practice, the following code contains multiple parts that used to crash the compiler:

const y = blk: {
    // Crazy contrived example of deeply nesting a comptime variable within types
    var x: u8 = 0;
    const z = *[*:.{(&[3]*u8{ undefined, &x, undefined }).ptr[3..4]}]@Vector(1, [*]const *u8);
    const S = anyerror!struct {
        a: u8,
        b: type,
    };
    const s: S = .{
        .a = 4,
        .b = z,
    };
    break :blk &(s catch unreachable).a;
};

comptime {
    _ = y;
}

And now, as ridiculous as that code was, we get a proper error message:

/abc/example.zig:1:16: error: global variable contains reference to comptime var
const y = blk: {
          ~~~~~^
/abc/example.zig:1:16: note: 'y' points to '(v0 catch unreachable).a', where
/abc/example.zig:1:16: note: '@typeInfo(@typeInfo((v0 catch unreachable).b).pointer.child).pointer.sentinel().?[0]' points to '@as([*]const *u8, @ptrCast(&v1[3])).*', where
/abc/example.zig:4:17: note: 'v1[1]' points to comptime var declared here
    var x: u8 = 0;

Adds an optional sema parameter to Type.print,
print_value.printPtrDeviation, and other related functions. Resolves the
TODO above Type.print. Additionally, fixed a crash with
`@compileLog(@typeof(.{&[comptime_var]}))`, although this case allows
for the capturing of a comptime variable pointer in a type via the default
field in a tuple, which should not be allowed (see ziglang#5718) and should be
rectified.
@SeanTheGleaming
Copy link
Contributor Author

I have been completely unable to recreate the CI failures locally, and do save from wasting a massive amount of CI time testing different combinations of these commits, I won't be able to get this in a working state for the forseeable future. That being said, I will close this for now, and instead open issues regarding the bugs in question.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant