fix @typeInfo unable to distinguish compile error vs no-payload

closes #1421
closes #1426
This commit is contained in:
Andrew Kelley 2018-08-27 17:11:43 -04:00
parent 2f2215c9f4
commit 009e90f446
No known key found for this signature in database
GPG Key ID: 4E7CD66038A4D47C
2 changed files with 83 additions and 69 deletions

View File

@ -14444,8 +14444,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
ConstExprValue *payload_val = union_val->data.x_union.payload; ConstExprValue *payload_val = union_val->data.x_union.payload;
TypeTableEntry *field_type = field->type_entry; TypeTableEntry *field_type = field->type_entry;
if (field_type->id == TypeTableEntryIdVoid) if (field_type->id == TypeTableEntryIdVoid) {
{
assert(payload_val == nullptr); assert(payload_val == nullptr);
payload_val = create_const_vals(1); payload_val = create_const_vals(1);
payload_val->special = ConstValSpecialStatic; payload_val->special = ConstValSpecialStatic;
@ -16797,12 +16796,11 @@ static TypeTableEntry *ir_type_info_get_type(IrAnalyze *ira, const char *type_na
return var->value->data.x_type; return var->value->data.x_type;
} }
static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, ScopeDecls *decls_scope) static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, ScopeDecls *decls_scope) {
{
Error err; Error err;
TypeTableEntry *type_info_definition_type = ir_type_info_get_type(ira, "Definition", nullptr); TypeTableEntry *type_info_definition_type = ir_type_info_get_type(ira, "Definition", nullptr);
if ((err = ensure_complete_type(ira->codegen, type_info_definition_type))) if ((err = ensure_complete_type(ira->codegen, type_info_definition_type)))
return false; return err;
ensure_field_index(type_info_definition_type, "name", 0); ensure_field_index(type_info_definition_type, "name", 0);
ensure_field_index(type_info_definition_type, "is_pub", 1); ensure_field_index(type_info_definition_type, "is_pub", 1);
@ -16810,38 +16808,33 @@ static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop
TypeTableEntry *type_info_definition_data_type = ir_type_info_get_type(ira, "Data", type_info_definition_type); TypeTableEntry *type_info_definition_data_type = ir_type_info_get_type(ira, "Data", type_info_definition_type);
if ((err = ensure_complete_type(ira->codegen, type_info_definition_data_type))) if ((err = ensure_complete_type(ira->codegen, type_info_definition_data_type)))
return false; return err;
TypeTableEntry *type_info_fn_def_type = ir_type_info_get_type(ira, "FnDef", type_info_definition_data_type); TypeTableEntry *type_info_fn_def_type = ir_type_info_get_type(ira, "FnDef", type_info_definition_data_type);
if ((err = ensure_complete_type(ira->codegen, type_info_fn_def_type))) if ((err = ensure_complete_type(ira->codegen, type_info_fn_def_type)))
return false; return err;
TypeTableEntry *type_info_fn_def_inline_type = ir_type_info_get_type(ira, "Inline", type_info_fn_def_type); TypeTableEntry *type_info_fn_def_inline_type = ir_type_info_get_type(ira, "Inline", type_info_fn_def_type);
if ((err = ensure_complete_type(ira->codegen, type_info_fn_def_inline_type))) if ((err = ensure_complete_type(ira->codegen, type_info_fn_def_inline_type)))
return false; return err;
// Loop through our definitions once to figure out how many definitions we will generate info for. // Loop through our definitions once to figure out how many definitions we will generate info for.
auto decl_it = decls_scope->decl_table.entry_iterator(); auto decl_it = decls_scope->decl_table.entry_iterator();
decltype(decls_scope->decl_table)::Entry *curr_entry = nullptr; decltype(decls_scope->decl_table)::Entry *curr_entry = nullptr;
int definition_count = 0; int definition_count = 0;
while ((curr_entry = decl_it.next()) != nullptr) while ((curr_entry = decl_it.next()) != nullptr) {
{
// If the definition is unresolved, force it to be resolved again. // If the definition is unresolved, force it to be resolved again.
if (curr_entry->value->resolution == TldResolutionUnresolved) if (curr_entry->value->resolution == TldResolutionUnresolved) {
{
resolve_top_level_decl(ira->codegen, curr_entry->value, false, curr_entry->value->source_node); resolve_top_level_decl(ira->codegen, curr_entry->value, false, curr_entry->value->source_node);
if (curr_entry->value->resolution != TldResolutionOk) if (curr_entry->value->resolution != TldResolutionOk) {
{ return ErrorSemanticAnalyzeFail;
return false;
} }
} }
// Skip comptime blocks and test functions. // Skip comptime blocks and test functions.
if (curr_entry->value->id != TldIdCompTime) if (curr_entry->value->id != TldIdCompTime) {
{ if (curr_entry->value->id == TldIdFn) {
if (curr_entry->value->id == TldIdFn)
{
FnTableEntry *fn_entry = ((TldFn *)curr_entry->value)->fn_entry; FnTableEntry *fn_entry = ((TldFn *)curr_entry->value)->fn_entry;
if (fn_entry->is_test) if (fn_entry->is_test)
continue; continue;
@ -16863,13 +16856,11 @@ static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop
decl_it = decls_scope->decl_table.entry_iterator(); decl_it = decls_scope->decl_table.entry_iterator();
curr_entry = nullptr; curr_entry = nullptr;
int definition_index = 0; int definition_index = 0;
while ((curr_entry = decl_it.next()) != nullptr) while ((curr_entry = decl_it.next()) != nullptr) {
{
// Skip comptime blocks and test functions. // Skip comptime blocks and test functions.
if (curr_entry->value->id == TldIdCompTime) if (curr_entry->value->id == TldIdCompTime) {
continue; continue;
else if (curr_entry->value->id == TldIdFn) } else if (curr_entry->value->id == TldIdFn) {
{
FnTableEntry *fn_entry = ((TldFn *)curr_entry->value)->fn_entry; FnTableEntry *fn_entry = ((TldFn *)curr_entry->value)->fn_entry;
if (fn_entry->is_test) if (fn_entry->is_test)
continue; continue;
@ -16892,13 +16883,12 @@ static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop
inner_fields[2].data.x_union.parent.data.p_struct.struct_val = definition_val; inner_fields[2].data.x_union.parent.data.p_struct.struct_val = definition_val;
inner_fields[2].data.x_union.parent.data.p_struct.field_index = 1; inner_fields[2].data.x_union.parent.data.p_struct.field_index = 1;
switch (curr_entry->value->id) switch (curr_entry->value->id) {
{
case TldIdVar: case TldIdVar:
{ {
VariableTableEntry *var = ((TldVar *)curr_entry->value)->var; VariableTableEntry *var = ((TldVar *)curr_entry->value)->var;
if ((err = ensure_complete_type(ira->codegen, var->value->type))) if ((err = ensure_complete_type(ira->codegen, var->value->type)))
return false; return ErrorSemanticAnalyzeFail;
if (var->value->type->id == TypeTableEntryIdMetaType) if (var->value->type->id == TypeTableEntryIdMetaType)
{ {
@ -17029,7 +17019,7 @@ static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop
{ {
TypeTableEntry *type_entry = ((TldContainer *)curr_entry->value)->type_entry; TypeTableEntry *type_entry = ((TldContainer *)curr_entry->value)->type_entry;
if ((err = ensure_complete_type(ira->codegen, type_entry))) if ((err = ensure_complete_type(ira->codegen, type_entry)))
return false; return ErrorSemanticAnalyzeFail;
// This is a type. // This is a type.
bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0); bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0);
@ -17051,7 +17041,7 @@ static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop
} }
assert(definition_index == definition_count); assert(definition_index == definition_count);
return true; return ErrorNone;
} }
static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, TypeTableEntry *ptr_type_entry) { static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, TypeTableEntry *ptr_type_entry) {
@ -17109,16 +17099,9 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, TypeTableEntry
return result; return result;
}; };
static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *type_entry) { static void make_enum_field_val(IrAnalyze *ira, ConstExprValue *enum_field_val, TypeEnumField *enum_field,
Error err; TypeTableEntry *type_info_enum_field_type)
assert(type_entry != nullptr); {
assert(!type_is_invalid(type_entry));
if ((err = ensure_complete_type(ira->codegen, type_entry)))
return nullptr;
const auto make_enum_field_val = [ira](ConstExprValue *enum_field_val, TypeEnumField *enum_field,
TypeTableEntry *type_info_enum_field_type) {
enum_field_val->special = ConstValSpecialStatic; enum_field_val->special = ConstValSpecialStatic;
enum_field_val->type = type_info_enum_field_type; enum_field_val->type = type_info_enum_field_type;
@ -17132,7 +17115,15 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
bigint_init_bigint(&inner_fields[1].data.x_bigint, &enum_field->value); bigint_init_bigint(&inner_fields[1].data.x_bigint, &enum_field->value);
enum_field_val->data.x_struct.fields = inner_fields; enum_field_val->data.x_struct.fields = inner_fields;
}; }
static Error ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *type_entry, ConstExprValue **out) {
Error err;
assert(type_entry != nullptr);
assert(!type_is_invalid(type_entry));
if ((err = ensure_complete_type(ira->codegen, type_entry)))
return err;
if (type_entry == ira->codegen->builtin_types.entry_global_error_set) { if (type_entry == ira->codegen->builtin_types.entry_global_error_set) {
zig_panic("TODO implement @typeInfo for global error set"); zig_panic("TODO implement @typeInfo for global error set");
@ -17155,13 +17146,16 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
case TypeTableEntryIdBlock: case TypeTableEntryIdBlock:
case TypeTableEntryIdArgTuple: case TypeTableEntryIdArgTuple:
case TypeTableEntryIdOpaque: case TypeTableEntryIdOpaque:
return nullptr; *out = nullptr;
return ErrorNone;
default: default:
{ {
// Lookup an available value in our cache. // Lookup an available value in our cache.
auto entry = ira->codegen->type_info_cache.maybe_get(type_entry); auto entry = ira->codegen->type_info_cache.maybe_get(type_entry);
if (entry != nullptr) if (entry != nullptr) {
return entry->value; *out = entry->value;
return ErrorNone;
}
// Fallthrough if we don't find one. // Fallthrough if we don't find one.
} }
@ -17312,15 +17306,15 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
{ {
TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index]; TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index];
ConstExprValue *enum_field_val = &enum_field_array->data.x_array.s_none.elements[enum_field_index]; ConstExprValue *enum_field_val = &enum_field_array->data.x_array.s_none.elements[enum_field_index];
make_enum_field_val(enum_field_val, enum_field, type_info_enum_field_type); make_enum_field_val(ira, enum_field_val, enum_field, type_info_enum_field_type);
enum_field_val->data.x_struct.parent.id = ConstParentIdArray; enum_field_val->data.x_struct.parent.id = ConstParentIdArray;
enum_field_val->data.x_struct.parent.data.p_array.array_val = enum_field_array; enum_field_val->data.x_struct.parent.data.p_array.array_val = enum_field_array;
enum_field_val->data.x_struct.parent.data.p_array.elem_index = enum_field_index; enum_field_val->data.x_struct.parent.data.p_array.elem_index = enum_field_index;
} }
// defs: []TypeInfo.Definition // defs: []TypeInfo.Definition
ensure_field_index(result->type, "defs", 3); ensure_field_index(result->type, "defs", 3);
if (!ir_make_type_info_defs(ira, &fields[3], type_entry->data.enumeration.decls_scope)) if ((err = ir_make_type_info_defs(ira, &fields[3], type_entry->data.enumeration.decls_scope)))
return nullptr; return err;
break; break;
} }
@ -17346,8 +17340,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
error_array->data.x_array.s_none.elements = create_const_vals(error_count); error_array->data.x_array.s_none.elements = create_const_vals(error_count);
init_const_slice(ira->codegen, &fields[0], error_array, 0, error_count, false); init_const_slice(ira->codegen, &fields[0], error_array, 0, error_count, false);
for (uint32_t error_index = 0; error_index < error_count; error_index++) for (uint32_t error_index = 0; error_index < error_count; error_index++) {
{
ErrorTableEntry *error = type_entry->data.error_set.errors[error_index]; ErrorTableEntry *error = type_entry->data.error_set.errors[error_index];
ConstExprValue *error_val = &error_array->data.x_array.s_none.elements[error_index]; ConstExprValue *error_val = &error_array->data.x_array.s_none.elements[error_index];
@ -17425,9 +17418,9 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
tag_type->type = ira->codegen->builtin_types.entry_type; tag_type->type = ira->codegen->builtin_types.entry_type;
tag_type->data.x_type = type_entry->data.unionation.tag_type; tag_type->data.x_type = type_entry->data.unionation.tag_type;
fields[1].data.x_optional = tag_type; fields[1].data.x_optional = tag_type;
} } else {
else
fields[1].data.x_optional = nullptr; fields[1].data.x_optional = nullptr;
}
// fields: []TypeInfo.UnionField // fields: []TypeInfo.UnionField
ensure_field_index(result->type, "fields", 2); ensure_field_index(result->type, "fields", 2);
@ -17460,7 +17453,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
inner_fields[1].data.x_optional = nullptr; inner_fields[1].data.x_optional = nullptr;
} else { } else {
inner_fields[1].data.x_optional = create_const_vals(1); inner_fields[1].data.x_optional = create_const_vals(1);
make_enum_field_val(inner_fields[1].data.x_optional, union_field->enum_field, type_info_enum_field_type); make_enum_field_val(ira, inner_fields[1].data.x_optional, union_field->enum_field, type_info_enum_field_type);
} }
inner_fields[2].special = ConstValSpecialStatic; inner_fields[2].special = ConstValSpecialStatic;
@ -17477,8 +17470,8 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
} }
// defs: []TypeInfo.Definition // defs: []TypeInfo.Definition
ensure_field_index(result->type, "defs", 3); ensure_field_index(result->type, "defs", 3);
if (!ir_make_type_info_defs(ira, &fields[3], type_entry->data.unionation.decls_scope)) if ((err = ir_make_type_info_defs(ira, &fields[3], type_entry->data.unionation.decls_scope)))
return nullptr; return err;
break; break;
} }
@ -17551,8 +17544,8 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
} }
// defs: []TypeInfo.Definition // defs: []TypeInfo.Definition
ensure_field_index(result->type, "defs", 2); ensure_field_index(result->type, "defs", 2);
if (!ir_make_type_info_defs(ira, &fields[2], type_entry->data.structure.decls_scope)) if ((err = ir_make_type_info_defs(ira, &fields[2], type_entry->data.structure.decls_scope)))
return nullptr; return err;
break; break;
} }
@ -17665,7 +17658,8 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
{ {
TypeTableEntry *fn_type = type_entry->data.bound_fn.fn_type; TypeTableEntry *fn_type = type_entry->data.bound_fn.fn_type;
assert(fn_type->id == TypeTableEntryIdFn); assert(fn_type->id == TypeTableEntryIdFn);
result = ir_make_type_info_value(ira, fn_type); if ((err = ir_make_type_info_value(ira, fn_type, &result)))
return err;
break; break;
} }
@ -17673,12 +17667,14 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
assert(result != nullptr); assert(result != nullptr);
ira->codegen->type_info_cache.put(type_entry, result); ira->codegen->type_info_cache.put(type_entry, result);
return result; *out = result;
return ErrorNone;
} }
static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira, static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira,
IrInstructionTypeInfo *instruction) IrInstructionTypeInfo *instruction)
{ {
Error err;
IrInstruction *type_value = instruction->type_value->other; IrInstruction *type_value = instruction->type_value->other;
TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); TypeTableEntry *type_entry = ir_resolve_type(ira, type_value);
if (type_is_invalid(type_entry)) if (type_is_invalid(type_entry))
@ -17686,15 +17682,16 @@ static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira,
TypeTableEntry *result_type = ir_type_info_get_type(ira, nullptr, nullptr); TypeTableEntry *result_type = ir_type_info_get_type(ira, nullptr, nullptr);
ConstExprValue *payload;
if ((err = ir_make_type_info_value(ira, type_entry, &payload)))
return ira->codegen->builtin_types.entry_invalid;
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
out_val->type = result_type; out_val->type = result_type;
bigint_init_unsigned(&out_val->data.x_union.tag, type_id_index(type_entry)); bigint_init_unsigned(&out_val->data.x_union.tag, type_id_index(type_entry));
ConstExprValue *payload = ir_make_type_info_value(ira, type_entry);
out_val->data.x_union.payload = payload; out_val->data.x_union.payload = payload;
if (payload != nullptr) if (payload != nullptr) {
{
assert(payload->type->id == TypeTableEntryIdStruct); assert(payload->type->id == TypeTableEntryIdStruct);
payload->data.x_struct.parent.id = ConstParentIdUnion; payload->data.x_struct.parent.id = ConstParentIdUnion;
payload->data.x_struct.parent.data.p_union.union_val = out_val; payload->data.x_struct.parent.data.p_union.union_val = out_val;

View File

@ -1,6 +1,23 @@
const tests = @import("tests.zig"); const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompileErrorContext) void { pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.add(
"@typeInfo causing depend on itself compile error",
\\const start = struct {
\\ fn crash() bug() {
\\ return bug;
\\ }
\\};
\\fn bug() void {
\\ _ = @typeInfo(start).Struct;
\\}
\\export fn entry() void {
\\ var boom = start.crash();
\\}
,
".tmp_source.zig:2:5: error: 'crash' depends on itself",
);
cases.add( cases.add(
"@handle() called outside of function definition", "@handle() called outside of function definition",
\\var handle_undef: promise = undefined; \\var handle_undef: promise = undefined;