Commit be5130ec53

Andrew Kelley <andrew@ziglang.org>
2021-12-29 08:39:25
compiler_rt: move more functions to the stage2 section
also move more already-passing behavior tests to the passing section.
1 parent efb7148
lib/std/special/compiler_rt/truncXfYf2.zig
@@ -7,23 +7,23 @@ const native_arch = builtin.cpu.arch;
 pub const F16T = if (native_arch.isAARCH64()) f16 else u16;
 
 pub fn __truncsfhf2(a: f32) callconv(.C) F16T {
-    return @bitCast(F16T, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f32, a }));
+    return @bitCast(F16T, truncXfYf2(f16, f32, a));
 }
 
 pub fn __truncdfhf2(a: f64) callconv(.C) F16T {
-    return @bitCast(F16T, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f64, a }));
+    return @bitCast(F16T, truncXfYf2(f16, f64, a));
 }
 
 pub fn __trunctfhf2(a: f128) callconv(.C) F16T {
-    return @bitCast(F16T, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f128, a }));
+    return @bitCast(F16T, truncXfYf2(f16, f128, a));
 }
 
 pub fn __trunctfsf2(a: f128) callconv(.C) f32 {
-    return @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f32, f128, a });
+    return truncXfYf2(f32, f128, a);
 }
 
 pub fn __trunctfdf2(a: f128) callconv(.C) f64 {
-    return @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f64, f128, a });
+    return truncXfYf2(f64, f128, a);
 }
 
 pub fn __trunctfxf2(a: f128) callconv(.C) c_longdouble {
@@ -32,25 +32,25 @@ pub fn __trunctfxf2(a: f128) callconv(.C) c_longdouble {
 }
 
 pub fn __truncdfsf2(a: f64) callconv(.C) f32 {
-    return @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f32, f64, a });
+    return truncXfYf2(f32, f64, a);
 }
 
 pub fn __aeabi_d2f(a: f64) callconv(.AAPCS) f32 {
     @setRuntimeSafety(false);
-    return @call(.{ .modifier = .always_inline }, __truncdfsf2, .{a});
+    return truncXfYf2(f32, f64, a);
 }
 
 pub fn __aeabi_d2h(a: f64) callconv(.AAPCS) u16 {
     @setRuntimeSafety(false);
-    return @call(.{ .modifier = .always_inline }, __truncdfhf2, .{a});
+    return @bitCast(F16T, truncXfYf2(f16, f64, a));
 }
 
 pub fn __aeabi_f2h(a: f32) callconv(.AAPCS) u16 {
     @setRuntimeSafety(false);
-    return @call(.{ .modifier = .always_inline }, __truncsfhf2, .{a});
+    return @bitCast(F16T, truncXfYf2(f16, f32, a));
 }
 
-fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
+inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
     const src_rep_t = std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits);
     const dst_rep_t = std.meta.Int(.unsigned, @typeInfo(dst_t).Float.bits);
     const srcSigBits = std.math.floatMantissaBits(src_t);
lib/std/special/compiler_rt.zig
@@ -159,6 +159,18 @@ comptime {
         @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage });
     }
 
+    const __truncdfhf2 = @import("compiler_rt/truncXfYf2.zig").__truncdfhf2;
+    @export(__truncdfhf2, .{ .name = "__truncdfhf2", .linkage = linkage });
+    const __trunctfhf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfhf2;
+    @export(__trunctfhf2, .{ .name = "__trunctfhf2", .linkage = linkage });
+    const __trunctfdf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfdf2;
+    @export(__trunctfdf2, .{ .name = "__trunctfdf2", .linkage = linkage });
+    const __trunctfsf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfsf2;
+    @export(__trunctfsf2, .{ .name = "__trunctfsf2", .linkage = linkage });
+
+    const __truncdfsf2 = @import("compiler_rt/truncXfYf2.zig").__truncdfsf2;
+    @export(__truncdfsf2, .{ .name = "__truncdfsf2", .linkage = linkage });
+
     if (!builtin.zig_is_stage2) {
         if (!long_double_is_f128) {
             // TODO implement these
@@ -318,18 +330,6 @@ comptime {
         if (!is_test) {
             @export(__truncsfhf2, .{ .name = "__gnu_f2h_ieee", .linkage = linkage });
         }
-        const __truncdfhf2 = @import("compiler_rt/truncXfYf2.zig").__truncdfhf2;
-        @export(__truncdfhf2, .{ .name = "__truncdfhf2", .linkage = linkage });
-        const __trunctfhf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfhf2;
-        @export(__trunctfhf2, .{ .name = "__trunctfhf2", .linkage = linkage });
-        const __trunctfdf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfdf2;
-        @export(__trunctfdf2, .{ .name = "__trunctfdf2", .linkage = linkage });
-        const __trunctfsf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfsf2;
-        @export(__trunctfsf2, .{ .name = "__trunctfsf2", .linkage = linkage });
-
-        const __truncdfsf2 = @import("compiler_rt/truncXfYf2.zig").__truncdfsf2;
-        @export(__truncdfsf2, .{ .name = "__truncdfsf2", .linkage = linkage });
-
         const __extendsfdf2 = @import("compiler_rt/extendXfYf2.zig").__extendsfdf2;
         @export(__extendsfdf2, .{ .name = "__extendsfdf2", .linkage = linkage });
 
test/behavior/bugs/1322.zig
@@ -1,19 +0,0 @@
-const std = @import("std");
-
-const B = union(enum) {
-    c: C,
-    None,
-};
-
-const A = struct {
-    b: B,
-};
-
-const C = struct {};
-
-test "tagged union with all void fields but a meaningful tag" {
-    var a: A = A{ .b = B{ .c = C{} } };
-    try std.testing.expect(@as(std.meta.Tag(B), a.b) == std.meta.Tag(B).c);
-    a = A{ .b = B.None };
-    try std.testing.expect(@as(std.meta.Tag(B), a.b) == std.meta.Tag(B).None);
-}
test/behavior/align.zig
@@ -120,3 +120,18 @@ test "size of extern struct with 128-bit field" {
         }) == 32);
     }
 }
+
+test "@ptrCast preserves alignment of bigger source" {
+    var x: u32 align(16) = 1234;
+    const ptr = @ptrCast(*u8, &x);
+    try expect(@TypeOf(ptr) == *align(16) u8);
+}
+
+test "alignstack" {
+    try expect(fnWithAlignedStack() == 1234);
+}
+
+fn fnWithAlignedStack() i32 {
+    @setAlignStack(256);
+    return 1234;
+}
test/behavior/align_stage1.zig
@@ -20,25 +20,6 @@ test "function alignment" {
     noop4();
 }
 
-var baz: packed struct {
-    a: u32,
-    b: u32,
-} = undefined;
-
-test "packed struct alignment" {
-    try expect(@TypeOf(&baz.b) == *align(1) u32);
-}
-
-const blah: packed struct {
-    a: u3,
-    b: u3,
-    c: u2,
-} = undefined;
-
-test "bit field alignment" {
-    try expect(@TypeOf(&blah.b) == *align(1:3:1) const u3);
-}
-
 test "implicitly decreasing fn alignment" {
     // function alignment is a compile error on wasm32/wasm64
     if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
@@ -90,12 +71,6 @@ fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
     return 0x1;
 }
 
-test "@ptrCast preserves alignment of bigger source" {
-    var x: u32 align(16) = 1234;
-    const ptr = @ptrCast(*u8, &x);
-    try expect(@TypeOf(ptr) == *align(16) u8);
-}
-
 test "runtime known array index has best alignment possible" {
     // take full advantage of over-alignment
     var array align(4) = [_]u8{ 1, 2, 3, 4 };
@@ -134,15 +109,6 @@ fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) !void {
     comptime try expect(@TypeOf(&ptr[index]) == T);
 }
 
