Commit 8d9b8ab930

LemonBoy <thatlemon@gmail.com>
2020-01-23 22:40:12
More error checking for unresolved TLDs
Closes #4274
1 parent 357f42d
Changed files (2)
src/ir.cpp
@@ -264,6 +264,7 @@ static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_n
     IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type);
 static ResultLoc *no_result_loc(void);
 static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value);
+static IrInstruction *ir_error_dependency_loop(IrAnalyze *ira, IrInstruction *source_instr);
 
 static void destroy_instruction(IrInstruction *inst) {
 #ifdef ZIG_ENABLE_MEM_PROFILE
@@ -20022,8 +20023,13 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
                 resolve_top_level_decl(ira->codegen, tld, source_instr->source_node, false);
                 if (tld->resolution == TldResolutionInvalid)
                     return ira->codegen->invalid_instruction;
+                if (tld->resolution == TldResolutionResolving)
+                    return ir_error_dependency_loop(ira, source_instr);
+
                 TldFn *tld_fn = (TldFn *)tld;
                 ZigFn *fn_entry = tld_fn->fn_entry;
+                assert(fn_entry != nullptr);
+
                 if (type_is_invalid(fn_entry->type_entry))
                     return ira->codegen->invalid_instruction;
 
@@ -20034,8 +20040,13 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
                 resolve_top_level_decl(ira->codegen, tld, source_instr->source_node, false);
                 if (tld->resolution == TldResolutionInvalid)
                     return ira->codegen->invalid_instruction;
+                if (tld->resolution == TldResolutionResolving)
+                    return ir_error_dependency_loop(ira, source_instr);
+
                 TldVar *tld_var = (TldVar *)tld;
                 ZigVar *var = tld_var->var;
+                assert(var != nullptr);
+
                 if (type_is_invalid(var->var_type))
                     return ira->codegen->invalid_instruction;
 
@@ -20369,9 +20380,10 @@ static IrInstruction *ir_error_dependency_loop(IrAnalyze *ira, IrInstruction *so
 
 static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instruction, Tld *tld) {
     resolve_top_level_decl(ira->codegen, tld, source_instruction->source_node, true);
-    if (tld->resolution == TldResolutionInvalid) {
+    if (tld->resolution == TldResolutionInvalid)
         return ira->codegen->invalid_instruction;
-    }
+    if (tld->resolution == TldResolutionResolving)
+        return ir_error_dependency_loop(ira, source_instruction);
 
     switch (tld->id) {
         case TldIdContainer:
@@ -20381,9 +20393,8 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_
         case TldIdVar: {
             TldVar *tld_var = (TldVar *)tld;
             ZigVar *var = tld_var->var;
-            if (var == nullptr) {
-                return ir_error_dependency_loop(ira, source_instruction);
-            }
+            assert(var != nullptr);
+
             if (tld_var->extern_lib_name != nullptr) {
                 add_link_lib_symbol(ira, tld_var->extern_lib_name, buf_create_from_str(var->name),
                         source_instruction->source_node);
@@ -20394,7 +20405,7 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_
         case TldIdFn: {
             TldFn *tld_fn = (TldFn *)tld;
             ZigFn *fn_entry = tld_fn->fn_entry;
-            assert(fn_entry->type_entry);
+            assert(fn_entry->type_entry != nullptr);
 
             if (type_is_invalid(fn_entry->type_entry))
                 return ira->codegen->invalid_instruction;
@@ -22628,11 +22639,14 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
 
     while ((curr_entry = decl_it.next()) != nullptr) {
         // If the declaration is unresolved, force it to be resolved again.
-        if (curr_entry->value->resolution == TldResolutionUnresolved) {
-            resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node, false);
-            if (curr_entry->value->resolution != TldResolutionOk) {
-                return ErrorSemanticAnalyzeFail;
-            }
+        resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node, false);
+        if (curr_entry->value->resolution == TldResolutionInvalid) {
+            return ErrorSemanticAnalyzeFail;
+        }
+
+        if (curr_entry->value->resolution == TldResolutionResolving) {
+            ir_error_dependency_loop(ira, source_instr);
+            return ErrorSemanticAnalyzeFail;
         }
 
         // Skip comptime blocks and test functions.
@@ -22689,6 +22703,8 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
             case TldIdVar:
                 {
                     ZigVar *var = ((TldVar *)curr_entry->value)->var;
+                    assert(var != nullptr);
+
                     if ((err = type_resolve(ira->codegen, var->const_value->type, ResolveStatusSizeKnown)))
                         return ErrorSemanticAnalyzeFail;
 
@@ -22719,11 +22735,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
 
                     ZigFn *fn_entry = ((TldFn *)curr_entry->value)->fn_entry;
                     assert(!fn_entry->is_test);
-
-                    if (fn_entry->type_entry == nullptr) {
-                        ir_error_dependency_loop(ira, source_instr);
-                        return ErrorSemanticAnalyzeFail;
-                    }
+                    assert(fn_entry->type_entry != nullptr);
 
                     AstNodeFnProto *fn_node = &fn_entry->proto_node->data.fn_proto;
 
test/compile_errors.zig
@@ -2,6 +2,12 @@ const tests = @import("tests.zig");
 const builtin = @import("builtin");
 
 pub fn addCases(cases: *tests.CompileErrorContext) void {
+    cases.addTest("dependency loop in top-level decl with @TypeInfo",
+        \\export const foo = @typeInfo(@This());
+    , &[_][]const u8{
+        "tmp.zig:1:20: error: dependency loop detected",
+    });
+
     cases.addTest("non-exhaustive enums",
         \\const A = enum {
         \\    a,