aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2018-05-03 23:02:33 -0400
committerGitHub <noreply@github.com>2018-05-03 23:02:33 -0400
commitb9e320dd521751663db7b040e65c8ff5420c824a (patch)
tree2c4161ebf8d1997ea45926af86301d64a960484c /test
parentaa2586de182e5587c924740e80468c4c4d509500 (diff)
parent849ea61fa11460b1a6df2529063a6b0cabc6e5e4 (diff)
downloadzig-b9e320dd521751663db7b040e65c8ff5420c824a.tar.gz
zig-b9e320dd521751663db7b040e65c8ff5420c824a.zip
Merge pull request #951 from alexnask/reflect_reify
Metaprogramming - @typeInfo [DONE]
Diffstat (limited to 'test')
-rw-r--r--test/behavior.zig1
-rw-r--r--test/cases/type_info.zig181
-rw-r--r--test/cases/union.zig10
-rw-r--r--test/compile_errors.zig13
4 files changed, 204 insertions, 1 deletions
diff --git a/test/behavior.zig b/test/behavior.zig
index 3e540e0cf4..d700faaebc 100644
--- a/test/behavior.zig
+++ b/test/behavior.zig
@@ -36,6 +36,7 @@ comptime {
_ = @import("cases/pub_enum/index.zig");
_ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
_ = @import("cases/reflection.zig");
+ _ = @import("cases/type_info.zig");
_ = @import("cases/sizeof_and_typeof.zig");
_ = @import("cases/slice.zig");
_ = @import("cases/struct.zig");
diff --git a/test/cases/type_info.zig b/test/cases/type_info.zig
new file mode 100644
index 0000000000..c9b15157e8
--- /dev/null
+++ b/test/cases/type_info.zig
@@ -0,0 +1,181 @@
+const assert = @import("std").debug.assert;
+const mem = @import("std").mem;
+const TypeInfo = @import("builtin").TypeInfo;
+const TypeId = @import("builtin").TypeId;
+
+test "type info: tag type, void info" {
+ comptime {
+ assert(@TagType(TypeInfo) == TypeId);
+ const void_info = @typeInfo(void);
+ assert(TypeId(void_info) == TypeId.Void);
+ assert(void_info.Void == {});
+ }
+}
+
+test "type info: integer, floating point type info" {
+ comptime {
+ const u8_info = @typeInfo(u8);
+ assert(TypeId(u8_info) == TypeId.Int);
+ assert(!u8_info.Int.is_signed);
+ assert(u8_info.Int.bits == 8);
+
+ const f64_info = @typeInfo(f64);
+ assert(TypeId(f64_info) == TypeId.Float);
+ assert(f64_info.Float.bits == 64);
+ }
+}
+
+test "type info: pointer, array and nullable type info" {
+ comptime {
+ const u32_ptr_info = @typeInfo(&u32);
+ assert(TypeId(u32_ptr_info) == TypeId.Pointer);
+ assert(u32_ptr_info.Pointer.is_const == false);
+ assert(u32_ptr_info.Pointer.is_volatile == false);
+ assert(u32_ptr_info.Pointer.alignment == 4);
+ assert(u32_ptr_info.Pointer.child == u32);
+
+ const arr_info = @typeInfo([42]bool);
+ assert(TypeId(arr_info) == TypeId.Array);
+ assert(arr_info.Array.len == 42);
+ assert(arr_info.Array.child == bool);
+
+ const null_info = @typeInfo(?void);
+ assert(TypeId(null_info) == TypeId.Nullable);
+ assert(null_info.Nullable.child == void);
+ }
+}
+
+test "type info: promise info" {
+ comptime {
+ const null_promise_info = @typeInfo(promise);
+ assert(TypeId(null_promise_info) == TypeId.Promise);
+ assert(null_promise_info.Promise.child == @typeOf(undefined));
+
+ const promise_info = @typeInfo(promise->usize);
+ assert(TypeId(promise_info) == TypeId.Promise);
+ assert(promise_info.Promise.child == usize);
+ }
+
+}
+
+test "type info: error set, error union info" {
+ comptime {
+ const TestErrorSet = error {
+ First,
+ Second,
+ Third,
+ };
+
+ const error_set_info = @typeInfo(TestErrorSet);
+ assert(TypeId(error_set_info) == TypeId.ErrorSet);
+ assert(error_set_info.ErrorSet.errors.len == 3);
+ assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
+ assert(error_set_info.ErrorSet.errors[2].value == usize(TestErrorSet.Third));
+
+ const error_union_info = @typeInfo(TestErrorSet!usize);
+ assert(TypeId(error_union_info) == TypeId.ErrorUnion);
+ assert(error_union_info.ErrorUnion.error_set == TestErrorSet);
+ assert(error_union_info.ErrorUnion.payload == usize);
+ }
+}
+
+test "type info: enum info" {
+ comptime {
+ const Os = @import("builtin").Os;
+
+ const os_info = @typeInfo(Os);
+ assert(TypeId(os_info) == TypeId.Enum);
+ assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
+ assert(os_info.Enum.fields.len == 32);
+ assert(mem.eql(u8, os_info.Enum.fields[1].name, "ananas"));
+ assert(os_info.Enum.fields[10].value == 10);
+ assert(os_info.Enum.tag_type == u5);
+ assert(os_info.Enum.defs.len == 0);
+ }
+}
+
+test "type info: union info" {
+ comptime {
+ const typeinfo_info = @typeInfo(TypeInfo);
+ assert(TypeId(typeinfo_info) == TypeId.Union);
+ assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
+ assert(typeinfo_info.Union.tag_type == TypeId);
+ assert(typeinfo_info.Union.fields.len == 25);
+ assert(typeinfo_info.Union.fields[4].enum_field != null);
+ assert((??typeinfo_info.Union.fields[4].enum_field).value == 4);
+ assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
+ assert(typeinfo_info.Union.defs.len == 20);
+
+ const TestNoTagUnion = union {
+ Foo: void,
+ Bar: u32,
+ };
+
+ const notag_union_info = @typeInfo(TestNoTagUnion);
+ assert(TypeId(notag_union_info) == TypeId.Union);
+ assert(notag_union_info.Union.tag_type == @typeOf(undefined));
+ assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
+ assert(notag_union_info.Union.fields.len == 2);
+ assert(notag_union_info.Union.fields[0].enum_field == null);
+ assert(notag_union_info.Union.fields[1].field_type == u32);
+
+ const TestExternUnion = extern union {
+ foo: &c_void,
+ };
+
+ const extern_union_info = @typeInfo(TestExternUnion);
+ assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
+ assert(extern_union_info.Union.tag_type == @typeOf(undefined));
+ assert(extern_union_info.Union.fields[0].enum_field == null);
+ assert(extern_union_info.Union.fields[0].field_type == &c_void);
+ }
+}
+
+test "type info: struct info" {
+ comptime {
+ const struct_info = @typeInfo(TestStruct);
+ assert(TypeId(struct_info) == TypeId.Struct);
+ assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
+ assert(struct_info.Struct.fields.len == 3);
+ assert(struct_info.Struct.fields[1].offset == null);
+ assert(struct_info.Struct.fields[2].field_type == &TestStruct);
+ assert(struct_info.Struct.defs.len == 2);
+ assert(struct_info.Struct.defs[0].is_pub);
+ assert(!struct_info.Struct.defs[0].data.Fn.is_extern);
+ assert(struct_info.Struct.defs[0].data.Fn.lib_name == null);
+ assert(struct_info.Struct.defs[0].data.Fn.return_type == void);
+ assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn(&const TestStruct)void);
+ }
+}
+
+const TestStruct = packed struct {
+ const Self = this;
+
+ fieldA: usize,
+ fieldB: void,
+ fieldC: &Self,
+
+ pub fn foo(self: &const Self) void {}
+};
+
+test "type info: function type info" {
+ comptime {
+ const fn_info = @typeInfo(@typeOf(foo));
+ assert(TypeId(fn_info) == TypeId.Fn);
+ assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
+ assert(fn_info.Fn.is_generic);
+ assert(fn_info.Fn.args.len == 2);
+ assert(fn_info.Fn.is_var_args);
+ assert(fn_info.Fn.return_type == @typeOf(undefined));
+ assert(fn_info.Fn.async_allocator_type == @typeOf(undefined));
+
+ const test_instance: TestStruct = undefined;
+ const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
+ assert(TypeId(bound_fn_info) == TypeId.BoundFn);
+ assert(bound_fn_info.BoundFn.args[0].arg_type == &const TestStruct);
+ }
+}
+
+fn foo(comptime a: usize, b: bool, args: ...) usize {
+ return 0;
+}
diff --git a/test/cases/union.zig b/test/cases/union.zig
index dc2a7c3414..e7d9c23d77 100644
--- a/test/cases/union.zig
+++ b/test/cases/union.zig
@@ -45,6 +45,16 @@ test "basic unions" {
assert(foo.float == 12.34);
}
+test "comptime union field access" {
+ comptime {
+ var foo = Foo { .int = 0 };
+ assert(foo.int == 0);
+
+ foo = Foo { .float = 42.42 };
+ assert(foo.float == 42.42);
+ }
+}
+
test "init union with runtime value" {
var foo: Foo = undefined;
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 52e063eb39..300f27cb6a 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -3210,6 +3210,18 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
,
".tmp_source.zig:5:42: error: zero-bit field 'val' in struct 'Empty' has no offset");
+ cases.add("invalid union field access in comptime",
+ \\const Foo = union {
+ \\ Bar: u8,
+ \\ Baz: void,
+ \\};
+ \\comptime {
+ \\ var foo = Foo {.Baz = {}};
+ \\ const bar_val = foo.Bar;
+ \\}
+ ,
+ ".tmp_source.zig:7:24: error: accessing union field 'Bar' while field 'Baz' is set");
+
cases.add("getting return type of generic function",
\\fn generic(a: var) void {}
\\comptime {
@@ -3225,5 +3237,4 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
\\}
,
".tmp_source.zig:3:36: error: @ArgType could not resolve the type of arg 0 because 'fn(var)var' is generic");
-
}