-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Endless loop in Semantic Analysis [x/y] #4572
Comments
I don't know if it's related, but compiling https://github.com/andrewrk/tetris with |
It seems like the issue during compilation of https://github.com/andrewrk/tetris is not related to this. |
I am able to trigger this bug with this recursive .format() function: https://gist.github.com/oatberry/fc89cba8e3bdbeaf9e474949f838cc7a |
As of zig 0.6.0+006b780d4, this bug is still present. const std = @import("std");
const E = enum { Leaf, Branch };
const R = union(E) {
Leaf: i32,
Branch: struct { left: *const R, right: *const R },
pub fn format(self: R, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
return switch (self) {
.Leaf => |n| std.fmt.format(writer, "Leaf({})", .{n}),
.Branch => |b| std.fmt.format(writer, "Branch({}, {})", .{ b.left, b.right }),
};
}
};
test "∞" {
const r: *const R = undefined; //runtime value here doesn't matter,
std.debug.print("{}\n", .{r}); //infinite analysis loop
} A possible work-around is to replace the recursive algorithm with an iterative one, like so: const std = @import("std");
const E = enum { Leaf, Branch };
const R = union(E) {
Leaf: i32,
Branch: struct { left: *const R, right: *const R },
pub fn format(self: R, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
var pool: [500]u8 = undefined;
var allocator = &std.heap.FixedBufferAllocator.init(&pool).allocator;
const FE = enum { r, s };
const F = union(FE) {
r: *const R, //actual value
s: []const u8, //some string to print
};
var stack = std.ArrayList(F).init(allocator);
var val: F = .{ .r = &self };
while (true) {
switch (val) {
.r => |r| switch (r.*) {
.Leaf => |n| {
try std.fmt.format(writer, "Leaf({})", .{n});
},
.Branch => |*b| {
try std.fmt.format(writer, "Branch(", .{});
//pushed in reverse order to how they'll be printed
stack.append(.{ .s = ")" }) catch unreachable;
stack.append(.{ .r = b.right }) catch unreachable;
stack.append(.{ .s = ", " }) catch unreachable;
stack.append(.{ .r = b.left }) catch unreachable;
},
},
.s => |s| try std.fmt.format(writer, "{}", .{s}),
}
if (stack.items.len == 0) break;
val = stack.pop();
}
}
};
test "✓" {
const r = &R{
.Branch = .{
.left = &R{
.Branch = .{
.left = &R{ .Leaf = 3 },
.right = &R{
.Branch = .{
.left = &R{ .Leaf = 0 },
.right = &R{ .Leaf = 9 },
},
},
},
},
.right = &R{
.Branch = .{
.left = &R{ .Leaf = -1 },
.right = &R{ .Leaf = 99 },
},
},
},
};
//output: Branch(Branch(Leaf(3), Branch(Leaf(0), Leaf(9))), Branch(Leaf(-1), Leaf(99)))
std.debug.print("{}\n", .{r});
} Though this gets quite unwieldy. |
Closes ziglang#4144 Closes ziglang#4255 Closes ziglang#4372 Closes ziglang#4375 Closes ziglang#4380 Closes ziglang#4417 Closes ziglang#4423 Closes ziglang#4476 Closes ziglang#4528 Closes ziglang#4562 Closes ziglang#4572 Closes ziglang#4597 Closes ziglang#4639 Closes ziglang#4672 Closes ziglang#4782 Closes ziglang#4955 Closes ziglang#4984 Closes ziglang#4997 Closes ziglang#5010 Closes ziglang#5114 Closes ziglang#5166 Closes ziglang#5173 Closes ziglang#5276
Closes ziglang#4144 Closes ziglang#4255 Closes ziglang#4372 Closes ziglang#4375 Closes ziglang#4380 Closes ziglang#4417 Closes ziglang#4423 Closes ziglang#4476 Closes ziglang#4528 Closes ziglang#4562 Closes ziglang#4572 Closes ziglang#4597 Closes ziglang#4639 Closes ziglang#4672 Closes ziglang#4782 Closes ziglang#4955 Closes ziglang#4984 Closes ziglang#4997 Closes ziglang#5010 Closes ziglang#5114 Closes ziglang#5166 Closes ziglang#5173 Closes ziglang#5276
Closes ziglang#4144 Closes ziglang#4255 Closes ziglang#4372 Closes ziglang#4375 Closes ziglang#4380 Closes ziglang#4417 Closes ziglang#4423 Closes ziglang#4476 Closes ziglang#4528 Closes ziglang#4562 Closes ziglang#4572 Closes ziglang#4597 Closes ziglang#4639 Closes ziglang#4672 Closes ziglang#4782 Closes ziglang#4955 Closes ziglang#4984 Closes ziglang#4997 Closes ziglang#5010 Closes ziglang#5114 Closes ziglang#5166 Closes ziglang#5173 Closes ziglang#5276
When compiling the following code, the compiler will run into an endless loop trying to analyze whatever it is to analyze:
This code will run into an endless loop of semantic analysis when using variant
@0
:It will run when using variant
@1
(using direct recursion) or variant@2
(calling a function that will call the formatter)Zig version:
0.5.0+330e30aec
The text was updated successfully, but these errors were encountered: