zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 6632d85e5f1120784b3eb0a7ab8be0792ba27b85 (tree)
parent 1d8b8ad687facd25a27b3ff6d083812b45cd529f
Author: Andrew Kelley <superjoe30@gmail.com>
Date:   Wed,  5 Sep 2018 21:21:59 -0400

stage1: improve handling of generic fn proto type expr

closes #902

Diffstat:
Msrc/analyze.cpp | 4++--
Msrc/analyze.hpp | 3+++
Msrc/ir.cpp | 21+++++++++++++++++++--
Mtest/cases/eval.zig | 8++++++++
Mtest/compile_errors.zig | 11+++++++++++
5 files changed, 43 insertions(+), 4 deletions(-)

diff --git a/src/analyze.cpp b/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: diff --git a/src/analyze.hpp b/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 diff --git a/src/ir.cpp b/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(&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; } } diff --git a/test/cases/eval.zig b/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 {} diff --git a/test/compile_errors.zig b/test/compile_errors.zig @@ -2,6 +2,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 { \\ const st = struct {