authorgravatar for me@tadeo.caTadeo Kondrak <me@tadeo.ca> 2020-09-25 14:12:11-06:00
committergravatar for me@tadeo.caTadeo Kondrak <me@tadeo.ca> 2020-10-06 22:08:24-06:00
log069fbb3c01d8be0940d60e3324213a0cde4a42d5
tree6e236ae2f9cca59057afd945ec5cad6fee855d27
parent7f7e2d608adb81cd00e54fd7fe5e7035a890565f
signature Commit is signed but in an unrecognized format.

Add opaque type syntax


15 files changed, 159 insertions(+), 29 deletions(-)

doc/langref.html.in+3-2
......@@ -11193,7 +11193,7 @@ PtrTypeStart
1119311193ContainerDeclAuto &lt;- ContainerDeclType LBRACE ContainerMembers RBRACE
1119411194
1119511195ContainerDeclType
11196 &lt;- (KEYWORD_struct / KEYWORD_enum) (LPAREN Expr RPAREN)?
11196 &lt;- (KEYWORD_struct / KEYWORD_enum / KEYWORD_opaque) (LPAREN Expr RPAREN)?
1119711197 / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
1119811198
1119911199# Alignment
......@@ -11340,6 +11340,7 @@ KEYWORD_inline &lt;- 'inline' end_of_word
1134011340KEYWORD_noalias &lt;- 'noalias' end_of_word
1134111341KEYWORD_nosuspend &lt;- 'nosuspend' end_of_word
1134211342KEYWORD_null &lt;- 'null' end_of_word
11343KEYWORD_opaque &lt;- 'opaque' end_of_word
1134311344KEYWORD_or &lt;- 'or' end_of_word
1134411345KEYWORD_orelse &lt;- 'orelse' end_of_word
1134511346KEYWORD_packed &lt;- 'packed' end_of_word
......@@ -11368,7 +11369,7 @@ keyword &lt;- KEYWORD_align / KEYWORD_and / KEYWORD_anyframe / KEYWORD_anytype
1136811369 / KEYWORD_defer / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer
1136911370 / KEYWORD_error / KEYWORD_export / KEYWORD_extern / KEYWORD_false
1137011371 / KEYWORD_fn / KEYWORD_for / KEYWORD_if / KEYWORD_inline
11371 / KEYWORD_noalias / KEYWORD_null / KEYWORD_or
11372 / KEYWORD_noalias / KEYWORD_null / KEYWORD_opaque / KEYWORD_or
1137211373 / KEYWORD_orelse / KEYWORD_packed / KEYWORD_pub
1137311374 / KEYWORD_resume / KEYWORD_return / KEYWORD_linksection
1137411375 / KEYWORD_struct / KEYWORD_suspend
lib/std/builtin.zig+7-1
......@@ -199,7 +199,7 @@ pub const TypeInfo = union(enum) {
199199 Union: Union,
200200 Fn: Fn,
201201 BoundFn: Fn,
202 Opaque: void,
202 Opaque: Opaque,
203203 Frame: Frame,
204204 AnyFrame: AnyFrame,
205205 Vector: Vector,
......@@ -360,6 +360,12 @@ pub const TypeInfo = union(enum) {
360360 args: []const FnArg,
361361 };
362362
363 /// This data structure is used by the Zig language code generation and
364 /// therefore must be kept in sync with the compiler implementation.
365 pub const Opaque = struct {
366 decls: []const Declaration,
367 };
368
363369 /// This data structure is used by the Zig language code generation and
364370 /// therefore must be kept in sync with the compiler implementation.
365371 pub const Frame = struct {
lib/std/zig/ast.zig+1-1
......@@ -288,7 +288,7 @@ pub const Error = union(enum) {
288288 pub const ExpectedVarDecl = SingleTokenError("Expected variable declaration, found '{}'");
289289 pub const ExpectedFn = SingleTokenError("Expected function, found '{}'");
290290 pub const ExpectedReturnType = SingleTokenError("Expected 'var' or return type expression, found '{}'");
291 pub const ExpectedAggregateKw = SingleTokenError("Expected '" ++ Token.Id.Keyword_struct.symbol() ++ "', '" ++ Token.Id.Keyword_union.symbol() ++ "', or '" ++ Token.Id.Keyword_enum.symbol() ++ "', found '{}'");
291 pub const ExpectedAggregateKw = SingleTokenError("Expected '" ++ Token.Id.Keyword_struct.symbol() ++ "', '" ++ Token.Id.Keyword_union.symbol() ++ "', '" ++ Token.Id.Keyword_enum.symbol() ++ "', or '" ++ Token.Id.Keyword_opaque.symbol() ++ "', found '{}'");
292292 pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found '{}'");
293293 pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found '{}'");
294294 pub const ExpectedSemiOrElse = SingleTokenError("Expected ';' or 'else', found '{}'");
lib/std/zig/parse.zig+2-1
......@@ -2896,11 +2896,12 @@ const Parser = struct {
28962896 /// <- KEYWORD_struct
28972897 /// / KEYWORD_enum (LPAREN Expr RPAREN)?
28982898 /// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
2899 /// / KEYWORD_opaque
28992900 fn parseContainerDeclType(p: *Parser) !?ContainerDeclType {
29002901 const kind_token = p.nextToken();
29012902
29022903 const init_arg_expr = switch (p.token_ids[kind_token]) {
2903 .Keyword_struct => Node.ContainerDecl.InitArg{ .None = {} },
2904 .Keyword_struct, .Keyword_opaque => Node.ContainerDecl.InitArg{ .None = {} },
29042905 .Keyword_enum => blk: {
29052906 if (p.eatToken(.LParen) != null) {
29062907 const expr = try p.expectNode(parseExpr, .{
lib/std/zig/render.zig+13-1
......@@ -1492,7 +1492,19 @@ fn renderExpression(
14921492
14931493 // TODO remove after 0.7.0 release
14941494 if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@OpaqueType"))
1495 return ais.writer().writeAll("@Type(.Opaque)");
1495 return ais.writer().writeAll("opaque {}");
1496
1497 // TODO remove after 0.7.0 release
1498 {
1499 const params = builtin_call.paramsConst();
1500 if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@Type") and
1501 params.len == 1)
1502 {
1503 if (params[0].castTag(.EnumLiteral)) |enum_literal|
1504 if (mem.eql(u8, tree.tokenSlice(enum_literal.name), "Opaque"))
1505 return ais.writer().writeAll("opaque {}");
1506 }
1507 }
14961508
14971509 try renderToken(tree, ais, builtin_call.builtin_token, Space.None); // @name
14981510
lib/std/zig/tokenizer.zig+3
......@@ -47,6 +47,7 @@ pub const Token = struct {
4747 .{ "noinline", .Keyword_noinline },
4848 .{ "nosuspend", .Keyword_nosuspend },
4949 .{ "null", .Keyword_null },
50 .{ "opaque", .Keyword_opaque },
5051 .{ "or", .Keyword_or },
5152 .{ "orelse", .Keyword_orelse },
5253 .{ "packed", .Keyword_packed },
......@@ -173,6 +174,7 @@ pub const Token = struct {
173174 Keyword_noinline,
174175 Keyword_nosuspend,
175176 Keyword_null,
177 Keyword_opaque,
176178 Keyword_or,
177179 Keyword_orelse,
178180 Keyword_packed,
......@@ -296,6 +298,7 @@ pub const Token = struct {
296298 .Keyword_noinline => "noinline",
297299 .Keyword_nosuspend => "nosuspend",
298300 .Keyword_null => "null",
301 .Keyword_opaque => "opaque",
299302 .Keyword_or => "or",
300303 .Keyword_orelse => "orelse",
301304 .Keyword_packed => "packed",
src/stage1/all_types.hpp+4
......@@ -1054,6 +1054,7 @@ enum ContainerKind {
10541054 ContainerKindStruct,
10551055 ContainerKindEnum,
10561056 ContainerKindUnion,
1057 ContainerKindOpaque,
10571058};
10581059
10591060enum ContainerLayout {
......@@ -1571,7 +1572,10 @@ enum OnePossibleValue {
15711572};
15721573
15731574struct ZigTypeOpaque {
1575 AstNode *decl_node;
15741576 Buf *bare_name;
1577
1578 ScopeDecls *decls_scope;
15751579};
15761580
15771581struct ZigTypeFnFrame {
src/stage1/analyze.cpp+44-10
......@@ -86,14 +86,18 @@ ZigType *new_type_table_entry(ZigTypeId id) {
8686}
8787
8888static ScopeDecls **get_container_scope_ptr(ZigType *type_entry) {
89 if (type_entry->id == ZigTypeIdStruct) {
90 return &type_entry->data.structure.decls_scope;
91 } else if (type_entry->id == ZigTypeIdEnum) {
92 return &type_entry->data.enumeration.decls_scope;
93 } else if (type_entry->id == ZigTypeIdUnion) {
94 return &type_entry->data.unionation.decls_scope;
89 switch (type_entry->id) {
90 case ZigTypeIdStruct:
91 return &type_entry->data.structure.decls_scope;
92 case ZigTypeIdEnum:
93 return &type_entry->data.enumeration.decls_scope;
94 case ZigTypeIdUnion:
95 return &type_entry->data.unionation.decls_scope;
96 case ZigTypeIdOpaque:
97 return &type_entry->data.opaque.decls_scope;
98 default:
99 zig_unreachable();
95100 }
96 zig_unreachable();
97101}
98102
99103static ScopeExpr *find_expr_scope(Scope *scope) {
......@@ -912,13 +916,17 @@ ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const c
912916 ZigType *import = scope ? get_scope_import(scope) : nullptr;
913917 unsigned line = source_node ? (unsigned)(source_node->line + 1) : 0;
914918
919 // Note: duplicated in get_partial_container_type
915920 entry->llvm_type = LLVMInt8Type();
916921 entry->llvm_di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder,
917922 ZigLLVMTag_DW_structure_type(), full_name,
918923 import ? ZigLLVMFileToScope(import->data.structure.root_struct->di_file) : nullptr,
919924 import ? import->data.structure.root_struct->di_file : nullptr,
920925 line);
926 entry->data.opaque.decl_node = source_node;
921927 entry->data.opaque.bare_name = bare_name;
928 entry->data.opaque.decls_scope = create_decls_scope(
929 g, source_node, scope, entry, import, &entry->name);
922930
923931 // The actual size is unknown, but the value must not be 0 because that
924932 // is how type_has_bits is determined.
......@@ -1080,6 +1088,8 @@ static ZigTypeId container_to_type(ContainerKind kind) {
10801088 return ZigTypeIdEnum;
10811089 case ContainerKindUnion:
10821090 return ZigTypeIdUnion;
1091 case ContainerKindOpaque:
1092 return ZigTypeIdOpaque;
10831093 }
10841094 zig_unreachable();
10851095}
......@@ -1121,6 +1131,22 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
11211131 entry->data.unionation.decl_node = decl_node;
11221132 entry->data.unionation.layout = layout;
11231133 break;
1134 case ContainerKindOpaque: {
1135 ZigType *import = scope ? get_scope_import(scope) : nullptr;
1136 unsigned line = decl_node ? (unsigned)(decl_node->line + 1) : 0;
1137 // Note: duplicated in get_opaque_type
1138 entry->llvm_type = LLVMInt8Type();
1139 entry->llvm_di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder,
1140 ZigLLVMTag_DW_structure_type(), full_name,
1141 import ? ZigLLVMFileToScope(import->data.structure.root_struct->di_file) : nullptr,
1142 import ? import->data.structure.root_struct->di_file : nullptr,
1143 line);
1144 entry->data.opaque.decl_node = decl_node;
1145 entry->abi_size = SIZE_MAX;
1146 entry->size_in_bits = SIZE_MAX;
1147 entry->abi_align = 1;
1148 break;
1149 }
11241150 }
11251151
11261152 buf_init_from_str(&entry->name, full_name);
......@@ -3430,6 +3456,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
34303456 return ErrorNone;
34313457}
34323458
3459static Error resolve_opaque_type(CodeGen *g, ZigType *opaque_type) {
3460 opaque_type->abi_align = UINT32_MAX;
3461 opaque_type->abi_size = SIZE_MAX;
3462 opaque_type->size_in_bits = SIZE_MAX;
3463 return ErrorNone;
3464}
3465
34333466void append_namespace_qualification(CodeGen *g, Buf *buf, ZigType *container_type) {
34343467 if (g->root_import == container_type || buf_len(&container_type->name) == 0) return;
34353468 buf_append_buf(buf, &container_type->name);
......@@ -3896,6 +3929,8 @@ static Error resolve_decl_container(CodeGen *g, TldContainer *tld_container) {
38963929 return resolve_enum_zero_bits(g, tld_container->type_entry);
38973930 case ZigTypeIdUnion:
38983931 return resolve_union_type(g, tld_container->type_entry);
3932 case ZigTypeIdOpaque:
3933 return resolve_opaque_type(g, tld_container->type_entry);
38993934 default:
39003935 zig_unreachable();
39013936 }
......@@ -4462,6 +4497,7 @@ bool is_container(ZigType *type_entry) {
44624497 return type_entry->data.structure.special != StructSpecialSlice;
44634498 case ZigTypeIdEnum:
44644499 case ZigTypeIdUnion:
4500 case ZigTypeIdOpaque:
44654501 return true;
44664502 case ZigTypeIdPointer:
44674503 case ZigTypeIdMetaType:
......@@ -4481,7 +4517,6 @@ bool is_container(ZigType *type_entry) {
44814517 case ZigTypeIdErrorSet:
44824518 case ZigTypeIdFn:
44834519 case ZigTypeIdBoundFn:
4484 case ZigTypeIdOpaque:
44854520 case ZigTypeIdVector:
44864521 case ZigTypeIdFnFrame:
44874522 case ZigTypeIdAnyFrame:
......@@ -8168,6 +8203,7 @@ const char *container_string(ContainerKind kind) {
81688203 case ContainerKindEnum: return "enum";
81698204 case ContainerKindStruct: return "struct";
81708205 case ContainerKindUnion: return "union";
8206 case ContainerKindOpaque: return "opaque";
81718207 }
81728208 zig_unreachable();
81738209}
......@@ -8186,8 +8222,6 @@ Buf *type_bare_name(ZigType *type_entry) {
81868222 return &type_entry->name;
81878223 } else if (is_container(type_entry)) {
81888224 return get_container_scope(type_entry)->bare_name;
8189 } else if (type_entry->id == ZigTypeIdOpaque) {
8190 return type_entry->data.opaque.bare_name;
81918225 } else {
81928226 return &type_entry->name;
81938227 }
src/stage1/ir.cpp+35-2
......@@ -22587,7 +22587,7 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name
2258722587 }
2258822588 }
2258922589
22590 if (bare_type->id == ZigTypeIdEnum) {
22590 if (bare_type->id == ZigTypeIdEnum || bare_type->id == ZigTypeIdOpaque) {
2259122591 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
2259222592 source_instr, container_ptr, container_ptr_src, container_type);
2259322593 }
......@@ -25183,7 +25183,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
2518325183 case ZigTypeIdEnumLiteral:
2518425184 case ZigTypeIdUndefined:
2518525185 case ZigTypeIdNull:
25186 case ZigTypeIdOpaque:
2518725186 result = ira->codegen->intern.for_void();
2518825187 break;
2518925188 case ZigTypeIdInt:
......@@ -25737,6 +25736,25 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
2573725736 if ((err = ir_make_type_info_value(ira, source_instr, fn_type, &result)))
2573825737 return err;
2573925738
25739 break;
25740 }
25741 case ZigTypeIdOpaque:
25742 {
25743 result = ira->codegen->pass1_arena->create<ZigValue>();
25744 result->special = ConstValSpecialStatic;
25745 result->type = ir_type_info_get_type(ira, "Opaque", nullptr);
25746
25747 ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 1);
25748 result->data.x_struct.fields = fields;
25749
25750 // decls: []TypeInfo.Declaration
25751 ensure_field_index(result->type, "decls", 0);
25752 if ((err = ir_make_type_info_decls(ira, source_instr, fields[0],
25753 type_entry->data.opaque.decls_scope, false)))
25754 {
25755 return err;
25756 }
25757
2574025758 break;
2574125759 }
2574225760 case ZigTypeIdFnFrame:
......@@ -26044,6 +26062,21 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
2604426062 return get_error_union_type(ira->codegen, err_set_type, payload_type);
2604526063 }
2604626064 case ZigTypeIdOpaque: {
26065 assert(payload->special == ConstValSpecialStatic);
26066 assert(payload->type == ir_type_info_get_type(ira, "Opaque", nullptr));
26067
26068 ZigValue *decls_value = get_const_field(ira, source_instr->source_node, payload, "decls", 0);
26069 if (decls_value == nullptr)
26070 return ira->codegen->invalid_inst_gen->value->type;
26071 assert(decls_value->special == ConstValSpecialStatic);
26072 assert(is_slice(decls_value->type));
26073 ZigValue *decls_len_value = decls_value->data.x_struct.fields[slice_len_index];
26074 size_t decls_len = bigint_as_usize(&decls_len_value->data.x_bigint);
26075 if (decls_len != 0) {
26076 ir_add_error(ira, source_instr, buf_create_from_str("TypeInfo.Struct.decls must be empty for @Type"));
26077 return ira->codegen->invalid_inst_gen->value->type;
26078 }
26079
2604726080 Buf *bare_name = buf_alloc();
2604826081 Buf *full_name = get_anon_type_name(ira->codegen,
2604926082 ira->old_irb.exec, "opaque", source_instr->scope, source_instr->source_node, bare_name);
src/stage1/parser.cpp+9
......@@ -2920,6 +2920,7 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc) {
29202920// <- KEYWORD_struct
29212921// / KEYWORD_enum (LPAREN Expr RPAREN)?
29222922// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
2923// / KEYWORD_opaque
29232924static AstNode *ast_parse_container_decl_type(ParseContext *pc) {
29242925 Token *first = eat_token_if(pc, TokenIdKeywordStruct);
29252926 if (first != nullptr) {
......@@ -2929,6 +2930,14 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) {
29292930 return res;
29302931 }
29312932
2933 first = eat_token_if(pc, TokenIdKeywordOpaque);
2934 if (first != nullptr) {
2935 AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first);
2936 res->data.container_decl.init_arg_expr = nullptr;
2937 res->data.container_decl.kind = ContainerKindOpaque;
2938 return res;
2939 }
2940
29322941 first = eat_token_if(pc, TokenIdKeywordEnum);
29332942 if (first != nullptr) {
29342943 AstNode *init_arg_expr = nullptr;
src/stage1/tokenizer.cpp+2
......@@ -133,6 +133,7 @@ static const struct ZigKeyword zig_keywords[] = {
133133 {"noinline", TokenIdKeywordNoInline},
134134 {"nosuspend", TokenIdKeywordNoSuspend},
135135 {"null", TokenIdKeywordNull},
136 {"opaque", TokenIdKeywordOpaque},
136137 {"or", TokenIdKeywordOr},
137138 {"orelse", TokenIdKeywordOrElse},
138139 {"packed", TokenIdKeywordPacked},
......@@ -1595,6 +1596,7 @@ const char * token_name(TokenId id) {
15951596 case TokenIdKeywordNoInline: return "noinline";
15961597 case TokenIdKeywordNoSuspend: return "nosuspend";
15971598 case TokenIdKeywordNull: return "null";
1599 case TokenIdKeywordOpaque: return "opaque";
15981600 case TokenIdKeywordOr: return "or";
15991601 case TokenIdKeywordOrElse: return "orelse";
16001602 case TokenIdKeywordPacked: return "packed";
src/stage1/tokenizer.hpp+1
......@@ -81,6 +81,7 @@ enum TokenId {
8181 TokenIdKeywordNoAlias,
8282 TokenIdKeywordNoSuspend,
8383 TokenIdKeywordNull,
84 TokenIdKeywordOpaque,
8485 TokenIdKeywordOr,
8586 TokenIdKeywordOrElse,
8687 TokenIdKeywordPacked,
src/translate_c.zig+8-8
......@@ -930,9 +930,9 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
930930 const init_node = blk: {
931931 const rp = makeRestorePoint(c);
932932 const record_def = ZigClangRecordDecl_getDefinition(record_decl) orelse {
933 const opaque = try transCreateNodeOpaqueType(c);
933 const opaque_type = try transCreateNodeOpaqueType(c);
934934 semicolon = try appendToken(c, .Semicolon, ";");
935 break :blk opaque;
935 break :blk opaque_type;
936936 };
937937
938938 const layout_tok = try if (ZigClangRecordDecl_getPackedAttribute(record_decl))
......@@ -954,17 +954,17 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
954954 const field_qt = ZigClangFieldDecl_getType(field_decl);
955955
956956 if (ZigClangFieldDecl_isBitField(field_decl)) {
957 const opaque = try transCreateNodeOpaqueType(c);
957 const opaque_type = try transCreateNodeOpaqueType(c);
958958 semicolon = try appendToken(c, .Semicolon, ";");
959959 try emitWarning(c, field_loc, "{} demoted to opaque type - has bitfield", .{container_kind_name});
960 break :blk opaque;
960 break :blk opaque_type;
961961 }
962962
963963 if (ZigClangType_isIncompleteOrZeroLengthArrayType(qualTypeCanon(field_qt), c.clang_context)) {
964 const opaque = try transCreateNodeOpaqueType(c);
964 const opaque_type = try transCreateNodeOpaqueType(c);
965965 semicolon = try appendToken(c, .Semicolon, ";");
966966 try emitWarning(c, field_loc, "{} demoted to opaque type - has variable length array", .{container_kind_name});
967 break :blk opaque;
967 break :blk opaque_type;
968968 }
969969
970970 var is_anon = false;
......@@ -979,10 +979,10 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
979979 _ = try appendToken(c, .Colon, ":");
980980 const field_type = transQualType(rp, field_qt, field_loc) catch |err| switch (err) {
981981 error.UnsupportedType => {
982 const opaque = try transCreateNodeOpaqueType(c);
982 const opaque_type = try transCreateNodeOpaqueType(c);
983983 semicolon = try appendToken(c, .Semicolon, ";");
984984 try emitWarning(c, record_loc, "{} demoted to opaque type - unable to translate type of field {}", .{ container_kind_name, raw_name });
985 break :blk opaque;
985 break :blk opaque_type;
986986 },
987987 else => |e| return e,
988988 };
test/stage1/behavior/type.zig+11-2
......@@ -190,8 +190,17 @@ test "Type.ErrorUnion" {
190190}
191191
192192test "Type.Opaque" {
193 testing.expect(@Type(.Opaque) != @Type(.Opaque));
194 testing.expect(@typeInfo(@Type(.Opaque)) == .Opaque);
193 const Opaque = @Type(.{
194 .Opaque = .{
195 .decls = &[_]TypeInfo.Declaration{},
196 },
197 });
198 testing.expect(Opaque != opaque {});
199 testing.expectEqualSlices(
200 TypeInfo.Declaration,
201 &[_]TypeInfo.Declaration{},
202 @typeInfo(Opaque).Opaque.decls,
203 );
195204}
196205
197206test "Type.Vector" {
test/stage1/behavior/type_info.zig+16-1
......@@ -199,7 +199,7 @@ fn testUnion() void {
199199 expect(typeinfo_info.Union.tag_type.? == TypeId);
200200 expect(typeinfo_info.Union.fields.len == 25);
201201 expect(typeinfo_info.Union.fields[4].field_type == @TypeOf(@typeInfo(u8).Int));
202 expect(typeinfo_info.Union.decls.len == 21);
202 expect(typeinfo_info.Union.decls.len == 22);
203203
204204 const TestNoTagUnion = union {
205205 Foo: void,
......@@ -265,6 +265,21 @@ const TestStruct = packed struct {
265265 const Self = @This();
266266};
267267
268test "type info: opaque info" {
269 testOpaque();
270 comptime testOpaque();
271}
272
273fn testOpaque() void {
274 const Foo = opaque {
275 const A = 1;
276 fn b() void {}
277 };
278
279 const foo_info = @typeInfo(Foo);
280 expect(foo_info.Opaque.decls.len == 2);
281}
282
268283test "type info: function type info" {
269284 // wasm doesn't support align attributes on functions
270285 if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest;