mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
Sema: fix parameter of type 'T' must be comptime error
Closes #12519 Closes #12505
This commit is contained in:
parent
b2f02a820f
commit
b55a5007fa
@ -5023,8 +5023,8 @@ fn shiftLeftOne(a: u32) callconv(.Inline) u32 {
|
|||||||
// Another file can use @import and call sub2
|
// Another file can use @import and call sub2
|
||||||
pub fn sub2(a: i8, b: i8) i8 { return a - b; }
|
pub fn sub2(a: i8, b: i8) i8 { return a - b; }
|
||||||
|
|
||||||
// Functions can be used as values and are equivalent to pointers.
|
// Function pointers are prefixed with `*const `.
|
||||||
const call2_op = fn (a: i8, b: i8) i8;
|
const call2_op = *const fn (a: i8, b: i8) i8;
|
||||||
fn do_op(fn_call: call2_op, op1: i8, op2: i8) i8 {
|
fn do_op(fn_call: call2_op, op1: i8, op2: i8) i8 {
|
||||||
return fn_call(op1, op2);
|
return fn_call(op1, op2);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,7 +42,7 @@ pub fn isSep(byte: u8) bool {
|
|||||||
|
|
||||||
/// This is different from mem.join in that the separator will not be repeated if
|
/// This is different from mem.join in that the separator will not be repeated if
|
||||||
/// it is found at the end or beginning of a pair of consecutive paths.
|
/// it is found at the end or beginning of a pair of consecutive paths.
|
||||||
fn joinSepMaybeZ(allocator: Allocator, separator: u8, sepPredicate: fn (u8) bool, paths: []const []const u8, zero: bool) ![]u8 {
|
fn joinSepMaybeZ(allocator: Allocator, separator: u8, comptime sepPredicate: fn (u8) bool, paths: []const []const u8, zero: bool) ![]u8 {
|
||||||
if (paths.len == 0) return if (zero) try allocator.dupe(u8, &[1]u8{0}) else &[0]u8{};
|
if (paths.len == 0) return if (zero) try allocator.dupe(u8, &[1]u8{0}) else &[0]u8{};
|
||||||
|
|
||||||
// Find first non-empty path index.
|
// Find first non-empty path index.
|
||||||
|
|||||||
@ -1548,7 +1548,7 @@ test "boolMask" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return the mod of `num` with the smallest integer type
|
/// Return the mod of `num` with the smallest integer type
|
||||||
pub fn comptimeMod(num: anytype, denom: comptime_int) IntFittingRange(0, denom - 1) {
|
pub fn comptimeMod(num: anytype, comptime denom: comptime_int) IntFittingRange(0, denom - 1) {
|
||||||
return @intCast(IntFittingRange(0, denom - 1), @mod(num, denom));
|
return @intCast(IntFittingRange(0, denom - 1), @mod(num, denom));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ inline fn mantissaOne(comptime T: type) comptime_int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates floating point type T from an unbiased exponent and raw mantissa.
|
/// Creates floating point type T from an unbiased exponent and raw mantissa.
|
||||||
inline fn reconstructFloat(comptime T: type, exponent: comptime_int, mantissa: comptime_int) T {
|
inline fn reconstructFloat(comptime T: type, comptime exponent: comptime_int, comptime mantissa: comptime_int) T {
|
||||||
const TBits = @Type(.{ .Int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } });
|
const TBits = @Type(.{ .Int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } });
|
||||||
const biased_exponent = @as(TBits, exponent + floatExponentMax(T));
|
const biased_exponent = @as(TBits, exponent + floatExponentMax(T));
|
||||||
return @bitCast(T, (biased_exponent << floatMantissaBits(T)) | @as(TBits, mantissa));
|
return @bitCast(T, (biased_exponent << floatMantissaBits(T)) | @as(TBits, mantissa));
|
||||||
|
|||||||
@ -349,7 +349,7 @@ test "shuffleVectorIndex" {
|
|||||||
|
|
||||||
/// Constructs a [*c] pointer with the const and volatile annotations
|
/// Constructs a [*c] pointer with the const and volatile annotations
|
||||||
/// from SelfType for pointing to a C flexible array of ElementType.
|
/// from SelfType for pointing to a C flexible array of ElementType.
|
||||||
pub fn FlexibleArrayType(comptime SelfType: type, ElementType: type) type {
|
pub fn FlexibleArrayType(comptime SelfType: type, comptime ElementType: type) type {
|
||||||
switch (@typeInfo(SelfType)) {
|
switch (@typeInfo(SelfType)) {
|
||||||
.Pointer => |ptr| {
|
.Pointer => |ptr| {
|
||||||
return @Type(.{ .Pointer = .{
|
return @Type(.{ .Pointer = .{
|
||||||
|
|||||||
@ -3670,7 +3670,7 @@ const Parser = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// KEYWORD_if LPAREN Expr RPAREN PtrPayload? Body (KEYWORD_else Payload? Body)?
|
/// KEYWORD_if LPAREN Expr RPAREN PtrPayload? Body (KEYWORD_else Payload? Body)?
|
||||||
fn parseIf(p: *Parser, bodyParseFn: fn (p: *Parser) Error!Node.Index) !Node.Index {
|
fn parseIf(p: *Parser, comptime bodyParseFn: fn (p: *Parser) Error!Node.Index) !Node.Index {
|
||||||
const if_token = p.eatToken(.keyword_if) orelse return null_node;
|
const if_token = p.eatToken(.keyword_if) orelse return null_node;
|
||||||
_ = try p.expectToken(.l_paren);
|
_ = try p.expectToken(.l_paren);
|
||||||
const condition = try p.expectExpr();
|
const condition = try p.expectExpr();
|
||||||
|
|||||||
@ -6072,17 +6072,17 @@ pub fn paramSrc(
|
|||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
var it = full.iterate(tree);
|
var it = full.iterate(tree);
|
||||||
while (true) {
|
var i: usize = 0;
|
||||||
if (it.param_i == param_i) {
|
while (it.next()) |param| : (i += 1) {
|
||||||
const param = it.next().?;
|
if (i == param_i) {
|
||||||
if (param.anytype_ellipsis3) |some| {
|
if (param.anytype_ellipsis3) |some| {
|
||||||
const main_token = tree.nodes.items(.main_token)[decl.src_node];
|
const main_token = tree.nodes.items(.main_token)[decl.src_node];
|
||||||
return .{ .token_offset_param = @bitCast(i32, some) - @bitCast(i32, main_token) };
|
return .{ .token_offset_param = @bitCast(i32, some) - @bitCast(i32, main_token) };
|
||||||
}
|
}
|
||||||
return .{ .node_offset_param = decl.nodeIndexToRelative(param.type_expr) };
|
return .{ .node_offset_param = decl.nodeIndexToRelative(param.type_expr) };
|
||||||
}
|
}
|
||||||
_ = it.next();
|
|
||||||
}
|
}
|
||||||
|
unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn argSrc(
|
pub fn argSrc(
|
||||||
|
|||||||
18
src/Sema.zig
18
src/Sema.zig
@ -76,6 +76,8 @@ types_to_resolve: std.ArrayListUnmanaged(Air.Inst.Ref) = .{},
|
|||||||
post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{},
|
post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{},
|
||||||
/// Populated with the last compile error created.
|
/// Populated with the last compile error created.
|
||||||
err: ?*Module.ErrorMsg = null,
|
err: ?*Module.ErrorMsg = null,
|
||||||
|
/// True when analyzing a generic instantiation. Used to suppress some errors.
|
||||||
|
is_generic_instantiation: bool = false,
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const math = std.math;
|
const math = std.math;
|
||||||
@ -6495,6 +6497,7 @@ fn instantiateGenericCall(
|
|||||||
.comptime_args = try new_decl_arena_allocator.alloc(TypedValue, uncasted_args.len),
|
.comptime_args = try new_decl_arena_allocator.alloc(TypedValue, uncasted_args.len),
|
||||||
.comptime_args_fn_inst = module_fn.zir_body_inst,
|
.comptime_args_fn_inst = module_fn.zir_body_inst,
|
||||||
.preallocated_new_func = new_module_func,
|
.preallocated_new_func = new_module_func,
|
||||||
|
.is_generic_instantiation = true,
|
||||||
};
|
};
|
||||||
defer child_sema.deinit();
|
defer child_sema.deinit();
|
||||||
|
|
||||||
@ -7789,6 +7792,7 @@ fn funcCommon(
|
|||||||
&is_generic,
|
&is_generic,
|
||||||
is_extern,
|
is_extern,
|
||||||
cc_workaround,
|
cc_workaround,
|
||||||
|
has_body,
|
||||||
) catch |err| switch (err) {
|
) catch |err| switch (err) {
|
||||||
error.NeededSourceLocation => {
|
error.NeededSourceLocation => {
|
||||||
const decl = sema.mod.declPtr(block.src_decl);
|
const decl = sema.mod.declPtr(block.src_decl);
|
||||||
@ -7802,6 +7806,7 @@ fn funcCommon(
|
|||||||
&is_generic,
|
&is_generic,
|
||||||
is_extern,
|
is_extern,
|
||||||
cc_workaround,
|
cc_workaround,
|
||||||
|
has_body,
|
||||||
);
|
);
|
||||||
return error.AnalysisFail;
|
return error.AnalysisFail;
|
||||||
},
|
},
|
||||||
@ -8005,6 +8010,7 @@ fn analyzeParameter(
|
|||||||
is_generic: *bool,
|
is_generic: *bool,
|
||||||
is_extern: bool,
|
is_extern: bool,
|
||||||
cc: std.builtin.CallingConvention,
|
cc: std.builtin.CallingConvention,
|
||||||
|
has_body: bool,
|
||||||
) !void {
|
) !void {
|
||||||
const requires_comptime = try sema.typeRequiresComptime(block, param_src, param.ty);
|
const requires_comptime = try sema.typeRequiresComptime(block, param_src, param.ty);
|
||||||
comptime_params[i] = param.is_comptime or requires_comptime;
|
comptime_params[i] = param.is_comptime or requires_comptime;
|
||||||
@ -8053,9 +8059,9 @@ fn analyzeParameter(
|
|||||||
};
|
};
|
||||||
return sema.failWithOwnedErrorMsg(msg);
|
return sema.failWithOwnedErrorMsg(msg);
|
||||||
}
|
}
|
||||||
if (requires_comptime and !param.is_comptime) {
|
if (!sema.is_generic_instantiation and requires_comptime and !param.is_comptime and has_body) {
|
||||||
const msg = msg: {
|
const msg = msg: {
|
||||||
const msg = try sema.errMsg(block, param_src, "parametter of type '{}' must be declared comptime", .{
|
const msg = try sema.errMsg(block, param_src, "parameter of type '{}' must be declared comptime", .{
|
||||||
param.ty.fmt(sema.mod),
|
param.ty.fmt(sema.mod),
|
||||||
});
|
});
|
||||||
errdefer msg.destroy(sema.gpa);
|
errdefer msg.destroy(sema.gpa);
|
||||||
@ -8153,7 +8159,7 @@ fn zirParam(
|
|||||||
|
|
||||||
try block.params.append(sema.gpa, .{
|
try block.params.append(sema.gpa, .{
|
||||||
.ty = param_ty,
|
.ty = param_ty,
|
||||||
.is_comptime = is_comptime,
|
.is_comptime = comptime_syntax,
|
||||||
.name = param_name,
|
.name = param_name,
|
||||||
});
|
});
|
||||||
const result = try sema.addConstant(param_ty, Value.initTag(.generic_poison));
|
const result = try sema.addConstant(param_ty, Value.initTag(.generic_poison));
|
||||||
@ -16318,7 +16324,7 @@ fn zirUnaryMath(
|
|||||||
block: *Block,
|
block: *Block,
|
||||||
inst: Zir.Inst.Index,
|
inst: Zir.Inst.Index,
|
||||||
air_tag: Air.Inst.Tag,
|
air_tag: Air.Inst.Tag,
|
||||||
eval: fn (Value, Type, Allocator, std.Target) Allocator.Error!Value,
|
comptime eval: fn (Value, Type, Allocator, std.Target) Allocator.Error!Value,
|
||||||
) CompileError!Air.Inst.Ref {
|
) CompileError!Air.Inst.Ref {
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
@ -17777,7 +17783,7 @@ fn zirBitCount(
|
|||||||
block: *Block,
|
block: *Block,
|
||||||
inst: Zir.Inst.Index,
|
inst: Zir.Inst.Index,
|
||||||
air_tag: Air.Inst.Tag,
|
air_tag: Air.Inst.Tag,
|
||||||
comptimeOp: fn (val: Value, ty: Type, target: std.Target) u64,
|
comptime comptimeOp: fn (val: Value, ty: Type, target: std.Target) u64,
|
||||||
) CompileError!Air.Inst.Ref {
|
) CompileError!Air.Inst.Ref {
|
||||||
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
|
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
|
||||||
const src = inst_data.src();
|
const src = inst_data.src();
|
||||||
@ -29491,7 +29497,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ
|
|||||||
=> {
|
=> {
|
||||||
const child_ty = ty.childType();
|
const child_ty = ty.childType();
|
||||||
if (child_ty.zigTypeTag() == .Fn) {
|
if (child_ty.zigTypeTag() == .Fn) {
|
||||||
return false;
|
return child_ty.fnInfo().is_generic;
|
||||||
} else {
|
} else {
|
||||||
return sema.typeRequiresComptime(block, src, child_ty);
|
return sema.typeRequiresComptime(block, src, child_ty);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2394,7 +2394,7 @@ pub const Type = extern union {
|
|||||||
if (ignore_comptime_only) {
|
if (ignore_comptime_only) {
|
||||||
return true;
|
return true;
|
||||||
} else if (ty.childType().zigTypeTag() == .Fn) {
|
} else if (ty.childType().zigTypeTag() == .Fn) {
|
||||||
return true;
|
return !ty.childType().fnInfo().is_generic;
|
||||||
} else if (sema_kit) |sk| {
|
} else if (sema_kit) |sk| {
|
||||||
return !(try sk.sema.typeRequiresComptime(sk.block, sk.src, ty));
|
return !(try sk.sema.typeRequiresComptime(sk.block, sk.src, ty));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -1281,7 +1281,7 @@ test "*const [N]null u8 to ?[]const u8" {
|
|||||||
test "cast between [*c]T and ?[*:0]T on fn parameter" {
|
test "cast between [*c]T and ?[*:0]T on fn parameter" {
|
||||||
const S = struct {
|
const S = struct {
|
||||||
const Handler = ?fn ([*c]const u8) callconv(.C) void;
|
const Handler = ?fn ([*c]const u8) callconv(.C) void;
|
||||||
fn addCallback(handler: Handler) void {
|
fn addCallback(comptime handler: Handler) void {
|
||||||
_ = handler;
|
_ = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -168,7 +168,7 @@ fn entryPtr() void {
|
|||||||
fooPtr(ptr);
|
fooPtr(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn foo2(f: fn () anyerror!void) void {
|
fn foo2(comptime f: fn () anyerror!void) void {
|
||||||
const x = f();
|
const x = f();
|
||||||
x catch {
|
x catch {
|
||||||
@panic("fail");
|
@panic("fail");
|
||||||
|
|||||||
@ -137,7 +137,7 @@ test "implicit cast function unreachable return" {
|
|||||||
wantsFnWithVoid(fnWithUnreachable);
|
wantsFnWithVoid(fnWithUnreachable);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wantsFnWithVoid(f: fn () void) void {
|
fn wantsFnWithVoid(comptime f: fn () void) void {
|
||||||
_ = f;
|
_ = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -147,7 +147,7 @@ test "fn call of struct field" {
|
|||||||
return 13;
|
return 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn callStructField(foo: Foo) i32 {
|
fn callStructField(comptime foo: Foo) i32 {
|
||||||
return foo.ptr();
|
return foo.ptr();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,23 @@
|
|||||||
|
fn f(_: anytype) void {}
|
||||||
|
fn g(h: *const fn (anytype) void) void {
|
||||||
|
h({});
|
||||||
|
}
|
||||||
|
pub export fn entry() void {
|
||||||
|
g(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn comptimeMod(num: anytype, denom: comptime_int) void {
|
||||||
|
_ = num;
|
||||||
|
_ = denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub export fn entry1() void {
|
||||||
|
_ = comptimeMod(1, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// error
|
||||||
|
// backend=stage2
|
||||||
|
// target=native
|
||||||
|
//
|
||||||
|
// :2:6: error: parameter of type '*const fn(anytype) void' must be declared comptime
|
||||||
|
// :9:34: error: parameter of type 'comptime_int' must be declared comptime
|
||||||
Loading…
x
Reference in New Issue
Block a user