mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 22:35:24 +00:00
Sema: fix generic function with void parameters
This also fixes a bug that I didn't see causing any problems yet in generic function instantiation where it would read from a GetOrPutResult too late. Also it delays full resolution of generic function type parameters until after the function body is finished being analyzed. closes #11291
This commit is contained in:
parent
7cfa97aa4e
commit
bb0e28a54f
22
src/Sema.zig
22
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,
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user