-test "alignstack" {
-    try expect(fnWithAlignedStack() == 1234);
-}
-
-fn fnWithAlignedStack() i32 {
-    @setAlignStack(256);
-    return 1234;
-}
-
 test "alignment of function with c calling convention" {
     var runtime_nothing = nothing;
     const casted1 = @ptrCast(*const u8, runtime_nothing);
test/behavior/cast_llvm.zig
@@ -197,3 +197,71 @@ test "cast between *[N]void and []void" {
     var b: []void = &a;
     try expect(b.len == 4);
 }
+
+test "peer resolve arrays of different size to const slice" {
+    try expect(mem.eql(u8, boolToStr(true), "true"));
+    try expect(mem.eql(u8, boolToStr(false), "false"));
+    comptime try expect(mem.eql(u8, boolToStr(true), "true"));
+    comptime try expect(mem.eql(u8, boolToStr(false), "false"));
+}
+fn boolToStr(b: bool) []const u8 {
+    return if (b) "true" else "false";
+}
+
+test "cast f16 to wider types" {
+    const S = struct {
+        fn doTheTest() !void {
+            var x: f16 = 1234.0;
+            try expect(@as(f32, 1234.0) == x);
+            try expect(@as(f64, 1234.0) == x);
+            try expect(@as(f128, 1234.0) == x);
+        }
+    };
+    try S.doTheTest();
+    comptime try S.doTheTest();
+}
+
+test "cast f128 to narrower types" {
+    const S = struct {
+        fn doTheTest() !void {
+            var x: f128 = 1234.0;
+            try expect(@as(f16, 1234.0) == @floatCast(f16, x));
+            try expect(@as(f32, 1234.0) == @floatCast(f32, x));
+            try expect(@as(f64, 1234.0) == @floatCast(f64, x));
+        }
+    };
+    try S.doTheTest();
+    comptime try S.doTheTest();
+}
+
+test "peer type resolution: unreachable, null, slice" {
+    const S = struct {
+        fn doTheTest(num: usize, word: []const u8) !void {
+            const result = switch (num) {
+                0 => null,
+                1 => word,
+                else => unreachable,
+            };
+            try expect(mem.eql(u8, result.?, "hi"));
+        }
+    };
+    try S.doTheTest(1, "hi");
+}
+
+test "cast i8 fn call peers to i32 result" {
+    const S = struct {
+        fn doTheTest() !void {
+            var cond = true;
+            const value: i32 = if (cond) smallBoi() else bigBoi();
+            try expect(value == 123);
+        }
+        fn smallBoi() i8 {
+            return 123;
+        }
+        fn bigBoi() i16 {
+            return 1234;
+        }
+    };
+    try S.doTheTest();
+    comptime try S.doTheTest();
+}
test/behavior/cast_stage1.zig
@@ -15,16 +15,6 @@ fn testCastIntToErr(err: anyerror) !void {
     try expect(error.ItBroke == y);
 }
 
-test "peer resolve arrays of different size to const slice" {
-    try expect(mem.eql(u8, boolToStr(true), "true"));
-    try expect(mem.eql(u8, boolToStr(false), "false"));
-    comptime try expect(mem.eql(u8, boolToStr(true), "true"));
-    comptime try expect(mem.eql(u8, boolToStr(false), "false"));
-}
-fn boolToStr(b: bool) []const u8 {
-    return if (b) "true" else "false";
-}
-
 test "peer resolve array and const slice" {
     try testPeerResolveArrayConstSlice(true);
     comptime try testPeerResolveArrayConstSlice(true);
@@ -174,32 +164,6 @@ test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
     try expect(mem.eql(u8, std.mem.sliceTo(@ptrCast([*:0]const u8, x[0].?), 0), "window name"));
 }
 
-test "cast f16 to wider types" {
-    const S = struct {
-        fn doTheTest() !void {
-            var x: f16 = 1234.0;
-            try std.testing.expectEqual(@as(f32, 1234.0), x);
-            try std.testing.expectEqual(@as(f64, 1234.0), x);
-            try std.testing.expectEqual(@as(f128, 1234.0), x);
-        }
-    };
-    try S.doTheTest();
-    comptime try S.doTheTest();
-}
-
-test "cast f128 to narrower types" {
-    const S = struct {
-        fn doTheTest() !void {
-            var x: f128 = 1234.0;
-            try std.testing.expectEqual(@as(f16, 1234.0), @floatCast(f16, x));
-            try std.testing.expectEqual(@as(f32, 1234.0), @floatCast(f32, x));
-            try std.testing.expectEqual(@as(f64, 1234.0), @floatCast(f64, x));
-        }
-    };
-    try S.doTheTest();
-    comptime try S.doTheTest();
-}
-
 test "vector casts" {
     const S = struct {
         fn doTheTest() !void {
@@ -250,20 +214,6 @@ test "@floatCast cast down" {
     }
 }
 
-test "peer type resolution: unreachable, null, slice" {
-    const S = struct {
-        fn doTheTest(num: usize, word: []const u8) !void {
-            const result = switch (num) {
-                0 => null,
-                1 => word,
-                else => unreachable,
-            };
-            try expect(mem.eql(u8, result.?, "hi"));
-        }
-    };
-    try S.doTheTest(1, "hi");
-}
-
 test "peer type resolution: unreachable, error set, unreachable" {
     const Error = error{
         FileDescriptorAlreadyPresentInSet,
@@ -374,24 +324,6 @@ test "type coercion related to sentinel-termination" {
     comptime try S.doTheTest();
 }
 
-test "cast i8 fn call peers to i32 result" {
-    const S = struct {
-        fn doTheTest() !void {
-            var cond = true;
-            const value: i32 = if (cond) smallBoi() else bigBoi();
-            try expect(value == 123);
-        }
-        fn smallBoi() i8 {
-            return 123;
-        }
-        fn bigBoi() i16 {
-            return 1234;
-        }
-    };
-    try S.doTheTest();
-    comptime try S.doTheTest();
-}
-
 test "peer type resolution implicit cast to return type" {
     const S = struct {
         fn doTheTest() !void {
test/behavior/defer.zig
@@ -2,3 +2,62 @@ const std = @import("std");
 const expect = std.testing.expect;
 const expectEqual = std.testing.expectEqual;
 const expectError = std.testing.expectError;
+
+test "break and continue inside loop inside defer expression" {
+    testBreakContInDefer(10);
+    comptime testBreakContInDefer(10);
+}
+
+fn testBreakContInDefer(x: usize) void {
+    defer {
+        var i: usize = 0;
+        while (i < x) : (i += 1) {
+            if (i < 5) continue;
+            if (i == 5) break;
+        }
+        expect(i == 5) catch @panic("test failure");
+    }
+}
+
+test "defer and labeled break" {
+    var i = @as(usize, 0);
+
+    blk: {
+        defer i += 1;
+        break :blk;
+    }
+
+    try expect(i == 1);
+}
+
+test "errdefer does not apply to fn inside fn" {
+    if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| try expect(e == error.Bad);
+}
+
+fn testNestedFnErrDefer() anyerror!void {
+    var a: i32 = 0;
+    errdefer a += 1;
+    const S = struct {
+        fn baz() anyerror {
+            return error.Bad;
+        }
+    };
+    return S.baz();
+}
+
+test "return variable while defer expression in scope to modify it" {
+    const S = struct {
+        fn doTheTest() !void {
+            try expect(notNull().? == 1);
+        }
+
+        fn notNull() ?u8 {
+            var res: ?u8 = 1;
+            defer res = null;
+            return res;
+        }
+    };
+
+    try S.doTheTest();
+    comptime try S.doTheTest();
+}
test/behavior/defer_stage1.zig
@@ -38,65 +38,6 @@ test "mixing normal and error defers" {
     try expect(result[2] == 'a');
 }
 
-test "break and continue inside loop inside defer expression" {
-    testBreakContInDefer(10);
-    comptime testBreakContInDefer(10);
-}
-
-fn testBreakContInDefer(x: usize) void {
-    defer {
-        var i: usize = 0;
-        while (i < x) : (i += 1) {
-            if (i < 5) continue;
-            if (i == 5) break;
-        }
-        expect(i == 5) catch @panic("test failure");
-    }
-}
-
-test "defer and labeled break" {
-    var i = @as(usize, 0);
-
-    blk: {
-        defer i += 1;
-        break :blk;
-    }
-
-    try expect(i == 1);
-}
-
-test "errdefer does not apply to fn inside fn" {
-    if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| try expect(e == error.Bad);
-}
-
-fn testNestedFnErrDefer() anyerror!void {
-    var a: i32 = 0;
-    errdefer a += 1;
-    const S = struct {
-        fn baz() anyerror {
-            return error.Bad;
-        }
-    };
-    return S.baz();
-}
-
-test "return variable while defer expression in scope to modify it" {
-    const S = struct {
-        fn doTheTest() !void {
-            try expect(notNull().? == 1);
-        }
-
-        fn notNull() ?u8 {
-            var res: ?u8 = 1;
-            defer res = null;
-            return res;
-        }
-    };
-
-    try S.doTheTest();
-    comptime try S.doTheTest();
-}
-
 test "errdefer with payload" {
     const S = struct {
         fn foo() !i32 {
test/behavior/eval.zig
@@ -467,3 +467,28 @@ test "comptime shlWithOverflow" {
 
     try expect(ct_shifted == rt_shifted);
 }
+
+test "const ptr to variable data changes at runtime" {
+    try expect(foo_ref.name[0] == 'a');
+    foo_ref.name = "b";
+    try expect(foo_ref.name[0] == 'b');
+}
+
+const Foo = struct {
+    name: []const u8,
+};
+
+var foo_contents = Foo{ .name = "a" };
+const foo_ref = &foo_contents;
+
+test "runtime 128 bit integer division" {
+    var a: u128 = 152313999999999991610955792383;
+    var b: u128 = 10000000000000000000;
+    var c = a / b;
+    try expect(c == 15231399999);
+}
+
+test "@tagName of @typeInfo" {
+    const str = @tagName(@typeInfo(u8));
+    try expect(std.mem.eql(u8, str, "Int"));
+}
test/behavior/eval_stage1.zig
@@ -86,19 +86,6 @@ fn testCompTimeUIntComparisons(x: u32) void {
     }
 }
 
-test "const ptr to variable data changes at runtime" {
-    try expect(foo_ref.name[0] == 'a');
-    foo_ref.name = "b";
-    try expect(foo_ref.name[0] == 'b');
-}
-
-const Foo = struct {
-    name: []const u8,
-};
-
-var foo_contents = Foo{ .name = "a" };
-const foo_ref = &foo_contents;
-
 const hi1 = "hi";
 const hi2 = hi1;
 test "const global shares pointer with other same one" {
@@ -162,13 +149,6 @@ test "const ptr to comptime mutable data is not memoized" {
     }
 }
 
-test "runtime 128 bit integer division" {
-    var a: u128 = 152313999999999991610955792383;
-    var b: u128 = 10000000000000000000;
-    var c = a / b;
-    try expect(c == 15231399999);
-}
-
 const Wrapper = struct {
     T: type,
 };
@@ -196,11 +176,6 @@ test "call method with comptime pass-by-non-copying-value self parameter" {
     try expect(b == 2);
 }
 
-test "@tagName of @typeInfo" {
-    const str = @tagName(@typeInfo(u8));
-    try expect(std.mem.eql(u8, str, "Int"));
-}
-
 test "setting backward branch quota just before a generic fn call" {
     @setEvalBranchQuota(1001);
     loopNTimes(1001);
test/behavior/struct.zig
@@ -199,3 +199,30 @@ test "struct field init with catch" {
     try S.doTheTest();
     comptime try S.doTheTest();
 }
+
+test "packed struct field alignment" {
+    const Stage1 = struct {
+        var baz: packed struct {
+            a: u32,
+            b: u32,
+        } = undefined;
+    };
+    const Stage2 = struct {
+        var baz: packed struct {
+            a: u32,
+            b: u32 align(1),
+        } = undefined;
+    };
+    const S = if (builtin.zig_is_stage2) Stage2 else Stage1;
+    try expect(@TypeOf(&S.baz.b) == *align(1) u32);
+}
+
+const blah: packed struct {
+    a: u3,
+    b: u3,
+    c: u2,
+} = undefined;
+
+test "bit field alignment" {
+    try expect(@TypeOf(&blah.b) == *align(1:3:1) const u3);
+}
test/behavior/type.zig
@@ -39,84 +39,6 @@ test "Type.Int" {
     try testTypes(&[_]type{ u8, u32, i64 });
 }
 
-test "Type.Float" {
-    try testing.expect(f16 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 16 } }));
-    try testing.expect(f32 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 32 } }));
-    try testing.expect(f64 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 64 } }));
-    try testing.expect(f128 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 128 } }));
-    try testTypes(&[_]type{ f16, f32, f64, f128 });
-}
-
-test "Type.Pointer" {
-    try testTypes(&[_]type{
-        // One Value Pointer Types
-        *u8,                               *const u8,
-        *volatile u8,                      *const volatile u8,
-        *align(4) u8,                      *align(4) const u8,
-        *align(4) volatile u8,             *align(4) const volatile u8,
-        *align(8) u8,                      *align(8) const u8,
-        *align(8) volatile u8,             *align(8) const volatile u8,
-        *allowzero u8,                     *allowzero const u8,
-        *allowzero volatile u8,            *allowzero const volatile u8,
-        *allowzero align(4) u8,            *allowzero align(4) const u8,
-        *allowzero align(4) volatile u8,   *allowzero align(4) const volatile u8,
-        // Many Values Pointer Types
-        [*]u8,                             [*]const u8,
-        [*]volatile u8,                    [*]const volatile u8,
-        [*]align(4) u8,                    [*]align(4) const u8,
-        [*]align(4) volatile u8,           [*]align(4) const volatile u8,
-        [*]align(8) u8,                    [*]align(8) const u8,
-        [*]align(8) volatile u8,           [*]align(8) const volatile u8,
-        [*]allowzero u8,                   [*]allowzero const u8,
-        [*]allowzero volatile u8,          [*]allowzero const volatile u8,
-        [*]allowzero align(4) u8,          [*]allowzero align(4) const u8,
-        [*]allowzero align(4) volatile u8, [*]allowzero align(4) const volatile u8,
-        // Slice Types
-        []u8,                              []const u8,
-        []volatile u8,                     []const volatile u8,
-        []align(4) u8,                     []align(4) const u8,
-        []align(4) volatile u8,            []align(4) const volatile u8,
-        []align(8) u8,                     []align(8) const u8,
-        []align(8) volatile u8,            []align(8) const volatile u8,
-        []allowzero u8,                    []allowzero const u8,
-        []allowzero volatile u8,           []allowzero const volatile u8,
-        []allowzero align(4) u8,           []allowzero align(4) const u8,
-        []allowzero align(4) volatile u8,  []allowzero align(4) const volatile u8,
-        // C Pointer Types
-        [*c]u8,                            [*c]const u8,
-        [*c]volatile u8,                   [*c]const volatile u8,
-        [*c]align(4) u8,                   [*c]align(4) const u8,
-        [*c]align(4) volatile u8,          [*c]align(4) const volatile u8,
-        [*c]align(8) u8,                   [*c]align(8) const u8,
-        [*c]align(8) volatile u8,          [*c]align(8) const volatile u8,
-    });
-}
-
-test "Type.Array" {
-    try testing.expect([123]u8 == @Type(TypeInfo{
-        .Array = TypeInfo.Array{
-            .len = 123,
-            .child = u8,
-            .sentinel = null,
-        },
-    }));
-    try testing.expect([2]u32 == @Type(TypeInfo{
-        .Array = TypeInfo.Array{
-            .len = 2,
-            .child = u32,
-            .sentinel = null,
-        },
-    }));
-    try testing.expect([2:0]u32 == @Type(TypeInfo{
-        .Array = TypeInfo.Array{
-            .len = 2,
-            .child = u32,
-            .sentinel = 0,
-        },
-    }));
-    try testTypes(&[_]type{ [1]u8, [30]usize, [7]bool });
-}
-
 test "Type.ComptimeFloat" {
     try testTypes(&[_]type{comptime_float});
 }
