Commit d15e8f8017

Andrew Kelley <andrew@ziglang.org>
2023-07-17 08:17:19
Sema: resolve inferred error set with function state in_progress
This way dependency loops are reported instead of the compiler crashing.
1 parent e1935d4
Changed files (2)
src/Module.zig
@@ -5348,6 +5348,27 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato
     sema.air_extra.appendSliceAssumeCapacity(inner_block.instructions.items);
     sema.air_extra.items[@intFromEnum(Air.ExtraIndex.main_block)] = main_block_index;
 
+    // Resolving inferred error sets is done *before* setting the function
+    // state to success, so that "unable to resolve inferred error set" errors
+    // can be emitted here.
+    if (sema.fn_ret_ty_ies) |ies| {
+        sema.resolveInferredErrorSetPtr(&inner_block, LazySrcLoc.nodeOffset(0), ies) catch |err| switch (err) {
+            error.NeededSourceLocation => unreachable,
+            error.GenericPoison => unreachable,
+            error.ComptimeReturn => unreachable,
+            error.ComptimeBreak => unreachable,
+            error.AnalysisFail => {
+                // In this case our function depends on a type that had a compile error.
+                // We should not try to lower this function.
+                decl.analysis = .dependency_failure;
+                return error.AnalysisFail;
+            },
+            else => |e| return e,
+        };
+        assert(ies.resolved != .none);
+        ip.funcIesResolved(func_index).* = ies.resolved;
+    }
+
     func.analysis(ip).state = .success;
 
     // Finally we must resolve the return type and parameter types so that backends
@@ -5355,7 +5376,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato
     // Crucially, this happens *after* we set the function state to success above,
     // so that dependencies on the function body will now be satisfied rather than
     // result in circular dependency errors.
-    sema.resolveFnTypes(&inner_block, LazySrcLoc.nodeOffset(0), fn_ty) catch |err| switch (err) {
+    sema.resolveFnTypes(fn_ty) catch |err| switch (err) {
         error.NeededSourceLocation => unreachable,
         error.GenericPoison => unreachable,
         error.ComptimeReturn => unreachable,
src/Sema.zig
@@ -30619,12 +30619,13 @@ fn analyzeIsNonErrComptimeOnly(
                             ies.func == func_index)
                         {
                             // Try to avoid resolving inferred error set if possible.
-                            if (ies.errors.count() != 0) break :blk;
+                            if (ies.errors.count() != 0) return .none;
                             switch (ies.resolved) {
-                                .anyerror_type => break :blk,
+                                .anyerror_type => return .none,
                                 .none => {},
-                                else => if (ip.indexToKey(ies.resolved).error_set_type.names.len != 0) {
-                                    break :blk;
+                                else => switch (ip.indexToKey(ies.resolved).error_set_type.names.len) {
+                                    0 => return .bool_true,
+                                    else => return .none,
                                 },
                             }
                             for (ies.inferred_error_sets.keys()) |other_ies_index| {
@@ -30633,10 +30634,10 @@ fn analyzeIsNonErrComptimeOnly(
                                     try sema.resolveInferredErrorSet(block, src, other_ies_index);
                                 if (other_resolved == .anyerror_type) {
                                     ies.resolved = .anyerror_type;
-                                    break :blk;
+                                    return .none;
                                 }
                                 if (ip.indexToKey(other_resolved).error_set_type.names.len != 0)
-                                    break :blk;
+                                    return .none;
                             }
                             return .bool_true;
                         }
@@ -33113,16 +33114,21 @@ fn typeIsArrayLike(sema: *Sema, ty: Type) ?ArrayLike {
     };
 }
 
-pub fn resolveFnTypes(sema: *Sema, block: *Block, src: LazySrcLoc, fn_ty: Type) CompileError!void {
+pub fn resolveIes(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError!void {
     const mod = sema.mod;
     const ip = &mod.intern_pool;
-    const fn_ty_info = mod.typeToFunc(fn_ty).?;
 
     if (sema.fn_ret_ty_ies) |ies| {
         try sema.resolveInferredErrorSetPtr(block, src, ies);
         assert(ies.resolved != .none);
         ip.funcIesResolved(sema.func_index).* = ies.resolved;
     }
+}
+
+pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void {
+    const mod = sema.mod;
+    const ip = &mod.intern_pool;
+    const fn_ty_info = mod.typeToFunc(fn_ty).?;
 
     try sema.resolveTypeFully(fn_ty_info.return_type.toType());
 
@@ -34111,7 +34117,7 @@ fn resolveInferredErrorSet(
     return final_resolved_ty;
 }
 
-fn resolveInferredErrorSetPtr(
+pub fn resolveInferredErrorSetPtr(
     sema: *Sema,
     block: *Block,
     src: LazySrcLoc,