Commit d291d3c8c0

Andrew Kelley <andrew@ziglang.org>
2019-09-02 19:07:44
fix using @typeOf on a generic function call
1 parent 0fe2885
Changed files (2)
src
test
stage1
behavior
src/ir.cpp
@@ -15648,6 +15648,31 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
     return &store_ptr->base;
 }
 
+static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,
+        ZigFn *fn_entry)
+{
+    if (call_instruction->new_stack == nullptr)
+        return nullptr;
+
+    IrInstruction *new_stack = call_instruction->new_stack->child;
+    if (type_is_invalid(new_stack->value.type))
+        return ira->codegen->invalid_instruction;
+
+    if (call_instruction->is_async_call_builtin &&
+        fn_entry != nullptr && new_stack->value.type->id == ZigTypeIdPointer &&
+        new_stack->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame)
+    {
+        ZigType *needed_frame_type = get_pointer_to_type(ira->codegen,
+                get_fn_frame_type(ira->codegen, fn_entry), false);
+        return ir_implicit_cast(ira, new_stack, needed_frame_type);
+    } else {
+        ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
+                false, false, PtrLenUnknown, target_fn_align(ira->codegen->zig_target), 0, 0, false);
+        ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
+        return ir_implicit_cast(ira, new_stack, u8_slice);
+    }
+}
+
 static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,
     ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
     IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)
@@ -15826,31 +15851,6 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
         return ir_finish_anal(ira, new_instruction);
     }
 
-    IrInstruction *casted_new_stack = nullptr;
-    if (call_instruction->new_stack != nullptr) {
-        IrInstruction *new_stack = call_instruction->new_stack->child;
-        if (type_is_invalid(new_stack->value.type))
-            return ira->codegen->invalid_instruction;
-
-        if (call_instruction->is_async_call_builtin &&
-            fn_entry != nullptr && new_stack->value.type->id == ZigTypeIdPointer && 
-            new_stack->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame)
-        {
-            ZigType *needed_frame_type = get_pointer_to_type(ira->codegen,
-                    get_fn_frame_type(ira->codegen, fn_entry), false);
-            casted_new_stack = ir_implicit_cast(ira, new_stack, needed_frame_type);
-            if (type_is_invalid(casted_new_stack->value.type))
-                return ira->codegen->invalid_instruction;
-        } else {
-            ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
-                    false, false, PtrLenUnknown, target_fn_align(ira->codegen->zig_target), 0, 0, false);
-            ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
-            casted_new_stack = ir_implicit_cast(ira, new_stack, u8_slice);
-            if (type_is_invalid(casted_new_stack->value.type))
-                return ira->codegen->invalid_instruction;
-        }
-    }
-
     if (fn_type->data.fn.is_generic) {
         if (!fn_entry) {
             ir_add_error(ira, call_instruction->fn_ref,
@@ -16063,6 +16063,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
             parent_fn_entry->calls_or_awaits_errorable_fn = true;
         }
 
+        IrInstruction *casted_new_stack = analyze_casted_new_stack(ira, call_instruction, impl_fn);
+        if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value.type))
+            return ira->codegen->invalid_instruction;
+
         size_t impl_param_count = impl_fn_type_id->param_count;
         if (call_instruction->is_async) {
             IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,
@@ -16211,6 +16215,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
         return ira->codegen->invalid_instruction;
     }
 
+    IrInstruction *casted_new_stack = analyze_casted_new_stack(ira, call_instruction, fn_entry);
+    if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value.type))
+        return ira->codegen->invalid_instruction;
+
     if (call_instruction->is_async) {
         IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref,
                 casted_args, call_param_count, casted_new_stack);
test/stage1/behavior/async_fn.zig
@@ -1031,3 +1031,28 @@ test "@typeOf an async function call of generic fn with error union type" {
     };
     _ = async S.func(i32);
 }
+
+test "using @typeOf on a generic function call" {
+    const S = struct {
+        var global_frame: anyframe = undefined;
+        var global_ok = false;
+
+        var buf: [100]u8 align(16) = undefined;
+
+        fn amain(x: var) void {
+            if (x == 0) {
+                global_ok = true;
+                return;
+            }
+            suspend {
+                global_frame = @frame();
+            }
+            const F = @typeOf(async amain(x - 1));
+            const frame = @intToPtr(*F, @ptrToInt(&buf));
+            return await @asyncCall(frame, {}, amain, x - 1);
+        }
+    };
+    _ = async S.amain(u32(1));
+    resume S.global_frame;
+    expect(S.global_ok);
+}