authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-29 00:39:25-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-29 00:39:25-07:00
logbe5130ec535456559497ac241ac9fa76c4bbb8ca
tree072927858110cb69ccc85c31ed1b2055ee83875e
parentefb7148a4574c608b21359fcbf2edf06afdb5e0c

compiler_rt: move more functions to the stage2 section

also move more already-passing behavior tests to the passing section.

18 files changed, 1119 insertions(+), 1084 deletions(-)

lib/std/special/compiler_rt.zig+12-12
......@@ -159,6 +159,18 @@ comptime {
159159 @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage });
160160 }
161161
162 const __truncdfhf2 = @import("compiler_rt/truncXfYf2.zig").__truncdfhf2;
163 @export(__truncdfhf2, .{ .name = "__truncdfhf2", .linkage = linkage });
164 const __trunctfhf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfhf2;
165 @export(__trunctfhf2, .{ .name = "__trunctfhf2", .linkage = linkage });
166 const __trunctfdf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfdf2;
167 @export(__trunctfdf2, .{ .name = "__trunctfdf2", .linkage = linkage });
168 const __trunctfsf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfsf2;
169 @export(__trunctfsf2, .{ .name = "__trunctfsf2", .linkage = linkage });
170
171 const __truncdfsf2 = @import("compiler_rt/truncXfYf2.zig").__truncdfsf2;
172 @export(__truncdfsf2, .{ .name = "__truncdfsf2", .linkage = linkage });
173
162174 if (!builtin.zig_is_stage2) {
163175 if (!long_double_is_f128) {
164176 // TODO implement these
......@@ -318,18 +330,6 @@ comptime {
318330 if (!is_test) {
319331 @export(__truncsfhf2, .{ .name = "__gnu_f2h_ieee", .linkage = linkage });
320332 }
321 const __truncdfhf2 = @import("compiler_rt/truncXfYf2.zig").__truncdfhf2;
322 @export(__truncdfhf2, .{ .name = "__truncdfhf2", .linkage = linkage });
323 const __trunctfhf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfhf2;
324 @export(__trunctfhf2, .{ .name = "__trunctfhf2", .linkage = linkage });
325 const __trunctfdf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfdf2;
326 @export(__trunctfdf2, .{ .name = "__trunctfdf2", .linkage = linkage });
327 const __trunctfsf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfsf2;
328 @export(__trunctfsf2, .{ .name = "__trunctfsf2", .linkage = linkage });
329
330 const __truncdfsf2 = @import("compiler_rt/truncXfYf2.zig").__truncdfsf2;
331 @export(__truncdfsf2, .{ .name = "__truncdfsf2", .linkage = linkage });
332
333333 const __extendsfdf2 = @import("compiler_rt/extendXfYf2.zig").__extendsfdf2;
334334 @export(__extendsfdf2, .{ .name = "__extendsfdf2", .linkage = linkage });
335335
lib/std/special/compiler_rt/truncXfYf2.zig+10-10
......@@ -7,23 +7,23 @@ const native_arch = builtin.cpu.arch;
77pub const F16T = if (native_arch.isAARCH64()) f16 else u16;
88
99pub fn __truncsfhf2(a: f32) callconv(.C) F16T {
10 return @bitCast(F16T, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f32, a }));
10 return @bitCast(F16T, truncXfYf2(f16, f32, a));
1111}
1212
1313pub fn __truncdfhf2(a: f64) callconv(.C) F16T {
14 return @bitCast(F16T, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f64, a }));
14 return @bitCast(F16T, truncXfYf2(f16, f64, a));
1515}
1616
1717pub fn __trunctfhf2(a: f128) callconv(.C) F16T {
18 return @bitCast(F16T, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f128, a }));
18 return @bitCast(F16T, truncXfYf2(f16, f128, a));
1919}
2020
2121pub fn __trunctfsf2(a: f128) callconv(.C) f32 {
22 return @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f32, f128, a });
22 return truncXfYf2(f32, f128, a);
2323}
2424
2525pub fn __trunctfdf2(a: f128) callconv(.C) f64 {
26 return @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f64, f128, a });
26 return truncXfYf2(f64, f128, a);
2727}
2828
2929pub fn __trunctfxf2(a: f128) callconv(.C) c_longdouble {
......@@ -32,25 +32,25 @@ pub fn __trunctfxf2(a: f128) callconv(.C) c_longdouble {
3232}
3333
3434pub fn __truncdfsf2(a: f64) callconv(.C) f32 {
35 return @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f32, f64, a });
35 return truncXfYf2(f32, f64, a);
3636}
3737
3838pub fn __aeabi_d2f(a: f64) callconv(.AAPCS) f32 {
3939 @setRuntimeSafety(false);
40 return @call(.{ .modifier = .always_inline }, __truncdfsf2, .{a});
40 return truncXfYf2(f32, f64, a);
4141}
4242
4343pub fn __aeabi_d2h(a: f64) callconv(.AAPCS) u16 {
4444 @setRuntimeSafety(false);
45 return @call(.{ .modifier = .always_inline }, __truncdfhf2, .{a});
45 return @bitCast(F16T, truncXfYf2(f16, f64, a));
4646}
4747
4848pub fn __aeabi_f2h(a: f32) callconv(.AAPCS) u16 {
4949 @setRuntimeSafety(false);
50 return @call(.{ .modifier = .always_inline }, __truncsfhf2, .{a});
50 return @bitCast(F16T, truncXfYf2(f16, f32, a));
5151}
5252
53fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
53inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
5454 const src_rep_t = std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits);
5555 const dst_rep_t = std.meta.Int(.unsigned, @typeInfo(dst_t).Float.bits);
5656 const srcSigBits = std.math.floatMantissaBits(src_t);
test/behavior.zig+4-3
......@@ -18,6 +18,8 @@ test {
1818 _ = @import("behavior/pub_enum.zig");
1919 _ = @import("behavior/slice_sentinel_comptime.zig");
2020 _ = @import("behavior/truncate.zig");
21 _ = @import("behavior/type.zig");
22 _ = @import("behavior/type_info.zig");
2123 _ = @import("behavior/usingnamespace.zig");
2224
2325 // Tests that pass for stage1, stage2 and the C backend, but not for the wasm backend
......@@ -124,7 +126,6 @@ test {
124126 _ = @import("behavior/bugs/1025.zig");
125127 _ = @import("behavior/bugs/1076.zig");
126128 _ = @import("behavior/bugs/1120.zig");
127 _ = @import("behavior/bugs/1322.zig");
128129 _ = @import("behavior/bugs/1421.zig");
129130 _ = @import("behavior/bugs/1442.zig");
130131 _ = @import("behavior/bugs/1607.zig");
......@@ -186,8 +187,8 @@ test {
186187 _ = @import("behavior/truncate_stage1.zig");
187188 _ = @import("behavior/try.zig");
188189 _ = @import("behavior/tuple.zig");
189 _ = @import("behavior/type.zig");
190 _ = @import("behavior/type_info.zig");
190 _ = @import("behavior/type_stage1.zig");
191 _ = @import("behavior/type_info_stage1.zig");
191192 _ = @import("behavior/typename.zig");
192193 _ = @import("behavior/union_stage1.zig");
193194 _ = @import("behavior/union_with_members.zig");
test/behavior/align.zig+15
......@@ -120,3 +120,18 @@ test "size of extern struct with 128-bit field" {
120120 }) == 32);
121121 }
122122}
123
124test "@ptrCast preserves alignment of bigger source" {
125 var x: u32 align(16) = 1234;
126 const ptr = @ptrCast(*u8, &x);
127 try expect(@TypeOf(ptr) == *align(16) u8);
128}
129
130test "alignstack" {
131 try expect(fnWithAlignedStack() == 1234);
132}
133
134fn fnWithAlignedStack() i32 {
135 @setAlignStack(256);
136 return 1234;
137}
test/behavior/align_stage1.zig-34
......@@ -20,25 +20,6 @@ test "function alignment" {
2020 noop4();
2121}
2222
23var baz: packed struct {
24 a: u32,
25 b: u32,
26} = undefined;
27
28test "packed struct alignment" {
29 try expect(@TypeOf(&baz.b) == *align(1) u32);
30}
31
32const blah: packed struct {
33 a: u3,
34 b: u3,
35 c: u2,
36} = undefined;
37
38test "bit field alignment" {
39 try expect(@TypeOf(&blah.b) == *align(1:3:1) const u3);
40}
41
4223test "implicitly decreasing fn alignment" {
4324 // function alignment is a compile error on wasm32/wasm64
4425 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 {
9071 return 0x1;
9172}
9273
93test "@ptrCast preserves alignment of bigger source" {
94 var x: u32 align(16) = 1234;
95 const ptr = @ptrCast(*u8, &x);
96 try expect(@TypeOf(ptr) == *align(16) u8);
97}
98
9974test "runtime known array index has best alignment possible" {
10075 // take full advantage of over-alignment
10176 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 {
134109 comptime try expect(@TypeOf(&ptr[index]) == T);
135110}
136111
137test "alignstack" {
138 try expect(fnWithAlignedStack() == 1234);
139}
140
141fn fnWithAlignedStack() i32 {
142 @setAlignStack(256);
143 return 1234;
144}
145
146112test "alignment of function with c calling convention" {
147113 var runtime_nothing = nothing;
148114 const casted1 = @ptrCast(*const u8, runtime_nothing);
test/behavior/bugs/1322.zig deleted-19
......@@ -1,19 +0,0 @@
1const std = @import("std");
2
3const B = union(enum) {
4 c: C,
5 None,
6};
7
8const A = struct {
9 b: B,
10};
11
12const C = struct {};
13
14test "tagged union with all void fields but a meaningful tag" {
15 var a: A = A{ .b = B{ .c = C{} } };
16 try std.testing.expect(@as(std.meta.Tag(B), a.b) == std.meta.Tag(B).c);
17 a = A{ .b = B.None };
18 try std.testing.expect(@as(std.meta.Tag(B), a.b) == std.meta.Tag(B).None);
19}
test/behavior/cast_llvm.zig+68
......@@ -197,3 +197,71 @@ test "cast between *[N]void and []void" {
197197 var b: []void = &a;
198198 try expect(b.len == 4);
199199}
200
201test "peer resolve arrays of different size to const slice" {
202 try expect(mem.eql(u8, boolToStr(true), "true"));
203 try expect(mem.eql(u8, boolToStr(false), "false"));
204 comptime try expect(mem.eql(u8, boolToStr(true), "true"));
205 comptime try expect(mem.eql(u8, boolToStr(false), "false"));
206}
207fn boolToStr(b: bool) []const u8 {
208 return if (b) "true" else "false";
209}
210
211test "cast f16 to wider types" {
212 const S = struct {
213 fn doTheTest() !void {
214 var x: f16 = 1234.0;
215 try expect(@as(f32, 1234.0) == x);
216 try expect(@as(f64, 1234.0) == x);
217 try expect(@as(f128, 1234.0) == x);
218 }
219 };
220 try S.doTheTest();
221 comptime try S.doTheTest();
222}
223
224test "cast f128 to narrower types" {
225 const S = struct {
226 fn doTheTest() !void {
227 var x: f128 = 1234.0;
228 try expect(@as(f16, 1234.0) == @floatCast(f16, x));
229 try expect(@as(f32, 1234.0) == @floatCast(f32, x));
230 try expect(@as(f64, 1234.0) == @floatCast(f64, x));
231 }
232 };
233 try S.doTheTest();
234 comptime try S.doTheTest();
235}
236
237test "peer type resolution: unreachable, null, slice" {
238 const S = struct {
239 fn doTheTest(num: usize, word: []const u8) !void {
240 const result = switch (num) {
241 0 => null,
242 1 => word,
243 else => unreachable,
244 };
245 try expect(mem.eql(u8, result.?, "hi"));
246 }
247 };
248 try S.doTheTest(1, "hi");
249}
250
251test "cast i8 fn call peers to i32 result" {
252 const S = struct {
253 fn doTheTest() !void {
254 var cond = true;
255 const value: i32 = if (cond) smallBoi() else bigBoi();
256 try expect(value == 123);
257 }
258 fn smallBoi() i8 {
259 return 123;
260 }
261 fn bigBoi() i16 {
262 return 1234;
263 }
264 };
265 try S.doTheTest();
266 comptime try S.doTheTest();
267}
test/behavior/cast_stage1.zig-68
......@@ -15,16 +15,6 @@ fn testCastIntToErr(err: anyerror) !void {
1515 try expect(error.ItBroke == y);
1616}
1717
18test "peer resolve arrays of different size to const slice" {
19 try expect(mem.eql(u8, boolToStr(true), "true"));
20 try expect(mem.eql(u8, boolToStr(false), "false"));
21 comptime try expect(mem.eql(u8, boolToStr(true), "true"));
22 comptime try expect(mem.eql(u8, boolToStr(false), "false"));
23}
24fn boolToStr(b: bool) []const u8 {
25 return if (b) "true" else "false";
26}
27
2818test "peer resolve array and const slice" {
2919 try testPeerResolveArrayConstSlice(true);
3020 comptime try testPeerResolveArrayConstSlice(true);
......@@ -174,32 +164,6 @@ test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
174164 try expect(mem.eql(u8, std.mem.sliceTo(@ptrCast([*:0]const u8, x[0].?), 0), "window name"));
175165}
176166
177test "cast f16 to wider types" {
178 const S = struct {
179 fn doTheTest() !void {
180 var x: f16 = 1234.0;
181 try std.testing.expectEqual(@as(f32, 1234.0), x);
182 try std.testing.expectEqual(@as(f64, 1234.0), x);
183 try std.testing.expectEqual(@as(f128, 1234.0), x);
184 }
185 };
186 try S.doTheTest();
187 comptime try S.doTheTest();
188}
189
190test "cast f128 to narrower types" {
191 const S = struct {
192 fn doTheTest() !void {
193 var x: f128 = 1234.0;
194 try std.testing.expectEqual(@as(f16, 1234.0), @floatCast(f16, x));
195 try std.testing.expectEqual(@as(f32, 1234.0), @floatCast(f32, x));
196 try std.testing.expectEqual(@as(f64, 1234.0), @floatCast(f64, x));
197 }
198 };
199 try S.doTheTest();
200 comptime try S.doTheTest();
201}
202
203167test "vector casts" {
204168 const S = struct {
205169 fn doTheTest() !void {
......@@ -250,20 +214,6 @@ test "@floatCast cast down" {
250214 }
251215}
252216
253test "peer type resolution: unreachable, null, slice" {
254 const S = struct {
255 fn doTheTest(num: usize, word: []const u8) !void {
256 const result = switch (num) {
257 0 => null,
258 1 => word,
259 else => unreachable,
260 };
261 try expect(mem.eql(u8, result.?, "hi"));
262 }
263 };
264 try S.doTheTest(1, "hi");
265}
266
267217test "peer type resolution: unreachable, error set, unreachable" {
268218 const Error = error{
269219 FileDescriptorAlreadyPresentInSet,
......@@ -374,24 +324,6 @@ test "type coercion related to sentinel-termination" {
374324 comptime try S.doTheTest();
375325}
376326
377test "cast i8 fn call peers to i32 result" {
378 const S = struct {
379 fn doTheTest() !void {
380 var cond = true;
381 const value: i32 = if (cond) smallBoi() else bigBoi();
382 try expect(value == 123);
383 }
384 fn smallBoi() i8 {
385 return 123;
386 }
387 fn bigBoi() i16 {
388 return 1234;
389 }
390 };
391 try S.doTheTest();
392 comptime try S.doTheTest();
393}
394
395327test "peer type resolution implicit cast to return type" {
396328 const S = struct {
397329 fn doTheTest() !void {
test/behavior/defer.zig+59
......@@ -2,3 +2,62 @@ const std = @import("std");
22const expect = std.testing.expect;
33const expectEqual = std.testing.expectEqual;
44const expectError = std.testing.expectError;
5
6test "break and continue inside loop inside defer expression" {
7 testBreakContInDefer(10);
8 comptime testBreakContInDefer(10);
9}
10
11fn testBreakContInDefer(x: usize) void {
12 defer {
13 var i: usize = 0;
14 while (i < x) : (i += 1) {
15 if (i < 5) continue;
16 if (i == 5) break;
17 }
18 expect(i == 5) catch @panic("test failure");
19 }
20}
21
22test "defer and labeled break" {
23 var i = @as(usize, 0);
24
25 blk: {
26 defer i += 1;
27 break :blk;
28 }
29
30 try expect(i == 1);
31}
32
33test "errdefer does not apply to fn inside fn" {
34 if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| try expect(e == error.Bad);
35}
36
37fn testNestedFnErrDefer() anyerror!void {
38 var a: i32 = 0;
39 errdefer a += 1;
40 const S = struct {
41 fn baz() anyerror {
42 return error.Bad;
43 }
44 };
45 return S.baz();
46}
47
48test "return variable while defer expression in scope to modify it" {
49 const S = struct {
50 fn doTheTest() !void {
51 try expect(notNull().? == 1);
52 }
53
54 fn notNull() ?u8 {
55 var res: ?u8 = 1;
56 defer res = null;
57 return res;
58 }
59 };
60
61 try S.doTheTest();
62 comptime try S.doTheTest();
63}
test/behavior/defer_stage1.zig-59
......@@ -38,65 +38,6 @@ test "mixing normal and error defers" {
3838 try expect(result[2] == 'a');
3939}
4040
41test "break and continue inside loop inside defer expression" {
42 testBreakContInDefer(10);
43 comptime testBreakContInDefer(10);
44}
45
46fn testBreakContInDefer(x: usize) void {
47 defer {
48 var i: usize = 0;
49 while (i < x) : (i += 1) {
50 if (i < 5) continue;
51 if (i == 5) break;
52 }
53 expect(i == 5) catch @panic("test failure");
54 }
55}
56
57test "defer and labeled break" {
58 var i = @as(usize, 0);
59
60 blk: {
61 defer i += 1;
62 break :blk;
63 }
64
65 try expect(i == 1);
66}
67
68test "errdefer does not apply to fn inside fn" {
69 if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| try expect(e == error.Bad);
70}
71
72fn testNestedFnErrDefer() anyerror!void {
73 var a: i32 = 0;
74 errdefer a += 1;
75 const S = struct {
76 fn baz() anyerror {
77 return error.Bad;
78 }
79 };
80 return S.baz();
81}
82
83test "return variable while defer expression in scope to modify it" {
84 const S = struct {
85 fn doTheTest() !void {
86 try expect(notNull().? == 1);
87 }
88
89 fn notNull() ?u8 {
90 var res: ?u8 = 1;
91 defer res = null;
92 return res;
93 }
94 };
95
96 try S.doTheTest();
97 comptime try S.doTheTest();
98}
99
10041test "errdefer with payload" {
10142 const S = struct {
10243 fn foo() !i32 {
test/behavior/eval.zig+25
......@@ -467,3 +467,28 @@ test "comptime shlWithOverflow" {
467467
468468 try expect(ct_shifted == rt_shifted);
469469}
470
471test "const ptr to variable data changes at runtime" {
472 try expect(foo_ref.name[0] == 'a');
473 foo_ref.name = "b";
474 try expect(foo_ref.name[0] == 'b');
475}
476
477const Foo = struct {
478 name: []const u8,
479};
480
481var foo_contents = Foo{ .name = "a" };
482const foo_ref = &foo_contents;
483
484test "runtime 128 bit integer division" {
485 var a: u128 = 152313999999999991610955792383;
486 var b: u128 = 10000000000000000000;
487 var c = a / b;
488 try expect(c == 15231399999);
489}
490
491test "@tagName of @typeInfo" {
492 const str = @tagName(@typeInfo(u8));
493 try expect(std.mem.eql(u8, str, "Int"));
494}
test/behavior/eval_stage1.zig-25
......@@ -86,19 +86,6 @@ fn testCompTimeUIntComparisons(x: u32) void {
8686 }
8787}
8888
89test "const ptr to variable data changes at runtime" {
90 try expect(foo_ref.name[0] == 'a');
91 foo_ref.name = "b";
92 try expect(foo_ref.name[0] == 'b');
93}
94
95const Foo = struct {
96 name: []const u8,
97};
98
99var foo_contents = Foo{ .name = "a" };
100const foo_ref = &foo_contents;
101
10289const hi1 = "hi";
10390const hi2 = hi1;
10491test "const global shares pointer with other same one" {
......@@ -162,13 +149,6 @@ test "const ptr to comptime mutable data is not memoized" {
162149 }
163150}
164151
165test "runtime 128 bit integer division" {
166 var a: u128 = 152313999999999991610955792383;
167 var b: u128 = 10000000000000000000;
168 var c = a / b;
169 try expect(c == 15231399999);
170}
171
172152const Wrapper = struct {
173153 T: type,
174154};
......@@ -196,11 +176,6 @@ test "call method with comptime pass-by-non-copying-value self parameter" {
196176 try expect(b == 2);
197177}
198178
199test "@tagName of @typeInfo" {
200 const str = @tagName(@typeInfo(u8));
201 try expect(std.mem.eql(u8, str, "Int"));
202}
203
204179test "setting backward branch quota just before a generic fn call" {
205180 @setEvalBranchQuota(1001);
206181 loopNTimes(1001);
test/behavior/struct.zig+27
......@@ -199,3 +199,30 @@ test "struct field init with catch" {
199199 try S.doTheTest();
200200 comptime try S.doTheTest();
201201}
202
203test "packed struct field alignment" {
204 const Stage1 = struct {
205 var baz: packed struct {
206 a: u32,
207 b: u32,
208 } = undefined;
209 };
210 const Stage2 = struct {
211 var baz: packed struct {
212 a: u32,
213 b: u32 align(1),
214 } = undefined;
215 };
216 const S = if (builtin.zig_is_stage2) Stage2 else Stage1;
217 try expect(@TypeOf(&S.baz.b) == *align(1) u32);
218}
219
220const blah: packed struct {
221 a: u3,
222 b: u3,
223 c: u2,
224} = undefined;
225
226test "bit field alignment" {
227 try expect(@TypeOf(&blah.b) == *align(1:3:1) const u3);
228}
test/behavior/type.zig-400
......@@ -39,84 +39,6 @@ test "Type.Int" {
3939 try testTypes(&[_]type{ u8, u32, i64 });
4040}
4141
42test "Type.Float" {
43 try testing.expect(f16 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 16 } }));
44 try testing.expect(f32 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 32 } }));
45 try testing.expect(f64 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 64 } }));
46 try testing.expect(f128 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 128 } }));
47 try testTypes(&[_]type{ f16, f32, f64, f128 });
48}
49
50test "Type.Pointer" {
51 try testTypes(&[_]type{
52 // One Value Pointer Types
53 *u8, *const u8,
54 *volatile u8, *const volatile u8,
55 *align(4) u8, *align(4) const u8,
56 *align(4) volatile u8, *align(4) const volatile u8,
57 *align(8) u8, *align(8) const u8,
58 *align(8) volatile u8, *align(8) const volatile u8,
59 *allowzero u8, *allowzero const u8,
60 *allowzero volatile u8, *allowzero const volatile u8,
61 *allowzero align(4) u8, *allowzero align(4) const u8,
62 *allowzero align(4) volatile u8, *allowzero align(4) const volatile u8,
63 // Many Values Pointer Types
64 [*]u8, [*]const u8,
65 [*]volatile u8, [*]const volatile u8,
66 [*]align(4) u8, [*]align(4) const u8,
67 [*]align(4) volatile u8, [*]align(4) const volatile u8,
68 [*]align(8) u8, [*]align(8) const u8,
69 [*]align(8) volatile u8, [*]align(8) const volatile u8,
70 [*]allowzero u8, [*]allowzero const u8,
71 [*]allowzero volatile u8, [*]allowzero const volatile u8,
72 [*]allowzero align(4) u8, [*]allowzero align(4) const u8,
73 [*]allowzero align(4) volatile u8, [*]allowzero align(4) const volatile u8,
74 // Slice Types
75 []u8, []const u8,
76 []volatile u8, []const volatile u8,
77 []align(4) u8, []align(4) const u8,
78 []align(4) volatile u8, []align(4) const volatile u8,
79 []align(8) u8, []align(8) const u8,
80 []align(8) volatile u8, []align(8) const volatile u8,
81 []allowzero u8, []allowzero const u8,
82 []allowzero volatile u8, []allowzero const volatile u8,
83 []allowzero align(4) u8, []allowzero align(4) const u8,
84 []allowzero align(4) volatile u8, []allowzero align(4) const volatile u8,
85 // C Pointer Types
86 [*c]u8, [*c]const u8,
87 [*c]volatile u8, [*c]const volatile u8,
88 [*c]align(4) u8, [*c]align(4) const u8,
89 [*c]align(4) volatile u8, [*c]align(4) const volatile u8,
90 [*c]align(8) u8, [*c]align(8) const u8,
91 [*c]align(8) volatile u8, [*c]align(8) const volatile u8,
92 });
93}
94
95test "Type.Array" {
96 try testing.expect([123]u8 == @Type(TypeInfo{
97 .Array = TypeInfo.Array{
98 .len = 123,
99 .child = u8,
100 .sentinel = null,
101 },
102 }));
103 try testing.expect([2]u32 == @Type(TypeInfo{
104 .Array = TypeInfo.Array{
105 .len = 2,
106 .child = u32,
107 .sentinel = null,
108 },
109 }));
110 try testing.expect([2:0]u32 == @Type(TypeInfo{
111 .Array = TypeInfo.Array{
112 .len = 2,
113 .child = u32,
114 .sentinel = 0,
115 },
116 }));
117 try testTypes(&[_]type{ [1]u8, [30]usize, [7]bool });
118}
119
12042test "Type.ComptimeFloat" {
12143 try testTypes(&[_]type{comptime_float});
12244}
......@@ -129,331 +51,9 @@ test "Type.Undefined" {
12951test "Type.Null" {
13052 try testTypes(&[_]type{@TypeOf(null)});
13153}
132test "@Type create slice with null sentinel" {
133 const Slice = @Type(TypeInfo{
134 .Pointer = .{
135 .size = .Slice,
136 .is_const = true,
137 .is_volatile = false,
138 .is_allowzero = false,
139 .alignment = 8,
140 .address_space = .generic,
141 .child = *i32,
142 .sentinel = null,
143 },
144 });
145 try testing.expect(Slice == []align(8) const *i32);
146}
147test "@Type picks up the sentinel value from TypeInfo" {
148 try testTypes(&[_]type{
149 [11:0]u8, [4:10]u8,
150 [*:0]u8, [*:0]const u8,
151 [*:0]volatile u8, [*:0]const volatile u8,
152 [*:0]align(4) u8, [*:0]align(4) const u8,
153 [*:0]align(4) volatile u8, [*:0]align(4) const volatile u8,
154 [*:0]align(8) u8, [*:0]align(8) const u8,
155 [*:0]align(8) volatile u8, [*:0]align(8) const volatile u8,
156 [*:0]allowzero u8, [*:0]allowzero const u8,
157 [*:0]allowzero volatile u8, [*:0]allowzero const volatile u8,
158 [*:0]allowzero align(4) u8, [*:0]allowzero align(4) const u8,
159 [*:0]allowzero align(4) volatile u8, [*:0]allowzero align(4) const volatile u8,
160 [*:5]allowzero align(4) volatile u8, [*:5]allowzero align(4) const volatile u8,
161 [:0]u8, [:0]const u8,
162 [:0]volatile u8, [:0]const volatile u8,
163 [:0]align(4) u8, [:0]align(4) const u8,
164 [:0]align(4) volatile u8, [:0]align(4) const volatile u8,
165 [:0]align(8) u8, [:0]align(8) const u8,
166 [:0]align(8) volatile u8, [:0]align(8) const volatile u8,
167 [:0]allowzero u8, [:0]allowzero const u8,
168 [:0]allowzero volatile u8, [:0]allowzero const volatile u8,
169 [:0]allowzero align(4) u8, [:0]allowzero align(4) const u8,
170 [:0]allowzero align(4) volatile u8, [:0]allowzero align(4) const volatile u8,
171 [:4]allowzero align(4) volatile u8, [:4]allowzero align(4) const volatile u8,
172 });
173}
174
175test "Type.Optional" {
176 try testTypes(&[_]type{
177 ?u8,
178 ?*u8,
179 ?[]u8,
180 ?[*]u8,
181 ?[*c]u8,
182 });
183}
184
185test "Type.ErrorUnion" {
186 try testTypes(&[_]type{
187 error{}!void,
188 error{Error}!void,
189 });
190}
191
192test "Type.Opaque" {
193 const Opaque = @Type(.{
194 .Opaque = .{
195 .decls = &[_]TypeInfo.Declaration{},
196 },
197 });
198 try testing.expect(Opaque != opaque {});
199 try testing.expectEqualSlices(
200 TypeInfo.Declaration,
201 &[_]TypeInfo.Declaration{},
202 @typeInfo(Opaque).Opaque.decls,
203 );
204}
205
206test "Type.Vector" {
207 try testTypes(&[_]type{
208 @Vector(0, u8),
209 @Vector(4, u8),
210 @Vector(8, *u8),
211 std.meta.Vector(0, u8),
212 std.meta.Vector(4, u8),
213 std.meta.Vector(8, *u8),
214 });
215}
216
217test "Type.AnyFrame" {
218 try testTypes(&[_]type{
219 anyframe,
220 anyframe->u8,
221 anyframe->anyframe->u8,
222 });
223}
22454
22555test "Type.EnumLiteral" {
22656 try testTypes(&[_]type{
22757 @TypeOf(.Dummy),
22858 });
22959}
230
231fn add(a: i32, b: i32) i32 {
232 return a + b;
233}
234
235test "Type.Frame" {
236 try testTypes(&[_]type{
237 @Frame(add),
238 });
239}
240
241test "Type.ErrorSet" {
242 // error sets don't compare equal so just check if they compile
243 _ = @Type(@typeInfo(error{}));
244 _ = @Type(@typeInfo(error{A}));
245 _ = @Type(@typeInfo(error{ A, B, C }));
246}
247
248test "Type.Struct" {
249 const A = @Type(@typeInfo(struct { x: u8, y: u32 }));
250 const infoA = @typeInfo(A).Struct;
251 try testing.expectEqual(TypeInfo.ContainerLayout.Auto, infoA.layout);
252 try testing.expectEqualSlices(u8, "x", infoA.fields[0].name);
253 try testing.expectEqual(u8, infoA.fields[0].field_type);
254 try testing.expectEqual(@as(?u8, null), infoA.fields[0].default_value);
255 try testing.expectEqualSlices(u8, "y", infoA.fields[1].name);
256 try testing.expectEqual(u32, infoA.fields[1].field_type);
257 try testing.expectEqual(@as(?u32, null), infoA.fields[1].default_value);
258 try testing.expectEqualSlices(TypeInfo.Declaration, &[_]TypeInfo.Declaration{}, infoA.decls);
259 try testing.expectEqual(@as(bool, false), infoA.is_tuple);
260
261 var a = A{ .x = 0, .y = 1 };
262 try testing.expectEqual(@as(u8, 0), a.x);
263 try testing.expectEqual(@as(u32, 1), a.y);
264 a.y += 1;
265 try testing.expectEqual(@as(u32, 2), a.y);
266
267 const B = @Type(@typeInfo(extern struct { x: u8, y: u32 = 5 }));
268 const infoB = @typeInfo(B).Struct;
269 try testing.expectEqual(TypeInfo.ContainerLayout.Extern, infoB.layout);
270 try testing.expectEqualSlices(u8, "x", infoB.fields[0].name);
271 try testing.expectEqual(u8, infoB.fields[0].field_type);
272 try testing.expectEqual(@as(?u8, null), infoB.fields[0].default_value);
273 try testing.expectEqualSlices(u8, "y", infoB.fields[1].name);
274 try testing.expectEqual(u32, infoB.fields[1].field_type);
275 try testing.expectEqual(@as(?u32, 5), infoB.fields[1].default_value);
276 try testing.expectEqual(@as(usize, 0), infoB.decls.len);
277 try testing.expectEqual(@as(bool, false), infoB.is_tuple);
278
279 const C = @Type(@typeInfo(packed struct { x: u8 = 3, y: u32 = 5 }));
280 const infoC = @typeInfo(C).Struct;
281 try testing.expectEqual(TypeInfo.ContainerLayout.Packed, infoC.layout);
282 try testing.expectEqualSlices(u8, "x", infoC.fields[0].name);
283 try testing.expectEqual(u8, infoC.fields[0].field_type);
284 try testing.expectEqual(@as(?u8, 3), infoC.fields[0].default_value);
285 try testing.expectEqualSlices(u8, "y", infoC.fields[1].name);
286 try testing.expectEqual(u32, infoC.fields[1].field_type);
287 try testing.expectEqual(@as(?u32, 5), infoC.fields[1].default_value);
288 try testing.expectEqual(@as(usize, 0), infoC.decls.len);
289 try testing.expectEqual(@as(bool, false), infoC.is_tuple);
290}
291
292test "Type.Enum" {
293 const Foo = @Type(.{
294 .Enum = .{
295 .layout = .Auto,
296 .tag_type = u8,
297 .fields = &[_]TypeInfo.EnumField{
298 .{ .name = "a", .value = 1 },
299 .{ .name = "b", .value = 5 },
300 },
301 .decls = &[_]TypeInfo.Declaration{},
302 .is_exhaustive = true,
303 },
304 });
305 try testing.expectEqual(true, @typeInfo(Foo).Enum.is_exhaustive);
306 try testing.expectEqual(@as(u8, 1), @enumToInt(Foo.a));
307 try testing.expectEqual(@as(u8, 5), @enumToInt(Foo.b));
308 const Bar = @Type(.{
309 .Enum = .{
310 .layout = .Extern,
311 .tag_type = u32,
312 .fields = &[_]TypeInfo.EnumField{
313 .{ .name = "a", .value = 1 },
314 .{ .name = "b", .value = 5 },
315 },
316 .decls = &[_]TypeInfo.Declaration{},
317 .is_exhaustive = false,
318 },
319 });
320 try testing.expectEqual(false, @typeInfo(Bar).Enum.is_exhaustive);
321 try testing.expectEqual(@as(u32, 1), @enumToInt(Bar.a));
322 try testing.expectEqual(@as(u32, 5), @enumToInt(Bar.b));
323 try testing.expectEqual(@as(u32, 6), @enumToInt(@intToEnum(Bar, 6)));
324}
325
326test "Type.Union" {
327 const Untagged = @Type(.{
328 .Union = .{
329 .layout = .Auto,
330 .tag_type = null,
331 .fields = &[_]TypeInfo.UnionField{
332 .{ .name = "int", .field_type = i32, .alignment = @alignOf(f32) },
333 .{ .name = "float", .field_type = f32, .alignment = @alignOf(f32) },
334 },
335 .decls = &[_]TypeInfo.Declaration{},
336 },
337 });
338 var untagged = Untagged{ .int = 1 };
339 untagged.float = 2.0;
340 untagged.int = 3;
341 try testing.expectEqual(@as(i32, 3), untagged.int);
342
343 const PackedUntagged = @Type(.{
344 .Union = .{
345 .layout = .Packed,
346 .tag_type = null,
347 .fields = &[_]TypeInfo.UnionField{
348 .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
349 .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
350 },
351 .decls = &[_]TypeInfo.Declaration{},
352 },
353 });
354 var packed_untagged = PackedUntagged{ .signed = -1 };
355 try testing.expectEqual(@as(i32, -1), packed_untagged.signed);
356 try testing.expectEqual(~@as(u32, 0), packed_untagged.unsigned);
357
358 const Tag = @Type(.{
359 .Enum = .{
360 .layout = .Auto,
361 .tag_type = u1,
362 .fields = &[_]TypeInfo.EnumField{
363 .{ .name = "signed", .value = 0 },
364 .{ .name = "unsigned", .value = 1 },
365 },
366 .decls = &[_]TypeInfo.Declaration{},
367 .is_exhaustive = true,
368 },
369 });
370 const Tagged = @Type(.{
371 .Union = .{
372 .layout = .Auto,
373 .tag_type = Tag,
374 .fields = &[_]TypeInfo.UnionField{
375 .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
376 .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
377 },
378 .decls = &[_]TypeInfo.Declaration{},
379 },
380 });
381 var tagged = Tagged{ .signed = -1 };
382 try testing.expectEqual(Tag.signed, tagged);
383 tagged = .{ .unsigned = 1 };
384 try testing.expectEqual(Tag.unsigned, tagged);
385}
386
387test "Type.Union from Type.Enum" {
388 const Tag = @Type(.{
389 .Enum = .{
390 .layout = .Auto,
391 .tag_type = u0,
392 .fields = &[_]TypeInfo.EnumField{
393 .{ .name = "working_as_expected", .value = 0 },
394 },
395 .decls = &[_]TypeInfo.Declaration{},
396 .is_exhaustive = true,
397 },
398 });
399 const T = @Type(.{
400 .Union = .{
401 .layout = .Auto,
402 .tag_type = Tag,
403 .fields = &[_]TypeInfo.UnionField{
404 .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
405 },
406 .decls = &[_]TypeInfo.Declaration{},
407 },
408 });
409 _ = T;
410 _ = @typeInfo(T).Union;
411}
412
413test "Type.Union from regular enum" {
414 const E = enum { working_as_expected };
415 const T = @Type(.{
416 .Union = .{
417 .layout = .Auto,
418 .tag_type = E,
419 .fields = &[_]TypeInfo.UnionField{
420 .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
421 },
422 .decls = &[_]TypeInfo.Declaration{},
423 },
424 });
425 _ = T;
426 _ = @typeInfo(T).Union;
427}
428
429test "Type.Fn" {
430 // wasm doesn't support align attributes on functions
431 if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
432
433 const foo = struct {
434 fn func(a: usize, b: bool) align(4) callconv(.C) usize {
435 _ = a;
436 _ = b;
437 return 0;
438 }
439 }.func;
440 const Foo = @Type(@typeInfo(@TypeOf(foo)));
441 const foo_2: Foo = foo;
442 _ = foo_2;
443}
444
445test "Type.BoundFn" {
446 // wasm doesn't support align attributes on functions
447 if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
448
449 const TestStruct = packed struct {
450 pub fn foo(self: *const @This()) align(4) callconv(.Unspecified) void {
451 _ = self;
452 }
453 };
454 const test_instance: TestStruct = undefined;
455 try testing.expect(std.meta.eql(
456 @typeName(@TypeOf(test_instance.foo)),
457 @typeName(@Type(@typeInfo(@TypeOf(test_instance.foo)))),
458 ));
459}
test/behavior/type_info.zig-454
......@@ -8,18 +8,6 @@ const TypeId = std.builtin.TypeId;
88const expect = std.testing.expect;
99const expectEqualStrings = std.testing.expectEqualStrings;
1010
11test "type info: tag type, void info" {
12 try testBasic();
13 comptime try testBasic();
14}
15
16fn testBasic() !void {
17 try expect(@typeInfo(TypeInfo).Union.tag_type == TypeId);
18 const void_info = @typeInfo(void);
19 try expect(void_info == TypeId.Void);
20 try expect(void_info.Void == {});
21}
22
2311test "type info: integer, floating point type info" {
2412 try testIntFloat();
2513 comptime try testIntFloat();
......@@ -36,107 +24,6 @@ fn testIntFloat() !void {
3624 try expect(f64_info.Float.bits == 64);
3725}
3826
39test "type info: pointer type info" {
40 try testPointer();
41 comptime try testPointer();
42}
43
44fn testPointer() !void {
45 const u32_ptr_info = @typeInfo(*u32);
46 try expect(u32_ptr_info == .Pointer);
47 try expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One);
48 try expect(u32_ptr_info.Pointer.is_const == false);
49 try expect(u32_ptr_info.Pointer.is_volatile == false);
50 try expect(u32_ptr_info.Pointer.alignment == @alignOf(u32));
51 try expect(u32_ptr_info.Pointer.child == u32);
52 try expect(u32_ptr_info.Pointer.sentinel == null);
53}
54
55test "type info: unknown length pointer type info" {
56 try testUnknownLenPtr();
57 comptime try testUnknownLenPtr();
58}
59
60fn testUnknownLenPtr() !void {
61 const u32_ptr_info = @typeInfo([*]const volatile f64);
62 try expect(u32_ptr_info == .Pointer);
63 try expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
64 try expect(u32_ptr_info.Pointer.is_const == true);
65 try expect(u32_ptr_info.Pointer.is_volatile == true);
66 try expect(u32_ptr_info.Pointer.sentinel == null);
67 try expect(u32_ptr_info.Pointer.alignment == @alignOf(f64));
68 try expect(u32_ptr_info.Pointer.child == f64);
69}
70
71test "type info: null terminated pointer type info" {
72 try testNullTerminatedPtr();
73 comptime try testNullTerminatedPtr();
74}
75
76fn testNullTerminatedPtr() !void {
77 const ptr_info = @typeInfo([*:0]u8);
78 try expect(ptr_info == .Pointer);
79 try expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
80 try expect(ptr_info.Pointer.is_const == false);
81 try expect(ptr_info.Pointer.is_volatile == false);
82 try expect(ptr_info.Pointer.sentinel.? == 0);
83
84 try expect(@typeInfo([:0]u8).Pointer.sentinel != null);
85}
86
87test "type info: C pointer type info" {
88 try testCPtr();
89 comptime try testCPtr();
90}
91
92fn testCPtr() !void {
93 const ptr_info = @typeInfo([*c]align(4) const i8);
94 try expect(ptr_info == .Pointer);
95 try expect(ptr_info.Pointer.size == .C);
96 try expect(ptr_info.Pointer.is_const);
97 try expect(!ptr_info.Pointer.is_volatile);
98 try expect(ptr_info.Pointer.alignment == 4);
99 try expect(ptr_info.Pointer.child == i8);
100}
101
102test "type info: slice type info" {
103 try testSlice();
104 comptime try testSlice();
105}
106
107fn testSlice() !void {
108 const u32_slice_info = @typeInfo([]u32);
109 try expect(u32_slice_info == .Pointer);
110 try expect(u32_slice_info.Pointer.size == .Slice);
111 try expect(u32_slice_info.Pointer.is_const == false);
112 try expect(u32_slice_info.Pointer.is_volatile == false);
113 try expect(u32_slice_info.Pointer.alignment == 4);
114 try expect(u32_slice_info.Pointer.child == u32);
115}
116
117test "type info: array type info" {
118 try testArray();
119 comptime try testArray();
120}
121
122fn testArray() !void {
123 {
124 const info = @typeInfo([42]u8);
125 try expect(info == .Array);
126 try expect(info.Array.len == 42);
127 try expect(info.Array.child == u8);
128 try expect(info.Array.sentinel == null);
129 }
130
131 {
132 const info = @typeInfo([10:0]u8);
133 try expect(info.Array.len == 10);
134 try expect(info.Array.child == u8);
135 try expect(info.Array.sentinel.? == @as(u8, 0));
136 try expect(@sizeOf([10:0]u8) == info.Array.len + 1);
137 }
138}
139
14027test "type info: optional type info" {
14128 try testOptional();
14229 comptime try testOptional();
......@@ -147,344 +34,3 @@ fn testOptional() !void {
14734 try expect(null_info == .Optional);
14835 try expect(null_info.Optional.child == void);
14936}
150
151test "type info: error set, error union info" {
152 try testErrorSet();
153 comptime try testErrorSet();
154}
155
156fn testErrorSet() !void {
157 const TestErrorSet = error{
158 First,
159 Second,
160 Third,
161 };
162
163 const error_set_info = @typeInfo(TestErrorSet);
164 try expect(error_set_info == .ErrorSet);
165 try expect(error_set_info.ErrorSet.?.len == 3);
166 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "First"));
167
168 const error_union_info = @typeInfo(TestErrorSet!usize);
169 try expect(error_union_info == .ErrorUnion);
170 try expect(error_union_info.ErrorUnion.error_set == TestErrorSet);
171 try expect(error_union_info.ErrorUnion.payload == usize);
172
173 const global_info = @typeInfo(anyerror);
174 try expect(global_info == .ErrorSet);
175 try expect(global_info.ErrorSet == null);
176}
177
178test "type info: enum info" {
179 try testEnum();
180 comptime try testEnum();
181}
182
183fn testEnum() !void {
184 const Os = enum {
185 Windows,
186 Macos,
187 Linux,
188 FreeBSD,
189 };
190
191 const os_info = @typeInfo(Os);
192 try expect(os_info == .Enum);
193 try expect(os_info.Enum.layout == .Auto);
194 try expect(os_info.Enum.fields.len == 4);
195 try expect(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
196 try expect(os_info.Enum.fields[3].value == 3);
197 try expect(os_info.Enum.tag_type == u2);
198 try expect(os_info.Enum.decls.len == 0);
199}
200
201test "type info: union info" {
202 try testUnion();
203 comptime try testUnion();
204}
205
206fn testUnion() !void {
207 const typeinfo_info = @typeInfo(TypeInfo);
208 try expect(typeinfo_info == .Union);
209 try expect(typeinfo_info.Union.layout == .Auto);
210 try expect(typeinfo_info.Union.tag_type.? == TypeId);
211 try expect(typeinfo_info.Union.fields.len == 25);
212 try expect(typeinfo_info.Union.fields[4].field_type == @TypeOf(@typeInfo(u8).Int));
213 try expect(typeinfo_info.Union.decls.len == 22);
214
215 const TestNoTagUnion = union {
216 Foo: void,
217 Bar: u32,
218 };
219
220 const notag_union_info = @typeInfo(TestNoTagUnion);
221 try expect(notag_union_info == .Union);
222 try expect(notag_union_info.Union.tag_type == null);
223 try expect(notag_union_info.Union.layout == .Auto);
224 try expect(notag_union_info.Union.fields.len == 2);
225 try expect(notag_union_info.Union.fields[0].alignment == @alignOf(void));
226 try expect(notag_union_info.Union.fields[1].field_type == u32);
227 try expect(notag_union_info.Union.fields[1].alignment == @alignOf(u32));
228
229 const TestExternUnion = extern union {
230 foo: *anyopaque,
231 };
232
233 const extern_union_info = @typeInfo(TestExternUnion);
234 try expect(extern_union_info.Union.layout == .Extern);
235 try expect(extern_union_info.Union.tag_type == null);
236 try expect(extern_union_info.Union.fields[0].field_type == *anyopaque);
237}
238
239test "type info: struct info" {
240 try testStruct();
241 comptime try testStruct();
242}
243
244fn testStruct() !void {
245 const unpacked_struct_info = @typeInfo(TestUnpackedStruct);
246 try expect(unpacked_struct_info.Struct.is_tuple == false);
247 try expect(unpacked_struct_info.Struct.fields[0].alignment == @alignOf(u32));
248 try expect(unpacked_struct_info.Struct.fields[0].default_value.? == 4);
249 try expectEqualStrings("foobar", unpacked_struct_info.Struct.fields[1].default_value.?);
250
251 const struct_info = @typeInfo(TestStruct);
252 try expect(struct_info == .Struct);
253 try expect(struct_info.Struct.is_tuple == false);
254 try expect(struct_info.Struct.layout == .Packed);
255 try expect(struct_info.Struct.fields.len == 4);
256 try expect(struct_info.Struct.fields[0].alignment == 2 * @alignOf(usize));
257 try expect(struct_info.Struct.fields[2].field_type == *TestStruct);
258 try expect(struct_info.Struct.fields[2].default_value == null);
259 try expect(struct_info.Struct.fields[3].default_value.? == 4);
260 try expect(struct_info.Struct.fields[3].alignment == 1);
261 try expect(struct_info.Struct.decls.len == 2);
262 try expect(struct_info.Struct.decls[0].is_pub);
263 try expect(!struct_info.Struct.decls[0].data.Fn.is_extern);
264 try expect(struct_info.Struct.decls[0].data.Fn.lib_name == null);
265 try expect(struct_info.Struct.decls[0].data.Fn.return_type == void);
266 try expect(struct_info.Struct.decls[0].data.Fn.fn_type == fn (*const TestStruct) void);
267}
268
269const TestUnpackedStruct = struct {
270 fieldA: u32 = 4,
271 fieldB: *const [6:0]u8 = "foobar",
272};
273
274const TestStruct = packed struct {
275 fieldA: usize align(2 * @alignOf(usize)),
276 fieldB: void,
277 fieldC: *Self,
278 fieldD: u32 = 4,
279
280 pub fn foo(self: *const Self) void {
281 _ = self;
282 }
283 const Self = @This();
284};
285
286test "type info: opaque info" {
287 try testOpaque();
288 comptime try testOpaque();
289}
290
291fn testOpaque() !void {
292 const Foo = opaque {
293 const A = 1;
294 fn b() void {}
295 };
296
297 const foo_info = @typeInfo(Foo);
298 try expect(foo_info.Opaque.decls.len == 2);
299}
300
301test "type info: function type info" {
302 // wasm doesn't support align attributes on functions
303 if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
304 try testFunction();
305 comptime try testFunction();
306}
307
308fn testFunction() !void {
309 const fn_info = @typeInfo(@TypeOf(foo));
310 try expect(fn_info == .Fn);
311 try expect(fn_info.Fn.alignment > 0);
312 try expect(fn_info.Fn.calling_convention == .C);
313 try expect(!fn_info.Fn.is_generic);
314 try expect(fn_info.Fn.args.len == 2);
315 try expect(fn_info.Fn.is_var_args);
316 try expect(fn_info.Fn.return_type.? == usize);
317 const fn_aligned_info = @typeInfo(@TypeOf(fooAligned));
318 try expect(fn_aligned_info.Fn.alignment == 4);
319
320 const test_instance: TestStruct = undefined;
321 const bound_fn_info = @typeInfo(@TypeOf(test_instance.foo));
322 try expect(bound_fn_info == .BoundFn);
323 try expect(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
324}
325
326extern fn foo(a: usize, b: bool, ...) callconv(.C) usize;
327extern fn fooAligned(a: usize, b: bool, ...) align(4) callconv(.C) usize;
328
329test "typeInfo with comptime parameter in struct fn def" {
330 const S = struct {
331 pub fn func(comptime x: f32) void {
332 _ = x;
333 }
334 };
335 comptime var info = @typeInfo(S);
336 _ = info;
337}
338
339test "type info: vectors" {
340 try testVector();
341 comptime try testVector();
342}
343
344fn testVector() !void {
345 const vec_info = @typeInfo(std.meta.Vector(4, i32));
346 try expect(vec_info == .Vector);
347 try expect(vec_info.Vector.len == 4);
348 try expect(vec_info.Vector.child == i32);
349}
350
351test "type info: anyframe and anyframe->T" {
352 try testAnyFrame();
353 comptime try testAnyFrame();
354}
355
356fn testAnyFrame() !void {
357 {
358 const anyframe_info = @typeInfo(anyframe->i32);
359 try expect(anyframe_info == .AnyFrame);
360 try expect(anyframe_info.AnyFrame.child.? == i32);
361 }
362
363 {
364 const anyframe_info = @typeInfo(anyframe);
365 try expect(anyframe_info == .AnyFrame);
366 try expect(anyframe_info.AnyFrame.child == null);
367 }
368}
369
370test "type info: pass to function" {
371 _ = passTypeInfo(@typeInfo(void));
372 _ = comptime passTypeInfo(@typeInfo(void));
373}
374
375fn passTypeInfo(comptime info: TypeInfo) type {
376 _ = info;
377 return void;
378}
379
380test "type info: TypeId -> TypeInfo impl cast" {
381 _ = passTypeInfo(TypeId.Void);
382 _ = comptime passTypeInfo(TypeId.Void);
383}
384
385test "type info: extern fns with and without lib names" {
386 const S = struct {
387 extern fn bar1() void;
388 extern "cool" fn bar2() void;
389 };
390 const info = @typeInfo(S);
391 comptime {
392 for (info.Struct.decls) |decl| {
393 if (std.mem.eql(u8, decl.name, "bar1")) {
394 try expect(decl.data.Fn.lib_name == null);
395 } else {
396 try expectEqualStrings("cool", decl.data.Fn.lib_name.?);
397 }
398 }
399 }
400}
401
402test "data field is a compile-time value" {
403 const S = struct {
404 const Bar = @as(isize, -1);
405 };
406 comptime try expect(@typeInfo(S).Struct.decls[0].data.Var == isize);
407}
408
409test "sentinel of opaque pointer type" {
410 const c_void_info = @typeInfo(*anyopaque);
411 try expect(c_void_info.Pointer.sentinel == null);
412}
413
414test "@typeInfo does not force declarations into existence" {
415 const S = struct {
416 x: i32,
417
418 fn doNotReferenceMe() void {
419 @compileError("test failed");
420 }
421 };
422 comptime try expect(@typeInfo(S).Struct.fields.len == 1);
423}
424
425test "defaut value for a var-typed field" {
426 const S = struct { x: anytype };
427 try expect(@typeInfo(S).Struct.fields[0].default_value == null);
428}
429
430fn add(a: i32, b: i32) i32 {
431 return a + b;
432}
433
434test "type info for async frames" {
435 switch (@typeInfo(@Frame(add))) {
436 .Frame => |frame| {
437 try expect(frame.function == add);
438 },
439 else => unreachable,
440 }
441}
442
443test "type info: value is correctly copied" {
444 comptime {
445 var ptrInfo = @typeInfo([]u32);
446 ptrInfo.Pointer.size = .One;
447 try expect(@typeInfo([]u32).Pointer.size == .Slice);
448 }
449}
450
451test "Declarations are returned in declaration order" {
452 const S = struct {
453 const a = 1;
454 const b = 2;
455 const c = 3;
456 const d = 4;
457 const e = 5;
458 };
459 const d = @typeInfo(S).Struct.decls;
460 try expect(std.mem.eql(u8, d[0].name, "a"));
461 try expect(std.mem.eql(u8, d[1].name, "b"));
462 try expect(std.mem.eql(u8, d[2].name, "c"));
463 try expect(std.mem.eql(u8, d[3].name, "d"));
464 try expect(std.mem.eql(u8, d[4].name, "e"));
465}
466
467test "Struct.is_tuple" {
468 try expect(@typeInfo(@TypeOf(.{0})).Struct.is_tuple);
469 try expect(!@typeInfo(@TypeOf(.{ .a = 0 })).Struct.is_tuple);
470}
471
472test "StructField.is_comptime" {
473 const info = @typeInfo(struct { x: u8 = 3, comptime y: u32 = 5 }).Struct;
474 try expect(!info.fields[0].is_comptime);
475 try expect(info.fields[1].is_comptime);
476}
477
478test "typeInfo resolves usingnamespace declarations" {
479 const A = struct {
480 pub const f1 = 42;
481 };
482
483 const B = struct {
484 const f0 = 42;
485 usingnamespace A;
486 };
487
488 try expect(@typeInfo(B).Struct.decls.len == 2);
489 //a
490}
test/behavior/type_info_stage1.zig created+463
......@@ -0,0 +1,463 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const mem = std.mem;
4
5const TypeInfo = std.builtin.TypeInfo;
6const TypeId = std.builtin.TypeId;
7
8const expect = std.testing.expect;
9const expectEqualStrings = std.testing.expectEqualStrings;
10
11test "type info: tag type, void info" {
12 try testBasic();
13 comptime try testBasic();
14}
15
16fn testBasic() !void {
17 try expect(@typeInfo(TypeInfo).Union.tag_type == TypeId);
18 const void_info = @typeInfo(void);
19 try expect(void_info == TypeId.Void);
20 try expect(void_info.Void == {});
21}
22
23test "type info: pointer type info" {
24 try testPointer();
25 comptime try testPointer();
26}
27
28fn testPointer() !void {
29 const u32_ptr_info = @typeInfo(*u32);
30 try expect(u32_ptr_info == .Pointer);
31 try expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One);
32 try expect(u32_ptr_info.Pointer.is_const == false);
33 try expect(u32_ptr_info.Pointer.is_volatile == false);
34 try expect(u32_ptr_info.Pointer.alignment == @alignOf(u32));
35 try expect(u32_ptr_info.Pointer.child == u32);
36 try expect(u32_ptr_info.Pointer.sentinel == null);
37}
38
39test "type info: unknown length pointer type info" {
40 try testUnknownLenPtr();
41 comptime try testUnknownLenPtr();
42}
43
44fn testUnknownLenPtr() !void {
45 const u32_ptr_info = @typeInfo([*]const volatile f64);
46 try expect(u32_ptr_info == .Pointer);
47 try expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
48 try expect(u32_ptr_info.Pointer.is_const == true);
49 try expect(u32_ptr_info.Pointer.is_volatile == true);
50 try expect(u32_ptr_info.Pointer.sentinel == null);
51 try expect(u32_ptr_info.Pointer.alignment == @alignOf(f64));
52 try expect(u32_ptr_info.Pointer.child == f64);
53}
54
55test "type info: null terminated pointer type info" {
56 try testNullTerminatedPtr();
57 comptime try testNullTerminatedPtr();
58}
59
60fn testNullTerminatedPtr() !void {
61 const ptr_info = @typeInfo([*:0]u8);
62 try expect(ptr_info == .Pointer);
63 try expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
64 try expect(ptr_info.Pointer.is_const == false);
65 try expect(ptr_info.Pointer.is_volatile == false);
66 try expect(ptr_info.Pointer.sentinel.? == 0);
67
68 try expect(@typeInfo([:0]u8).Pointer.sentinel != null);
69}
70
71test "type info: C pointer type info" {
72 try testCPtr();
73 comptime try testCPtr();
74}
75
76fn testCPtr() !void {
77 const ptr_info = @typeInfo([*c]align(4) const i8);
78 try expect(ptr_info == .Pointer);
79 try expect(ptr_info.Pointer.size == .C);
80 try expect(ptr_info.Pointer.is_const);
81 try expect(!ptr_info.Pointer.is_volatile);
82 try expect(ptr_info.Pointer.alignment == 4);
83 try expect(ptr_info.Pointer.child == i8);
84}
85
86test "type info: slice type info" {
87 try testSlice();
88 comptime try testSlice();
89}
90
91fn testSlice() !void {
92 const u32_slice_info = @typeInfo([]u32);
93 try expect(u32_slice_info == .Pointer);
94 try expect(u32_slice_info.Pointer.size == .Slice);
95 try expect(u32_slice_info.Pointer.is_const == false);
96 try expect(u32_slice_info.Pointer.is_volatile == false);
97 try expect(u32_slice_info.Pointer.alignment == 4);
98 try expect(u32_slice_info.Pointer.child == u32);
99}
100
101test "type info: array type info" {
102 try testArray();
103 comptime try testArray();
104}
105
106fn testArray() !void {
107 {
108 const info = @typeInfo([42]u8);
109 try expect(info == .Array);
110 try expect(info.Array.len == 42);
111 try expect(info.Array.child == u8);
112 try expect(info.Array.sentinel == null);
113 }
114
115 {
116 const info = @typeInfo([10:0]u8);
117 try expect(info.Array.len == 10);
118 try expect(info.Array.child == u8);
119 try expect(info.Array.sentinel.? == @as(u8, 0));
120 try expect(@sizeOf([10:0]u8) == info.Array.len + 1);
121 }
122}
123
124test "type info: error set, error union info" {
125 try testErrorSet();
126 comptime try testErrorSet();
127}
128
129fn testErrorSet() !void {
130 const TestErrorSet = error{
131 First,
132 Second,
133 Third,
134 };
135
136 const error_set_info = @typeInfo(TestErrorSet);
137 try expect(error_set_info == .ErrorSet);
138 try expect(error_set_info.ErrorSet.?.len == 3);
139 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "First"));
140
141 const error_union_info = @typeInfo(TestErrorSet!usize);
142 try expect(error_union_info == .ErrorUnion);
143 try expect(error_union_info.ErrorUnion.error_set == TestErrorSet);
144 try expect(error_union_info.ErrorUnion.payload == usize);
145
146 const global_info = @typeInfo(anyerror);
147 try expect(global_info == .ErrorSet);
148 try expect(global_info.ErrorSet == null);
149}
150
151test "type info: enum info" {
152 try testEnum();
153 comptime try testEnum();
154}
155
156fn testEnum() !void {
157 const Os = enum {
158 Windows,
159 Macos,
160 Linux,
161 FreeBSD,
162 };
163
164 const os_info = @typeInfo(Os);
165 try expect(os_info == .Enum);
166 try expect(os_info.Enum.layout == .Auto);
167 try expect(os_info.Enum.fields.len == 4);
168 try expect(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
169 try expect(os_info.Enum.fields[3].value == 3);
170 try expect(os_info.Enum.tag_type == u2);
171 try expect(os_info.Enum.decls.len == 0);
172}
173
174test "type info: union info" {
175 try testUnion();
176 comptime try testUnion();
177}
178
179fn testUnion() !void {
180 const typeinfo_info = @typeInfo(TypeInfo);
181 try expect(typeinfo_info == .Union);
182 try expect(typeinfo_info.Union.layout == .Auto);
183 try expect(typeinfo_info.Union.tag_type.? == TypeId);
184 try expect(typeinfo_info.Union.fields.len == 25);
185 try expect(typeinfo_info.Union.fields[4].field_type == @TypeOf(@typeInfo(u8).Int));
186 try expect(typeinfo_info.Union.decls.len == 22);
187
188 const TestNoTagUnion = union {
189 Foo: void,
190 Bar: u32,
191 };
192
193 const notag_union_info = @typeInfo(TestNoTagUnion);
194 try expect(notag_union_info == .Union);
195 try expect(notag_union_info.Union.tag_type == null);
196 try expect(notag_union_info.Union.layout == .Auto);
197 try expect(notag_union_info.Union.fields.len == 2);
198 try expect(notag_union_info.Union.fields[0].alignment == @alignOf(void));
199 try expect(notag_union_info.Union.fields[1].field_type == u32);
200 try expect(notag_union_info.Union.fields[1].alignment == @alignOf(u32));
201
202 const TestExternUnion = extern union {
203 foo: *anyopaque,
204 };
205
206 const extern_union_info = @typeInfo(TestExternUnion);
207 try expect(extern_union_info.Union.layout == .Extern);
208 try expect(extern_union_info.Union.tag_type == null);
209 try expect(extern_union_info.Union.fields[0].field_type == *anyopaque);
210}
211
212test "type info: struct info" {
213 try testStruct();
214 comptime try testStruct();
215}
216
217fn testStruct() !void {
218 const unpacked_struct_info = @typeInfo(TestUnpackedStruct);
219 try expect(unpacked_struct_info.Struct.is_tuple == false);
220 try expect(unpacked_struct_info.Struct.fields[0].alignment == @alignOf(u32));
221 try expect(unpacked_struct_info.Struct.fields[0].default_value.? == 4);
222 try expectEqualStrings("foobar", unpacked_struct_info.Struct.fields[1].default_value.?);
223
224 const struct_info = @typeInfo(TestStruct);
225 try expect(struct_info == .Struct);
226 try expect(struct_info.Struct.is_tuple == false);
227 try expect(struct_info.Struct.layout == .Packed);
228 try expect(struct_info.Struct.fields.len == 4);
229 try expect(struct_info.Struct.fields[0].alignment == 2 * @alignOf(usize));
230 try expect(struct_info.Struct.fields[2].field_type == *TestStruct);
231 try expect(struct_info.Struct.fields[2].default_value == null);
232 try expect(struct_info.Struct.fields[3].default_value.? == 4);
233 try expect(struct_info.Struct.fields[3].alignment == 1);
234 try expect(struct_info.Struct.decls.len == 2);
235 try expect(struct_info.Struct.decls[0].is_pub);
236 try expect(!struct_info.Struct.decls[0].data.Fn.is_extern);
237 try expect(struct_info.Struct.decls[0].data.Fn.lib_name == null);
238 try expect(struct_info.Struct.decls[0].data.Fn.return_type == void);
239 try expect(struct_info.Struct.decls[0].data.Fn.fn_type == fn (*const TestStruct) void);
240}
241
242const TestUnpackedStruct = struct {
243 fieldA: u32 = 4,
244 fieldB: *const [6:0]u8 = "foobar",
245};
246
247const TestStruct = packed struct {
248 fieldA: usize align(2 * @alignOf(usize)),
249 fieldB: void,
250 fieldC: *Self,
251 fieldD: u32 = 4,
252
253 pub fn foo(self: *const Self) void {
254 _ = self;
255 }
256 const Self = @This();
257};
258
259test "type info: opaque info" {
260 try testOpaque();
261 comptime try testOpaque();
262}
263
264fn testOpaque() !void {
265 const Foo = opaque {
266 const A = 1;
267 fn b() void {}
268 };
269
270 const foo_info = @typeInfo(Foo);
271 try expect(foo_info.Opaque.decls.len == 2);
272}
273
274test "type info: function type info" {
275 // wasm doesn't support align attributes on functions
276 if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
277 try testFunction();
278 comptime try testFunction();
279}
280
281fn testFunction() !void {
282 const fn_info = @typeInfo(@TypeOf(foo));
283 try expect(fn_info == .Fn);
284 try expect(fn_info.Fn.alignment > 0);
285 try expect(fn_info.Fn.calling_convention == .C);
286 try expect(!fn_info.Fn.is_generic);
287 try expect(fn_info.Fn.args.len == 2);
288 try expect(fn_info.Fn.is_var_args);
289 try expect(fn_info.Fn.return_type.? == usize);
290 const fn_aligned_info = @typeInfo(@TypeOf(fooAligned));
291 try expect(fn_aligned_info.Fn.alignment == 4);
292
293 const test_instance: TestStruct = undefined;
294 const bound_fn_info = @typeInfo(@TypeOf(test_instance.foo));
295 try expect(bound_fn_info == .BoundFn);
296 try expect(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
297}
298
299extern fn foo(a: usize, b: bool, ...) callconv(.C) usize;
300extern fn fooAligned(a: usize, b: bool, ...) align(4) callconv(.C) usize;
301
302test "typeInfo with comptime parameter in struct fn def" {
303 const S = struct {
304 pub fn func(comptime x: f32) void {
305 _ = x;
306 }
307 };
308 comptime var info = @typeInfo(S);
309 _ = info;
310}
311
312test "type info: vectors" {
313 try testVector();
314 comptime try testVector();
315}
316
317fn testVector() !void {
318 const vec_info = @typeInfo(std.meta.Vector(4, i32));
319 try expect(vec_info == .Vector);
320 try expect(vec_info.Vector.len == 4);
321 try expect(vec_info.Vector.child == i32);
322}
323
324test "type info: anyframe and anyframe->T" {
325 try testAnyFrame();
326 comptime try testAnyFrame();
327}
328
329fn testAnyFrame() !void {
330 {
331 const anyframe_info = @typeInfo(anyframe->i32);
332 try expect(anyframe_info == .AnyFrame);
333 try expect(anyframe_info.AnyFrame.child.? == i32);
334 }
335
336 {
337 const anyframe_info = @typeInfo(anyframe);
338 try expect(anyframe_info == .AnyFrame);
339 try expect(anyframe_info.AnyFrame.child == null);
340 }
341}
342
343test "type info: pass to function" {
344 _ = passTypeInfo(@typeInfo(void));
345 _ = comptime passTypeInfo(@typeInfo(void));
346}
347
348fn passTypeInfo(comptime info: TypeInfo) type {
349 _ = info;
350 return void;
351}
352
353test "type info: TypeId -> TypeInfo impl cast" {
354 _ = passTypeInfo(TypeId.Void);
355 _ = comptime passTypeInfo(TypeId.Void);
356}
357
358test "type info: extern fns with and without lib names" {
359 const S = struct {
360 extern fn bar1() void;
361 extern "cool" fn bar2() void;
362 };
363 const info = @typeInfo(S);
364 comptime {
365 for (info.Struct.decls) |decl| {
366 if (std.mem.eql(u8, decl.name, "bar1")) {
367 try expect(decl.data.Fn.lib_name == null);
368 } else {
369 try expectEqualStrings("cool", decl.data.Fn.lib_name.?);
370 }
371 }
372 }
373}
374
375test "data field is a compile-time value" {
376 const S = struct {
377 const Bar = @as(isize, -1);
378 };
379 comptime try expect(@typeInfo(S).Struct.decls[0].data.Var == isize);
380}
381
382test "sentinel of opaque pointer type" {
383 const c_void_info = @typeInfo(*anyopaque);
384 try expect(c_void_info.Pointer.sentinel == null);
385}
386
387test "@typeInfo does not force declarations into existence" {
388 const S = struct {
389 x: i32,
390
391 fn doNotReferenceMe() void {
392 @compileError("test failed");
393 }
394 };
395 comptime try expect(@typeInfo(S).Struct.fields.len == 1);
396}
397
398test "defaut value for a var-typed field" {
399 const S = struct { x: anytype };
400 try expect(@typeInfo(S).Struct.fields[0].default_value == null);
401}
402
403fn add(a: i32, b: i32) i32 {
404 return a + b;
405}
406
407test "type info for async frames" {
408 switch (@typeInfo(@Frame(add))) {
409 .Frame => |frame| {
410 try expect(frame.function == add);
411 },
412 else => unreachable,
413 }
414}
415
416test "type info: value is correctly copied" {
417 comptime {
418 var ptrInfo = @typeInfo([]u32);
419 ptrInfo.Pointer.size = .One;
420 try expect(@typeInfo([]u32).Pointer.size == .Slice);
421 }
422}
423
424test "Declarations are returned in declaration order" {
425 const S = struct {
426 const a = 1;
427 const b = 2;
428 const c = 3;
429 const d = 4;
430 const e = 5;
431 };
432 const d = @typeInfo(S).Struct.decls;
433 try expect(std.mem.eql(u8, d[0].name, "a"));
434 try expect(std.mem.eql(u8, d[1].name, "b"));
435 try expect(std.mem.eql(u8, d[2].name, "c"));
436 try expect(std.mem.eql(u8, d[3].name, "d"));
437 try expect(std.mem.eql(u8, d[4].name, "e"));
438}
439
440test "Struct.is_tuple" {
441 try expect(@typeInfo(@TypeOf(.{0})).Struct.is_tuple);
442 try expect(!@typeInfo(@TypeOf(.{ .a = 0 })).Struct.is_tuple);
443}
444
445test "StructField.is_comptime" {
446 const info = @typeInfo(struct { x: u8 = 3, comptime y: u32 = 5 }).Struct;
447 try expect(!info.fields[0].is_comptime);
448 try expect(info.fields[1].is_comptime);
449}
450
451test "typeInfo resolves usingnamespace declarations" {
452 const A = struct {
453 pub const f1 = 42;
454 };
455
456 const B = struct {
457 const f0 = 42;
458 usingnamespace A;
459 };
460
461 try expect(@typeInfo(B).Struct.decls.len == 2);
462 //a
463}
test/behavior/type_stage1.zig created+411
......@@ -0,0 +1,411 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const TypeInfo = std.builtin.TypeInfo;
4const testing = std.testing;
5
6fn testTypes(comptime types: []const type) !void {
7 inline for (types) |testType| {
8 try testing.expect(testType == @Type(@typeInfo(testType)));
9 }
10}
11
12test "Type.Float" {
13 try testing.expect(f16 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 16 } }));
14 try testing.expect(f32 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 32 } }));
15 try testing.expect(f64 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 64 } }));
16 try testing.expect(f128 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 128 } }));
17 try testTypes(&[_]type{ f16, f32, f64, f128 });
18}
19
20test "Type.Pointer" {
21 try testTypes(&[_]type{
22 // One Value Pointer Types
23 *u8, *const u8,
24 *volatile u8, *const volatile u8,
25 *align(4) u8, *align(4) const u8,
26 *align(4) volatile u8, *align(4) const volatile u8,
27 *align(8) u8, *align(8) const u8,
28 *align(8) volatile u8, *align(8) const volatile u8,
29 *allowzero u8, *allowzero const u8,
30 *allowzero volatile u8, *allowzero const volatile u8,
31 *allowzero align(4) u8, *allowzero align(4) const u8,
32 *allowzero align(4) volatile u8, *allowzero align(4) const volatile u8,
33 // Many Values Pointer Types
34 [*]u8, [*]const u8,
35 [*]volatile u8, [*]const volatile u8,
36 [*]align(4) u8, [*]align(4) const u8,
37 [*]align(4) volatile u8, [*]align(4) const volatile u8,
38 [*]align(8) u8, [*]align(8) const u8,
39 [*]align(8) volatile u8, [*]align(8) const volatile u8,
40 [*]allowzero u8, [*]allowzero const u8,
41 [*]allowzero volatile u8, [*]allowzero const volatile u8,
42 [*]allowzero align(4) u8, [*]allowzero align(4) const u8,
43 [*]allowzero align(4) volatile u8, [*]allowzero align(4) const volatile u8,
44 // Slice Types
45 []u8, []const u8,
46 []volatile u8, []const volatile u8,
47 []align(4) u8, []align(4) const u8,
48 []align(4) volatile u8, []align(4) const volatile u8,
49 []align(8) u8, []align(8) const u8,
50 []align(8) volatile u8, []align(8) const volatile u8,
51 []allowzero u8, []allowzero const u8,
52 []allowzero volatile u8, []allowzero const volatile u8,
53 []allowzero align(4) u8, []allowzero align(4) const u8,
54 []allowzero align(4) volatile u8, []allowzero align(4) const volatile u8,
55 // C Pointer Types
56 [*c]u8, [*c]const u8,
57 [*c]volatile u8, [*c]const volatile u8,
58 [*c]align(4) u8, [*c]align(4) const u8,
59 [*c]align(4) volatile u8, [*c]align(4) const volatile u8,
60 [*c]align(8) u8, [*c]align(8) const u8,
61 [*c]align(8) volatile u8, [*c]align(8) const volatile u8,
62 });
63}
64
65test "Type.Array" {
66 try testing.expect([123]u8 == @Type(TypeInfo{
67 .Array = TypeInfo.Array{
68 .len = 123,
69 .child = u8,
70 .sentinel = null,
71 },
72 }));
73 try testing.expect([2]u32 == @Type(TypeInfo{
74 .Array = TypeInfo.Array{
75 .len = 2,
76 .child = u32,
77 .sentinel = null,
78 },
79 }));
80 try testing.expect([2:0]u32 == @Type(TypeInfo{
81 .Array = TypeInfo.Array{
82 .len = 2,
83 .child = u32,
84 .sentinel = 0,
85 },
86 }));
87 try testTypes(&[_]type{ [1]u8, [30]usize, [7]bool });
88}
89
90test "@Type create slice with null sentinel" {
91 const Slice = @Type(TypeInfo{
92 .Pointer = .{
93 .size = .Slice,
94 .is_const = true,
95 .is_volatile = false,
96 .is_allowzero = false,
97 .alignment = 8,
98 .address_space = .generic,
99 .child = *i32,
100 .sentinel = null,
101 },
102 });
103 try testing.expect(Slice == []align(8) const *i32);
104}
105test "@Type picks up the sentinel value from TypeInfo" {
106 try testTypes(&[_]type{
107 [11:0]u8, [4:10]u8,
108 [*:0]u8, [*:0]const u8,
109 [*:0]volatile u8, [*:0]const volatile u8,
110 [*:0]align(4) u8, [*:0]align(4) const u8,
111 [*:0]align(4) volatile u8, [*:0]align(4) const volatile u8,
112 [*:0]align(8) u8, [*:0]align(8) const u8,
113 [*:0]align(8) volatile u8, [*:0]align(8) const volatile u8,
114 [*:0]allowzero u8, [*:0]allowzero const u8,
115 [*:0]allowzero volatile u8, [*:0]allowzero const volatile u8,
116 [*:0]allowzero align(4) u8, [*:0]allowzero align(4) const u8,
117 [*:0]allowzero align(4) volatile u8, [*:0]allowzero align(4) const volatile u8,
118 [*:5]allowzero align(4) volatile u8, [*:5]allowzero align(4) const volatile u8,
119 [:0]u8, [:0]const u8,
120 [:0]volatile u8, [:0]const volatile u8,
121 [:0]align(4) u8, [:0]align(4) const u8,
122 [:0]align(4) volatile u8, [:0]align(4) const volatile u8,
123 [:0]align(8) u8, [:0]align(8) const u8,
124 [:0]align(8) volatile u8, [:0]align(8) const volatile u8,
125 [:0]allowzero u8, [:0]allowzero const u8,
126 [:0]allowzero volatile u8, [:0]allowzero const volatile u8,
127 [:0]allowzero align(4) u8, [:0]allowzero align(4) const u8,
128 [:0]allowzero align(4) volatile u8, [:0]allowzero align(4) const volatile u8,
129 [:4]allowzero align(4) volatile u8, [:4]allowzero align(4) const volatile u8,
130 });
131}
132
133test "Type.Optional" {
134 try testTypes(&[_]type{
135 ?u8,
136 ?*u8,
137 ?[]u8,
138 ?[*]u8,
139 ?[*c]u8,
140 });
141}
142
143test "Type.ErrorUnion" {
144 try testTypes(&[_]type{
145 error{}!void,
146 error{Error}!void,
147 });
148}
149
150test "Type.Opaque" {
151 const Opaque = @Type(.{
152 .Opaque = .{
153 .decls = &[_]TypeInfo.Declaration{},
154 },
155 });
156 try testing.expect(Opaque != opaque {});
157 try testing.expectEqualSlices(
158 TypeInfo.Declaration,
159 &[_]TypeInfo.Declaration{},
160 @typeInfo(Opaque).Opaque.decls,
161 );
162}
163
164test "Type.Vector" {
165 try testTypes(&[_]type{
166 @Vector(0, u8),
167 @Vector(4, u8),
168 @Vector(8, *u8),
169 std.meta.Vector(0, u8),
170 std.meta.Vector(4, u8),
171 std.meta.Vector(8, *u8),
172 });
173}
174
175test "Type.AnyFrame" {
176 try testTypes(&[_]type{
177 anyframe,
178 anyframe->u8,
179 anyframe->anyframe->u8,
180 });
181}
182
183fn add(a: i32, b: i32) i32 {
184 return a + b;
185}
186
187test "Type.Frame" {
188 try testTypes(&[_]type{
189 @Frame(add),
190 });
191}
192
193test "Type.ErrorSet" {
194 // error sets don't compare equal so just check if they compile
195 _ = @Type(@typeInfo(error{}));
196 _ = @Type(@typeInfo(error{A}));
197 _ = @Type(@typeInfo(error{ A, B, C }));
198}
199
200test "Type.Struct" {
201 const A = @Type(@typeInfo(struct { x: u8, y: u32 }));
202 const infoA = @typeInfo(A).Struct;
203 try testing.expectEqual(TypeInfo.ContainerLayout.Auto, infoA.layout);
204 try testing.expectEqualSlices(u8, "x", infoA.fields[0].name);
205 try testing.expectEqual(u8, infoA.fields[0].field_type);
206 try testing.expectEqual(@as(?u8, null), infoA.fields[0].default_value);
207 try testing.expectEqualSlices(u8, "y", infoA.fields[1].name);
208 try testing.expectEqual(u32, infoA.fields[1].field_type);
209 try testing.expectEqual(@as(?u32, null), infoA.fields[1].default_value);
210 try testing.expectEqualSlices(TypeInfo.Declaration, &[_]TypeInfo.Declaration{}, infoA.decls);
211 try testing.expectEqual(@as(bool, false), infoA.is_tuple);
212
213 var a = A{ .x = 0, .y = 1 };
214 try testing.expectEqual(@as(u8, 0), a.x);
215 try testing.expectEqual(@as(u32, 1), a.y);
216 a.y += 1;
217 try testing.expectEqual(@as(u32, 2), a.y);
218
219 const B = @Type(@typeInfo(extern struct { x: u8, y: u32 = 5 }));
220 const infoB = @typeInfo(B).Struct;
221 try testing.expectEqual(TypeInfo.ContainerLayout.Extern, infoB.layout);
222 try testing.expectEqualSlices(u8, "x", infoB.fields[0].name);
223 try testing.expectEqual(u8, infoB.fields[0].field_type);
224 try testing.expectEqual(@as(?u8, null), infoB.fields[0].default_value);
225 try testing.expectEqualSlices(u8, "y", infoB.fields[1].name);
226 try testing.expectEqual(u32, infoB.fields[1].field_type);
227 try testing.expectEqual(@as(?u32, 5), infoB.fields[1].default_value);
228 try testing.expectEqual(@as(usize, 0), infoB.decls.len);
229 try testing.expectEqual(@as(bool, false), infoB.is_tuple);
230
231 const C = @Type(@typeInfo(packed struct { x: u8 = 3, y: u32 = 5 }));
232 const infoC = @typeInfo(C).Struct;
233 try testing.expectEqual(TypeInfo.ContainerLayout.Packed, infoC.layout);
234 try testing.expectEqualSlices(u8, "x", infoC.fields[0].name);
235 try testing.expectEqual(u8, infoC.fields[0].field_type);
236 try testing.expectEqual(@as(?u8, 3), infoC.fields[0].default_value);
237 try testing.expectEqualSlices(u8, "y", infoC.fields[1].name);
238 try testing.expectEqual(u32, infoC.fields[1].field_type);
239 try testing.expectEqual(@as(?u32, 5), infoC.fields[1].default_value);
240 try testing.expectEqual(@as(usize, 0), infoC.decls.len);
241 try testing.expectEqual(@as(bool, false), infoC.is_tuple);
242}
243
244test "Type.Enum" {
245 const Foo = @Type(.{
246 .Enum = .{
247 .layout = .Auto,
248 .tag_type = u8,
249 .fields = &[_]TypeInfo.EnumField{
250 .{ .name = "a", .value = 1 },
251 .{ .name = "b", .value = 5 },
252 },
253 .decls = &[_]TypeInfo.Declaration{},
254 .is_exhaustive = true,
255 },
256 });
257 try testing.expectEqual(true, @typeInfo(Foo).Enum.is_exhaustive);
258 try testing.expectEqual(@as(u8, 1), @enumToInt(Foo.a));
259 try testing.expectEqual(@as(u8, 5), @enumToInt(Foo.b));
260 const Bar = @Type(.{
261 .Enum = .{
262 .layout = .Extern,
263 .tag_type = u32,
264 .fields = &[_]TypeInfo.EnumField{
265 .{ .name = "a", .value = 1 },
266 .{ .name = "b", .value = 5 },
267 },
268 .decls = &[_]TypeInfo.Declaration{},
269 .is_exhaustive = false,
270 },
271 });
272 try testing.expectEqual(false, @typeInfo(Bar).Enum.is_exhaustive);
273 try testing.expectEqual(@as(u32, 1), @enumToInt(Bar.a));
274 try testing.expectEqual(@as(u32, 5), @enumToInt(Bar.b));
275 try testing.expectEqual(@as(u32, 6), @enumToInt(@intToEnum(Bar, 6)));
276}
277
278test "Type.Union" {
279 const Untagged = @Type(.{
280 .Union = .{
281 .layout = .Auto,
282 .tag_type = null,
283 .fields = &[_]TypeInfo.UnionField{
284 .{ .name = "int", .field_type = i32, .alignment = @alignOf(f32) },
285 .{ .name = "float", .field_type = f32, .alignment = @alignOf(f32) },
286 },
287 .decls = &[_]TypeInfo.Declaration{},
288 },
289 });
290 var untagged = Untagged{ .int = 1 };
291 untagged.float = 2.0;
292 untagged.int = 3;
293 try testing.expectEqual(@as(i32, 3), untagged.int);
294
295 const PackedUntagged = @Type(.{
296 .Union = .{
297 .layout = .Packed,
298 .tag_type = null,
299 .fields = &[_]TypeInfo.UnionField{
300 .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
301 .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
302 },
303 .decls = &[_]TypeInfo.Declaration{},
304 },
305 });
306 var packed_untagged = PackedUntagged{ .signed = -1 };
307 try testing.expectEqual(@as(i32, -1), packed_untagged.signed);
308 try testing.expectEqual(~@as(u32, 0), packed_untagged.unsigned);
309
310 const Tag = @Type(.{
311 .Enum = .{
312 .layout = .Auto,
313 .tag_type = u1,
314 .fields = &[_]TypeInfo.EnumField{
315 .{ .name = "signed", .value = 0 },
316 .{ .name = "unsigned", .value = 1 },
317 },
318 .decls = &[_]TypeInfo.Declaration{},
319 .is_exhaustive = true,
320 },
321 });
322 const Tagged = @Type(.{
323 .Union = .{
324 .layout = .Auto,
325 .tag_type = Tag,
326 .fields = &[_]TypeInfo.UnionField{
327 .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
328 .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
329 },
330 .decls = &[_]TypeInfo.Declaration{},
331 },
332 });
333 var tagged = Tagged{ .signed = -1 };
334 try testing.expectEqual(Tag.signed, tagged);
335 tagged = .{ .unsigned = 1 };
336 try testing.expectEqual(Tag.unsigned, tagged);
337}
338
339test "Type.Union from Type.Enum" {
340 const Tag = @Type(.{
341 .Enum = .{
342 .layout = .Auto,
343 .tag_type = u0,
344 .fields = &[_]TypeInfo.EnumField{
345 .{ .name = "working_as_expected", .value = 0 },
346 },
347 .decls = &[_]TypeInfo.Declaration{},
348 .is_exhaustive = true,
349 },
350 });
351 const T = @Type(.{
352 .Union = .{
353 .layout = .Auto,
354 .tag_type = Tag,
355 .fields = &[_]TypeInfo.UnionField{
356 .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
357 },
358 .decls = &[_]TypeInfo.Declaration{},
359 },
360 });
361 _ = T;
362 _ = @typeInfo(T).Union;
363}
364
365test "Type.Union from regular enum" {
366 const E = enum { working_as_expected };
367 const T = @Type(.{
368 .Union = .{
369 .layout = .Auto,
370 .tag_type = E,
371 .fields = &[_]TypeInfo.UnionField{
372 .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
373 },
374 .decls = &[_]TypeInfo.Declaration{},
375 },
376 });
377 _ = T;
378 _ = @typeInfo(T).Union;
379}
380
381test "Type.Fn" {
382 // wasm doesn't support align attributes on functions
383 if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
384
385 const foo = struct {
386 fn func(a: usize, b: bool) align(4) callconv(.C) usize {
387 _ = a;
388 _ = b;
389 return 0;
390 }
391 }.func;
392 const Foo = @Type(@typeInfo(@TypeOf(foo)));
393 const foo_2: Foo = foo;
394 _ = foo_2;
395}
396
397test "Type.BoundFn" {
398 // wasm doesn't support align attributes on functions
399 if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
400
401 const TestStruct = packed struct {
402 pub fn foo(self: *const @This()) align(4) callconv(.Unspecified) void {
403 _ = self;
404 }
405 };
406 const test_instance: TestStruct = undefined;
407 try testing.expect(std.meta.eql(
408 @typeName(@TypeOf(test_instance.foo)),
409 @typeName(@Type(@typeInfo(@TypeOf(test_instance.foo)))),
410 ));
411}
test/behavior/union.zig+25
......@@ -460,3 +460,28 @@ test "tagged union as return value" {
460460fn returnAnInt(x: i32) TaggedFoo {
461461 return TaggedFoo{ .One = x };
462462}
463
464test "tagged union with all void fields but a meaningful tag" {
465 const S = struct {
466 const B = union(enum) {
467 c: C,
468 None,
469 };
470
471 const A = struct {
472 b: B,
473 };
474
475 const C = struct {};
476
477 fn doTheTest() !void {
478 var a: A = A{ .b = B{ .c = C{} } };
479 try expect(@as(Tag(B), a.b) == Tag(B).c);
480 a = A{ .b = B.None };
481 try expect(@as(Tag(B), a.b) == Tag(B).None);
482 }
483 };
484 try S.doTheTest();
485 // TODO enable the test at comptime too
486 //comptime try S.doTheTest();
487}