authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2021-10-17 15:52:19+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-17 16:06:40-04:00
log51be575745adfe21a5367f206c156f2d589ad436
treea888b7e8eb55a0c91c7686ef5b0570c8085bc11d
parent98a37dfb23202e3f56e1596a19be3fa563f65eeb

std: Fix endless loop in fmt impl

Apparently there's a stage1 bug that may sometimes lead to an endless loop being generated when unrolling the fmt impl. Closes #9961

1 files changed, 16 insertions(+), 14 deletions(-)

lib/std/fmt.zig+16-14
...@@ -295,21 +295,21 @@ pub fn format(...@@ -295,21 +295,21 @@ pub fn format(
295 }295 }
296296
297 // Parse the width parameter297 // Parse the width parameter
298 options.width = init: {298 options.width = comptime init: {
299 if (comptime parser.maybe('[')) {299 if (parser.maybe('[')) {
300 const arg_name = comptime parser.until(']');300 const arg_name = parser.until(']');
301301
302 if (!comptime parser.maybe(']')) {302 if (!parser.maybe(']')) {
303 @compileError("Expected closing ]");303 @compileError("Expected closing ]");
304 }304 }
305305
306 const index = comptime meta.fieldIndex(ArgsType, arg_name) orelse306 const index = meta.fieldIndex(ArgsType, arg_name) orelse
307 @compileError("No argument with name '" ++ arg_name ++ "'");307 @compileError("No argument with name '" ++ arg_name ++ "'");
308 const arg_index = comptime arg_state.nextArg(index);308 const arg_index = arg_state.nextArg(index);
309309
310 break :init @field(args, fields_info[arg_index].name);310 break :init @field(args, fields_info[arg_index].name);
311 } else {311 } else {
312 break :init comptime parser.number();312 break :init parser.number();
313 }313 }
314 };314 };
315315
...@@ -321,21 +321,21 @@ pub fn format(...@@ -321,21 +321,21 @@ pub fn format(
321 }321 }
322322
323 // Parse the precision parameter323 // Parse the precision parameter
324 options.precision = init: {324 options.precision = comptime init: {
325 if (comptime parser.maybe('[')) {325 if (parser.maybe('[')) {
326 const arg_name = comptime parser.until(']');326 const arg_name = parser.until(']');
327327
328 if (!comptime parser.maybe(']')) {328 if (!parser.maybe(']')) {
329 @compileError("Expected closing ]");329 @compileError("Expected closing ]");
330 }330 }
331331
332 const arg_i = comptime meta.fieldIndex(ArgsType, arg_name) orelse332 const arg_i = meta.fieldIndex(ArgsType, arg_name) orelse
333 @compileError("No argument with name '" ++ arg_name ++ "'");333 @compileError("No argument with name '" ++ arg_name ++ "'");
334 const arg_to_use = comptime arg_state.nextArg(arg_i);334 const arg_to_use = arg_state.nextArg(arg_i);
335335
336 break :init @field(args, fields_info[arg_to_use].name);336 break :init @field(args, fields_info[arg_to_use].name);
337 } else {337 } else {
338 break :init comptime parser.number();338 break :init parser.number();
339 }339 }
340 };340 };
341341
...@@ -2576,6 +2576,8 @@ test "runtime width specifier" {...@@ -2576,6 +2576,8 @@ test "runtime width specifier" {
2576 var width: usize = 9;2576 var width: usize = 9;
2577 try expectFmt("~~hello~~", "{s:~^[1]}", .{ "hello", width });2577 try expectFmt("~~hello~~", "{s:~^[1]}", .{ "hello", width });
2578 try expectFmt("~~hello~~", "{s:~^[width]}", .{ .string = "hello", .width = width });2578 try expectFmt("~~hello~~", "{s:~^[width]}", .{ .string = "hello", .width = width });
2579 try expectFmt(" hello", "{s:[1]}", .{ "hello", width });
2580 try expectFmt("42 hello", "{d} {s:[2]}", .{ 42, "hello", width });
2579}2581}
25802582
2581test "runtime precision specifier" {2583test "runtime precision specifier" {