Commit 03b356e34a
Changed files (9)
src
test
cases
compile_errors
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;
},
test/cases/compile_errors/stage1/obj/bad_usage_of_call.zig
@@ -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
test/cases/compile_errors/stage1/test/call_rejects_non_comptime-known_fn-always_inline.zig
@@ -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
test/cases/compile_errors/stage1/test/call_rejects_non_comptime-known_fn-compile_time.zig
@@ -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
test/cases/compile_errors/stage1/test/comparison_of_non-tagged_union_and_enum_literal.zig
@@ -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
test/cases/compile_errors/stage1/test/alignCast_of_zero_sized_types.zig → test/cases/compile_errors/stage1/alignCast_of_zero_sized_types.zig
@@ -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'
test/cases/compile_errors/stage1/test/ptrToInt_with_pointer_to_zero-sized_type.zig → test/cases/compile_errors/stage1/ptrToInt_with_pointer_to_zero-sized_type.zig
@@ -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
test/cases/compile_errors/bad_usage_of_call.zig
@@ -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
test/cases/comparison_of_non-tagged_union_and_enum_literal.zig
@@ -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