diff options
| author | Veikka Tuominen <git@vexu.eu> | 2022-08-30 14:04:13 +0300 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-08-30 12:22:07 -0700 |
| commit | 67a44211f7a442d33096cc0dfff059eee9315bc6 (patch) | |
| tree | 7cdb35205977cab28a9ed8cc5846096d2a57ed4d /test | |
| parent | 0a42602418dcaf08f13b4220b6c216356f87cbfc (diff) | |
| download | zig-67a44211f7a442d33096cc0dfff059eee9315bc6.tar.gz zig-67a44211f7a442d33096cc0dfff059eee9315bc6.zip | |
Sema: improve handling of always_tail call modifier
Closes #4301
Closes #5692
Closes #6281
Closes #10786
Closes #11149
Closes #11776
Diffstat (limited to 'test')
| -rw-r--r-- | test/behavior/call.zig | 54 | ||||
| -rw-r--r-- | test/cases/compile_errors/invalid_tail_call.zig | 12 | ||||
| -rw-r--r-- | test/cases/taill_call_noreturn.zig | 18 |
3 files changed, 84 insertions, 0 deletions
diff --git a/test/behavior/call.zig b/test/behavior/call.zig index eafd2ef4e9..4c697ed542 100644 --- a/test/behavior/call.zig +++ b/test/behavior/call.zig @@ -261,3 +261,57 @@ test "arguments to comptime parameters generated in comptime blocks" { }; S.foo(S.fortyTwo()); } + +test "forced tail call" { + if (builtin.zig_backend == .stage1) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const S = struct { + fn fibonacciTailInternal(n: u16, a: u16, b: u16) u16 { + if (n == 0) return a; + if (n == 1) return b; + return @call( + .{ .modifier = .always_tail }, + fibonacciTailInternal, + .{ n - 1, b, a + b }, + ); + } + + fn fibonacciTail(n: u16) u16 { + return fibonacciTailInternal(n, 0, 1); + } + }; + try expect(S.fibonacciTail(10) == 55); +} + +test "inline call preserves tail call" { + if (builtin.zig_backend == .stage1) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const max = std.math.maxInt(u16); + const S = struct { + var a: u16 = 0; + fn foo() void { + return bar(); + } + + inline fn bar() void { + if (a == max) return; + // Stack overflow if not tail called + var buf: [max]u16 = undefined; + buf[a] = a; + a += 1; + return @call(.{ .modifier = .always_tail }, foo, .{}); + } + }; + S.foo(); + try expect(S.a == std.math.maxInt(u16)); +} diff --git a/test/cases/compile_errors/invalid_tail_call.zig b/test/cases/compile_errors/invalid_tail_call.zig new file mode 100644 index 0000000000..cdeb9df930 --- /dev/null +++ b/test/cases/compile_errors/invalid_tail_call.zig @@ -0,0 +1,12 @@ +fn myFn(_: usize) void { + return; +} +pub export fn entry() void { + @call(.{ .modifier = .always_tail }, myFn, .{0}); +} + +// error +// backend=llvm +// target=native +// +// :5:5: error: unable to perform tail call: type of function being called 'fn(usize) void' does not match type of calling function 'fn() callconv(.C) void' diff --git a/test/cases/taill_call_noreturn.zig b/test/cases/taill_call_noreturn.zig new file mode 100644 index 0000000000..0c2497d6ce --- /dev/null +++ b/test/cases/taill_call_noreturn.zig @@ -0,0 +1,18 @@ +const std = @import("std"); +const builtin = std.builtin; +pub fn foo(message: []const u8, stack_trace: ?*builtin.StackTrace) noreturn { + @call(.{ .modifier = .always_tail }, bar, .{ message, stack_trace }); +} +pub fn bar(message: []const u8, stack_trace: ?*builtin.StackTrace) noreturn { + _ = message; + _ = stack_trace; + std.process.exit(0); +} + +pub fn main() void { + foo("foo", null); +} + +// run +// backend=llvm +// target=native |
