Commit 17f057c556

Andrew Kelley <andrew@ziglang.org>
2021-11-27 08:23:54
stage2: implement `@typeName`
* stage1: change the `@typeName` of `@TypeOf(undefined)`, `@TypeOf(null)`, and `@TypeOf(.foo)` to match stage2. * move passing behavior tests to the passing-for-stage2 section.
1 parent f0deef1
src/stage1/codegen.cpp
@@ -8755,17 +8755,17 @@ static void define_builtin_types(CodeGen *g) {
     }
     {
         ZigType *entry = new_type_table_entry(ZigTypeIdEnumLiteral);
-        buf_init_from_str(&entry->name, "(enum literal)");
+        buf_init_from_str(&entry->name, "@Type(.EnumLiteral)");
         g->builtin_types.entry_enum_literal = entry;
     }
     {
         ZigType *entry = new_type_table_entry(ZigTypeIdUndefined);
-        buf_init_from_str(&entry->name, "(undefined)");
+        buf_init_from_str(&entry->name, "@Type(.Undefined)");
         g->builtin_types.entry_undef = entry;
     }
     {
         ZigType *entry = new_type_table_entry(ZigTypeIdNull);
-        buf_init_from_str(&entry->name, "(null)");
+        buf_init_from_str(&entry->name, "@Type(.Null)");
         g->builtin_types.entry_null = entry;
     }
     {
src/Sema.zig
@@ -2771,20 +2771,16 @@ fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
     // expression of a variable declaration. We need the memory to be in the new
     // anonymous Decl's arena.
 
-    var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
-    errdefer new_decl_arena.deinit();
+    var anon_decl = try block.startAnonDecl();
+    defer anon_decl.deinit();
 
-    const bytes = try new_decl_arena.allocator.dupeZ(u8, zir_bytes);
+    const bytes = try anon_decl.arena().dupeZ(u8, zir_bytes);
 
-    const decl_ty = try Type.Tag.array_u8_sentinel_0.create(&new_decl_arena.allocator, bytes.len);
-    const decl_val = try Value.Tag.bytes.create(&new_decl_arena.allocator, bytes[0 .. bytes.len + 1]);
+    const new_decl = try anon_decl.finish(
+        try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
+        try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
+    );
 
-    const new_decl = try sema.mod.createAnonymousDecl(block, .{
-        .ty = decl_ty,
-        .val = decl_val,
-    });
-    errdefer sema.mod.abortAnonDecl(new_decl);
-    try new_decl.finalizeNewArena(&new_decl_arena);
     return sema.analyzeDeclRef(new_decl);
 }
 
@@ -9741,8 +9737,20 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
 
 fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
     const inst_data = sema.code.instructions.items(.data)[inst].un_node;
-    const src = inst_data.src();
-    return sema.fail(block, src, "TODO: Sema.zirTypeName", .{});
+    const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
+    const ty = try sema.resolveType(block, ty_src, inst_data.operand);
+
+    var anon_decl = try block.startAnonDecl();
+    defer anon_decl.deinit();
+
+    const bytes = try ty.nameAlloc(anon_decl.arena());
+
+    const new_decl = try anon_decl.finish(
+        try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
+        try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
+    );
+
+    return sema.analyzeDeclRef(new_decl);
 }
 
 fn zirFrameType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
src/type.zig
@@ -1197,6 +1197,113 @@ pub const Type = extern union {
         }
     }
 
