Commit 6da070c5ac

Veikka Tuominen <git@vexu.eu>
2022-12-20 16:32:04
Sema: fix crash with generic function with generic function parameter
Closes #12810
1 parent 6511afc
Changed files (2)
src
test
behavior
src/Sema.zig
@@ -7256,6 +7256,7 @@ fn instantiateGenericCall(
         child_block.error_return_trace_index = error_return_trace_index;
 
         const new_func_inst = child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst) catch |err| {
+            if (err == error.GenericPoison) return error.GenericPoison;
             // TODO look up the compile error that happened here and attach a note to it
             // pointing here, at the generic instantiation callsite.
             if (sema.owner_func) |owner_func| {
@@ -8864,6 +8865,11 @@ fn zirParam(
         };
         switch (err) {
             error.GenericPoison => {
+                if (sema.inst_map.get(inst)) |_| {
+                    // A generic function is about to evaluate to another generic function.
+                    // Return an error instead.
+                    return error.GenericPoison;
+                }
                 // The type is not available until the generic instantiation.
                 // We result the param instruction with a poison value and
                 // insert an anytype parameter.
@@ -8880,6 +8886,11 @@ fn zirParam(
     };
     const is_comptime = sema.typeRequiresComptime(param_ty) catch |err| switch (err) {
         error.GenericPoison => {
+            if (sema.inst_map.get(inst)) |_| {
+                // A generic function is about to evaluate to another generic function.
+                // Return an error instead.
+                return error.GenericPoison;
+            }
             // The type is not available until the generic instantiation.
             // We result the param instruction with a poison value and
             // insert an anytype parameter.
test/behavior/call.zig
@@ -369,3 +369,15 @@ test "Enum constructed by @Type passed as generic argument" {
         try S.foo(@intToEnum(S.E, i), i);
     }
 }
+
+test "generic function with generic function parameter" {
+    const S = struct {
+        fn f(comptime a: fn (anytype) anyerror!void, b: anytype) anyerror!void {
+            try a(b);
+        }
+        fn g(a: anytype) anyerror!void {
+            try expect(a == 123);
+        }
+    };
+    try S.f(S.g, 123);
+}