fix using @typeOf on a generic function call

This commit is contained in:
Andrew Kelley 2019-09-02 13:07:44 -04:00
parent 0fe28855c5
commit d291d3c8c0
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
2 changed files with 58 additions and 25 deletions

View File

@ -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);

View File

@ -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);
}