+    /// Returns a name suitable for `@typeName`.
+    pub fn nameAlloc(ty: Type, arena: *Allocator) Allocator.Error![:0]const u8 {
+        const t = ty.tag();
+        switch (t) {
+            .inferred_alloc_const => unreachable,
+            .inferred_alloc_mut => unreachable,
+            .generic_poison => unreachable,
+
+            .u1,
+            .u8,
+            .i8,
+            .u16,
+            .i16,
+            .u32,
+            .i32,
+            .u64,
+            .i64,
+            .u128,
+            .i128,
+            .usize,
+            .isize,
+            .c_short,
+            .c_ushort,
+            .c_int,
+            .c_uint,
+            .c_long,
+            .c_ulong,
+            .c_longlong,
+            .c_ulonglong,
+            .c_longdouble,
+            .c_void,
+            .f16,
+            .f32,
+            .f64,
+            .f128,
+            .bool,
+            .void,
+            .type,
+            .anyerror,
+            .@"anyframe",
+            .comptime_int,
+            .comptime_float,
+            .noreturn,
+            .var_args_param,
+            .bound_fn,
+            => return @tagName(t),
+
+            .enum_literal => return "@Type(.EnumLiteral)",
+            .@"null" => return "@Type(.Null)",
+            .@"undefined" => return "@Type(.Undefined)",
+
+            .empty_struct, .empty_struct_literal => return "struct {}",
+
+            .@"struct" => {
+                const struct_obj = ty.castTag(.@"struct").?.data;
+                return try arena.dupeZ(u8, std.mem.sliceTo(struct_obj.owner_decl.name, 0));
+            },
+            .@"union", .union_tagged => {
+                const union_obj = ty.cast(Payload.Union).?.data;
+                return try arena.dupeZ(u8, std.mem.sliceTo(union_obj.owner_decl.name, 0));
+            },
+            .enum_full, .enum_nonexhaustive => {
+                const enum_full = ty.cast(Payload.EnumFull).?.data;
+                return try arena.dupeZ(u8, std.mem.sliceTo(enum_full.owner_decl.name, 0));
+            },
+            .enum_simple => {
+                const enum_simple = ty.castTag(.enum_simple).?.data;
+                return try arena.dupeZ(u8, std.mem.sliceTo(enum_simple.owner_decl.name, 0));
+            },
+            .enum_numbered => {
+                const enum_numbered = ty.castTag(.enum_numbered).?.data;
+                return try arena.dupeZ(u8, std.mem.sliceTo(enum_numbered.owner_decl.name, 0));
+            },
+            .@"opaque" => {
+                // TODO use declaration name
+                return "opaque {}";
+            },
+
+            .anyerror_void_error_union => return "anyerror!void",
+            .const_slice_u8 => return "[]const u8",
+            .fn_noreturn_no_args => return "fn() noreturn",
+            .fn_void_no_args => return "fn() void",
+            .fn_naked_noreturn_no_args => return "fn() callconv(.Naked) noreturn",
+            .fn_ccc_void_no_args => return "fn() callconv(.C) void",
+            .single_const_pointer_to_comptime_int => return "*const comptime_int",
+            .manyptr_u8 => return "[*]u8",
+            .manyptr_const_u8 => return "[*]const u8",
+            .atomic_order => return "AtomicOrder",
+            .atomic_rmw_op => return "AtomicRmwOp",
+            .calling_convention => return "CallingConvention",
+            .address_space => return "AddressSpace",
+            .float_mode => return "FloatMode",
+            .reduce_op => return "ReduceOp",
+            .call_options => return "CallOptions",
+            .export_options => return "ExportOptions",
+            .extern_options => return "ExternOptions",
+            .type_info => return "TypeInfo",
+
+            else => {
+                // TODO this is wasteful and also an incorrect implementation of `@typeName`
+                var buf = std.ArrayList(u8).init(arena);
+                try buf.writer().print("{}", .{ty});
+                return try buf.toOwnedSliceSentinel(0);
+            },
+        }
+    }
+
     /// Anything that reports hasCodeGenBits() false returns false here as well.
     /// `generic_poison` will return false.
     pub fn requiresComptime(ty: Type) bool {
test/behavior/enum.zig
@@ -583,3 +583,25 @@ test "peer type resolution with enum literal" {
     try expect(Items.two == .two);
     try expect(.two == Items.two);
 }
+
+const MultipleChoice = enum(u32) {
+    A = 20,
+    B = 40,
+    C = 60,
+    D = 1000,
+};
+
+fn testEnumWithSpecifiedTagValues(x: MultipleChoice) !void {
+    try expect(@enumToInt(x) == 60);
+    try expect(1234 == switch (x) {
+        MultipleChoice.A => 1,
+        MultipleChoice.B => 2,
+        MultipleChoice.C => @as(u32, 1234),
+        MultipleChoice.D => 4,
+    });
+}
+
+test "enum with specified tag values" {
+    try testEnumWithSpecifiedTagValues(MultipleChoice.C);
+    comptime try testEnumWithSpecifiedTagValues(MultipleChoice.C);
+}
test/behavior/enum_stage1.zig
@@ -2,28 +2,6 @@ const expect = @import("std").testing.expect;
 const mem = @import("std").mem;
 const Tag = @import("std").meta.Tag;
 
-const MultipleChoice = enum(u32) {
-    A = 20,
-    B = 40,
-    C = 60,
-    D = 1000,
-};
-
-fn testEnumWithSpecifiedTagValues(x: MultipleChoice) !void {
-    try expect(@enumToInt(x) == 60);
-    try expect(1234 == switch (x) {
-        MultipleChoice.A => 1,
-        MultipleChoice.B => 2,
-        MultipleChoice.C => @as(u32, 1234),
-        MultipleChoice.D => 4,
-    });
-}
-
-test "enum with specified tag values" {
-    try testEnumWithSpecifiedTagValues(MultipleChoice.C);
-    comptime try testEnumWithSpecifiedTagValues(MultipleChoice.C);
-}
-
 test "non-exhaustive enum" {
     const S = struct {
         const E = enum(u8) {
test/behavior/fn.zig
@@ -163,3 +163,84 @@ fn fComplexCallconvRet(x: u32) callconv(blk: {
 test "function with complex callconv and return type expressions" {
     try expect(fComplexCallconvRet(3).x == 9);
 }
+
+test "pass by non-copying value" {
+    try expect(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
+}
+
+const Point = struct {
+    x: i32,
+    y: i32,
+};
+
+fn addPointCoords(pt: Point) i32 {
+    return pt.x + pt.y;
+}
+
+test "pass by non-copying value through var arg" {
+    try expect((try addPointCoordsVar(Point{ .x = 1, .y = 2 })) == 3);
+}
+
+fn addPointCoordsVar(pt: anytype) !i32 {
+    comptime try expect(@TypeOf(pt) == Point);
+    return pt.x + pt.y;
+}
+
+test "pass by non-copying value as method" {
+    var pt = Point2{ .x = 1, .y = 2 };
+    try expect(pt.addPointCoords() == 3);
+}
+
+const Point2 = struct {
+    x: i32,
+    y: i32,
+
+    fn addPointCoords(self: Point2) i32 {
+        return self.x + self.y;
+    }
+};
+
+test "pass by non-copying value as method, which is generic" {
+    var pt = Point3{ .x = 1, .y = 2 };
+    try expect(pt.addPointCoords(i32) == 3);
+}
+
+const Point3 = struct {
+    x: i32,
+    y: i32,
+
+    fn addPointCoords(self: Point3, comptime T: type) i32 {
+        _ = T;
+        return self.x + self.y;
+    }
+};
+
+test "pass by non-copying value as method, at comptime" {
+    comptime {
+        var pt = Point2{ .x = 1, .y = 2 };
+        try expect(pt.addPointCoords() == 3);
+    }
+}
+
+test "implicit cast fn call result to optional in field result" {
+    const S = struct {
+        fn entry() !void {
+            var x = Foo{
+                .field = optionalPtr(),
+            };
+            try expect(x.field.?.* == 999);
+        }
+
+        const glob: i32 = 999;
+
+        fn optionalPtr() *const i32 {
+            return &glob;
+        }
+
+        const Foo = struct {
+            field: ?*const i32,
+        };
+    };
+    try S.entry();
+    comptime try S.entry();
+}
test/behavior/fn_stage1.zig
@@ -56,87 +56,6 @@ fn numberLiteralArg(a: anytype) !void {
     try expect(a == 3);
 }
 
-test "pass by non-copying value" {
-    try expect(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
-}
-
-const Point = struct {
-    x: i32,
-    y: i32,
-};
-
-fn addPointCoords(pt: Point) i32 {
-    return pt.x + pt.y;
-}
-
-test "pass by non-copying value through var arg" {
-    try expect((try addPointCoordsVar(Point{ .x = 1, .y = 2 })) == 3);
-}
-
-fn addPointCoordsVar(pt: anytype) !i32 {
-    comptime try expect(@TypeOf(pt) == Point);
-    return pt.x + pt.y;
-}
-
-test "pass by non-copying value as method" {
-    var pt = Point2{ .x = 1, .y = 2 };
-    try expect(pt.addPointCoords() == 3);
-}
-
-const Point2 = struct {
-    x: i32,
-    y: i32,
-
-    fn addPointCoords(self: Point2) i32 {
-        return self.x + self.y;
-    }
-};
-
-test "pass by non-copying value as method, which is generic" {
-    var pt = Point3{ .x = 1, .y = 2 };
-    try expect(pt.addPointCoords(i32) == 3);
-}
-
-const Point3 = struct {
-    x: i32,
-    y: i32,
-
-    fn addPointCoords(self: Point3, comptime T: type) i32 {
-        _ = T;
-        return self.x + self.y;
-    }
-};
-
-test "pass by non-copying value as method, at comptime" {
-    comptime {
-        var pt = Point2{ .x = 1, .y = 2 };
-        try expect(pt.addPointCoords() == 3);
-    }
-}
-
-test "implicit cast fn call result to optional in field result" {
-    const S = struct {
-        fn entry() !void {
-            var x = Foo{
-                .field = optionalPtr(),
-            };
-            try expect(x.field.?.* == 999);
-        }
-
-        const glob: i32 = 999;
-
-        fn optionalPtr() *const i32 {
-            return &glob;
-        }
-
-        const Foo = struct {
-            field: ?*const i32,
-        };
-    };
-    try S.entry();
-    comptime try S.entry();
-}
-
 test "function call with anon list literal" {
     const S = struct {
         fn doTheTest() !void {
test/behavior/for.zig
@@ -60,3 +60,59 @@ test "ignore lval with underscore (for loop)" {
         break;
     }
 }
+
+test "basic for loop" {
+    const expected_result = [_]u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3;
+
+    var buffer: [expected_result.len]u8 = undefined;
+    var buf_index: usize = 0;
+
+    const array = [_]u8{ 9, 8, 7, 6 };
+    for (array) |item| {
+        buffer[buf_index] = item;
+        buf_index += 1;
+    }
+    for (array) |item, index| {
+        _ = item;
+        buffer[buf_index] = @intCast(u8, index);
+        buf_index += 1;
+    }
+    const array_ptr = &array;
+    for (array_ptr) |item| {
+        buffer[buf_index] = item;
+        buf_index += 1;
+    }
+    for (array_ptr) |item, index| {
+        _ = item;
+        buffer[buf_index] = @intCast(u8, index);
+        buf_index += 1;
+    }
+    const unknown_size: []const u8 = &array;
+    for (unknown_size) |item| {
+        buffer[buf_index] = item;
+        buf_index += 1;
+    }
+    for (unknown_size) |_, index| {
+        buffer[buf_index] = @intCast(u8, index);
+        buf_index += 1;
+    }
+
+    try expect(mem.eql(u8, buffer[0..buf_index], &expected_result));
+}
+
+test "for with null and T peer types and inferred result location type" {
+    const S = struct {
+        fn doTheTest(slice: []const u8) !void {
+            if (for (slice) |item| {
+                if (item == 10) {
+                    break item;
+                }
+            } else null) |v| {
+                _ = v;
+                @panic("fail");
+            }
+        }
+    };
+    try S.doTheTest(&[_]u8{ 1, 2 });
+    comptime try S.doTheTest(&[_]u8{ 1, 2 });
+}
test/behavior/for_stage1.zig
@@ -26,45 +26,6 @@ fn mangleString(s: []u8) void {
     }
 }
 
-test "basic for loop" {
-    const expected_result = [_]u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3;
-
-    var buffer: [expected_result.len]u8 = undefined;
-    var buf_index: usize = 0;
-
-    const array = [_]u8{ 9, 8, 7, 6 };
-    for (array) |item| {
-        buffer[buf_index] = item;
-        buf_index += 1;
-    }
-    for (array) |item, index| {
-        _ = item;
-        buffer[buf_index] = @intCast(u8, index);
-        buf_index += 1;
-    }
-    const array_ptr = &array;
-    for (array_ptr) |item| {
-        buffer[buf_index] = item;
-        buf_index += 1;
-    }
-    for (array_ptr) |item, index| {
-        _ = item;
-        buffer[buf_index] = @intCast(u8, index);
-        buf_index += 1;
-    }
-    const unknown_size: []const u8 = &array;
-    for (unknown_size) |item| {
-        buffer[buf_index] = item;
-        buf_index += 1;
-    }
-    for (unknown_size) |_, index| {
-        buffer[buf_index] = @intCast(u8, index);
-        buf_index += 1;
-    }
-
-    try expect(mem.eql(u8, buffer[0..buf_index], &expected_result));
-}
-
 test "2 break statements and an else" {
     const S = struct {
         fn entry(t: bool, f: bool) !void {
@@ -82,23 +43,6 @@ test "2 break statements and an else" {
     comptime try S.entry(true, false);
 }
 
-test "for with null and T peer types and inferred result location type" {
-    const S = struct {
-        fn doTheTest(slice: []const u8) !void {
-            if (for (slice) |item| {
-                if (item == 10) {
-                    break item;
-                }
-            } else null) |v| {
-                _ = v;
-                @panic("fail");
-            }
-        }
-    };
-    try S.doTheTest(&[_]u8{ 1, 2 });
-    comptime try S.doTheTest(&[_]u8{ 1, 2 });
-}
-
 test "for copies its payload" {
     const S = struct {
         fn doTheTest() !void {
test/behavior/import.zig
@@ -3,7 +3,7 @@ const expectEqual = @import("std").testing.expectEqual;
 const a_namespace = @import("import/a_namespace.zig");
 
 test "call fn via namespace lookup" {
-    try expectEqual(@as(i32, 1234), a_namespace.foo());
+    try expect(@as(i32, 1234) == a_namespace.foo());
 }
 
 test "importing the same thing gives the same import" {
@@ -14,7 +14,7 @@ test "import in non-toplevel scope" {
     const S = struct {
         usingnamespace @import("import/a_namespace.zig");
     };
-    try expectEqual(@as(i32, 1234), S.foo());
+    try expect(@as(i32, 1234) == S.foo());
 }
 
 test "import empty file" {
test/behavior/null.zig
@@ -115,3 +115,28 @@ test "optional pointer to 0 bit type null value at runtime" {
     var x: ?*EmptyStruct = null;
     try expect(x == null);
 }
+
+test "if var maybe pointer" {
+    try expect(shouldBeAPlus1(Particle{
+        .a = 14,
+        .b = 1,
+        .c = 1,
+        .d = 1,
+    }) == 15);
+}
+fn shouldBeAPlus1(p: Particle) u64 {
+    var maybe_particle: ?Particle = p;
+    if (maybe_particle) |*particle| {
+        particle.a += 1;
+    }
+    if (maybe_particle) |particle| {
+        return particle.a;
+    }
+    return 0;
+}
+const Particle = struct {
+    a: u64,
+    b: u64,
+    c: u64,
+    d: u64,
+};
test/behavior/undefined.zig
@@ -65,5 +65,5 @@ test "assign undefined to struct with method" {
 
 test "type name of undefined" {
     const x = undefined;
-    try expect(mem.eql(u8, @typeName(@TypeOf(x)), "(undefined)"));
+    try expect(mem.eql(u8, @typeName(@TypeOf(x)), "@Type(.Undefined)"));
 }
test/behavior/while.zig
@@ -153,6 +153,20 @@ test "while with optional as condition with else" {
     try expect(got_else == 1);
 }
 
+test "while with error union condition" {
+    numbers_left = 10;
+    var sum: i32 = 0;
+    var got_else: i32 = 0;
+    while (getNumberOrErr()) |value| {
+        sum += value;
+    } else |err| {
+        try expect(err == error.OutOfNumbers);
+        got_else += 1;
+    }
+    try expect(sum == 45);
+    try expect(got_else == 1);
+}
+
 test "while on bool with else result follow else prong" {
     const result = while (returnFalse()) {
         break @as(i32, 10);
@@ -199,3 +213,26 @@ fn returnFalse() bool {
 fn returnTrue() bool {
     return true;
 }
+
+test "return with implicit cast from while loop" {
+    returnWithImplicitCastFromWhileLoopTest() catch unreachable;
+}
+fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {
+    while (true) {
+        return;
+    }
+}
+
+test "while on error union with else result follow else prong" {
+    const result = while (returnError()) |value| {
+        break value;
+    } else |_| @as(i32, 2);
+    try expect(result == 2);
+}
+
+test "while on error union with else result follow break prong" {
+    const result = while (returnSuccess(10)) |value| {
+        break value;
+    } else |_| @as(i32, 2);
+    try expect(result == 10);
+}
test/behavior/while_stage1.zig
@@ -1,76 +1,6 @@
 const std = @import("std");
 const expect = std.testing.expect;
 
-test "return with implicit cast from while loop" {
-    returnWithImplicitCastFromWhileLoopTest() catch unreachable;
-}
-fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {
-    while (true) {
-        return;
-    }
-}
-
-test "while with error union condition" {
-    numbers_left = 10;
-    var sum: i32 = 0;
-    var got_else: i32 = 0;
-    while (getNumberOrErr()) |value| {
-        sum += value;
-    } else |err| {
-        try expect(err == error.OutOfNumbers);
-        got_else += 1;
-    }
-    try expect(sum == 45);
-    try expect(got_else == 1);
-}
-
-var numbers_left: i32 = undefined;
-fn getNumberOrErr() anyerror!i32 {
-    return if (numbers_left == 0) error.OutOfNumbers else x: {
-        numbers_left -= 1;
-        break :x numbers_left;
-    };
-}
-fn getNumberOrNull() ?i32 {
-    return if (numbers_left == 0) null else x: {
-        numbers_left -= 1;
-        break :x numbers_left;
-    };
-}
-
-test "while on error union with else result follow else prong" {
-    const result = while (returnError()) |value| {
-        break value;
-    } else |_| @as(i32, 2);
-    try expect(result == 2);
-}
-
-test "while on error union with else result follow break prong" {
-    const result = while (returnSuccess(10)) |value| {
-        break value;
-    } else |_| @as(i32, 2);
-    try expect(result == 10);
-}
-
-fn returnNull() ?i32 {
-    return null;
-}
-fn returnOptional(x: i32) ?i32 {
-    return x;
-}
-fn returnError() anyerror!i32 {
-    return error.YouWantedAnError;
-}
-fn returnSuccess(x: i32) anyerror!i32 {
-    return x;
-}
-fn returnFalse() bool {
-    return false;
-}
-fn returnTrue() bool {
-    return true;
-}
-
 test "while bool 2 break statements and an else" {
     const S = struct {
         fn entry(t: bool, f: bool) !void {
test/behavior.zig
@@ -24,11 +24,11 @@ test {
     _ = @import("behavior/defer.zig");
     _ = @import("behavior/enum.zig");
     _ = @import("behavior/error.zig");
-    _ = @import("behavior/error.zig");
     _ = @import("behavior/generics.zig");
     _ = @import("behavior/hasdecl.zig");
     _ = @import("behavior/hasfield.zig");
     _ = @import("behavior/if.zig");
+    _ = @import("behavior/import.zig");
     _ = @import("behavior/int128.zig");
     _ = @import("behavior/member_func.zig");
     _ = @import("behavior/null.zig");
@@ -73,7 +73,9 @@ test {
         _ = @import("behavior/slice.zig");
         _ = @import("behavior/struct_llvm.zig");
         _ = @import("behavior/switch.zig");
+        _ = @import("behavior/undefined.zig");
         _ = @import("behavior/union.zig");
+        _ = @import("behavior/void.zig");
         _ = @import("behavior/widening.zig");
 
         if (builtin.zig_is_stage2) {
@@ -151,7 +153,6 @@ test {
             _ = @import("behavior/fn_in_struct_in_comptime.zig");
             _ = @import("behavior/for_stage1.zig");
             _ = @import("behavior/if_stage1.zig");
-            _ = @import("behavior/import.zig");
             _ = @import("behavior/incomplete_struct_param_tld.zig");
             _ = @import("behavior/inttoptr.zig");
             _ = @import("behavior/ir_block_deps.zig");
@@ -183,13 +184,11 @@ test {
             _ = @import("behavior/type.zig");
             _ = @import("behavior/type_info.zig");
             _ = @import("behavior/typename.zig");
-            _ = @import("behavior/undefined.zig");
             _ = @import("behavior/union_stage1.zig");
             _ = @import("behavior/union_with_members.zig");
             _ = @import("behavior/usingnamespace_stage1.zig");
             _ = @import("behavior/var_args.zig");
             _ = @import("behavior/vector.zig");
-            _ = @import("behavior/void.zig");
             if (builtin.target.cpu.arch == .wasm32) {
                 _ = @import("behavior/wasm.zig");
             }
test/compile_errors.zig
@@ -2674,7 +2674,7 @@ pub fn addCases(ctx: *TestContext) !void {
         \\    }
         \\}
     , &[_][]const u8{
-        "tmp.zig:3:9: error: expected type 'error{Hi}', found '(enum literal)'",
+        "tmp.zig:3:9: error: expected type 'error{Hi}', found '@Type(.EnumLiteral)'",
     });
 
     ctx.objErrStage1("@sizeOf bad type",
@@ -2682,7 +2682,7 @@ pub fn addCases(ctx: *TestContext) !void {
         \\    return @sizeOf(@TypeOf(null));
         \\}
     , &[_][]const u8{
-        "tmp.zig:2:20: error: no size available for type '(null)'",
+        "tmp.zig:2:20: error: no size available for type '@Type(.Null)'",
     });
 
     ctx.objErrStage1("generic function where return type is self-referenced",
@@ -5783,7 +5783,7 @@ pub fn addCases(ctx: *TestContext) !void {
         \\
         \\export fn entry() usize { return @sizeOf(@TypeOf(a)); }
     , &[_][]const u8{
-        "tmp.zig:1:16: error: expected type '*u8', found '(null)'",
+        "tmp.zig:1:16: error: expected type '*u8', found '@Type(.Null)'",
     });
 
     ctx.objErrStage1("indexing an array of size zero",
@@ -7506,12 +7506,12 @@ pub fn addCases(ctx: *TestContext) !void {
         \\};
     , &[_][]const u8{
         "tmp.zig:2:4: error: variable of type '*const comptime_int' must be const or comptime",
-        "tmp.zig:6:4: error: variable of type '(undefined)' must be const or comptime",
+        "tmp.zig:6:4: error: variable of type '@Type(.Undefined)' must be const or comptime",
         "tmp.zig:10:4: error: variable of type 'comptime_int' must be const or comptime",
         "tmp.zig:10:4: note: to modify this variable at runtime, it must be given an explicit fixed-size number type",
         "tmp.zig:14:4: error: variable of type 'comptime_float' must be const or comptime",
         "tmp.zig:14:4: note: to modify this variable at runtime, it must be given an explicit fixed-size number type",
-        "tmp.zig:18:4: error: variable of type '(null)' must be const or comptime",
+        "tmp.zig:18:4: error: variable of type '@Type(.Null)' must be const or comptime",
         "tmp.zig:22:4: error: variable of type 'Opaque' not allowed",
         "tmp.zig:26:4: error: variable of type 'type' must be const or comptime",
         "tmp.zig:30:4: error: variable of type '(bound fn(*const Foo) void)' must be const or comptime",
@@ -8278,8 +8278,8 @@ pub fn addCases(ctx: *TestContext) !void {
     , &[_][]const u8{
         "tmp.zig:2:18: error: Opaque return type 'FooType' not allowed",
         "tmp.zig:1:1: note: type declared here",
-        "tmp.zig:5:18: error: Null return type '(null)' not allowed",
-        "tmp.zig:8:18: error: Undefined return type '(undefined)' not allowed",
+        "tmp.zig:5:18: error: Null return type '@Type(.Null)' not allowed",
+        "tmp.zig:8:18: error: Undefined return type '@Type(.Undefined)' not allowed",
     });
 
     ctx.objErrStage1("generic function returning opaque type",
@@ -8300,9 +8300,9 @@ pub fn addCases(ctx: *TestContext) !void {
         "tmp.zig:6:16: error: call to generic function with Opaque return type 'FooType' not allowed",
         "tmp.zig:2:1: note: function declared here",
         "tmp.zig:1:1: note: type declared here",
-        "tmp.zig:9:16: error: call to generic function with Null return type '(null)' not allowed",
+        "tmp.zig:9:16: error: call to generic function with Null return type '@Type(.Null)' not allowed",
         "tmp.zig:2:1: note: function declared here",
-        "tmp.zig:12:16: error: call to generic function with Undefined return type '(undefined)' not allowed",
+        "tmp.zig:12:16: error: call to generic function with Undefined return type '@Type(.Undefined)' not allowed",
         "tmp.zig:2:1: note: function declared here",
     });
 
@@ -8329,9 +8329,9 @@ pub fn addCases(ctx: *TestContext) !void {
         \\}
     , &[_][]const u8{
         "tmp.zig:3:28: error: parameter of opaque type 'FooType' not allowed",
-        "tmp.zig:8:28: error: parameter of type '(null)' not allowed",
+        "tmp.zig:8:28: error: parameter of type '@Type(.Null)' not allowed",
         "tmp.zig:12:11: error: parameter of opaque type 'FooType' not allowed",
-        "tmp.zig:17:11: error: parameter of type '(null)' not allowed",
+        "tmp.zig:17:11: error: parameter of type '@Type(.Null)' not allowed",
     });
 
     ctx.objErrStage1( // fixed bug #2032