Skip to content

Commit b8bcd48

Browse files
Vexukristoff-it
authored andcommitted
Sema: fix parameter of type 'T' must be comptime error
Closes #12519 Closes #12505
1 parent bd3f212 commit b8bcd48

File tree

14 files changed

+51
-22
lines changed

14 files changed

+51
-22
lines changed

doc/langref.html.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5024,8 +5024,8 @@ fn shiftLeftOne(a: u32) callconv(.Inline) u32 {
50245024
// Another file can use @import and call sub2
50255025
pub fn sub2(a: i8, b: i8) i8 { return a - b; }
50265026

5027-
// Functions can be used as values and are equivalent to pointers.
5028-
const call2_op = fn (a: i8, b: i8) i8;
5027+
// Function pointers are prefixed with `*const `.
5028+
const call2_op = *const fn (a: i8, b: i8) i8;
50295029
fn do_op(fn_call: call2_op, op1: i8, op2: i8) i8 {
50305030
return fn_call(op1, op2);
50315031
}

lib/std/fs/path.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub fn isSep(byte: u8) bool {
4242

4343
/// This is different from mem.join in that the separator will not be repeated if
4444
/// it is found at the end or beginning of a pair of consecutive paths.
45-
fn joinSepMaybeZ(allocator: Allocator, separator: u8, sepPredicate: fn (u8) bool, paths: []const []const u8, zero: bool) ![]u8 {
45+
fn joinSepMaybeZ(allocator: Allocator, separator: u8, comptime sepPredicate: fn (u8) bool, paths: []const []const u8, zero: bool) ![]u8 {
4646
if (paths.len == 0) return if (zero) try allocator.dupe(u8, &[1]u8{0}) else &[0]u8{};
4747

4848
// Find first non-empty path index.

lib/std/math.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1548,7 +1548,7 @@ test "boolMask" {
15481548
}
15491549

15501550
/// Return the mod of `num` with the smallest integer type
1551-
pub fn comptimeMod(num: anytype, denom: comptime_int) IntFittingRange(0, denom - 1) {
1551+
pub fn comptimeMod(num: anytype, comptime denom: comptime_int) IntFittingRange(0, denom - 1) {
15521552
return @intCast(IntFittingRange(0, denom - 1), @mod(num, denom));
15531553
}
15541554

lib/std/math/float.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ inline fn mantissaOne(comptime T: type) comptime_int {
88
}
99

1010
/// Creates floating point type T from an unbiased exponent and raw mantissa.
11-
inline fn reconstructFloat(comptime T: type, exponent: comptime_int, mantissa: comptime_int) T {
11+
inline fn reconstructFloat(comptime T: type, comptime exponent: comptime_int, comptime mantissa: comptime_int) T {
1212
const TBits = @Type(.{ .Int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } });
1313
const biased_exponent = @as(TBits, exponent + floatExponentMax(T));
1414
return @bitCast(T, (biased_exponent << floatMantissaBits(T)) | @as(TBits, mantissa));

lib/std/zig/c_translation.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ test "shuffleVectorIndex" {
349349

350350
/// Constructs a [*c] pointer with the const and volatile annotations
351351
/// from SelfType for pointing to a C flexible array of ElementType.
352-
pub fn FlexibleArrayType(comptime SelfType: type, ElementType: type) type {
352+
pub fn FlexibleArrayType(comptime SelfType: type, comptime ElementType: type) type {
353353
switch (@typeInfo(SelfType)) {
354354
.Pointer => |ptr| {
355355
return @Type(.{ .Pointer = .{

lib/std/zig/parse.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3670,7 +3670,7 @@ const Parser = struct {
36703670
}
36713671

36723672
/// KEYWORD_if LPAREN Expr RPAREN PtrPayload? Body (KEYWORD_else Payload? Body)?
3673-
fn parseIf(p: *Parser, bodyParseFn: fn (p: *Parser) Error!Node.Index) !Node.Index {
3673+
fn parseIf(p: *Parser, comptime bodyParseFn: fn (p: *Parser) Error!Node.Index) !Node.Index {
36743674
const if_token = p.eatToken(.keyword_if) orelse return null_node;
36753675
_ = try p.expectToken(.l_paren);
36763676
const condition = try p.expectExpr();

src/Module.zig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6072,17 +6072,17 @@ pub fn paramSrc(
60726072
else => unreachable,
60736073
};
60746074
var it = full.iterate(tree);
6075-
while (true) {
6076-
if (it.param_i == param_i) {
6077-
const param = it.next().?;
6075+
var i: usize = 0;
6076+
while (it.next()) |param| : (i += 1) {
6077+
if (i == param_i) {
60786078
if (param.anytype_ellipsis3) |some| {
60796079
const main_token = tree.nodes.items(.main_token)[decl.src_node];
60806080
return .{ .token_offset_param = @bitCast(i32, some) - @bitCast(i32, main_token) };
60816081
}
60826082
return .{ .node_offset_param = decl.nodeIndexToRelative(param.type_expr) };
60836083
}
6084-
_ = it.next();
60856084
}
6085+
unreachable;
60866086
}
60876087

60886088
pub fn argSrc(

src/Sema.zig

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ types_to_resolve: std.ArrayListUnmanaged(Air.Inst.Ref) = .{},
7676
post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{},
7777
/// Populated with the last compile error created.
7878
err: ?*Module.ErrorMsg = null,
79+
/// True when analyzing a generic instantiation. Used to suppress some errors.
80+
is_generic_instantiation: bool = false,
7981

8082
const std = @import("std");
8183
const math = std.math;
@@ -6495,6 +6497,7 @@ fn instantiateGenericCall(
64956497
.comptime_args = try new_decl_arena_allocator.alloc(TypedValue, uncasted_args.len),
64966498
.comptime_args_fn_inst = module_fn.zir_body_inst,
64976499
.preallocated_new_func = new_module_func,
6500+
.is_generic_instantiation = true,
64986501
};
64996502
defer child_sema.deinit();
65006503

@@ -7789,6 +7792,7 @@ fn funcCommon(
77897792
&is_generic,
77907793
is_extern,
77917794
cc_workaround,
7795+
has_body,
77927796
) catch |err| switch (err) {
77937797
error.NeededSourceLocation => {
77947798
const decl = sema.mod.declPtr(block.src_decl);
@@ -7802,6 +7806,7 @@ fn funcCommon(
78027806
&is_generic,
78037807
is_extern,
78047808
cc_workaround,
7809+
has_body,
78057810
);
78067811
return error.AnalysisFail;
78077812
},
@@ -8005,6 +8010,7 @@ fn analyzeParameter(
80058010
is_generic: *bool,
80068011
is_extern: bool,
80078012
cc: std.builtin.CallingConvention,
8013+
has_body: bool,
80088014
) !void {
80098015
const requires_comptime = try sema.typeRequiresComptime(block, param_src, param.ty);
80108016
comptime_params[i] = param.is_comptime or requires_comptime;
@@ -8053,9 +8059,9 @@ fn analyzeParameter(
80538059
};
80548060
return sema.failWithOwnedErrorMsg(msg);
80558061
}
8056-
if (requires_comptime and !param.is_comptime) {
8062+
if (!sema.is_generic_instantiation and requires_comptime and !param.is_comptime and has_body) {
80578063
const msg = msg: {
8058-
const msg = try sema.errMsg(block, param_src, "parametter of type '{}' must be declared comptime", .{
8064+
const msg = try sema.errMsg(block, param_src, "parameter of type '{}' must be declared comptime", .{
80598065
param.ty.fmt(sema.mod),
80608066
});
80618067
errdefer msg.destroy(sema.gpa);
@@ -8153,7 +8159,7 @@ fn zirParam(
81538159

81548160
try block.params.append(sema.gpa, .{
81558161
.ty = param_ty,
8156-
.is_comptime = is_comptime,
8162+
.is_comptime = comptime_syntax,
81578163
.name = param_name,
81588164
});
81598165
const result = try sema.addConstant(param_ty, Value.initTag(.generic_poison));
@@ -16318,7 +16324,7 @@ fn zirUnaryMath(
1631816324
block: *Block,
1631916325
inst: Zir.Inst.Index,
1632016326
air_tag: Air.Inst.Tag,
16321-
eval: fn (Value, Type, Allocator, std.Target) Allocator.Error!Value,
16327+
comptime eval: fn (Value, Type, Allocator, std.Target) Allocator.Error!Value,
1632216328
) CompileError!Air.Inst.Ref {
1632316329
const tracy = trace(@src());
1632416330
defer tracy.end();
@@ -17777,7 +17783,7 @@ fn zirBitCount(
1777717783
block: *Block,
1777817784
inst: Zir.Inst.Index,
1777917785
air_tag: Air.Inst.Tag,
17780-
comptimeOp: fn (val: Value, ty: Type, target: std.Target) u64,
17786+
comptime comptimeOp: fn (val: Value, ty: Type, target: std.Target) u64,
1778117787
) CompileError!Air.Inst.Ref {
1778217788
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1778317789
const src = inst_data.src();
@@ -29491,7 +29497,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ
2949129497
=> {
2949229498
const child_ty = ty.childType();
2949329499
if (child_ty.zigTypeTag() == .Fn) {
29494-
return false;
29500+
return child_ty.fnInfo().is_generic;
2949529501
} else {
2949629502
return sema.typeRequiresComptime(block, src, child_ty);
2949729503
}

src/type.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2394,7 +2394,7 @@ pub const Type = extern union {
23942394
if (ignore_comptime_only) {
23952395
return true;
23962396
} else if (ty.childType().zigTypeTag() == .Fn) {
2397-
return true;
2397+
return !ty.childType().fnInfo().is_generic;
23982398
} else if (sema_kit) |sk| {
23992399
return !(try sk.sema.typeRequiresComptime(sk.block, sk.src, ty));
24002400
} else {

test/behavior/cast.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1281,7 +1281,7 @@ test "*const [N]null u8 to ?[]const u8" {
12811281
test "cast between [*c]T and ?[*:0]T on fn parameter" {
12821282
const S = struct {
12831283
const Handler = ?fn ([*c]const u8) callconv(.C) void;
1284-
fn addCallback(handler: Handler) void {
1284+
fn addCallback(comptime handler: Handler) void {
12851285
_ = handler;
12861286
}
12871287

test/behavior/error.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ fn entryPtr() void {
168168
fooPtr(ptr);
169169
}
170170

171-
fn foo2(f: fn () anyerror!void) void {
171+
fn foo2(comptime f: fn () anyerror!void) void {
172172
const x = f();
173173
x catch {
174174
@panic("fail");

test/behavior/fn.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ test "implicit cast function unreachable return" {
137137
wantsFnWithVoid(fnWithUnreachable);
138138
}
139139

140-
fn wantsFnWithVoid(f: fn () void) void {
140+
fn wantsFnWithVoid(comptime f: fn () void) void {
141141
_ = f;
142142
}
143143

test/behavior/struct.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ test "fn call of struct field" {
147147
return 13;
148148
}
149149

150-
fn callStructField(foo: Foo) i32 {
150+
fn callStructField(comptime foo: Foo) i32 {
151151
return foo.ptr();
152152
}
153153
};
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
fn f(_: anytype) void {}
2+
fn g(h: *const fn (anytype) void) void {
3+
h({});
4+
}
5+
pub export fn entry() void {
6+
g(f);
7+
}
8+
9+
pub fn comptimeMod(num: anytype, denom: comptime_int) void {
10+
_ = num;
11+
_ = denom;
12+
}
13+
14+
pub export fn entry1() void {
15+
_ = comptimeMod(1, 2);
16+
}
17+
18+
// error
19+
// backend=stage2
20+
// target=native
21+
//
22+
// :2:6: error: parameter of type '*const fn(anytype) void' must be declared comptime
23+
// :9:34: error: parameter of type 'comptime_int' must be declared comptime

0 commit comments

Comments
 (0)