stage1: improve handling of generic fn proto type expr

closes #902
This commit is contained in:
Andrew Kelley 2018-09-05 21:21:59 -04:00
parent 1d8b8ad687
commit 6632d85e5f
No known key found for this signature in database
GPG Key ID: 4E7CD66038A4D47C
5 changed files with 43 additions and 4 deletions

View File

@ -1013,7 +1013,7 @@ bool calling_convention_does_first_arg_return(CallingConvention cc) {
return cc == CallingConventionUnspecified;
}
static const char *calling_convention_name(CallingConvention cc) {
const char *calling_convention_name(CallingConvention cc) {
switch (cc) {
case CallingConventionUnspecified: return "undefined";
case CallingConventionC: return "ccc";
@ -1037,7 +1037,7 @@ static const char *calling_convention_fn_type_str(CallingConvention cc) {
zig_unreachable();
}
static bool calling_convention_allows_zig_types(CallingConvention cc) {
bool calling_convention_allows_zig_types(CallingConvention cc) {
switch (cc) {
case CallingConventionUnspecified:
case CallingConventionAsync:

View File

@ -207,4 +207,7 @@ AstNode *type_decl_node(ZigType *type_entry);
ZigType *get_primitive_type(CodeGen *g, Buf *name);
bool calling_convention_allows_zig_types(CallingConvention cc);
const char *calling_convention_name(CallingConvention cc);
#endif

View File

@ -19595,6 +19595,7 @@ static ZigType *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
}
static ZigType *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {
Error err;
AstNode *proto_node = instruction->base.source_node;
assert(proto_node->type == NodeTypeFnProto);
@ -19636,9 +19637,25 @@ static ZigType *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnP
IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->other;
if (type_is_invalid(param_type_value->value.type))
return ira->codegen->builtin_types.entry_invalid;
param_info->type = ir_resolve_type(ira, param_type_value);
if (type_is_invalid(param_info->type))
ZigType *param_type = ir_resolve_type(ira, param_type_value);
if (type_is_invalid(param_type))
return ira->codegen->builtin_types.entry_invalid;
if ((err = type_ensure_zero_bits_known(ira->codegen, param_type)))
return ira->codegen->builtin_types.entry_invalid;
if (type_requires_comptime(param_type)) {
if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
ir_add_error(ira, &instruction->base,
buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'",
buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc)));
return ira->codegen->builtin_types.entry_invalid;
}
param_info->type = param_type;
fn_type_id.next_param_index += 1;
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
out_val->data.x_type = get_generic_fn_type(ira->codegen, &fn_type_id);
return ira->codegen->builtin_types.entry_type;
}
param_info->type = param_type;
}
}

View File

@ -674,3 +674,11 @@ test "inline for with same type but different values" {
}
assert(res == 5);
}
test "refer to the type of a generic function" {
const Func = fn (type) void;
const f: Func = doNothingWithType;
f(i32);
}
fn doNothingWithType(comptime T: type) void {}

View File

@ -1,6 +1,17 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.add(
"refer to the type of a generic function",
\\export fn entry() void {
\\ const Func = fn (type) void;
\\ const f: Func = undefined;
\\ f(i32);
\\}
,
".tmp_source.zig:4:5: error: use of undefined value",
);
cases.add(
"accessing runtime parameter from outer function",
\\fn outer(y: u32) fn (u32) u32 {