Primitive type as field access expression

why is this allowed

const std = @import("std");

pub fn main() void {
    std.debug.print("{any}\n", .{S.bool}); // ? prints true
    std.debug.print("{any}\n", .{S.@"bool"}); // identifier; prints true
}

const S = struct {
    pub const @"bool" = true;
};

You probably already are aware but note that there is a distinction between keywords like struct or error and primitives like bool or true. Keywords must always be quoted regardless of context, whether they are declared or used as fields, decls, labels, etc. Primitives only need to be quoted in a decl context (i.e. var, const, fn or a function parameter), but not in other contexts such as declaring or accessing fields, including accessing decls as fields via a namespace prefix.

So, the following is expected:

const Foo = struct {
    const @"true": i32 = 0; // primitive
    const @"struct": i32 = 0; // keyword

    false: i32, // primitive
    @"union": i32, // keyword

    comptime {
        assert(@"true" == 0); // direct decl access
        assert(@"struct" == 0);
        assert(Foo.true == 0); // namespace field access
        assert(Foo.@"struct" == 0);

        const f: Foo = .{ .false = 0, .@"union" = 0 };
        assert(f.false == 0);
        assert(f.@"union" == 0);

        // enum literals also work like field accesses
        // basically, the rule of thumb is:
        // primitive after a dot . goes unquoted
        _ = .true;
        _ = .@"struct";
    }
};
1 Like

I’m surprised that bool isn’t a keyword.

Would you be more or less surprised if the example used usize, which behaves the same way, instead?

I think I would have expected primitives to Work more or less lke consts/decls hidden somewhere in the compiler.
But I guess being able to name a decl @"true" can be useful for auto generated code.