mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
Add opaque type syntax
This commit is contained in:
parent
7f7e2d608a
commit
069fbb3c01
@ -11193,7 +11193,7 @@ PtrTypeStart
|
||||
ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE
|
||||
|
||||
ContainerDeclType
|
||||
<- (KEYWORD_struct / KEYWORD_enum) (LPAREN Expr RPAREN)?
|
||||
<- (KEYWORD_struct / KEYWORD_enum / KEYWORD_opaque) (LPAREN Expr RPAREN)?
|
||||
/ KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
|
||||
|
||||
# Alignment
|
||||
@ -11340,6 +11340,7 @@ KEYWORD_inline <- 'inline' end_of_word
|
||||
KEYWORD_noalias <- 'noalias' end_of_word
|
||||
KEYWORD_nosuspend <- 'nosuspend' end_of_word
|
||||
KEYWORD_null <- 'null' end_of_word
|
||||
KEYWORD_opaque <- 'opaque' end_of_word
|
||||
KEYWORD_or <- 'or' end_of_word
|
||||
KEYWORD_orelse <- 'orelse' end_of_word
|
||||
KEYWORD_packed <- 'packed' end_of_word
|
||||
@ -11368,7 +11369,7 @@ keyword <- KEYWORD_align / KEYWORD_and / KEYWORD_anyframe / KEYWORD_anytype
|
||||
/ KEYWORD_defer / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer
|
||||
/ KEYWORD_error / KEYWORD_export / KEYWORD_extern / KEYWORD_false
|
||||
/ KEYWORD_fn / KEYWORD_for / KEYWORD_if / KEYWORD_inline
|
||||
/ KEYWORD_noalias / KEYWORD_null / KEYWORD_or
|
||||
/ KEYWORD_noalias / KEYWORD_null / KEYWORD_opaque / KEYWORD_or
|
||||
/ KEYWORD_orelse / KEYWORD_packed / KEYWORD_pub
|
||||
/ KEYWORD_resume / KEYWORD_return / KEYWORD_linksection
|
||||
/ KEYWORD_struct / KEYWORD_suspend
|
||||
|
||||
@ -199,7 +199,7 @@ pub const TypeInfo = union(enum) {
|
||||
Union: Union,
|
||||
Fn: Fn,
|
||||
BoundFn: Fn,
|
||||
Opaque: void,
|
||||
Opaque: Opaque,
|
||||
Frame: Frame,
|
||||
AnyFrame: AnyFrame,
|
||||
Vector: Vector,
|
||||
@ -360,6 +360,12 @@ pub const TypeInfo = union(enum) {
|
||||
args: []const FnArg,
|
||||
};
|
||||
|
||||
/// This data structure is used by the Zig language code generation and
|
||||
/// therefore must be kept in sync with the compiler implementation.
|
||||
pub const Opaque = struct {
|
||||
decls: []const Declaration,
|
||||
};
|
||||
|
||||
/// This data structure is used by the Zig language code generation and
|
||||
/// therefore must be kept in sync with the compiler implementation.
|
||||
pub const Frame = struct {
|
||||
|
||||
@ -288,7 +288,7 @@ pub const Error = union(enum) {
|
||||
pub const ExpectedVarDecl = SingleTokenError("Expected variable declaration, found '{}'");
|
||||
pub const ExpectedFn = SingleTokenError("Expected function, found '{}'");
|
||||
pub const ExpectedReturnType = SingleTokenError("Expected 'var' or return type expression, found '{}'");
|
||||
pub const ExpectedAggregateKw = SingleTokenError("Expected '" ++ Token.Id.Keyword_struct.symbol() ++ "', '" ++ Token.Id.Keyword_union.symbol() ++ "', or '" ++ Token.Id.Keyword_enum.symbol() ++ "', found '{}'");
|
||||
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 '{}'");
|
||||
pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found '{}'");
|
||||
pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found '{}'");
|
||||
pub const ExpectedSemiOrElse = SingleTokenError("Expected ';' or 'else', found '{}'");
|
||||
|
||||
@ -2896,11 +2896,12 @@ const Parser = struct {
|
||||
/// <- KEYWORD_struct
|
||||
/// / KEYWORD_enum (LPAREN Expr RPAREN)?
|
||||
/// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
|
||||
/// / KEYWORD_opaque
|
||||
fn parseContainerDeclType(p: *Parser) !?ContainerDeclType {
|
||||
const kind_token = p.nextToken();
|
||||
|
||||
const init_arg_expr = switch (p.token_ids[kind_token]) {
|
||||
.Keyword_struct => Node.ContainerDecl.InitArg{ .None = {} },
|
||||
.Keyword_struct, .Keyword_opaque => Node.ContainerDecl.InitArg{ .None = {} },
|
||||
.Keyword_enum => blk: {
|
||||
if (p.eatToken(.LParen) != null) {
|
||||
const expr = try p.expectNode(parseExpr, .{
|
||||
|
||||
@ -1492,7 +1492,19 @@ fn renderExpression(
|
||||
|
||||
// TODO remove after 0.7.0 release
|
||||
if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@OpaqueType"))
|
||||
return ais.writer().writeAll("@Type(.Opaque)");
|
||||
return ais.writer().writeAll("opaque {}");
|
||||
|
||||
// TODO remove after 0.7.0 release
|
||||
{
|
||||
const params = builtin_call.paramsConst();
|
||||
if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@Type") and
|
||||
params.len == 1)
|
||||
{
|
||||
if (params[0].castTag(.EnumLiteral)) |enum_literal|
|
||||
if (mem.eql(u8, tree.tokenSlice(enum_literal.name), "Opaque"))
|
||||
return ais.writer().writeAll("opaque {}");
|
||||
}
|
||||
}
|
||||
|
||||
try renderToken(tree, ais, builtin_call.builtin_token, Space.None); // @name
|
||||
|
||||
|
||||
@ -47,6 +47,7 @@ pub const Token = struct {
|
||||
.{ "noinline", .Keyword_noinline },
|
||||
.{ "nosuspend", .Keyword_nosuspend },
|
||||
.{ "null", .Keyword_null },
|
||||
.{ "opaque", .Keyword_opaque },
|
||||
.{ "or", .Keyword_or },
|
||||
.{ "orelse", .Keyword_orelse },
|
||||
.{ "packed", .Keyword_packed },
|
||||
@ -173,6 +174,7 @@ pub const Token = struct {
|
||||
Keyword_noinline,
|
||||
Keyword_nosuspend,
|
||||
Keyword_null,
|
||||
Keyword_opaque,
|
||||
Keyword_or,
|
||||
Keyword_orelse,
|
||||
Keyword_packed,
|
||||
@ -296,6 +298,7 @@ pub const Token = struct {
|
||||
.Keyword_noinline => "noinline",
|
||||
.Keyword_nosuspend => "nosuspend",
|
||||
.Keyword_null => "null",
|
||||
.Keyword_opaque => "opaque",
|
||||
.Keyword_or => "or",
|
||||
.Keyword_orelse => "orelse",
|
||||
.Keyword_packed => "packed",
|
||||
|
||||
@ -1054,6 +1054,7 @@ enum ContainerKind {
|
||||
ContainerKindStruct,
|
||||
ContainerKindEnum,
|
||||
ContainerKindUnion,
|
||||
ContainerKindOpaque,
|
||||
};
|
||||
|
||||
enum ContainerLayout {
|
||||
@ -1571,7 +1572,10 @@ enum OnePossibleValue {
|
||||
};
|
||||
|
||||
struct ZigTypeOpaque {
|
||||
AstNode *decl_node;
|
||||
Buf *bare_name;
|
||||
|
||||
ScopeDecls *decls_scope;
|
||||
};
|
||||
|
||||
struct ZigTypeFnFrame {
|
||||
|
||||
@ -86,14 +86,18 @@ ZigType *new_type_table_entry(ZigTypeId id) {
|
||||
}
|
||||
|
||||
static ScopeDecls **get_container_scope_ptr(ZigType *type_entry) {
|
||||
if (type_entry->id == ZigTypeIdStruct) {
|
||||
return &type_entry->data.structure.decls_scope;
|
||||
} else if (type_entry->id == ZigTypeIdEnum) {
|
||||
return &type_entry->data.enumeration.decls_scope;
|
||||
} else if (type_entry->id == ZigTypeIdUnion) {
|
||||
return &type_entry->data.unionation.decls_scope;
|
||||
switch (type_entry->id) {
|
||||
case ZigTypeIdStruct:
|
||||
return &type_entry->data.structure.decls_scope;
|
||||
case ZigTypeIdEnum:
|
||||
return &type_entry->data.enumeration.decls_scope;
|
||||
case ZigTypeIdUnion:
|
||||
return &type_entry->data.unionation.decls_scope;
|
||||
case ZigTypeIdOpaque:
|
||||
return &type_entry->data.opaque.decls_scope;
|
||||
default:
|
||||
zig_unreachable();
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static ScopeExpr *find_expr_scope(Scope *scope) {
|
||||
@ -912,13 +916,17 @@ ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const c
|
||||
ZigType *import = scope ? get_scope_import(scope) : nullptr;
|
||||
unsigned line = source_node ? (unsigned)(source_node->line + 1) : 0;
|
||||
|
||||
// Note: duplicated in get_partial_container_type
|
||||
entry->llvm_type = LLVMInt8Type();
|
||||
entry->llvm_di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder,
|
||||
ZigLLVMTag_DW_structure_type(), full_name,
|
||||
import ? ZigLLVMFileToScope(import->data.structure.root_struct->di_file) : nullptr,
|
||||
import ? import->data.structure.root_struct->di_file : nullptr,
|
||||
line);
|
||||
entry->data.opaque.decl_node = source_node;
|
||||
entry->data.opaque.bare_name = bare_name;
|
||||
entry->data.opaque.decls_scope = create_decls_scope(
|
||||
g, source_node, scope, entry, import, &entry->name);
|
||||
|
||||
// The actual size is unknown, but the value must not be 0 because that
|
||||
// is how type_has_bits is determined.
|
||||
@ -1080,6 +1088,8 @@ static ZigTypeId container_to_type(ContainerKind kind) {
|
||||
return ZigTypeIdEnum;
|
||||
case ContainerKindUnion:
|
||||
return ZigTypeIdUnion;
|
||||
case ContainerKindOpaque:
|
||||
return ZigTypeIdOpaque;
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
@ -1121,6 +1131,22 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
|
||||
entry->data.unionation.decl_node = decl_node;
|
||||
entry->data.unionation.layout = layout;
|
||||
break;
|
||||
case ContainerKindOpaque: {
|
||||
ZigType *import = scope ? get_scope_import(scope) : nullptr;
|
||||
unsigned line = decl_node ? (unsigned)(decl_node->line + 1) : 0;
|
||||
// Note: duplicated in get_opaque_type
|
||||
entry->llvm_type = LLVMInt8Type();
|
||||
entry->llvm_di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder,
|
||||
ZigLLVMTag_DW_structure_type(), full_name,
|
||||
import ? ZigLLVMFileToScope(import->data.structure.root_struct->di_file) : nullptr,
|
||||
import ? import->data.structure.root_struct->di_file : nullptr,
|
||||
line);
|
||||
entry->data.opaque.decl_node = decl_node;
|
||||
entry->abi_size = SIZE_MAX;
|
||||
entry->size_in_bits = SIZE_MAX;
|
||||
entry->abi_align = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buf_init_from_str(&entry->name, full_name);
|
||||
@ -3430,6 +3456,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
static Error resolve_opaque_type(CodeGen *g, ZigType *opaque_type) {
|
||||
opaque_type->abi_align = UINT32_MAX;
|
||||
opaque_type->abi_size = SIZE_MAX;
|
||||
opaque_type->size_in_bits = SIZE_MAX;
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
void append_namespace_qualification(CodeGen *g, Buf *buf, ZigType *container_type) {
|
||||
if (g->root_import == container_type || buf_len(&container_type->name) == 0) return;
|
||||
buf_append_buf(buf, &container_type->name);
|
||||
@ -3896,6 +3929,8 @@ static Error resolve_decl_container(CodeGen *g, TldContainer *tld_container) {
|
||||
return resolve_enum_zero_bits(g, tld_container->type_entry);
|
||||
case ZigTypeIdUnion:
|
||||
return resolve_union_type(g, tld_container->type_entry);
|
||||
case ZigTypeIdOpaque:
|
||||
return resolve_opaque_type(g, tld_container->type_entry);
|
||||
default:
|
||||
zig_unreachable();
|
||||
}
|
||||
@ -4462,6 +4497,7 @@ bool is_container(ZigType *type_entry) {
|
||||
return type_entry->data.structure.special != StructSpecialSlice;
|
||||
case ZigTypeIdEnum:
|
||||
case ZigTypeIdUnion:
|
||||
case ZigTypeIdOpaque:
|
||||
return true;
|
||||
case ZigTypeIdPointer:
|
||||
case ZigTypeIdMetaType:
|
||||
@ -4481,7 +4517,6 @@ bool is_container(ZigType *type_entry) {
|
||||
case ZigTypeIdErrorSet:
|
||||
case ZigTypeIdFn:
|
||||
case ZigTypeIdBoundFn:
|
||||
case ZigTypeIdOpaque:
|
||||
case ZigTypeIdVector:
|
||||
case ZigTypeIdFnFrame:
|
||||
case ZigTypeIdAnyFrame:
|
||||
@ -8168,6 +8203,7 @@ const char *container_string(ContainerKind kind) {
|
||||
case ContainerKindEnum: return "enum";
|
||||
case ContainerKindStruct: return "struct";
|
||||
case ContainerKindUnion: return "union";
|
||||
case ContainerKindOpaque: return "opaque";
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
@ -8186,8 +8222,6 @@ Buf *type_bare_name(ZigType *type_entry) {
|
||||
return &type_entry->name;
|
||||
} else if (is_container(type_entry)) {
|
||||
return get_container_scope(type_entry)->bare_name;
|
||||
} else if (type_entry->id == ZigTypeIdOpaque) {
|
||||
return type_entry->data.opaque.bare_name;
|
||||
} else {
|
||||
return &type_entry->name;
|
||||
}
|
||||
|
||||
@ -22587,7 +22587,7 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name
|
||||
}
|
||||
}
|
||||
|
||||
if (bare_type->id == ZigTypeIdEnum) {
|
||||
if (bare_type->id == ZigTypeIdEnum || bare_type->id == ZigTypeIdOpaque) {
|
||||
return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
|
||||
source_instr, container_ptr, container_ptr_src, container_type);
|
||||
}
|
||||
@ -25183,7 +25183,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
|
||||
case ZigTypeIdEnumLiteral:
|
||||
case ZigTypeIdUndefined:
|
||||
case ZigTypeIdNull:
|
||||
case ZigTypeIdOpaque:
|
||||
result = ira->codegen->intern.for_void();
|
||||
break;
|
||||
case ZigTypeIdInt:
|
||||
@ -25737,6 +25736,25 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
|
||||
if ((err = ir_make_type_info_value(ira, source_instr, fn_type, &result)))
|
||||
return err;
|
||||
|
||||
break;
|
||||
}
|
||||
case ZigTypeIdOpaque:
|
||||
{
|
||||
result = ira->codegen->pass1_arena->create<ZigValue>();
|
||||
result->special = ConstValSpecialStatic;
|
||||
result->type = ir_type_info_get_type(ira, "Opaque", nullptr);
|
||||
|
||||
ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 1);
|
||||
result->data.x_struct.fields = fields;
|
||||
|
||||
// decls: []TypeInfo.Declaration
|
||||
ensure_field_index(result->type, "decls", 0);
|
||||
if ((err = ir_make_type_info_decls(ira, source_instr, fields[0],
|
||||
type_entry->data.opaque.decls_scope, false)))
|
||||
{
|
||||
return err;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ZigTypeIdFnFrame:
|
||||
@ -26044,6 +26062,21 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
|
||||
return get_error_union_type(ira->codegen, err_set_type, payload_type);
|
||||
}
|
||||
case ZigTypeIdOpaque: {
|
||||
assert(payload->special == ConstValSpecialStatic);
|
||||
assert(payload->type == ir_type_info_get_type(ira, "Opaque", nullptr));
|
||||
|
||||
ZigValue *decls_value = get_const_field(ira, source_instr->source_node, payload, "decls", 0);
|
||||
if (decls_value == nullptr)
|
||||
return ira->codegen->invalid_inst_gen->value->type;
|
||||
assert(decls_value->special == ConstValSpecialStatic);
|
||||
assert(is_slice(decls_value->type));
|
||||
ZigValue *decls_len_value = decls_value->data.x_struct.fields[slice_len_index];
|
||||
size_t decls_len = bigint_as_usize(&decls_len_value->data.x_bigint);
|
||||
if (decls_len != 0) {
|
||||
ir_add_error(ira, source_instr, buf_create_from_str("TypeInfo.Struct.decls must be empty for @Type"));
|
||||
return ira->codegen->invalid_inst_gen->value->type;
|
||||
}
|
||||
|
||||
Buf *bare_name = buf_alloc();
|
||||
Buf *full_name = get_anon_type_name(ira->codegen,
|
||||
ira->old_irb.exec, "opaque", source_instr->scope, source_instr->source_node, bare_name);
|
||||
|
||||
@ -2920,6 +2920,7 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc) {
|
||||
// <- KEYWORD_struct
|
||||
// / KEYWORD_enum (LPAREN Expr RPAREN)?
|
||||
// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
|
||||
// / KEYWORD_opaque
|
||||
static AstNode *ast_parse_container_decl_type(ParseContext *pc) {
|
||||
Token *first = eat_token_if(pc, TokenIdKeywordStruct);
|
||||
if (first != nullptr) {
|
||||
@ -2929,6 +2930,14 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) {
|
||||
return res;
|
||||
}
|
||||
|
||||
first = eat_token_if(pc, TokenIdKeywordOpaque);
|
||||
if (first != nullptr) {
|
||||
AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first);
|
||||
res->data.container_decl.init_arg_expr = nullptr;
|
||||
res->data.container_decl.kind = ContainerKindOpaque;
|
||||
return res;
|
||||
}
|
||||
|
||||
first = eat_token_if(pc, TokenIdKeywordEnum);
|
||||
if (first != nullptr) {
|
||||
AstNode *init_arg_expr = nullptr;
|
||||
|
||||
@ -133,6 +133,7 @@ static const struct ZigKeyword zig_keywords[] = {
|
||||
{"noinline", TokenIdKeywordNoInline},
|
||||
{"nosuspend", TokenIdKeywordNoSuspend},
|
||||
{"null", TokenIdKeywordNull},
|
||||
{"opaque", TokenIdKeywordOpaque},
|
||||
{"or", TokenIdKeywordOr},
|
||||
{"orelse", TokenIdKeywordOrElse},
|
||||
{"packed", TokenIdKeywordPacked},
|
||||
@ -1595,6 +1596,7 @@ const char * token_name(TokenId id) {
|
||||
case TokenIdKeywordNoInline: return "noinline";
|
||||
case TokenIdKeywordNoSuspend: return "nosuspend";
|
||||
case TokenIdKeywordNull: return "null";
|
||||
case TokenIdKeywordOpaque: return "opaque";
|
||||
case TokenIdKeywordOr: return "or";
|
||||
case TokenIdKeywordOrElse: return "orelse";
|
||||
case TokenIdKeywordPacked: return "packed";
|
||||
|
||||
@ -81,6 +81,7 @@ enum TokenId {
|
||||
TokenIdKeywordNoAlias,
|
||||
TokenIdKeywordNoSuspend,
|
||||
TokenIdKeywordNull,
|
||||
TokenIdKeywordOpaque,
|
||||
TokenIdKeywordOr,
|
||||
TokenIdKeywordOrElse,
|
||||
TokenIdKeywordPacked,
|
||||
|
||||
@ -930,9 +930,9 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
|
||||
const init_node = blk: {
|
||||
const rp = makeRestorePoint(c);
|
||||
const record_def = ZigClangRecordDecl_getDefinition(record_decl) orelse {
|
||||
const opaque = try transCreateNodeOpaqueType(c);
|
||||
const opaque_type = try transCreateNodeOpaqueType(c);
|
||||
semicolon = try appendToken(c, .Semicolon, ";");
|
||||
break :blk opaque;
|
||||
break :blk opaque_type;
|
||||
};
|
||||
|
||||
const layout_tok = try if (ZigClangRecordDecl_getPackedAttribute(record_decl))
|
||||
@ -954,17 +954,17 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
|
||||
const field_qt = ZigClangFieldDecl_getType(field_decl);
|
||||
|
||||
if (ZigClangFieldDecl_isBitField(field_decl)) {
|
||||
const opaque = try transCreateNodeOpaqueType(c);
|
||||
const opaque_type = try transCreateNodeOpaqueType(c);
|
||||
semicolon = try appendToken(c, .Semicolon, ";");
|
||||
try emitWarning(c, field_loc, "{} demoted to opaque type - has bitfield", .{container_kind_name});
|
||||
break :blk opaque;
|
||||
break :blk opaque_type;
|
||||
}
|
||||
|
||||
if (ZigClangType_isIncompleteOrZeroLengthArrayType(qualTypeCanon(field_qt), c.clang_context)) {
|
||||
const opaque = try transCreateNodeOpaqueType(c);
|
||||
const opaque_type = try transCreateNodeOpaqueType(c);
|
||||
semicolon = try appendToken(c, .Semicolon, ";");
|
||||
try emitWarning(c, field_loc, "{} demoted to opaque type - has variable length array", .{container_kind_name});
|
||||
break :blk opaque;
|
||||
break :blk opaque_type;
|
||||
}
|
||||
|
||||
var is_anon = false;
|
||||
@ -979,10 +979,10 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
|
||||
_ = try appendToken(c, .Colon, ":");
|
||||
const field_type = transQualType(rp, field_qt, field_loc) catch |err| switch (err) {
|
||||
error.UnsupportedType => {
|
||||
const opaque = try transCreateNodeOpaqueType(c);
|
||||
const opaque_type = try transCreateNodeOpaqueType(c);
|
||||
semicolon = try appendToken(c, .Semicolon, ";");
|
||||
try emitWarning(c, record_loc, "{} demoted to opaque type - unable to translate type of field {}", .{ container_kind_name, raw_name });
|
||||
break :blk opaque;
|
||||
break :blk opaque_type;
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
|
||||
@ -190,8 +190,17 @@ test "Type.ErrorUnion" {
|
||||
}
|
||||
|
||||
test "Type.Opaque" {
|
||||
testing.expect(@Type(.Opaque) != @Type(.Opaque));
|
||||
testing.expect(@typeInfo(@Type(.Opaque)) == .Opaque);
|
||||
const Opaque = @Type(.{
|
||||
.Opaque = .{
|
||||
.decls = &[_]TypeInfo.Declaration{},
|
||||
},
|
||||
});
|
||||
testing.expect(Opaque != opaque {});
|
||||
testing.expectEqualSlices(
|
||||
TypeInfo.Declaration,
|
||||
&[_]TypeInfo.Declaration{},
|
||||
@typeInfo(Opaque).Opaque.decls,
|
||||
);
|
||||
}
|
||||
|
||||
test "Type.Vector" {
|
||||
|
||||
@ -199,7 +199,7 @@ fn testUnion() void {
|
||||
expect(typeinfo_info.Union.tag_type.? == TypeId);
|
||||
expect(typeinfo_info.Union.fields.len == 25);
|
||||
expect(typeinfo_info.Union.fields[4].field_type == @TypeOf(@typeInfo(u8).Int));
|
||||
expect(typeinfo_info.Union.decls.len == 21);
|
||||
expect(typeinfo_info.Union.decls.len == 22);
|
||||
|
||||
const TestNoTagUnion = union {
|
||||
Foo: void,
|
||||
@ -265,6 +265,21 @@ const TestStruct = packed struct {
|
||||
const Self = @This();
|
||||
};
|
||||
|
||||
test "type info: opaque info" {
|
||||
testOpaque();
|
||||
comptime testOpaque();
|
||||
}
|
||||
|
||||
fn testOpaque() void {
|
||||
const Foo = opaque {
|
||||
const A = 1;
|
||||
fn b() void {}
|
||||
};
|
||||
|
||||
const foo_info = @typeInfo(Foo);
|
||||
expect(foo_info.Opaque.decls.len == 2);
|
||||
}
|
||||
|
||||
test "type info: function type info" {
|
||||
// wasm doesn't support align attributes on functions
|
||||
if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user