@@ -129,331 +51,9 @@ test "Type.Undefined" {
 test "Type.Null" {
     try testTypes(&[_]type{@TypeOf(null)});
 }
-test "@Type create slice with null sentinel" {
-    const Slice = @Type(TypeInfo{
-        .Pointer = .{
-            .size = .Slice,
-            .is_const = true,
-            .is_volatile = false,
-            .is_allowzero = false,
-            .alignment = 8,
-            .address_space = .generic,
-            .child = *i32,
-            .sentinel = null,
-        },
-    });
-    try testing.expect(Slice == []align(8) const *i32);
-}
-test "@Type picks up the sentinel value from TypeInfo" {
-    try testTypes(&[_]type{
-        [11:0]u8,                            [4:10]u8,
-        [*:0]u8,                             [*:0]const u8,
-        [*:0]volatile u8,                    [*:0]const volatile u8,
-        [*:0]align(4) u8,                    [*:0]align(4) const u8,
-        [*:0]align(4) volatile u8,           [*:0]align(4) const volatile u8,
-        [*:0]align(8) u8,                    [*:0]align(8) const u8,
-        [*:0]align(8) volatile u8,           [*:0]align(8) const volatile u8,
-        [*:0]allowzero u8,                   [*:0]allowzero const u8,
-        [*:0]allowzero volatile u8,          [*:0]allowzero const volatile u8,
-        [*:0]allowzero align(4) u8,          [*:0]allowzero align(4) const u8,
-        [*:0]allowzero align(4) volatile u8, [*:0]allowzero align(4) const volatile u8,
-        [*:5]allowzero align(4) volatile u8, [*:5]allowzero align(4) const volatile u8,
-        [:0]u8,                              [:0]const u8,
-        [:0]volatile u8,                     [:0]const volatile u8,
-        [:0]align(4) u8,                     [:0]align(4) const u8,
-        [:0]align(4) volatile u8,            [:0]align(4) const volatile u8,
-        [:0]align(8) u8,                     [:0]align(8) const u8,
-        [:0]align(8) volatile u8,            [:0]align(8) const volatile u8,
-        [:0]allowzero u8,                    [:0]allowzero const u8,
-        [:0]allowzero volatile u8,           [:0]allowzero const volatile u8,
-        [:0]allowzero align(4) u8,           [:0]allowzero align(4) const u8,
-        [:0]allowzero align(4) volatile u8,  [:0]allowzero align(4) const volatile u8,
-        [:4]allowzero align(4) volatile u8,  [:4]allowzero align(4) const volatile u8,
-    });
-}
-
-test "Type.Optional" {
-    try testTypes(&[_]type{
-        ?u8,
-        ?*u8,
-        ?[]u8,
-        ?[*]u8,
-        ?[*c]u8,
-    });
-}
-
-test "Type.ErrorUnion" {
-    try testTypes(&[_]type{
-        error{}!void,
-        error{Error}!void,
-    });
-}
-
-test "Type.Opaque" {
-    const Opaque = @Type(.{
-        .Opaque = .{
-            .decls = &[_]TypeInfo.Declaration{},
-        },
-    });
-    try testing.expect(Opaque != opaque {});
-    try testing.expectEqualSlices(
-        TypeInfo.Declaration,
-        &[_]TypeInfo.Declaration{},
-        @typeInfo(Opaque).Opaque.decls,
-    );
-}
-
-test "Type.Vector" {
-    try testTypes(&[_]type{
-        @Vector(0, u8),
-        @Vector(4, u8),
-        @Vector(8, *u8),
-        std.meta.Vector(0, u8),
-        std.meta.Vector(4, u8),
-        std.meta.Vector(8, *u8),
-    });
-}
-
-test "Type.AnyFrame" {
-    try testTypes(&[_]type{
-        anyframe,
-        anyframe->u8,
-        anyframe->anyframe->u8,
-    });
-}
 
 test "Type.EnumLiteral" {
     try testTypes(&[_]type{
         @TypeOf(.Dummy),
     });
 }
-
-fn add(a: i32, b: i32) i32 {
-    return a + b;
-}
-
-test "Type.Frame" {
-    try testTypes(&[_]type{
-        @Frame(add),
-    });
-}
-
-test "Type.ErrorSet" {
-    // error sets don't compare equal so just check if they compile
-    _ = @Type(@typeInfo(error{}));
-    _ = @Type(@typeInfo(error{A}));
-    _ = @Type(@typeInfo(error{ A, B, C }));
-}
-
-test "Type.Struct" {
-    const A = @Type(@typeInfo(struct { x: u8, y: u32 }));
-    const infoA = @typeInfo(A).Struct;
-    try testing.expectEqual(TypeInfo.ContainerLayout.Auto, infoA.layout);
-    try testing.expectEqualSlices(u8, "x", infoA.fields[0].name);
-    try testing.expectEqual(u8, infoA.fields[0].field_type);
-    try testing.expectEqual(@as(?u8, null), infoA.fields[0].default_value);
-    try testing.expectEqualSlices(u8, "y", infoA.fields[1].name);
-    try testing.expectEqual(u32, infoA.fields[1].field_type);
-    try testing.expectEqual(@as(?u32, null), infoA.fields[1].default_value);
-    try testing.expectEqualSlices(TypeInfo.Declaration, &[_]TypeInfo.Declaration{}, infoA.decls);
-    try testing.expectEqual(@as(bool, false), infoA.is_tuple);
-
-    var a = A{ .x = 0, .y = 1 };
-    try testing.expectEqual(@as(u8, 0), a.x);
-    try testing.expectEqual(@as(u32, 1), a.y);
-    a.y += 1;
-    try testing.expectEqual(@as(u32, 2), a.y);
-
-    const B = @Type(@typeInfo(extern struct { x: u8, y: u32 = 5 }));
-    const infoB = @typeInfo(B).Struct;
-    try testing.expectEqual(TypeInfo.ContainerLayout.Extern, infoB.layout);
-    try testing.expectEqualSlices(u8, "x", infoB.fields[0].name);
-    try testing.expectEqual(u8, infoB.fields[0].field_type);
-    try testing.expectEqual(@as(?u8, null), infoB.fields[0].default_value);
-    try testing.expectEqualSlices(u8, "y", infoB.fields[1].name);
-    try testing.expectEqual(u32, infoB.fields[1].field_type);
-    try testing.expectEqual(@as(?u32, 5), infoB.fields[1].default_value);
-    try testing.expectEqual(@as(usize, 0), infoB.decls.len);
-    try testing.expectEqual(@as(bool, false), infoB.is_tuple);
-
-    const C = @Type(@typeInfo(packed struct { x: u8 = 3, y: u32 = 5 }));
-    const infoC = @typeInfo(C).Struct;
-    try testing.expectEqual(TypeInfo.ContainerLayout.Packed, infoC.layout);
-    try testing.expectEqualSlices(u8, "x", infoC.fields[0].name);
-    try testing.expectEqual(u8, infoC.fields[0].field_type);
-    try testing.expectEqual(@as(?u8, 3), infoC.fields[0].default_value);
-    try testing.expectEqualSlices(u8, "y", infoC.fields[1].name);
-    try testing.expectEqual(u32, infoC.fields[1].field_type);
-    try testing.expectEqual(@as(?u32, 5), infoC.fields[1].default_value);
-    try testing.expectEqual(@as(usize, 0), infoC.decls.len);
-    try testing.expectEqual(@as(bool, false), infoC.is_tuple);
-}
-
-test "Type.Enum" {
-    const Foo = @Type(.{
-        .Enum = .{
-            .layout = .Auto,
-            .tag_type = u8,
-            .fields = &[_]TypeInfo.EnumField{
-                .{ .name = "a", .value = 1 },
-                .{ .name = "b", .value = 5 },
-            },
-            .decls = &[_]TypeInfo.Declaration{},
-            .is_exhaustive = true,
-        },
-    });
-    try testing.expectEqual(true, @typeInfo(Foo).Enum.is_exhaustive);
-    try testing.expectEqual(@as(u8, 1), @enumToInt(Foo.a));
-    try testing.expectEqual(@as(u8, 5), @enumToInt(Foo.b));
-    const Bar = @Type(.{
-        .Enum = .{
-            .layout = .Extern,
-            .tag_type = u32,
-            .fields = &[_]TypeInfo.EnumField{
-                .{ .name = "a", .value = 1 },
-                .{ .name = "b", .value = 5 },
-            },
-            .decls = &[_]TypeInfo.Declaration{},
-            .is_exhaustive = false,
-        },
-    });
-    try testing.expectEqual(false, @typeInfo(Bar).Enum.is_exhaustive);
-    try testing.expectEqual(@as(u32, 1), @enumToInt(Bar.a));
-    try testing.expectEqual(@as(u32, 5), @enumToInt(Bar.b));
-    try testing.expectEqual(@as(u32, 6), @enumToInt(@intToEnum(Bar, 6)));
-}
-
-test "Type.Union" {
-    const Untagged = @Type(.{
-        .Union = .{
-            .layout = .Auto,
-            .tag_type = null,
-            .fields = &[_]TypeInfo.UnionField{
-                .{ .name = "int", .field_type = i32, .alignment = @alignOf(f32) },
-                .{ .name = "float", .field_type = f32, .alignment = @alignOf(f32) },
-            },
-            .decls = &[_]TypeInfo.Declaration{},
-        },
-    });
-    var untagged = Untagged{ .int = 1 };
-    untagged.float = 2.0;
-    untagged.int = 3;
-    try testing.expectEqual(@as(i32, 3), untagged.int);
-
-    const PackedUntagged = @Type(.{
-        .Union = .{
-            .layout = .Packed,
-            .tag_type = null,
-            .fields = &[_]TypeInfo.UnionField{
-                .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
-                .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
-            },
-            .decls = &[_]TypeInfo.Declaration{},
-        },
-    });
-    var packed_untagged = PackedUntagged{ .signed = -1 };
-    try testing.expectEqual(@as(i32, -1), packed_untagged.signed);
-    try testing.expectEqual(~@as(u32, 0), packed_untagged.unsigned);
-
-    const Tag = @Type(.{
-        .Enum = .{
-            .layout = .Auto,
-            .tag_type = u1,
-            .fields = &[_]TypeInfo.EnumField{
-                .{ .name = "signed", .value = 0 },
-                .{ .name = "unsigned", .value = 1 },
-            },
-            .decls = &[_]TypeInfo.Declaration{},
-            .is_exhaustive = true,
-        },
-    });
-    const Tagged = @Type(.{
-        .Union = .{
-            .layout = .Auto,
-            .tag_type = Tag,
-            .fields = &[_]TypeInfo.UnionField{
-                .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
-                .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
-            },
-            .decls = &[_]TypeInfo.Declaration{},
-        },
-    });
-    var tagged = Tagged{ .signed = -1 };
-    try testing.expectEqual(Tag.signed, tagged);
-    tagged = .{ .unsigned = 1 };
-    try testing.expectEqual(Tag.unsigned, tagged);
-}
-
-test "Type.Union from Type.Enum" {
-    const Tag = @Type(.{
-        .Enum = .{
-            .layout = .Auto,
-            .tag_type = u0,
-            .fields = &[_]TypeInfo.EnumField{
-                .{ .name = "working_as_expected", .value = 0 },
-            },
-            .decls = &[_]TypeInfo.Declaration{},
-            .is_exhaustive = true,
-        },
-    });
-    const T = @Type(.{
-        .Union = .{
-            .layout = .Auto,
-            .tag_type = Tag,
-            .fields = &[_]TypeInfo.UnionField{
-                .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
-            },
-            .decls = &[_]TypeInfo.Declaration{},
-        },
-    });
-    _ = T;
-    _ = @typeInfo(T).Union;
-}
-
-test "Type.Union from regular enum" {
-    const E = enum { working_as_expected };
-    const T = @Type(.{
-        .Union = .{
-            .layout = .Auto,
-            .tag_type = E,
-            .fields = &[_]TypeInfo.UnionField{
-                .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
-            },
-            .decls = &[_]TypeInfo.Declaration{},
-        },
-    });
-    _ = T;
-    _ = @typeInfo(T).Union;
-}
-
-test "Type.Fn" {
-    // wasm doesn't support align attributes on functions
-    if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
-
-    const foo = struct {
-        fn func(a: usize, b: bool) align(4) callconv(.C) usize {
-            _ = a;
-            _ = b;
-            return 0;
-        }
-    }.func;
-    const Foo = @Type(@typeInfo(@TypeOf(foo)));
-    const foo_2: Foo = foo;
-    _ = foo_2;
-}
-
-test "Type.BoundFn" {
-    // wasm doesn't support align attributes on functions
-    if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
-
-    const TestStruct = packed struct {
-        pub fn foo(self: *const @This()) align(4) callconv(.Unspecified) void {
-            _ = self;
-        }
-    };
-    const test_instance: TestStruct = undefined;
-    try testing.expect(std.meta.eql(
-        @typeName(@TypeOf(test_instance.foo)),
-        @typeName(@Type(@typeInfo(@TypeOf(test_instance.foo)))),
-    ));
-}
test/behavior/type_info.zig
@@ -8,18 +8,6 @@ const TypeId = std.builtin.TypeId;
 const expect = std.testing.expect;
 const expectEqualStrings = std.testing.expectEqualStrings;
 
-test "type info: tag type, void info" {
-    try testBasic();
-    comptime try testBasic();
-}
-
-fn testBasic() !void {
-    try expect(@typeInfo(TypeInfo).Union.tag_type == TypeId);
-    const void_info = @typeInfo(void);
-    try expect(void_info == TypeId.Void);
-    try expect(void_info.Void == {});
-}
-
 test "type info: integer, floating point type info" {
     try testIntFloat();
     comptime try testIntFloat();
@@ -36,107 +24,6 @@ fn testIntFloat() !void {
     try expect(f64_info.Float.bits == 64);
 }
 
-test "type info: pointer type info" {
-    try testPointer();
-    comptime try testPointer();
-}
-
-fn testPointer() !void {
-    const u32_ptr_info = @typeInfo(*u32);
-    try expect(u32_ptr_info == .Pointer);
-    try expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One);
-    try expect(u32_ptr_info.Pointer.is_const == false);
-    try expect(u32_ptr_info.Pointer.is_volatile == false);
-    try expect(u32_ptr_info.Pointer.alignment == @alignOf(u32));
-    try expect(u32_ptr_info.Pointer.child == u32);
-    try expect(u32_ptr_info.Pointer.sentinel == null);
-}
-
-test "type info: unknown length pointer type info" {
-    try testUnknownLenPtr();
-    comptime try testUnknownLenPtr();
-}
-
-fn testUnknownLenPtr() !void {
-    const u32_ptr_info = @typeInfo([*]const volatile f64);
-    try expect(u32_ptr_info == .Pointer);
-    try expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
-    try expect(u32_ptr_info.Pointer.is_const == true);
-    try expect(u32_ptr_info.Pointer.is_volatile == true);
-    try expect(u32_ptr_info.Pointer.sentinel == null);
-    try expect(u32_ptr_info.Pointer.alignment == @alignOf(f64));
-    try expect(u32_ptr_info.Pointer.child == f64);
-}
-
-test "type info: null terminated pointer type info" {
-    try testNullTerminatedPtr();
-    comptime try testNullTerminatedPtr();
-}
-
-fn testNullTerminatedPtr() !void {
-    const ptr_info = @typeInfo([*:0]u8);
-    try expect(ptr_info == .Pointer);
-    try expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
-    try expect(ptr_info.Pointer.is_const == false);
-    try expect(ptr_info.Pointer.is_volatile == false);
-    try expect(ptr_info.Pointer.sentinel.? == 0);
-
-    try expect(@typeInfo([:0]u8).Pointer.sentinel != null);
-}
-
-test "type info: C pointer type info" {
-    try testCPtr();
-    comptime try testCPtr();
-}
-
-fn testCPtr() !void {
-    const ptr_info = @typeInfo([*c]align(4) const i8);
-    try expect(ptr_info == .Pointer);
-    try expect(ptr_info.Pointer.size == .C);
-    try expect(ptr_info.Pointer.is_const);
-    try expect(!ptr_info.Pointer.is_volatile);
-    try expect(ptr_info.Pointer.alignment == 4);
-    try expect(ptr_info.Pointer.child == i8);
-}
-
-test "type info: slice type info" {
-    try testSlice();
-    comptime try testSlice();
-}
-
-fn testSlice() !void {
-    const u32_slice_info = @typeInfo([]u32);
-    try expect(u32_slice_info == .Pointer);
-    try expect(u32_slice_info.Pointer.size == .Slice);
-    try expect(u32_slice_info.Pointer.is_const == false);
-    try expect(u32_slice_info.Pointer.is_volatile == false);
-    try expect(u32_slice_info.Pointer.alignment == 4);
-    try expect(u32_slice_info.Pointer.child == u32);
-}
-
-test "type info: array type info" {
-    try testArray();
-    comptime try testArray();
-}
-
-fn testArray() !void {
-    {
-        const info = @typeInfo([42]u8);
-        try expect(info == .Array);
-        try expect(info.Array.len == 42);
-        try expect(info.Array.child == u8);
-        try expect(info.Array.sentinel == null);
-    }
-
-    {
-        const info = @typeInfo([10:0]u8);
-        try expect(info.Array.len == 10);
-        try expect(info.Array.child == u8);
-        try expect(info.Array.sentinel.? == @as(u8, 0));
-        try expect(@sizeOf([10:0]u8) == info.Array.len + 1);
-    }
-}
-
 test "type info: optional type info" {
     try testOptional();
     comptime try testOptional();
@@ -147,344 +34,3 @@ fn testOptional() !void {
     try expect(null_info == .Optional);
     try expect(null_info.Optional.child == void);
 }
-
-test "type info: error set, error union info" {
-    try testErrorSet();
-    comptime try testErrorSet();
-}
-
-fn testErrorSet() !void {
-    const TestErrorSet = error{
-        First,
-        Second,
-        Third,
-    };
-
-    const error_set_info = @typeInfo(TestErrorSet);
-    try expect(error_set_info == .ErrorSet);
-    try expect(error_set_info.ErrorSet.?.len == 3);
-    try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "First"));
-
-    const error_union_info = @typeInfo(TestErrorSet!usize);
-    try expect(error_union_info == .ErrorUnion);
-    try expect(error_union_info.ErrorUnion.error_set == TestErrorSet);
-    try expect(error_union_info.ErrorUnion.payload == usize);
-
-    const global_info = @typeInfo(anyerror);
-    try expect(global_info == .ErrorSet);
-    try expect(global_info.ErrorSet == null);
-}
-
-test "type info: enum info" {
-    try testEnum();
-    comptime try testEnum();
-}
-
-fn testEnum() !void {
-    const Os = enum {
-        Windows,
-        Macos,
-        Linux,
-        FreeBSD,
-    };
-
-    const os_info = @typeInfo(Os);
-    try expect(os_info == .Enum);
-    try expect(os_info.Enum.layout == .Auto);
-    try expect(os_info.Enum.fields.len == 4);
-    try expect(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
-    try expect(os_info.Enum.fields[3].value == 3);
-    try expect(os_info.Enum.tag_type == u2);
-    try expect(os_info.Enum.decls.len == 0);
-}
-
-test "type info: union info" {
-    try testUnion();
-    comptime try testUnion();
-}
-
-fn testUnion() !void {
-    const typeinfo_info = @typeInfo(TypeInfo);
-    try expect(typeinfo_info == .Union);
-    try expect(typeinfo_info.Union.layout == .Auto);
-    try expect(typeinfo_info.Union.tag_type.? == TypeId);
-    try expect(typeinfo_info.Union.fields.len == 25);
-    try expect(typeinfo_info.Union.fields[4].field_type == @TypeOf(@typeInfo(u8).Int));
-    try expect(typeinfo_info.Union.decls.len == 22);
-
-    const TestNoTagUnion = union {
-        Foo: void,
-        Bar: u32,
-    };
-
-    const notag_union_info = @typeInfo(TestNoTagUnion);
-    try expect(notag_union_info == .Union);
-    try expect(notag_union_info.Union.tag_type == null);
-    try expect(notag_union_info.Union.layout == .Auto);
-    try expect(notag_union_info.Union.fields.len == 2);
-    try expect(notag_union_info.Union.fields[0].alignment == @alignOf(void));
-    try expect(notag_union_info.Union.fields[1].field_type == u32);
-    try expect(notag_union_info.Union.fields[1].alignment == @alignOf(u32));
-
-    const TestExternUnion = extern union {
-        foo: *anyopaque,
-    };
-
-    const extern_union_info = @typeInfo(TestExternUnion);
-    try expect(extern_union_info.Union.layout == .Extern);
-    try expect(extern_union_info.Union.tag_type == null);
-    try expect(extern_union_info.Union.fields[0].field_type == *anyopaque);
-}
-
-test "type info: struct info" {
-    try testStruct();
-    comptime try testStruct();
-}
-
-fn testStruct() !void {
-    const unpacked_struct_info = @typeInfo(TestUnpackedStruct);
-    try expect(unpacked_struct_info.Struct.is_tuple == false);
-    try expect(unpacked_struct_info.Struct.fields[0].alignment == @alignOf(u32));
-    try expect(unpacked_struct_info.Struct.fields[0].default_value.? == 4);
-    try expectEqualStrings("foobar", unpacked_struct_info.Struct.fields[1].default_value.?);
-
-    const struct_info = @typeInfo(TestStruct);
-    try expect(struct_info == .Struct);
-    try expect(struct_info.Struct.is_tuple == false);
-    try expect(struct_info.Struct.layout == .Packed);
-    try expect(struct_info.Struct.fields.len == 4);
-    try expect(struct_info.Struct.fields[0].alignment == 2 * @alignOf(usize));
-    try expect(struct_info.Struct.fields[2].field_type == *TestStruct);
-    try expect(struct_info.Struct.fields[2].default_value == null);
-    try expect(struct_info.Struct.fields[3].default_value.? == 4);
-    try expect(struct_info.Struct.fields[3].alignment == 1);
-    try expect(struct_info.Struct.decls.len == 2);
-    try expect(struct_info.Struct.decls[0].is_pub);
-    try expect(!struct_info.Struct.decls[0].data.Fn.is_extern);
-    try expect(struct_info.Struct.decls[0].data.Fn.lib_name == null);
-    try expect(struct_info.Struct.decls[0].data.Fn.return_type == void);
-    try expect(struct_info.Struct.decls[0].data.Fn.fn_type == fn (*const TestStruct) void);
-}
-
-const TestUnpackedStruct = struct {
-    fieldA: u32 = 4,
-    fieldB: *const [6:0]u8 = "foobar",
-};
-
-const TestStruct = packed struct {
-    fieldA: usize align(2 * @alignOf(usize)),
-    fieldB: void,
-    fieldC: *Self,
-    fieldD: u32 = 4,
-
-    pub fn foo(self: *const Self) void {
-        _ = self;
-    }
-    const Self = @This();
-};
-
-test "type info: opaque info" {
-    try testOpaque();
-    comptime try testOpaque();
-}
-
-fn testOpaque() !void {
-    const Foo = opaque {
-        const A = 1;
-        fn b() void {}
-    };
-
-    const foo_info = @typeInfo(Foo);
-    try expect(foo_info.Opaque.decls.len == 2);
-}
-
-test "type info: function type info" {
-    // wasm doesn't support align attributes on functions
-    if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
-    try testFunction();
-    comptime try testFunction();
-}
-
-fn testFunction() !void {
-    const fn_info = @typeInfo(@TypeOf(foo));
-    try expect(fn_info == .Fn);
-    try expect(fn_info.Fn.alignment > 0);
-    try expect(fn_info.Fn.calling_convention == .C);
-    try expect(!fn_info.Fn.is_generic);
-    try expect(fn_info.Fn.args.len == 2);
-    try expect(fn_info.Fn.is_var_args);
-    try expect(fn_info.Fn.return_type.? == usize);
-    const fn_aligned_info = @typeInfo(@TypeOf(fooAligned));
-    try expect(fn_aligned_info.Fn.alignment == 4);
-
-    const test_instance: TestStruct = undefined;
-    const bound_fn_info = @typeInfo(@TypeOf(test_instance.foo));
-    try expect(bound_fn_info == .BoundFn);
-    try expect(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
-}
-
-extern fn foo(a: usize, b: bool, ...) callconv(.C) usize;
-extern fn fooAligned(a: usize, b: bool, ...) align(4) callconv(.C) usize;
-
-test "typeInfo with comptime parameter in struct fn def" {
-    const S = struct {
-        pub fn func(comptime x: f32) void {
-            _ = x;
-        }
-    };
-    comptime var info = @typeInfo(S);
-    _ = info;
-}
-
-test "type info: vectors" {
-    try testVector();
-    comptime try testVector();
-}
-
-fn testVector() !void {
-    const vec_info = @typeInfo(std.meta.Vector(4, i32));
-    try expect(vec_info == .Vector);
-    try expect(vec_info.Vector.len == 4);
-    try expect(vec_info.Vector.child == i32);
-}
-
-test "type info: anyframe and anyframe->T" {
-    try testAnyFrame();
-    comptime try testAnyFrame();
-}
-
-fn testAnyFrame() !void {
-    {
-        const anyframe_info = @typeInfo(anyframe->i32);
-        try expect(anyframe_info == .AnyFrame);
-        try expect(anyframe_info.AnyFrame.child.? == i32);
-    }
-
-    {
-        const anyframe_info = @typeInfo(anyframe);
-        try expect(anyframe_info == .AnyFrame);
-        try expect(anyframe_info.AnyFrame.child == null);
-    }
-}
-
-test "type info: pass to function" {
-    _ = passTypeInfo(@typeInfo(void));
-    _ = comptime passTypeInfo(@typeInfo(void));
-}
-
-fn passTypeInfo(comptime info: TypeInfo) type {
-    _ = info;
-    return void;
-}
-
-test "type info: TypeId -> TypeInfo impl cast" {
-    _ = passTypeInfo(TypeId.Void);
-    _ = comptime passTypeInfo(TypeId.Void);
-}
-
-test "type info: extern fns with and without lib names" {
-    const S = struct {
-        extern fn bar1() void;
-        extern "cool" fn bar2() void;
-    };
-    const info = @typeInfo(S);
-    comptime {
-        for (info.Struct.decls) |decl| {
-            if (std.mem.eql(u8, decl.name, "bar1")) {
-                try expect(decl.data.Fn.lib_name == null);
-            } else {
-                try expectEqualStrings("cool", decl.data.Fn.lib_name.?);
-            }
-        }
-    }
-}
-
-test "data field is a compile-time value" {
-    const S = struct {
-        const Bar = @as(isize, -1);
-    };
-    comptime try expect(@typeInfo(S).Struct.decls[0].data.Var == isize);
-}
-
-test "sentinel of opaque pointer type" {
-    const c_void_info = @typeInfo(*anyopaque);
-    try expect(c_void_info.Pointer.sentinel == null);
-}
-
-test "@typeInfo does not force declarations into existence" {
-    const S = struct {
-        x: i32,
-
-        fn doNotReferenceMe() void {
-            @compileError("test failed");
-        }
-    };
-    comptime try expect(@typeInfo(S).Struct.fields.len == 1);
-}
-
-test "defaut value for a var-typed field" {
-    const S = struct { x: anytype };
-    try expect(@typeInfo(S).Struct.fields[0].default_value == null);
-}
-
-fn add(a: i32, b: i32) i32 {
-    return a + b;
-}
-
-test "type info for async frames" {
-    switch (@typeInfo(@Frame(add))) {
-        .Frame => |frame| {
-            try expect(frame.function == add);
-        },
-        else => unreachable,
-    }
-}
-
-test "type info: value is correctly copied" {
-    comptime {
-        var ptrInfo = @typeInfo([]u32);
-        ptrInfo.Pointer.size = .One;
-        try expect(@typeInfo([]u32).Pointer.size == .Slice);
-    }
-}
-
-test "Declarations are returned in declaration order" {
-    const S = struct {
-        const a = 1;
-        const b = 2;
-        const c = 3;
-        const d = 4;
-        const e = 5;
-    };
-    const d = @typeInfo(S).Struct.decls;
-    try expect(std.mem.eql(u8, d[0].name, "a"));
-    try expect(std.mem.eql(u8, d[1].name, "b"));
-    try expect(std.mem.eql(u8, d[2].name, "c"));
-    try expect(std.mem.eql(u8, d[3].name, "d"));
-    try expect(std.mem.eql(u8, d[4].name, "e"));
-}
-
-test "Struct.is_tuple" {
-    try expect(@typeInfo(@TypeOf(.{0})).Struct.is_tuple);
-    try expect(!@typeInfo(@TypeOf(.{ .a = 0 })).Struct.is_tuple);
-}
-
-test "StructField.is_comptime" {
-    const info = @typeInfo(struct { x: u8 = 3, comptime y: u32 = 5 }).Struct;
-    try expect(!info.fields[0].is_comptime);
-    try expect(info.fields[1].is_comptime);
-}
-
-test "typeInfo resolves usingnamespace declarations" {
-    const A = struct {
-        pub const f1 = 42;
-    };
-
-    const B = struct {
-        const f0 = 42;
-        usingnamespace A;
-    };
-
-    try expect(@typeInfo(B).Struct.decls.len == 2);
-    //a
-}
test/behavior/type_info_stage1.zig
@@ -0,0 +1,463 @@
+const std = @import("std");
+const builtin = @import("builtin");
+const mem = std.mem;
+
+const TypeInfo = std.builtin.TypeInfo;
+const TypeId = std.builtin.TypeId;
+
+const expect = std.testing.expect;
+const expectEqualStrings = std.testing.expectEqualStrings;
+
+test "type info: tag type, void info" {
+    try testBasic();
+    comptime try testBasic();
+}
+
+fn testBasic() !void {
+    try expect(@typeInfo(TypeInfo).Union.tag_type == TypeId);
+    const void_info = @typeInfo(void);
+    try expect(void_info == TypeId.Void);
+    try expect(void_info.Void == {});
+}
+
+test "type info: pointer type info" {
+    try testPointer();
+    comptime try testPointer();
+}
+
+fn testPointer() !void {
+    const u32_ptr_info = @typeInfo(*u32);
+    try expect(u32_ptr_info == .Pointer);
+    try expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One);
+    try expect(u32_ptr_info.Pointer.is_const == false);
+    try expect(u32_ptr_info.Pointer.is_volatile == false);
+    try expect(u32_ptr_info.Pointer.alignment == @alignOf(u32));
+    try expect(u32_ptr_info.Pointer.child == u32);
+    try expect(u32_ptr_info.Pointer.sentinel == null);
+}
+
+test "type info: unknown length pointer type info" {
+    try testUnknownLenPtr();
+    comptime try testUnknownLenPtr();
+}
+
+fn testUnknownLenPtr() !void {
+    const u32_ptr_info = @typeInfo([*]const volatile f64);
+    try expect(u32_ptr_info == .Pointer);
+    try expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
+    try expect(u32_ptr_info.Pointer.is_const == true);
+    try expect(u32_ptr_info.Pointer.is_volatile == true);
+    try expect(u32_ptr_info.Pointer.sentinel == null);
+    try expect(u32_ptr_info.Pointer.alignment == @alignOf(f64));
+    try expect(u32_ptr_info.Pointer.child == f64);
+}
+
+test "type info: null terminated pointer type info" {
+    try testNullTerminatedPtr();
+    comptime try testNullTerminatedPtr();
+}
+
+fn testNullTerminatedPtr() !void {
+    const ptr_info = @typeInfo([*:0]u8);
+    try expect(ptr_info == .Pointer);
+    try expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
+    try expect(ptr_info.Pointer.is_const == false);
+    try expect(ptr_info.Pointer.is_volatile == false);
+    try expect(ptr_info.Pointer.sentinel.? == 0);
+
+    try expect(@typeInfo([:0]u8).Pointer.sentinel != null);
+}
+
+test "type info: C pointer type info" {
+    try testCPtr();
+    comptime try testCPtr();
+}
+
+fn testCPtr() !void {
+    const ptr_info = @typeInfo([*c]align(4) const i8);
+    try expect(ptr_info == .Pointer);
+    try expect(ptr_info.Pointer.size == .C);
+    try expect(ptr_info.Pointer.is_const);
+    try expect(!ptr_info.Pointer.is_volatile);
+    try expect(ptr_info.Pointer.alignment == 4);
+    try expect(ptr_info.Pointer.child == i8);
+}
+
+test "type info: slice type info" {
+    try testSlice();
+    comptime try testSlice();
+}
+
+fn testSlice() !void {
+    const u32_slice_info = @typeInfo([]u32);
+    try expect(u32_slice_info == .Pointer);
+    try expect(u32_slice_info.Pointer.size == .Slice);
+    try expect(u32_slice_info.Pointer.is_const == false);
+    try expect(u32_slice_info.Pointer.is_volatile == false);
+    try expect(u32_slice_info.Pointer.alignment == 4);
+    try expect(u32_slice_info.Pointer.child == u32);
+}
+
+test "type info: array type info" {
+    try testArray();
+    comptime try testArray();
+}
+
+fn testArray() !void {
+    {
+        const info = @typeInfo([42]u8);
+        try expect(info == .Array);
+        try expect(info.Array.len == 42);
+        try expect(info.Array.child == u8);
+        try expect(info.Array.sentinel == null);
+    }
+
+    {
+        const info = @typeInfo([10:0]u8);
+        try expect(info.Array.len == 10);
+        try expect(info.Array.child == u8);
+        try expect(info.Array.sentinel.? == @as(u8, 0));
+        try expect(@sizeOf([10:0]u8) == info.Array.len + 1);
+    }
+}
+
+test "type info: error set, error union info" {
+    try testErrorSet();
+    comptime try testErrorSet();
+}
+
+fn testErrorSet() !void {
+    const TestErrorSet = error{
+        First,
+        Second,
+        Third,
+    };
+
+    const error_set_info = @typeInfo(TestErrorSet);
+    try expect(error_set_info == .ErrorSet);
+    try expect(error_set_info.ErrorSet.?.len == 3);
+    try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "First"));
+
+    const error_union_info = @typeInfo(TestErrorSet!usize);
+    try expect(error_union_info == .ErrorUnion);
+    try expect(error_union_info.ErrorUnion.error_set == TestErrorSet);
+    try expect(error_union_info.ErrorUnion.payload == usize);
+
+    const global_info = @typeInfo(anyerror);
+    try expect(global_info == .ErrorSet);
+    try expect(global_info.ErrorSet == null);
+}
+
+test "type info: enum info" {
+    try testEnum();
+    comptime try testEnum();
+}
+
+fn testEnum() !void {
+    const Os = enum {
+        Windows,
+        Macos,
+        Linux,
+        FreeBSD,
+    };
+
+    const os_info = @typeInfo(Os);
+    try expect(os_info == .Enum);
+    try expect(os_info.Enum.layout == .Auto);
+    try expect(os_info.Enum.fields.len == 4);
+    try expect(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
+    try expect(os_info.Enum.fields[3].value == 3);
+    try expect(os_info.Enum.tag_type == u2);
+    try expect(os_info.Enum.decls.len == 0);
+}
+
+test "type info: union info" {
+    try testUnion();
+    comptime try testUnion();
+}
+
+fn testUnion() !void {
+    const typeinfo_info = @typeInfo(TypeInfo);
+    try expect(typeinfo_info == .Union);
+    try expect(typeinfo_info.Union.layout == .Auto);
+    try expect(typeinfo_info.Union.tag_type.? == TypeId);
+    try expect(typeinfo_info.Union.fields.len == 25);
+    try expect(typeinfo_info.Union.fields[4].field_type == @TypeOf(@typeInfo(u8).Int));
+    try expect(typeinfo_info.Union.decls.len == 22);
+
+    const TestNoTagUnion = union {
+        Foo: void,
+        Bar: u32,
+    };
+
+    const notag_union_info = @typeInfo(TestNoTagUnion);
+    try expect(notag_union_info == .Union);
+    try expect(notag_union_info.Union.tag_type == null);
+    try expect(notag_union_info.Union.layout == .Auto);
+    try expect(notag_union_info.Union.fields.len == 2);
+    try expect(notag_union_info.Union.fields[0].alignment == @alignOf(void));
+    try expect(notag_union_info.Union.fields[1].field_type == u32);
+    try expect(notag_union_info.Union.fields[1].alignment == @alignOf(u32));
+
+    const TestExternUnion = extern union {
+        foo: *anyopaque,
+    };
+
+    const extern_union_info = @typeInfo(TestExternUnion);
+    try expect(extern_union_info.Union.layout == .Extern);
+    try expect(extern_union_info.Union.tag_type == null);
+    try expect(extern_union_info.Union.fields[0].field_type == *anyopaque);
+}
+
+test "type info: struct info" {
+    try testStruct();
+    comptime try testStruct();
+}
+
+fn testStruct() !void {
+    const unpacked_struct_info = @typeInfo(TestUnpackedStruct);
+    try expect(unpacked_struct_info.Struct.is_tuple == false);
+    try expect(unpacked_struct_info.Struct.fields[0].alignment == @alignOf(u32));
+    try expect(unpacked_struct_info.Struct.fields[0].default_value.? == 4);
+    try expectEqualStrings("foobar", unpacked_struct_info.Struct.fields[1].default_value.?);
+
+    const struct_info = @typeInfo(TestStruct);
+    try expect(struct_info == .Struct);
+    try expect(struct_info.Struct.is_tuple == false);
+    try expect(struct_info.Struct.layout == .Packed);
+    try expect(struct_info.Struct.fields.len == 4);
+    try expect(struct_info.Struct.fields[0].alignment == 2 * @alignOf(usize));
+    try expect(struct_info.Struct.fields[2].field_type == *TestStruct);
+    try expect(struct_info.Struct.fields[2].default_value == null);
+    try expect(struct_info.Struct.fields[3].default_value.? == 4);
+    try expect(struct_info.Struct.fields[3].alignment == 1);
+    try expect(struct_info.Struct.decls.len == 2);
+    try expect(struct_info.Struct.decls[0].is_pub);
+    try expect(!struct_info.Struct.decls[0].data.Fn.is_extern);
+    try expect(struct_info.Struct.decls[0].data.Fn.lib_name == null);
+    try expect(struct_info.Struct.decls[0].data.Fn.return_type == void);
+    try expect(struct_info.Struct.decls[0].data.Fn.fn_type == fn (*const TestStruct) void);
+}
+
+const TestUnpackedStruct = struct {
+    fieldA: u32 = 4,
+    fieldB: *const [6:0]u8 = "foobar",
+};
+
+const TestStruct = packed struct {
+    fieldA: usize align(2 * @alignOf(usize)),
+    fieldB: void,
+    fieldC: *Self,
+    fieldD: u32 = 4,
+
+    pub fn foo(self: *const Self) void {
+        _ = self;
+    }
+    const Self = @This();
+};
+
+test "type info: opaque info" {
+    try testOpaque();
+    comptime try testOpaque();
+}
+
+fn testOpaque() !void {
+    const Foo = opaque {
+        const A = 1;
+        fn b() void {}
+    };
+
+    const foo_info = @typeInfo(Foo);
+    try expect(foo_info.Opaque.decls.len == 2);
+}
+
+test "type info: function type info" {
+    // wasm doesn't support align attributes on functions
+    if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
+    try testFunction();
+    comptime try testFunction();
+}
+
+fn testFunction() !void {
+    const fn_info = @typeInfo(@TypeOf(foo));
+    try expect(fn_info == .Fn);
+    try expect(fn_info.Fn.alignment > 0);
+    try expect(fn_info.Fn.calling_convention == .C);
+    try expect(!fn_info.Fn.is_generic);
+    try expect(fn_info.Fn.args.len == 2);
+    try expect(fn_info.Fn.is_var_args);
+    try expect(fn_info.Fn.return_type.? == usize);
+    const fn_aligned_info = @typeInfo(@TypeOf(fooAligned));
+    try expect(fn_aligned_info.Fn.alignment == 4);
+
+    const test_instance: TestStruct = undefined;
+    const bound_fn_info = @typeInfo(@TypeOf(test_instance.foo));
+    try expect(bound_fn_info == .BoundFn);
+    try expect(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
+}
+
+extern fn foo(a: usize, b: bool, ...) callconv(.C) usize;
+extern fn fooAligned(a: usize, b: bool, ...) align(4) callconv(.C) usize;
+
+test "typeInfo with comptime parameter in struct fn def" {
+    const S = struct {
+        pub fn func(comptime x: f32) void {
+            _ = x;
+        }
+    };
+    comptime var info = @typeInfo(S);
+    _ = info;
+}
+
+test "type info: vectors" {
+    try testVector();
+    comptime try testVector();
+}
+
+fn testVector() !void {
+    const vec_info = @typeInfo(std.meta.Vector(4, i32));
+    try expect(vec_info == .Vector);
+    try expect(vec_info.Vector.len == 4);
+    try expect(vec_info.Vector.child == i32);
+}
+
+test "type info: anyframe and anyframe->T" {
+    try testAnyFrame();
+    comptime try testAnyFrame();
+}
+
+fn testAnyFrame() !void {
+    {
+        const anyframe_info = @typeInfo(anyframe->i32);
+        try expect(anyframe_info == .AnyFrame);
+        try expect(anyframe_info.AnyFrame.child.? == i32);
+    }
+
+    {
+        const anyframe_info = @typeInfo(anyframe);
+        try expect(anyframe_info == .AnyFrame);
+        try expect(anyframe_info.AnyFrame.child == null);
+    }
+}
+
+test "type info: pass to function" {
+    _ = passTypeInfo(@typeInfo(void));
+    _ = comptime passTypeInfo(@typeInfo(void));
+}
+
+fn passTypeInfo(comptime info: TypeInfo) type {
+    _ = info;
+    return void;
+}
+
+test "type info: TypeId -> TypeInfo impl cast" {
+    _ = passTypeInfo(TypeId.Void);
+    _ = comptime passTypeInfo(TypeId.Void);
+}
+
+test "type info: extern fns with and without lib names" {
+    const S = struct {
+        extern fn bar1() void;
+        extern "cool" fn bar2() void;
+    };
+    const info = @typeInfo(S);
+    comptime {
+        for (info.Struct.decls) |decl| {
+            if (std.mem.eql(u8, decl.name, "bar1")) {
+                try expect(decl.data.Fn.lib_name == null);
+            } else {
+                try expectEqualStrings("cool", decl.data.Fn.lib_name.?);
+            }
+        }
+    }
+}
+
+test "data field is a compile-time value" {
+    const S = struct {
+        const Bar = @as(isize, -1);
+    };
+    comptime try expect(@typeInfo(S).Struct.decls[0].data.Var == isize);
+}
+
+test "sentinel of opaque pointer type" {
+    const c_void_info = @typeInfo(*anyopaque);
+    try expect(c_void_info.Pointer.sentinel == null);
+}
+
+test "@typeInfo does not force declarations into existence" {
+    const S = struct {
+        x: i32,
+
+        fn doNotReferenceMe() void {
+            @compileError("test failed");
+        }
+    };
+    comptime try expect(@typeInfo(S).Struct.fields.len == 1);
+}
+
+test "defaut value for a var-typed field" {
+    const S = struct { x: anytype };
+    try expect(@typeInfo(S).Struct.fields[0].default_value == null);
+}
+
+fn add(a: i32, b: i32) i32 {
+    return a + b;
+}
+
+test "type info for async frames" {
+    switch (@typeInfo(@Frame(add))) {
+        .Frame => |frame| {
+            try expect(frame.function == add);
+        },
+        else => unreachable,
+    }
+}
+
+test "type info: value is correctly copied" {
+    comptime {
+        var ptrInfo = @typeInfo([]u32);
+        ptrInfo.Pointer.size = .One;
+        try expect(@typeInfo([]u32).Pointer.size == .Slice);
+    }
+}
+
+test "Declarations are returned in declaration order" {
+    const S = struct {
+        const a = 1;
+        const b = 2;
+        const c = 3;
+        const d = 4;
+        const e = 5;
+    };
+    const d = @typeInfo(S).Struct.decls;
+    try expect(std.mem.eql(u8, d[0].name, "a"));
+    try expect(std.mem.eql(u8, d[1].name, "b"));
+    try expect(std.mem.eql(u8, d[2].name, "c"));
+    try expect(std.mem.eql(u8, d[3].name, "d"));
+    try expect(std.mem.eql(u8, d[4].name, "e"));
+}
+
+test "Struct.is_tuple" {
+    try expect(@typeInfo(@TypeOf(.{0})).Struct.is_tuple);
+    try expect(!@typeInfo(@TypeOf(.{ .a = 0 })).Struct.is_tuple);
+}
+
+test "StructField.is_comptime" {
+    const info = @typeInfo(struct { x: u8 = 3, comptime y: u32 = 5 }).Struct;
+    try expect(!info.fields[0].is_comptime);
+    try expect(info.fields[1].is_comptime);
+}
+
+test "typeInfo resolves usingnamespace declarations" {
+    const A = struct {
+        pub const f1 = 42;
+    };
+
+    const B = struct {
+        const f0 = 42;
+        usingnamespace A;
+    };
+
+    try expect(@typeInfo(B).Struct.decls.len == 2);
+    //a
+}
test/behavior/type_stage1.zig
@@ -0,0 +1,411 @@
+const std = @import("std");
+const builtin = @import("builtin");
+const TypeInfo = std.builtin.TypeInfo;
+const testing = std.testing;
+
+fn testTypes(comptime types: []const type) !void {
+    inline for (types) |testType| {
+        try testing.expect(testType == @Type(@typeInfo(testType)));
+    }
+}
+
+test "Type.Float" {
+    try testing.expect(f16 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 16 } }));
+    try testing.expect(f32 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 32 } }));
+    try testing.expect(f64 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 64 } }));
+    try testing.expect(f128 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 128 } }));
+    try testTypes(&[_]type{ f16, f32, f64, f128 });
+}
+
+test "Type.Pointer" {
+    try testTypes(&[_]type{
+        // One Value Pointer Types
+        *u8,                               *const u8,
+        *volatile u8,                      *const volatile u8,
+        *align(4) u8,                      *align(4) const u8,
+        *align(4) volatile u8,             *align(4) const volatile u8,
+        *align(8) u8,                      *align(8) const u8,
+        *align(8) volatile u8,             *align(8) const volatile u8,
+        *allowzero u8,                     *allowzero const u8,
+        *allowzero volatile u8,            *allowzero const volatile u8,
+        *allowzero align(4) u8,            *allowzero align(4) const u8,
+        *allowzero align(4) volatile u8,   *allowzero align(4) const volatile u8,
+        // Many Values Pointer Types
+        [*]u8,                             [*]const u8,
+        [*]volatile u8,                    [*]const volatile u8,
+        [*]align(4) u8,                    [*]align(4) const u8,
+        [*]align(4) volatile u8,           [*]align(4) const volatile u8,
+        [*]align(8) u8,                    [*]align(8) const u8,
+        [*]align(8) volatile u8,           [*]align(8) const volatile u8,
+        [*]allowzero u8,                   [*]allowzero const u8,
+        [*]allowzero volatile u8,          [*]allowzero const volatile u8,
+        [*]allowzero align(4) u8,          [*]allowzero align(4) const u8,
+        [*]allowzero align(4) volatile u8, [*]allowzero align(4) const volatile u8,
+        // Slice Types
+        []u8,                              []const u8,
+        []volatile u8,                     []const volatile u8,
+        []align(4) u8,                     []align(4) const u8,
+        []align(4) volatile u8,            []align(4) const volatile u8,
+        []align(8) u8,                     []align(8) const u8,
+        []align(8) volatile u8,            []align(8) const volatile u8,
+        []allowzero u8,                    []allowzero const u8,
+        []allowzero volatile u8,           []allowzero const volatile u8,
+        []allowzero align(4) u8,           []allowzero align(4) const u8,
+        []allowzero align(4) volatile u8,  []allowzero align(4) const volatile u8,
+        // C Pointer Types
+        [*c]u8,                            [*c]const u8,
+        [*c]volatile u8,                   [*c]const volatile u8,
+        [*c]align(4) u8,                   [*c]align(4) const u8,
+        [*c]align(4) volatile u8,          [*c]align(4) const volatile u8,
+        [*c]align(8) u8,                   [*c]align(8) const u8,
+        [*c]align(8) volatile u8,          [*c]align(8) const volatile u8,
+    });
+}
+
+test "Type.Array" {
+    try testing.expect([123]u8 == @Type(TypeInfo{
+        .Array = TypeInfo.Array{
+            .len = 123,
+            .child = u8,
+            .sentinel = null,
+        },
+    }));
+    try testing.expect([2]u32 == @Type(TypeInfo{
+        .Array = TypeInfo.Array{
+            .len = 2,
+            .child = u32,
+            .sentinel = null,
+        },
+    }));
+    try testing.expect([2:0]u32 == @Type(TypeInfo{
+        .Array = TypeInfo.Array{
+            .len = 2,
+            .child = u32,
+            .sentinel = 0,
+        },
+    }));
+    try testTypes(&[_]type{ [1]u8, [30]usize, [7]bool });
+}
+
+test "@Type create slice with null sentinel" {
+    const Slice = @Type(TypeInfo{
+        .Pointer = .{
+            .size = .Slice,
+            .is_const = true,
+            .is_volatile = false,
+            .is_allowzero = false,
+            .alignment = 8,
+            .address_space = .generic,
+            .child = *i32,
+            .sentinel = null,
+        },
+    });
+    try testing.expect(Slice == []align(8) const *i32);
+}
+test "@Type picks up the sentinel value from TypeInfo" {
+    try testTypes(&[_]type{
+        [11:0]u8,                            [4:10]u8,
+        [*:0]u8,                             [*:0]const u8,
+        [*:0]volatile u8,                    [*:0]const volatile u8,
+        [*:0]align(4) u8,                    [*:0]align(4) const u8,
+        [*:0]align(4) volatile u8,           [*:0]align(4) const volatile u8,
+        [*:0]align(8) u8,                    [*:0]align(8) const u8,
+        [*:0]align(8) volatile u8,           [*:0]align(8) const volatile u8,
+        [*:0]allowzero u8,                   [*:0]allowzero const u8,
+        [*:0]allowzero volatile u8,          [*:0]allowzero const volatile u8,
+        [*:0]allowzero align(4) u8,          [*:0]allowzero align(4) const u8,
+        [*:0]allowzero align(4) volatile u8, [*:0]allowzero align(4) const volatile u8,
+        [*:5]allowzero align(4) volatile u8, [*:5]allowzero align(4) const volatile u8,
+        [:0]u8,                              [:0]const u8,
+        [:0]volatile u8,                     [:0]const volatile u8,
+        [:0]align(4) u8,                     [:0]align(4) const u8,
+        [:0]align(4) volatile u8,            [:0]align(4) const volatile u8,
+        [:0]align(8) u8,                     [:0]align(8) const u8,
+        [:0]align(8) volatile u8,            [:0]align(8) const volatile u8,
+        [:0]allowzero u8,                    [:0]allowzero const u8,
+        [:0]allowzero volatile u8,           [:0]allowzero const volatile u8,
+        [:0]allowzero align(4) u8,           [:0]allowzero align(4) const u8,
+        [:0]allowzero align(4) volatile u8,  [:0]allowzero align(4) const volatile u8,
+        [:4]allowzero align(4) volatile u8,  [:4]allowzero align(4) const volatile u8,
+    });
+}
+
+test "Type.Optional" {
+    try testTypes(&[_]type{
+        ?u8,
+        ?*u8,
+        ?[]u8,
+        ?[*]u8,
+        ?[*c]u8,
+    });
+}
+
+test "Type.ErrorUnion" {
+    try testTypes(&[_]type{
+        error{}!void,
+        error{Error}!void,
+    });
+}
+
+test "Type.Opaque" {
+    const Opaque = @Type(.{
+        .Opaque = .{
+            .decls = &[_]TypeInfo.Declaration{},
+        },
+    });
+    try testing.expect(Opaque != opaque {});
+    try testing.expectEqualSlices(
+        TypeInfo.Declaration,
+        &[_]TypeInfo.Declaration{},
+        @typeInfo(Opaque).Opaque.decls,
+    );
+}
+
+test "Type.Vector" {
+    try testTypes(&[_]type{
+        @Vector(0, u8),
+        @Vector(4, u8),
+        @Vector(8, *u8),
+        std.meta.Vector(0, u8),
+        std.meta.Vector(4, u8),
+        std.meta.Vector(8, *u8),
+    });
+}
+
+test "Type.AnyFrame" {
+    try testTypes(&[_]type{
+        anyframe,
+        anyframe->u8,
+        anyframe->anyframe->u8,
+    });
+}
+
+fn add(a: i32, b: i32) i32 {
+    return a + b;
+}
+
+test "Type.Frame" {
+    try testTypes(&[_]type{
+        @Frame(add),
+    });
+}
+
+test "Type.ErrorSet" {
+    // error sets don't compare equal so just check if they compile
+    _ = @Type(@typeInfo(error{}));
+    _ = @Type(@typeInfo(error{A}));
+    _ = @Type(@typeInfo(error{ A, B, C }));
+}
+
+test "Type.Struct" {
+    const A = @Type(@typeInfo(struct { x: u8, y: u32 }));
+    const infoA = @typeInfo(A).Struct;
+    try testing.expectEqual(TypeInfo.ContainerLayout.Auto, infoA.layout);
+    try testing.expectEqualSlices(u8, "x", infoA.fields[0].name);
+    try testing.expectEqual(u8, infoA.fields[0].field_type);
+    try testing.expectEqual(@as(?u8, null), infoA.fields[0].default_value);
+    try testing.expectEqualSlices(u8, "y", infoA.fields[1].name);
+    try testing.expectEqual(u32, infoA.fields[1].field_type);
+    try testing.expectEqual(@as(?u32, null), infoA.fields[1].default_value);
+    try testing.expectEqualSlices(TypeInfo.Declaration, &[_]TypeInfo.Declaration{}, infoA.decls);
+    try testing.expectEqual(@as(bool, false), infoA.is_tuple);
+
+    var a = A{ .x = 0, .y = 1 };
+    try testing.expectEqual(@as(u8, 0), a.x);
+    try testing.expectEqual(@as(u32, 1), a.y);
+    a.y += 1;
+    try testing.expectEqual(@as(u32, 2), a.y);
+
+    const B = @Type(@typeInfo(extern struct { x: u8, y: u32 = 5 }));
+    const infoB = @typeInfo(B).Struct;
+    try testing.expectEqual(TypeInfo.ContainerLayout.Extern, infoB.layout);
+    try testing.expectEqualSlices(u8, "x", infoB.fields[0].name);
+    try testing.expectEqual(u8, infoB.fields[0].field_type);
+    try testing.expectEqual(@as(?u8, null), infoB.fields[0].default_value);
+    try testing.expectEqualSlices(u8, "y", infoB.fields[1].name);
+    try testing.expectEqual(u32, infoB.fields[1].field_type);
+    try testing.expectEqual(@as(?u32, 5), infoB.fields[1].default_value);
+    try testing.expectEqual(@as(usize, 0), infoB.decls.len);
+    try testing.expectEqual(@as(bool, false), infoB.is_tuple);
+
+    const C = @Type(@typeInfo(packed struct { x: u8 = 3, y: u32 = 5 }));
+    const infoC = @typeInfo(C).Struct;
+    try testing.expectEqual(TypeInfo.ContainerLayout.Packed, infoC.layout);
+    try testing.expectEqualSlices(u8, "x", infoC.fields[0].name);
+    try testing.expectEqual(u8, infoC.fields[0].field_type);
+    try testing.expectEqual(@as(?u8, 3), infoC.fields[0].default_value);
+    try testing.expectEqualSlices(u8, "y", infoC.fields[1].name);
+    try testing.expectEqual(u32, infoC.fields[1].field_type);
+    try testing.expectEqual(@as(?u32, 5), infoC.fields[1].default_value);
+    try testing.expectEqual(@as(usize, 0), infoC.decls.len);
+    try testing.expectEqual(@as(bool, false), infoC.is_tuple);
+}
+
+test "Type.Enum" {
+    const Foo = @Type(.{
+        .Enum = .{
+            .layout = .Auto,
+            .tag_type = u8,
+            .fields = &[_]TypeInfo.EnumField{
+                .{ .name = "a", .value = 1 },
+                .{ .name = "b", .value = 5 },
+            },
+            .decls = &[_]TypeInfo.Declaration{},
+            .is_exhaustive = true,
+        },
+    });
+    try testing.expectEqual(true, @typeInfo(Foo).Enum.is_exhaustive);
+    try testing.expectEqual(@as(u8, 1), @enumToInt(Foo.a));
+    try testing.expectEqual(@as(u8, 5), @enumToInt(Foo.b));
+    const Bar = @Type(.{
+        .Enum = .{
+            .layout = .Extern,
+            .tag_type = u32,
+            .fields = &[_]TypeInfo.EnumField{
+                .{ .name = "a", .value = 1 },
+                .{ .name = "b", .value = 5 },
+            },
+            .decls = &[_]TypeInfo.Declaration{},
+            .is_exhaustive = false,
+        },
+    });
+    try testing.expectEqual(false, @typeInfo(Bar).Enum.is_exhaustive);
+    try testing.expectEqual(@as(u32, 1), @enumToInt(Bar.a));
+    try testing.expectEqual(@as(u32, 5), @enumToInt(Bar.b));
+    try testing.expectEqual(@as(u32, 6), @enumToInt(@intToEnum(Bar, 6)));
+}
+
+test "Type.Union" {
+    const Untagged = @Type(.{
+        .Union = .{
+            .layout = .Auto,
+            .tag_type = null,
+            .fields = &[_]TypeInfo.UnionField{
+                .{ .name = "int", .field_type = i32, .alignment = @alignOf(f32) },
+                .{ .name = "float", .field_type = f32, .alignment = @alignOf(f32) },
+            },
+            .decls = &[_]TypeInfo.Declaration{},
+        },
+    });
+    var untagged = Untagged{ .int = 1 };
+    untagged.float = 2.0;
+    untagged.int = 3;
+    try testing.expectEqual(@as(i32, 3), untagged.int);
+
+    const PackedUntagged = @Type(.{
+        .Union = .{
+            .layout = .Packed,
+            .tag_type = null,
+            .fields = &[_]TypeInfo.UnionField{
+                .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
+                .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
+            },
+            .decls = &[_]TypeInfo.Declaration{},
+        },
+    });
+    var packed_untagged = PackedUntagged{ .signed = -1 };
+    try testing.expectEqual(@as(i32, -1), packed_untagged.signed);
+    try testing.expectEqual(~@as(u32, 0), packed_untagged.unsigned);
+
+    const Tag = @Type(.{
+        .Enum = .{
+            .layout = .Auto,
+            .tag_type = u1,
+            .fields = &[_]TypeInfo.EnumField{
+                .{ .name = "signed", .value = 0 },
+                .{ .name = "unsigned", .value = 1 },
+            },
+            .decls = &[_]TypeInfo.Declaration{},
+            .is_exhaustive = true,
+        },
+    });
+    const Tagged = @Type(.{
+        .Union = .{
+            .layout = .Auto,
+            .tag_type = Tag,
+            .fields = &[_]TypeInfo.UnionField{
+                .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
+                .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
+            },
+            .decls = &[_]TypeInfo.Declaration{},
+        },
+    });
+    var tagged = Tagged{ .signed = -1 };
+    try testing.expectEqual(Tag.signed, tagged);
+    tagged = .{ .unsigned = 1 };
+    try testing.expectEqual(Tag.unsigned, tagged);
+}
+
+test "Type.Union from Type.Enum" {
+    const Tag = @Type(.{
+        .Enum = .{
+            .layout = .Auto,
+            .tag_type = u0,
+            .fields = &[_]TypeInfo.EnumField{
+                .{ .name = "working_as_expected", .value = 0 },
+            },
+            .decls = &[_]TypeInfo.Declaration{},
+            .is_exhaustive = true,
+        },
+    });
+    const T = @Type(.{
+        .Union = .{
+            .layout = .Auto,
+            .tag_type = Tag,
+            .fields = &[_]TypeInfo.UnionField{
+                .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
+            },
+            .decls = &[_]TypeInfo.Declaration{},
+        },
+    });
+    _ = T;
+    _ = @typeInfo(T).Union;
+}
+
+test "Type.Union from regular enum" {
+    const E = enum { working_as_expected };
+    const T = @Type(.{
+        .Union = .{
+            .layout = .Auto,
+            .tag_type = E,
+            .fields = &[_]TypeInfo.UnionField{
+                .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
+            },
+            .decls = &[_]TypeInfo.Declaration{},
+        },
+    });
+    _ = T;
+    _ = @typeInfo(T).Union;
+}
+
+test "Type.Fn" {
+    // wasm doesn't support align attributes on functions
+    if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
+
+    const foo = struct {
+        fn func(a: usize, b: bool) align(4) callconv(.C) usize {
+            _ = a;
+            _ = b;
+            return 0;
+        }
+    }.func;
+    const Foo = @Type(@typeInfo(@TypeOf(foo)));
+    const foo_2: Foo = foo;
+    _ = foo_2;
+}
+
+test "Type.BoundFn" {
+    // wasm doesn't support align attributes on functions
+    if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
+
+    const TestStruct = packed struct {
+        pub fn foo(self: *const @This()) align(4) callconv(.Unspecified) void {
+            _ = self;
+        }
+    };
+    const test_instance: TestStruct = undefined;
+    try testing.expect(std.meta.eql(
+        @typeName(@TypeOf(test_instance.foo)),
+        @typeName(@Type(@typeInfo(@TypeOf(test_instance.foo)))),
+    ));
+}
test/behavior/union.zig
@@ -460,3 +460,28 @@ test "tagged union as return value" {
 fn returnAnInt(x: i32) TaggedFoo {
     return TaggedFoo{ .One = x };
 }
+
+test "tagged union with all void fields but a meaningful tag" {
+    const S = struct {
+        const B = union(enum) {
+            c: C,
+            None,
+        };
+
+        const A = struct {
+            b: B,
+        };
+
+        const C = struct {};
+
+        fn doTheTest() !void {
+            var a: A = A{ .b = B{ .c = C{} } };
+            try expect(@as(Tag(B), a.b) == Tag(B).c);
+            a = A{ .b = B.None };
+            try expect(@as(Tag(B), a.b) == Tag(B).None);
+        }
+    };
+    try S.doTheTest();
+    // TODO enable the test at comptime too
+    //comptime try S.doTheTest();
+}
test/behavior.zig
@@ -18,6 +18,8 @@ test {
     _ = @import("behavior/pub_enum.zig");
     _ = @import("behavior/slice_sentinel_comptime.zig");
     _ = @import("behavior/truncate.zig");
+    _ = @import("behavior/type.zig");
+    _ = @import("behavior/type_info.zig");
     _ = @import("behavior/usingnamespace.zig");
 
     // Tests that pass for stage1, stage2 and the C backend, but not for the wasm backend
@@ -124,7 +126,6 @@ test {
                 _ = @import("behavior/bugs/1025.zig");
                 _ = @import("behavior/bugs/1076.zig");
                 _ = @import("behavior/bugs/1120.zig");
-                _ = @import("behavior/bugs/1322.zig");
                 _ = @import("behavior/bugs/1421.zig");
                 _ = @import("behavior/bugs/1442.zig");
                 _ = @import("behavior/bugs/1607.zig");
@@ -186,8 +187,8 @@ test {
                 _ = @import("behavior/truncate_stage1.zig");
                 _ = @import("behavior/try.zig");
                 _ = @import("behavior/tuple.zig");
-                _ = @import("behavior/type.zig");
-                _ = @import("behavior/type_info.zig");
+                _ = @import("behavior/type_stage1.zig");
+                _ = @import("behavior/type_info_stage1.zig");
                 _ = @import("behavior/typename.zig");
                 _ = @import("behavior/union_stage1.zig");
                 _ = @import("behavior/union_with_members.zig");