Commit be5130ec53
Changed files (18)
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");