diff --git a/src/Sema.zig b/src/Sema.zig index e8ef948abd..03a51dc20d 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5149,7 +5149,7 @@ fn instantiateGenericCall( .target = target, }; const gop = try mod.monomorphed_funcs.getOrPutContextAdapted(gpa, {}, adapter, .{ .target = target }); - if (!gop.found_existing) { + const callee = if (!gop.found_existing) callee: { const new_module_func = try gpa.create(Module.Fn); gop.key_ptr.* = new_module_func; errdefer gpa.destroy(new_module_func); @@ -5357,9 +5357,9 @@ fn instantiateGenericCall( try mod.comp.work_queue.writeItem(.{ .codegen_func = new_func }); try new_decl.finalizeNewArena(&new_decl_arena); - } + break :callee new_func; + } else gop.key_ptr.*; - const callee = gop.key_ptr.*; const callee_inst = try sema.analyzeDeclVal(block, func_src, callee.owner_decl); // Make a runtime call to the new function, making sure to omit the comptime args. @@ -5397,8 +5397,8 @@ fn instantiateGenericCall( const param_ty = new_fn_info.param_types[runtime_i]; const arg_src = call_src; // TODO: better source location const uncasted_arg = uncasted_args[total_i]; - try sema.resolveTypeFully(block, arg_src, param_ty); const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src); + try sema.queueFullTypeResolution(param_ty); runtime_args[runtime_i] = casted_arg; runtime_i += 1; } @@ -6474,10 +6474,13 @@ fn zirParam( const err = err: { // Make sure any nested param instructions don't clobber our work. const prev_params = block.params; + const prev_preallocated_new_func = sema.preallocated_new_func; block.params = .{}; + sema.preallocated_new_func = null; defer { block.params.deinit(sema.gpa); block.params = prev_params; + sema.preallocated_new_func = prev_preallocated_new_func; } if (sema.resolveBody(block, body, inst)) |param_ty_inst| { @@ -6524,6 +6527,17 @@ fn zirParam( assert(sema.inst_map.remove(inst)); } + if (sema.preallocated_new_func != null) { + if (try sema.typeHasOnePossibleValue(block, src, param_ty)) |opv| { + // In this case we are instantiating a generic function call with a non-comptime + // non-anytype parameter that ended up being a one-possible-type. + // We don't want the parameter to be part of the instantiated function type. + const result = try sema.addConstant(param_ty, opv); + try sema.inst_map.put(sema.gpa, inst, result); + return; + } + } + try block.params.append(sema.gpa, .{ .ty = param_ty, .is_comptime = is_comptime, diff --git a/test/behavior/generics.zig b/test/behavior/generics.zig index 767c2f3ee3..867cf940b8 100644 --- a/test/behavior/generics.zig +++ b/test/behavior/generics.zig @@ -277,3 +277,16 @@ test "generic function instantiation turns into comptime call" { }; try S.doTheTest(); } + +test "generic function with void and comptime parameter" { + const S = struct { x: i32 }; + const namespace = struct { + fn foo(v: void, s: *S, comptime T: type) !void { + _ = @as(void, v); + try expect(s.x == 1234); + try expect(T == u8); + } + }; + var s: S = .{ .x = 1234 }; + try namespace.foo({}, &s, u8); +}