Commit 6632d85e5f
Changed files (5)
test
src/analyze.cpp
@@ -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:
src/analyze.hpp
@@ -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
src/ir.cpp
@@ -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(¶m_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;
}
}
test/cases/eval.zig
@@ -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 {}
test/compile_errors.zig
@@ -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 {