mirror of
https://github.com/ziglang/zig.git
synced 2024-11-27 07:32:44 +00:00
Implement @Type for Enum
This commit is contained in:
parent
a2f1f01e77
commit
5a5956bd20
231
src/analyze.cpp
231
src/analyze.cpp
@ -2586,7 +2586,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
|
||||
return ErrorNone;
|
||||
|
||||
AstNode *decl_node = enum_type->data.enumeration.decl_node;
|
||||
assert(decl_node->type == NodeTypeContainerDecl);
|
||||
|
||||
if (enum_type->data.enumeration.resolve_loop_flag) {
|
||||
if (enum_type->data.enumeration.resolve_status != ResolveStatusInvalid) {
|
||||
@ -2600,15 +2599,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
|
||||
|
||||
enum_type->data.enumeration.resolve_loop_flag = true;
|
||||
|
||||
assert(!enum_type->data.enumeration.fields);
|
||||
uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length;
|
||||
if (field_count == 0) {
|
||||
add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields"));
|
||||
uint32_t field_count;
|
||||
if (decl_node->type == NodeTypeContainerDecl) {
|
||||
assert(!enum_type->data.enumeration.fields);
|
||||
field_count = (uint32_t)decl_node->data.container_decl.fields.length;
|
||||
if (field_count == 0) {
|
||||
add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields"));
|
||||
|
||||
enum_type->data.enumeration.src_field_count = field_count;
|
||||
enum_type->data.enumeration.fields = nullptr;
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
enum_type->data.enumeration.src_field_count = field_count;
|
||||
enum_type->data.enumeration.fields = nullptr;
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
} else {
|
||||
field_count = enum_type->data.enumeration.src_field_count;
|
||||
}
|
||||
|
||||
Scope *scope = &enum_type->data.enumeration.decls_scope->base;
|
||||
@ -2624,8 +2628,16 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
|
||||
enum_type->abi_size = tag_int_type->abi_size;
|
||||
enum_type->abi_align = tag_int_type->abi_align;
|
||||
|
||||
if (decl_node->data.container_decl.init_arg_expr != nullptr) {
|
||||
ZigType *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);
|
||||
ZigType *wanted_tag_int_type = nullptr;
|
||||
if (decl_node->type == NodeTypeContainerDecl) {
|
||||
if (decl_node->data.container_decl.init_arg_expr != nullptr) {
|
||||
wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);
|
||||
}
|
||||
} else {
|
||||
wanted_tag_int_type = enum_type->data.enumeration.tag_int_type;
|
||||
}
|
||||
|
||||
if (wanted_tag_int_type != nullptr) {
|
||||
if (type_is_invalid(wanted_tag_int_type)) {
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
} else if (wanted_tag_int_type->id != ZigTypeIdInt &&
|
||||
@ -2654,7 +2666,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
|
||||
}
|
||||
}
|
||||
|
||||
enum_type->data.enumeration.non_exhaustive = false;
|
||||
enum_type->data.enumeration.tag_int_type = tag_int_type;
|
||||
enum_type->size_in_bits = tag_int_type->size_in_bits;
|
||||
enum_type->abi_size = tag_int_type->abi_size;
|
||||
@ -2663,121 +2674,131 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
|
||||
BigInt bi_one;
|
||||
bigint_init_unsigned(&bi_one, 1);
|
||||
|
||||
AstNode *last_field_node = decl_node->data.container_decl.fields.at(field_count - 1);
|
||||
if (buf_eql_str(last_field_node->data.struct_field.name, "_")) {
|
||||
field_count -= 1;
|
||||
if (field_count > 1 && log2_u64(field_count) == enum_type->size_in_bits) {
|
||||
add_node_error(g, last_field_node, buf_sprintf("non-exhaustive enum specifies every value"));
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
if (decl_node->type == NodeTypeContainerDecl) {
|
||||
AstNode *last_field_node = decl_node->data.container_decl.fields.at(field_count - 1);
|
||||
if (buf_eql_str(last_field_node->data.struct_field.name, "_")) {
|
||||
if (last_field_node->data.struct_field.value != nullptr) {
|
||||
add_node_error(g, last_field_node, buf_sprintf("value assigned to '_' field of non-exhaustive enum"));
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
}
|
||||
if (decl_node->data.container_decl.init_arg_expr == nullptr) {
|
||||
add_node_error(g, decl_node, buf_sprintf("non-exhaustive enum must specify size"));
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
}
|
||||
enum_type->data.enumeration.non_exhaustive = true;
|
||||
} else {
|
||||
enum_type->data.enumeration.non_exhaustive = false;
|
||||
}
|
||||
if (decl_node->data.container_decl.init_arg_expr == nullptr) {
|
||||
add_node_error(g, last_field_node, buf_sprintf("non-exhaustive enum must specify size"));
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
}
|
||||
if (last_field_node->data.struct_field.value != nullptr) {
|
||||
add_node_error(g, last_field_node, buf_sprintf("value assigned to '_' field of non-exhaustive enum"));
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
}
|
||||
enum_type->data.enumeration.non_exhaustive = true;
|
||||
}
|
||||
|
||||
enum_type->data.enumeration.src_field_count = field_count;
|
||||
enum_type->data.enumeration.fields = heap::c_allocator.allocate<TypeEnumField>(field_count);
|
||||
enum_type->data.enumeration.fields_by_name.init(field_count);
|
||||
|
||||
HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {};
|
||||
occupied_tag_values.init(field_count);
|
||||
|
||||
TypeEnumField *last_enum_field = nullptr;
|
||||
|
||||
for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {
|
||||
AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);
|
||||
TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i];
|
||||
type_enum_field->name = field_node->data.struct_field.name;
|
||||
type_enum_field->decl_index = field_i;
|
||||
type_enum_field->decl_node = field_node;
|
||||
|
||||
if (field_node->data.struct_field.type != nullptr) {
|
||||
ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.type,
|
||||
buf_sprintf("structs and unions, not enums, support field types"));
|
||||
add_error_note(g, msg, decl_node,
|
||||
buf_sprintf("consider 'union(enum)' here"));
|
||||
} else if (field_node->data.struct_field.align_expr != nullptr) {
|
||||
ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.align_expr,
|
||||
buf_sprintf("structs and unions, not enums, support field alignment"));
|
||||
add_error_note(g, msg, decl_node,
|
||||
buf_sprintf("consider 'union(enum)' here"));
|
||||
}
|
||||
|
||||
if (buf_eql_str(type_enum_field->name, "_")) {
|
||||
add_node_error(g, field_node, buf_sprintf("'_' field of non-exhaustive enum must be last"));
|
||||
if (enum_type->data.enumeration.non_exhaustive) {
|
||||
field_count -= 1;
|
||||
if (field_count > 1 && log2_u64(field_count) == enum_type->size_in_bits) {
|
||||
add_node_error(g, decl_node, buf_sprintf("non-exhaustive enum specifies every value"));
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
auto field_entry = enum_type->data.enumeration.fields_by_name.put_unique(type_enum_field->name, type_enum_field);
|
||||
if (field_entry != nullptr) {
|
||||
ErrorMsg *msg = add_node_error(g, field_node,
|
||||
buf_sprintf("duplicate enum field: '%s'", buf_ptr(type_enum_field->name)));
|
||||
add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
continue;
|
||||
}
|
||||
if (decl_node->type == NodeTypeContainerDecl) {
|
||||
enum_type->data.enumeration.src_field_count = field_count;
|
||||
enum_type->data.enumeration.fields = heap::c_allocator.allocate<TypeEnumField>(field_count);
|
||||
enum_type->data.enumeration.fields_by_name.init(field_count);
|
||||
|
||||
AstNode *tag_value = field_node->data.struct_field.value;
|
||||
HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {};
|
||||
occupied_tag_values.init(field_count);
|
||||
|
||||
if (tag_value != nullptr) {
|
||||
// A user-specified value is available
|
||||
ZigValue *result = analyze_const_value(g, scope, tag_value, tag_int_type,
|
||||
nullptr, UndefBad);
|
||||
if (type_is_invalid(result->type)) {
|
||||
TypeEnumField *last_enum_field = nullptr;
|
||||
|
||||
for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {
|
||||
AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);
|
||||
TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i];
|
||||
type_enum_field->name = field_node->data.struct_field.name;
|
||||
type_enum_field->decl_index = field_i;
|
||||
type_enum_field->decl_node = field_node;
|
||||
|
||||
if (field_node->data.struct_field.type != nullptr) {
|
||||
ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.type,
|
||||
buf_sprintf("structs and unions, not enums, support field types"));
|
||||
add_error_note(g, msg, decl_node,
|
||||
buf_sprintf("consider 'union(enum)' here"));
|
||||
} else if (field_node->data.struct_field.align_expr != nullptr) {
|
||||
ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.align_expr,
|
||||
buf_sprintf("structs and unions, not enums, support field alignment"));
|
||||
add_error_note(g, msg, decl_node,
|
||||
buf_sprintf("consider 'union(enum)' here"));
|
||||
}
|
||||
|
||||
if (buf_eql_str(type_enum_field->name, "_")) {
|
||||
add_node_error(g, field_node, buf_sprintf("'_' field of non-exhaustive enum must be last"));
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
}
|
||||
|
||||
auto field_entry = enum_type->data.enumeration.fields_by_name.put_unique(type_enum_field->name, type_enum_field);
|
||||
if (field_entry != nullptr) {
|
||||
ErrorMsg *msg = add_node_error(g, field_node,
|
||||
buf_sprintf("duplicate enum field: '%s'", buf_ptr(type_enum_field->name)));
|
||||
add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(result->special != ConstValSpecialRuntime);
|
||||
assert(result->type->id == ZigTypeIdInt || result->type->id == ZigTypeIdComptimeInt);
|
||||
AstNode *tag_value = field_node->data.struct_field.value;
|
||||
|
||||
bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint);
|
||||
} else {
|
||||
// No value was explicitly specified: allocate the last value + 1
|
||||
// or, if this is the first element, zero
|
||||
if (last_enum_field != nullptr) {
|
||||
bigint_add(&type_enum_field->value, &last_enum_field->value, &bi_one);
|
||||
if (tag_value != nullptr) {
|
||||
// A user-specified value is available
|
||||
ZigValue *result = analyze_const_value(g, scope, tag_value, tag_int_type,
|
||||
nullptr, UndefBad);
|
||||
if (type_is_invalid(result->type)) {
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(result->special != ConstValSpecialRuntime);
|
||||
assert(result->type->id == ZigTypeIdInt || result->type->id == ZigTypeIdComptimeInt);
|
||||
|
||||
bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint);
|
||||
} else {
|
||||
bigint_init_unsigned(&type_enum_field->value, 0);
|
||||
// No value was explicitly specified: allocate the last value + 1
|
||||
// or, if this is the first element, zero
|
||||
if (last_enum_field != nullptr) {
|
||||
bigint_add(&type_enum_field->value, &last_enum_field->value, &bi_one);
|
||||
} else {
|
||||
bigint_init_unsigned(&type_enum_field->value, 0);
|
||||
}
|
||||
|
||||
// Make sure we can represent this number with tag_int_type
|
||||
if (!bigint_fits_in_bits(&type_enum_field->value,
|
||||
tag_int_type->size_in_bits,
|
||||
tag_int_type->data.integral.is_signed)) {
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
|
||||
Buf *val_buf = buf_alloc();
|
||||
bigint_append_buf(val_buf, &type_enum_field->value, 10);
|
||||
add_node_error(g, field_node,
|
||||
buf_sprintf("enumeration value %s too large for type '%s'",
|
||||
buf_ptr(val_buf), buf_ptr(&tag_int_type->name)));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we can represent this number with tag_int_type
|
||||
if (!bigint_fits_in_bits(&type_enum_field->value,
|
||||
tag_int_type->size_in_bits,
|
||||
tag_int_type->data.integral.is_signed)) {
|
||||
// Make sure the value is unique
|
||||
auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node);
|
||||
if (entry != nullptr && enum_type->data.enumeration.layout != ContainerLayoutExtern) {
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
|
||||
Buf *val_buf = buf_alloc();
|
||||
bigint_append_buf(val_buf, &type_enum_field->value, 10);
|
||||
add_node_error(g, field_node,
|
||||
buf_sprintf("enumeration value %s too large for type '%s'",
|
||||
buf_ptr(val_buf), buf_ptr(&tag_int_type->name)));
|
||||
|
||||
break;
|
||||
ErrorMsg *msg = add_node_error(g, field_node,
|
||||
buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
|
||||
add_error_note(g, msg, entry->value,
|
||||
buf_sprintf("other occurrence here"));
|
||||
}
|
||||
|
||||
last_enum_field = type_enum_field;
|
||||
}
|
||||
|
||||
// Make sure the value is unique
|
||||
auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node);
|
||||
if (entry != nullptr && enum_type->data.enumeration.layout != ContainerLayoutExtern) {
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
|
||||
Buf *val_buf = buf_alloc();
|
||||
bigint_append_buf(val_buf, &type_enum_field->value, 10);
|
||||
|
||||
ErrorMsg *msg = add_node_error(g, field_node,
|
||||
buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
|
||||
add_error_note(g, msg, entry->value,
|
||||
buf_sprintf("other occurrence here"));
|
||||
}
|
||||
|
||||
last_enum_field = type_enum_field;
|
||||
occupied_tag_values.deinit();
|
||||
}
|
||||
|
||||
if (enum_type->data.enumeration.resolve_status == ResolveStatusInvalid)
|
||||
@ -2786,8 +2807,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
|
||||
enum_type->data.enumeration.resolve_loop_flag = false;
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusSizeKnown;
|
||||
|
||||
occupied_tag_values.deinit();
|
||||
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
|
69
src/ir.cpp
69
src/ir.cpp
@ -26276,7 +26276,74 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
|
||||
|
||||
return entry;
|
||||
}
|
||||
case ZigTypeIdEnum:
|
||||
case ZigTypeIdEnum: {
|
||||
assert(payload->special == ConstValSpecialStatic);
|
||||
assert(payload->type == ir_type_info_get_type(ira, "Enum", nullptr));
|
||||
|
||||
ZigValue *layout_value = get_const_field(ira, source_instr->source_node, payload, "layout", 0);
|
||||
assert(layout_value->special == ConstValSpecialStatic);
|
||||
assert(layout_value->type == ir_type_info_get_type(ira, "ContainerLayout", nullptr));
|
||||
ContainerLayout layout = (ContainerLayout)bigint_as_u32(&layout_value->data.x_enum_tag);
|
||||
|
||||
ZigType *tag_type = get_const_field_meta_type(ira, source_instr->source_node, payload, "tag_type", 1);
|
||||
|
||||
ZigValue *fields_value = get_const_field(ira, source_instr->source_node, payload, "fields", 2);
|
||||
assert(fields_value->special == ConstValSpecialStatic);
|
||||
assert(is_slice(fields_value->type));
|
||||
ZigValue *fields_ptr = fields_value->data.x_struct.fields[slice_ptr_index];
|
||||
ZigValue *fields_len_value = fields_value->data.x_struct.fields[slice_len_index];
|
||||
size_t fields_len = bigint_as_usize(&fields_len_value->data.x_bigint);
|
||||
|
||||
ZigValue *decls_value = get_const_field(ira, source_instr->source_node, payload, "decls", 3);
|
||||
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.Enum.decls must be empty for @Type"));
|
||||
return ira->codegen->invalid_inst_gen->value->type;
|
||||
}
|
||||
|
||||
Error err;
|
||||
bool is_exhaustive;
|
||||
if ((err = get_const_field_bool(ira, source_instr->source_node, payload, "is_exhaustive", 4, &is_exhaustive)))
|
||||
return ira->codegen->invalid_inst_gen->value->type;
|
||||
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdEnum);
|
||||
buf_init_from_buf(&entry->name,
|
||||
get_anon_type_name(ira->codegen, ira->old_irb.exec, "enum", source_instr->scope, source_instr->source_node, &entry->name));
|
||||
entry->data.enumeration.decl_node = source_instr->source_node;
|
||||
entry->data.enumeration.tag_int_type = tag_type;
|
||||
entry->data.enumeration.decls_scope = create_decls_scope(ira->codegen, nullptr, nullptr, entry, entry, &entry->name);
|
||||
entry->data.enumeration.fields = heap::c_allocator.allocate<TypeEnumField>(fields_len);
|
||||
entry->data.enumeration.fields_by_name.init(fields_len);
|
||||
entry->data.enumeration.src_field_count = fields_len;
|
||||
entry->data.enumeration.layout = layout;
|
||||
entry->data.enumeration.non_exhaustive = !is_exhaustive;
|
||||
|
||||
assert(fields_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);
|
||||
assert(fields_ptr->data.x_ptr.data.base_array.elem_index == 0);
|
||||
ZigValue *fields_arr = fields_ptr->data.x_ptr.data.base_array.array_val;
|
||||
assert(fields_arr->special == ConstValSpecialStatic);
|
||||
assert(fields_arr->data.x_array.special == ConstArraySpecialNone);
|
||||
for (size_t i = 0; i < fields_len; i++) {
|
||||
ZigValue *field_value = &fields_arr->data.x_array.data.s_none.elements[i];
|
||||
assert(field_value->type == ir_type_info_get_type(ira, "EnumField", nullptr));
|
||||
TypeEnumField *field = &entry->data.enumeration.fields[i];
|
||||
field->name = buf_alloc();
|
||||
if ((err = get_const_field_buf(ira, source_instr->source_node, field_value, "name", 0, field->name)))
|
||||
return ira->codegen->invalid_inst_gen->value->type;
|
||||
field->decl_index = i;
|
||||
field->decl_node = source_instr->source_node;
|
||||
if (entry->data.enumeration.fields_by_name.put_unique(field->name, field) != nullptr) {
|
||||
ir_add_error(ira, source_instr, buf_sprintf("duplicate enum field '%s'", buf_ptr(field->name)));
|
||||
return ira->codegen->invalid_inst_gen->value->type;
|
||||
}
|
||||
field->value = *get_const_field_lit_int(ira, source_instr->source_node, field_value, "value", 1);
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
case ZigTypeIdUnion:
|
||||
ir_add_error(ira, source_instr, buf_sprintf(
|
||||
"TODO implement @Type for 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907", type_id_name(tagTypeId)));
|
||||
|
@ -2,6 +2,22 @@ const tests = @import("tests.zig");
|
||||
const std = @import("std");
|
||||
|
||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
cases.add("struct with declarations unavailable for @Type",
|
||||
\\export fn entry() void {
|
||||
\\ _ = @Type(@typeInfo(struct { const foo = 1; }));
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:2:15: error: TypeInfo.Struct.decls must be empty for @Type",
|
||||
});
|
||||
|
||||
cases.add("enum with declarations unavailable for @Type",
|
||||
\\export fn entry() void {
|
||||
\\ _ = @Type(@typeInfo(enum { foo, const bar = 1; }));
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:2:15: error: TypeInfo.Enum.decls must be empty for @Type",
|
||||
});
|
||||
|
||||
cases.addTest("reject extern variables with initializers",
|
||||
\\extern var foo: int = 2;
|
||||
, &[_][]const u8{
|
||||
@ -1400,15 +1416,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:3:36: error: expected type 'std.builtin.TypeInfo', found 'std.builtin.Int'",
|
||||
});
|
||||
|
||||
cases.add("struct with declarations unavailable for @Type",
|
||||
\\export fn entry() void {
|
||||
\\ _ = @Type(@typeInfo(struct { const foo = 1; }));
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:2:15: error: TypeInfo.Struct.decls must be empty for @Type",
|
||||
});
|
||||
|
||||
cases.add("wrong type for argument tuple to @asyncCall",
|
||||
\\export fn entry1() void {
|
||||
\\ var frame: @Frame(foo) = undefined;
|
||||
|
@ -280,3 +280,37 @@ test "Type.Struct" {
|
||||
testing.expectEqual(@as(usize, 0), infoC.decls.len);
|
||||
testing.expectEqual(@as(bool, false), infoC.is_tuple);
|
||||
}
|
||||
|
||||
test "Type.Enum" {
|
||||
const Foo = @Type(.{
|
||||
.Enum = .{
|
||||
.layout = .Auto,
|
||||
.tag_type = u8,
|
||||
.fields = &[_]TypeInfo.EnumField{
|
||||
.{ .name = "a", .value = 1 },
|
||||
.{ .name = "b", .value = 5 },
|
||||
},
|
||||
.decls = &[_]TypeInfo.Declaration{},
|
||||
.is_exhaustive = true,
|
||||
},
|
||||
});
|
||||
testing.expectEqual(true, @typeInfo(Foo).Enum.is_exhaustive);
|
||||
testing.expectEqual(@as(u8, 1), @enumToInt(Foo.a));
|
||||
testing.expectEqual(@as(u8, 5), @enumToInt(Foo.b));
|
||||
const Bar = @Type(.{
|
||||
.Enum = .{
|
||||
.layout = .Extern,
|
||||
.tag_type = u32,
|
||||
.fields = &[_]TypeInfo.EnumField{
|
||||
.{ .name = "a", .value = 1 },
|
||||
.{ .name = "b", .value = 5 },
|
||||
},
|
||||
.decls = &[_]TypeInfo.Declaration{},
|
||||
.is_exhaustive = false,
|
||||
},
|
||||
});
|
||||
testing.expectEqual(false, @typeInfo(Bar).Enum.is_exhaustive);
|
||||
testing.expectEqual(@as(u32, 1), @enumToInt(Bar.a));
|
||||
testing.expectEqual(@as(u32, 5), @enumToInt(Bar.b));
|
||||
testing.expectEqual(@as(u32, 6), @enumToInt(@intToEnum(Bar, 6)));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user