mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 13:30:45 +00:00
Sema: ignore comptime params in partial func type check
This fixes a bug exposed by cd1833044ab7505bc101c85f59889bd3ea3fac80 where a function type would be converted to generic_poison even after being instantiated due to containing comptime only types. This could also be fixed by just checking `is_generic_instantiation` but this way also provides better type names. Closes #12625
This commit is contained in:
parent
3a7ea0b65e
commit
4405188cf7
27
src/Sema.zig
27
src/Sema.zig
@ -7720,7 +7720,6 @@ fn funcCommon(
|
||||
noalias_bits: u32,
|
||||
is_noinline: bool,
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const fn_src = LazySrcLoc.nodeOffset(src_node_offset);
|
||||
const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
|
||||
const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset };
|
||||
|
||||
@ -7791,13 +7790,11 @@ fn funcCommon(
|
||||
param_types[i] = param.ty;
|
||||
sema.analyzeParameter(
|
||||
block,
|
||||
fn_src,
|
||||
.unneeded,
|
||||
param,
|
||||
comptime_params,
|
||||
i,
|
||||
&is_generic,
|
||||
is_extern,
|
||||
cc_workaround,
|
||||
has_body,
|
||||
) catch |err| switch (err) {
|
||||
@ -7805,13 +7802,11 @@ fn funcCommon(
|
||||
const decl = sema.mod.declPtr(block.src_decl);
|
||||
try sema.analyzeParameter(
|
||||
block,
|
||||
fn_src,
|
||||
Module.paramSrc(src_node_offset, sema.gpa, decl, i),
|
||||
param,
|
||||
comptime_params,
|
||||
i,
|
||||
&is_generic,
|
||||
is_extern,
|
||||
cc_workaround,
|
||||
has_body,
|
||||
);
|
||||
@ -7821,9 +7816,10 @@ fn funcCommon(
|
||||
};
|
||||
}
|
||||
|
||||
var is_comptime_ret = false;
|
||||
const ret_poison = if (!is_generic) rp: {
|
||||
if (sema.typeRequiresComptime(block, ret_ty_src, bare_return_type)) |ret_comptime| {
|
||||
is_generic = ret_comptime;
|
||||
is_comptime_ret = ret_comptime;
|
||||
break :rp bare_return_type.tag() == .generic_poison;
|
||||
} else |err| switch (err) {
|
||||
error.GenericPoison => {
|
||||
@ -7920,6 +7916,8 @@ fn funcCommon(
|
||||
return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
|
||||
}
|
||||
if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;
|
||||
for (comptime_params) |ct| is_generic = is_generic or ct;
|
||||
is_generic = is_generic or is_comptime_ret;
|
||||
|
||||
break :fn_ty try Type.Tag.function.create(sema.arena, .{
|
||||
.param_types = param_types,
|
||||
@ -8010,31 +8008,20 @@ fn funcCommon(
|
||||
fn analyzeParameter(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
func_src: LazySrcLoc,
|
||||
param_src: LazySrcLoc,
|
||||
param: Block.Param,
|
||||
comptime_params: []bool,
|
||||
i: usize,
|
||||
is_generic: *bool,
|
||||
is_extern: bool,
|
||||
cc: std.builtin.CallingConvention,
|
||||
has_body: bool,
|
||||
) !void {
|
||||
const requires_comptime = try sema.typeRequiresComptime(block, param_src, param.ty);
|
||||
comptime_params[i] = param.is_comptime or requires_comptime;
|
||||
const this_generic = comptime_params[i] or param.ty.tag() == .generic_poison;
|
||||
const this_generic = param.ty.tag() == .generic_poison;
|
||||
is_generic.* = is_generic.* or this_generic;
|
||||
if (is_extern and this_generic) {
|
||||
// TODO this check should exist somewhere for notes.
|
||||
if (param_src == .unneeded) return error.NeededSourceLocation;
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, func_src, "extern function cannot be generic", .{});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
|
||||
try sema.errNote(block, param_src, msg, "function is generic because of this parameter", .{});
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(msg);
|
||||
if (param.is_comptime and !Type.fnCallingConventionAllowsZigTypes(cc)) {
|
||||
return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
|
||||
}
|
||||
if (this_generic and !Type.fnCallingConventionAllowsZigTypes(cc)) {
|
||||
return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
|
||||
|
||||
@ -235,3 +235,14 @@ test "local variable" {
|
||||
try expectEqualStrings("behavior.typename.test.local variable.Qux", @typeName(Qux));
|
||||
try expectEqualStrings("behavior.typename.test.local variable.Quux", @typeName(Quux));
|
||||
}
|
||||
|
||||
test "comptime parameters not converted to anytype in function type" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
const T = fn (fn (type) void, void) void;
|
||||
try expectEqualStrings("fn(fn(type) void, void) void", @typeName(T));
|
||||
}
|
||||
|
||||
@ -6,4 +6,4 @@ export fn foo(comptime x: anytype, y: i32) i32{
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :1:15: error: generic parameters not allowed in function with calling convention 'C'
|
||||
// :1:15: error: comptime parameters not allowed in function with calling convention 'C'
|
||||
|
||||
@ -12,9 +12,6 @@ comptime { _ = entry2; }
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :5:12: error: extern function cannot be generic
|
||||
// :5:30: note: function is generic because of this parameter
|
||||
// :6:12: error: extern function cannot be generic
|
||||
// :6:30: note: function is generic because of this parameter
|
||||
// :1:8: error: extern function cannot be generic
|
||||
// :1:15: note: function is generic because of this parameter
|
||||
// :1:15: error: comptime parameters not allowed in function with calling convention 'C'
|
||||
// :5:30: error: comptime parameters not allowed in function with calling convention 'C'
|
||||
// :6:30: error: generic parameters not allowed in function with calling convention 'C'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user