mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
Sema: improve @call errors
This commit is contained in:
parent
3204d00a5e
commit
03b356e34a
9 changed files with 77 additions and 75 deletions
36
src/Sema.zig
36
src/Sema.zig
|
|
@ -5231,6 +5231,10 @@ fn analyzeCall(
|
|||
.async_kw => return sema.fail(block, call_src, "TODO implement async call", .{}),
|
||||
};
|
||||
|
||||
if (modifier == .never_inline and func_ty_info.cc == .Inline) {
|
||||
return sema.fail(block, call_src, "no-inline call of inline function", .{});
|
||||
}
|
||||
|
||||
const gpa = sema.gpa;
|
||||
|
||||
var is_generic_call = func_ty_info.is_generic;
|
||||
|
|
@ -5270,6 +5274,10 @@ fn analyzeCall(
|
|||
}
|
||||
}
|
||||
|
||||
if (is_comptime_call and modifier == .never_inline) {
|
||||
return sema.fail(block, call_src, "unable to perform 'never_inline' call at compile-time", .{});
|
||||
}
|
||||
|
||||
const result: Air.Inst.Ref = if (is_inline_call) res: {
|
||||
const func_val = try sema.resolveConstValue(block, func_src, func);
|
||||
const module_fn = switch (func_val.tag()) {
|
||||
|
|
@ -11612,8 +11620,13 @@ fn analyzeCmpUnionTag(
|
|||
) CompileError!Air.Inst.Ref {
|
||||
const union_ty = try sema.resolveTypeFields(block, un_src, sema.typeOf(un));
|
||||
const union_tag_ty = union_ty.unionTagType() orelse {
|
||||
// TODO note at declaration site that says "union foo is not tagged"
|
||||
return sema.fail(block, un_src, "comparison of union and enum literal is only valid for tagged union types", .{});
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, un_src, "comparison of union and enum literal is only valid for tagged union types", .{});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
try sema.mod.errNoteNonLazy(union_ty.declSrcLoc(sema.mod), msg, "union '{}' is not a tagged union", .{union_ty.fmt(sema.mod)});
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(block, msg);
|
||||
};
|
||||
// Coerce both the union and the tag to the union's tag type, and then execute the
|
||||
// enum comparison codepath.
|
||||
|
|
@ -16878,10 +16891,15 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
|||
break :modifier modifier_val.toEnum(std.builtin.CallOptions.Modifier);
|
||||
};
|
||||
|
||||
const is_comptime = extra.flags.is_comptime or block.is_comptime;
|
||||
|
||||
const modifier: std.builtin.CallOptions.Modifier = switch (wanted_modifier) {
|
||||
// These can be upgraded to comptime or nosuspend calls.
|
||||
.auto, .never_tail, .no_async => m: {
|
||||
if (extra.flags.is_comptime) {
|
||||
if (is_comptime) {
|
||||
if (wanted_modifier == .never_tail) {
|
||||
return sema.fail(block, options_src, "unable to perform 'never_tail' call at compile-time", .{});
|
||||
}
|
||||
break :m .compile_time;
|
||||
}
|
||||
if (extra.flags.is_nosuspend) {
|
||||
|
|
@ -16891,7 +16909,11 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
|||
},
|
||||
// These can be upgraded to comptime. nosuspend bit can be safely ignored.
|
||||
.always_tail, .always_inline, .compile_time => m: {
|
||||
if (extra.flags.is_comptime) {
|
||||
_ = (try sema.resolveDefinedValue(block, func_src, func)) orelse {
|
||||
return sema.fail(block, func_src, "modifier '{s}' requires a comptime-known function", .{@tagName(wanted_modifier)});
|
||||
};
|
||||
|
||||
if (is_comptime) {
|
||||
break :m .compile_time;
|
||||
}
|
||||
break :m wanted_modifier;
|
||||
|
|
@ -16900,14 +16922,14 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
|||
if (extra.flags.is_nosuspend) {
|
||||
return sema.fail(block, options_src, "modifier 'async_kw' cannot be used inside nosuspend block", .{});
|
||||
}
|
||||
if (extra.flags.is_comptime) {
|
||||
if (is_comptime) {
|
||||
return sema.fail(block, options_src, "modifier 'async_kw' cannot be used in combination with comptime function call", .{});
|
||||
}
|
||||
break :m wanted_modifier;
|
||||
},
|
||||
.never_inline => m: {
|
||||
if (extra.flags.is_comptime) {
|
||||
return sema.fail(block, options_src, "modifier 'never_inline' cannot be used in combination with comptime function call", .{});
|
||||
if (is_comptime) {
|
||||
return sema.fail(block, options_src, "unable to perform 'never_inline' call at compile-time", .{});
|
||||
}
|
||||
break :m wanted_modifier;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
export fn entry() void {
|
||||
const U = union { A: u32, B: u64 };
|
||||
var u = U{ .A = 42 };
|
||||
var ok = u == .A;
|
||||
_ = ok;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :4:14: error: comparison of union and enum literal is only valid for tagged union types
|
||||
// :2:15: note: union 'tmp.entry.U' is not a tagged union
|
||||
35
test/cases/compile_errors/bad_usage_of_call.zig
Normal file
35
test/cases/compile_errors/bad_usage_of_call.zig
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
export fn entry1() void {
|
||||
@call(.{}, foo, {});
|
||||
}
|
||||
export fn entry2() void {
|
||||
comptime @call(.{ .modifier = .never_inline }, foo, .{});
|
||||
}
|
||||
export fn entry3() void {
|
||||
comptime @call(.{ .modifier = .never_tail }, foo, .{});
|
||||
}
|
||||
export fn entry4() void {
|
||||
@call(.{ .modifier = .never_inline }, bar, .{});
|
||||
}
|
||||
export fn entry5(c: bool) void {
|
||||
var baz = if (c) &baz1 else &baz2;
|
||||
@call(.{ .modifier = .compile_time }, baz, .{});
|
||||
}
|
||||
pub export fn entry() void {
|
||||
var call_me: *const fn () void = undefined;
|
||||
@call(.{ .modifier = .always_inline }, call_me, .{});
|
||||
}
|
||||
fn foo() void {}
|
||||
fn bar() callconv(.Inline) void {}
|
||||
fn baz1() void {}
|
||||
fn baz2() void {}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:21: error: expected a tuple, found 'void'
|
||||
// :5:21: error: unable to perform 'never_inline' call at compile-time
|
||||
// :8:21: error: unable to perform 'never_tail' call at compile-time
|
||||
// :11:5: error: no-inline call of inline function
|
||||
// :15:43: error: modifier 'compile_time' requires a comptime-known function
|
||||
// :19:44: error: modifier 'always_inline' requires a comptime-known function
|
||||
|
|
@ -20,7 +20,6 @@ export fn qux() void {
|
|||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
// is_test=1
|
||||
//
|
||||
// tmp.zig:3:23: error: cannot adjust alignment of zero sized type '*void'
|
||||
// tmp.zig:7:23: error: cannot adjust alignment of zero sized type '?*void'
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
export fn entry1() void {
|
||||
@call(.{}, foo, {});
|
||||
}
|
||||
export fn entry2() void {
|
||||
comptime @call(.{ .modifier = .never_inline }, foo, .{});
|
||||
}
|
||||
export fn entry3() void {
|
||||
comptime @call(.{ .modifier = .never_tail }, foo, .{});
|
||||
}
|
||||
export fn entry4() void {
|
||||
@call(.{ .modifier = .never_inline }, bar, .{});
|
||||
}
|
||||
export fn entry5(c: bool) void {
|
||||
var baz = if (c) baz1 else baz2;
|
||||
@call(.{ .modifier = .compile_time }, baz, .{});
|
||||
}
|
||||
fn foo() void {}
|
||||
fn bar() callconv(.Inline) void {}
|
||||
fn baz1() void {}
|
||||
fn baz2() void {}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:2:21: error: expected tuple or struct, found 'void'
|
||||
// tmp.zig:5:14: error: unable to perform 'never_inline' call at compile-time
|
||||
// tmp.zig:8:14: error: unable to perform 'never_tail' call at compile-time
|
||||
// tmp.zig:11:5: error: no-inline call of inline function
|
||||
// tmp.zig:15:5: error: the specified modifier requires a comptime-known function
|
||||
|
|
@ -7,6 +7,5 @@ export fn entry() void {
|
|||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
// is_test=1
|
||||
//
|
||||
// tmp.zig:3:23: error: pointer to size 0 type has no address
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
pub export fn entry() void {
|
||||
var call_me: fn () void = undefined;
|
||||
@call(.{ .modifier = .always_inline }, call_me, .{});
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
// is_test=1
|
||||
//
|
||||
// tmp.zig:3:5: error: the specified modifier requires a comptime-known function
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
pub export fn entry() void {
|
||||
var call_me: fn () void = undefined;
|
||||
@call(.{ .modifier = .compile_time }, call_me, .{});
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
// is_test=1
|
||||
//
|
||||
// tmp.zig:3:5: error: the specified modifier requires a comptime-known function
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
export fn entry() void {
|
||||
const U = union { A: u32, B: u64 };
|
||||
var u = U{ .A = 42 };
|
||||
var ok = u == .A;
|
||||
_ = ok;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
// is_test=1
|
||||
//
|
||||
// tmp.zig:4:16: error: comparison of union and enum literal is only valid for tagged union types
|
||||
// tmp.zig:2:15: note: type U is not a tagged union
|
||||
Loading…
Add table
Reference in a new issue