authorgravatar for johnnymarler@gmail.comJonathan Marler <johnnymarler@gmail.com> 2021-01-03 02:20:37-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-09 22:25:52-08:00
log1480c428065c01c6feff22ce84021c2e0e30aa9b
treeb54dc7156319d92d5947188b4684b4faae1ee8eb
parent6a5a6386c60143258fc9970f52e26e3a974b52b5

require specifier for arrayish types


8 files changed, 71 insertions(+), 46 deletions(-)

lib/std/build.zig+1-1
...@@ -739,7 +739,7 @@ pub const Builder = struct {...@@ -739,7 +739,7 @@ pub const Builder = struct {
739 return args.default_target;739 return args.default_target;
740 },740 },
741 else => |e| {741 else => |e| {
742 warn("Unable to parse target '{}': {s}\n\n", .{ triple, @errorName(e) });742 warn("Unable to parse target '{s}': {s}\n\n", .{ triple, @errorName(e) });
743 self.markInvalidUserInput();743 self.markInvalidUserInput();
744 return args.default_target;744 return args.default_target;
745 },745 },
lib/std/fmt.zig+55-30
...@@ -69,6 +69,7 @@ pub const FormatOptions = struct {...@@ -69,6 +69,7 @@ pub const FormatOptions = struct {
69/// - `c`: output integer as an ASCII character. Integer type must have 8 bits at max.69/// - `c`: output integer as an ASCII character. Integer type must have 8 bits at max.
70/// - `u`: output integer as an UTF-8 sequence. Integer type must have 21 bits at max.70/// - `u`: output integer as an UTF-8 sequence. Integer type must have 21 bits at max.
71/// - `*`: output the address of the value instead of the value itself.71/// - `*`: output the address of the value instead of the value itself.
72/// - `any`: output a value of any type using its default format
72///73///
73/// If a formatted user type contains a function of the type74/// If a formatted user type contains a function of the type
74/// ```75/// ```
...@@ -387,17 +388,32 @@ pub fn formatAddress(value: anytype, options: FormatOptions, writer: anytype) @T...@@ -387,17 +388,32 @@ pub fn formatAddress(value: anytype, options: FormatOptions, writer: anytype) @T
387 return;388 return;
388 }389 }
389 },390 },
390 .Array => |info| {
391 try writer.writeAll(@typeName(info.child) ++ "@");
392 try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, writer);
393 return;
394 },
395 else => {},391 else => {},
396 }392 }
397393
398 @compileError("Cannot format non-pointer type " ++ @typeName(T) ++ " with * specifier");394 @compileError("Cannot format non-pointer type " ++ @typeName(T) ++ " with * specifier");
399}395}
400396
397// This ANY const is a workaround for: https://github.com/ziglang/zig/issues/7948
398const ANY = "any";
399
400fn defaultSpec(comptime T: type) [:0]const u8 {
401 switch (@typeInfo(T)) {
402 .Array => |_| return ANY,
403 .Pointer => |ptr_info| switch (ptr_info.size) {
404 .One => switch (@typeInfo(ptr_info.child)) {
405 .Array => |_| return "*",
406 else => {},
407 },
408 .Many, .C => return "*",
409 .Slice => return ANY,
410 },
411 .Optional => |info| return defaultSpec(info.child),
412 else => {},
413 }
414 return "";
415}
416
401pub fn formatType(417pub fn formatType(
402 value: anytype,418 value: anytype,
403 comptime fmt: []const u8,419 comptime fmt: []const u8,
...@@ -405,18 +421,19 @@ pub fn formatType(...@@ -405,18 +421,19 @@ pub fn formatType(
405 writer: anytype,421 writer: anytype,
406 max_depth: usize,422 max_depth: usize,
407) @TypeOf(writer).Error!void {423) @TypeOf(writer).Error!void {
408 if (comptime std.mem.eql(u8, fmt, "*")) {424 const actual_fmt = comptime if (std.mem.eql(u8, fmt, ANY)) defaultSpec(@TypeOf(value)) else fmt;
425 if (comptime std.mem.eql(u8, actual_fmt, "*")) {
409 return formatAddress(value, options, writer);426 return formatAddress(value, options, writer);
410 }427 }
411428
412 const T = @TypeOf(value);429 const T = @TypeOf(value);
413 if (comptime std.meta.trait.hasFn("format")(T)) {430 if (comptime std.meta.trait.hasFn("format")(T)) {
414 return try value.format(fmt, options, writer);431 return try value.format(actual_fmt, options, writer);
415 }432 }
416433
417 switch (@typeInfo(T)) {434 switch (@typeInfo(T)) {
418 .ComptimeInt, .Int, .ComptimeFloat, .Float => {435 .ComptimeInt, .Int, .ComptimeFloat, .Float => {
419 return formatValue(value, fmt, options, writer);436 return formatValue(value, actual_fmt, options, writer);
420 },437 },
421 .Void => {438 .Void => {
422 return formatBuf("void", options, writer);439 return formatBuf("void", options, writer);
...@@ -426,16 +443,16 @@ pub fn formatType(...@@ -426,16 +443,16 @@ pub fn formatType(
426 },443 },
427 .Optional => {444 .Optional => {
428 if (value) |payload| {445 if (value) |payload| {
429 return formatType(payload, fmt, options, writer, max_depth);446 return formatType(payload, actual_fmt, options, writer, max_depth);
430 } else {447 } else {
431 return formatBuf("null", options, writer);448 return formatBuf("null", options, writer);
432 }449 }
433 },450 },
434 .ErrorUnion => {451 .ErrorUnion => {
435 if (value) |payload| {452 if (value) |payload| {
436 return formatType(payload, fmt, options, writer, max_depth);453 return formatType(payload, actual_fmt, options, writer, max_depth);
437 } else |err| {454 } else |err| {
438 return formatType(err, fmt, options, writer, max_depth);455 return formatType(err, actual_fmt, options, writer, max_depth);
439 }456 }
440 },457 },
441 .ErrorSet => {458 .ErrorSet => {
...@@ -461,7 +478,7 @@ pub fn formatType(...@@ -461,7 +478,7 @@ pub fn formatType(
461 }478 }
462479
463 try writer.writeAll("(");480 try writer.writeAll("(");
464 try formatType(@enumToInt(value), fmt, options, writer, max_depth);481 try formatType(@enumToInt(value), actual_fmt, options, writer, max_depth);
465 try writer.writeAll(")");482 try writer.writeAll(")");
466 },483 },
467 .Union => |info| {484 .Union => |info| {
...@@ -475,7 +492,7 @@ pub fn formatType(...@@ -475,7 +492,7 @@ pub fn formatType(
475 try writer.writeAll(" = ");492 try writer.writeAll(" = ");
476 inline for (info.fields) |u_field| {493 inline for (info.fields) |u_field| {
477 if (value == @field(UnionTagType, u_field.name)) {494 if (value == @field(UnionTagType, u_field.name)) {
478 try formatType(@field(value, u_field.name), fmt, options, writer, max_depth - 1);495 try formatType(@field(value, u_field.name), ANY, options, writer, max_depth - 1);
479 }496 }
480 }497 }
481 try writer.writeAll(" }");498 try writer.writeAll(" }");
...@@ -497,48 +514,54 @@ pub fn formatType(...@@ -497,48 +514,54 @@ pub fn formatType(
497 }514 }
498 try writer.writeAll(f.name);515 try writer.writeAll(f.name);
499 try writer.writeAll(" = ");516 try writer.writeAll(" = ");
500 try formatType(@field(value, f.name), fmt, options, writer, max_depth - 1);517 try formatType(@field(value, f.name), ANY, options, writer, max_depth - 1);
501 }518 }
502 try writer.writeAll(" }");519 try writer.writeAll(" }");
503 },520 },
504 .Pointer => |ptr_info| switch (ptr_info.size) {521 .Pointer => |ptr_info| switch (ptr_info.size) {
505 .One => switch (@typeInfo(ptr_info.child)) {522 .One => switch (@typeInfo(ptr_info.child)) {
506 .Array => |info| {523 .Array => |info| {
524 if (actual_fmt.len == 0)
525 @compileError("cannot format array ref without a specifier (i.e. {s} or {*})");
507 if (info.child == u8) {526 if (info.child == u8) {
508 if (fmt.len > 0 and comptime mem.indexOfScalar(u8, "sxXeEzZ", fmt[0]) != null) {527 if (comptime mem.indexOfScalar(u8, "sxXeEzZ", actual_fmt[0]) != null) {
509 return formatText(value, fmt, options, writer);528 return formatText(value, actual_fmt, options, writer);
510 }529 }
511 }530 }
512 return format(writer, "{s}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value) });531 @compileError("Unknown format string: '" ++ actual_fmt ++ "'");
513 },532 },
514 .Enum, .Union, .Struct => {533 .Enum, .Union, .Struct => {
515 return formatType(value.*, fmt, options, writer, max_depth);534 return formatType(value.*, actual_fmt, options, writer, max_depth);
516 },535 },
517 else => return format(writer, "{s}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value) }),536 else => return format(writer, "{s}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value) }),
518 },537 },
519 .Many, .C => {538 .Many, .C => {
539 if (actual_fmt.len == 0)
540 @compileError("cannot format pointer without a specifier (i.e. {s} or {*})");
520 if (ptr_info.sentinel) |sentinel| {541 if (ptr_info.sentinel) |sentinel| {
521 return formatType(mem.span(value), fmt, options, writer, max_depth);542 return formatType(mem.span(value), actual_fmt, options, writer, max_depth);
522 }543 }
523 if (ptr_info.child == u8) {544 if (ptr_info.child == u8) {
524 if (fmt.len > 0 and comptime mem.indexOfScalar(u8, "sxXeEzZ", fmt[0]) != null) {545 if (comptime mem.indexOfScalar(u8, "sxXeEzZ", actual_fmt[0]) != null) {
525 return formatText(mem.span(value), fmt, options, writer);546 return formatText(mem.span(value), actual_fmt, options, writer);
526 }547 }
527 }548 }
528 return format(writer, "{s}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value) });549 @compileError("Unknown format string: '" ++ actual_fmt ++ "'");
529 },550 },
530 .Slice => {551 .Slice => {
552 if (actual_fmt.len == 0)
553 @compileError("cannot format slice without a specifier (i.e. {s} or {any})");
531 if (max_depth == 0) {554 if (max_depth == 0) {
532 return writer.writeAll("{ ... }");555 return writer.writeAll("{ ... }");
533 }556 }
534 if (ptr_info.child == u8) {557 if (ptr_info.child == u8) {
535 if (fmt.len > 0 and comptime mem.indexOfScalar(u8, "sxXeEzZ", fmt[0]) != null) {558 if (comptime mem.indexOfScalar(u8, "sxXeEzZ", actual_fmt[0]) != null) {
536 return formatText(value, fmt, options, writer);559 return formatText(value, actual_fmt, options, writer);
537 }560 }
538 }561 }
539 try writer.writeAll("{ ");562 try writer.writeAll("{ ");
540 for (value) |elem, i| {563 for (value) |elem, i| {
541 try formatType(elem, fmt, options, writer, max_depth - 1);564 try formatType(elem, actual_fmt, options, writer, max_depth - 1);
542 if (i != value.len - 1) {565 if (i != value.len - 1) {
543 try writer.writeAll(", ");566 try writer.writeAll(", ");
544 }567 }
...@@ -547,17 +570,19 @@ pub fn formatType(...@@ -547,17 +570,19 @@ pub fn formatType(
547 },570 },
548 },571 },
549 .Array => |info| {572 .Array => |info| {
573 if (actual_fmt.len == 0)
574 @compileError("cannot format array without a specifier (i.e. {s} or {any})");
550 if (max_depth == 0) {575 if (max_depth == 0) {
551 return writer.writeAll("{ ... }");576 return writer.writeAll("{ ... }");
552 }577 }
553 if (info.child == u8) {578 if (info.child == u8) {
554 if (fmt.len > 0 and comptime mem.indexOfScalar(u8, "sxXeEzZ", fmt[0]) != null) {579 if (comptime mem.indexOfScalar(u8, "sxXeEzZ", actual_fmt[0]) != null) {
555 return formatText(&value, fmt, options, writer);580 return formatText(&value, actual_fmt, options, writer);
556 }581 }
557 }582 }
558 try writer.writeAll("{ ");583 try writer.writeAll("{ ");
559 for (value) |elem, i| {584 for (value) |elem, i| {
560 try formatType(elem, fmt, options, writer, max_depth - 1);585 try formatType(elem, actual_fmt, options, writer, max_depth - 1);
561 if (i < value.len - 1) {586 if (i < value.len - 1) {
562 try writer.writeAll(", ");587 try writer.writeAll(", ");
563 }588 }
...@@ -568,7 +593,7 @@ pub fn formatType(...@@ -568,7 +593,7 @@ pub fn formatType(
568 try writer.writeAll("{ ");593 try writer.writeAll("{ ");
569 var i: usize = 0;594 var i: usize = 0;
570 while (i < info.len) : (i += 1) {595 while (i < info.len) : (i += 1) {
571 try formatValue(value[i], fmt, options, writer);596 try formatValue(value[i], actual_fmt, options, writer);
572 if (i < info.len - 1) {597 if (i < info.len - 1) {
573 try writer.writeAll(", ");598 try writer.writeAll(", ");
574 }599 }
...@@ -1668,7 +1693,7 @@ test "slice" {...@@ -1668,7 +1693,7 @@ test "slice" {
1668 {1693 {
1669 var int_slice = [_]u32{ 1, 4096, 391891, 1111111111 };1694 var int_slice = [_]u32{ 1, 4096, 391891, 1111111111 };
1670 var runtime_zero: usize = 0;1695 var runtime_zero: usize = 0;
1671 try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {}", .{int_slice[runtime_zero..]});1696 try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {any}", .{int_slice[runtime_zero..]});
1672 try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {d}", .{int_slice[runtime_zero..]});1697 try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {d}", .{int_slice[runtime_zero..]});
1673 try expectFmt("int: { 1, 1000, 5fad3, 423a35c7 }", "int: {x}", .{int_slice[runtime_zero..]});1698 try expectFmt("int: { 1, 1000, 5fad3, 423a35c7 }", "int: {x}", .{int_slice[runtime_zero..]});
1674 try expectFmt("int: { 00001, 01000, 5fad3, 423a35c7 }", "int: {x:0>5}", .{int_slice[runtime_zero..]});1699 try expectFmt("int: { 00001, 01000, 5fad3, 423a35c7 }", "int: {x:0>5}", .{int_slice[runtime_zero..]});
lib/std/testing.zig+7-7
...@@ -29,7 +29,7 @@ pub var zig_exe_path: []const u8 = undefined;...@@ -29,7 +29,7 @@ pub var zig_exe_path: []const u8 = undefined;
29/// and then aborts when actual_error_union is not expected_error.29/// and then aborts when actual_error_union is not expected_error.
30pub fn expectError(expected_error: anyerror, actual_error_union: anytype) void {30pub fn expectError(expected_error: anyerror, actual_error_union: anytype) void {
31 if (actual_error_union) |actual_payload| {31 if (actual_error_union) |actual_payload| {
32 std.debug.panic("expected error.{s}, found {}", .{ @errorName(expected_error), actual_payload });32 std.debug.panic("expected error.{s}, found {any}", .{ @errorName(expected_error), actual_payload });
33 } else |actual_error| {33 } else |actual_error| {
34 if (expected_error != actual_error) {34 if (expected_error != actual_error) {
35 std.debug.panic("expected error.{s}, found error.{s}", .{35 std.debug.panic("expected error.{s}, found error.{s}", .{
...@@ -88,7 +88,7 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) void {...@@ -88,7 +88,7 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) void {
88 },88 },
89 .Slice => {89 .Slice => {
90 if (actual.ptr != expected.ptr) {90 if (actual.ptr != expected.ptr) {
91 std.debug.panic("expected slice ptr {}, found {}", .{ expected.ptr, actual.ptr });91 std.debug.panic("expected slice ptr {*}, found {*}", .{ expected.ptr, actual.ptr });
92 }92 }
93 if (actual.len != expected.len) {93 if (actual.len != expected.len) {
94 std.debug.panic("expected slice len {}, found {}", .{ expected.len, actual.len });94 std.debug.panic("expected slice len {}, found {}", .{ expected.len, actual.len });
...@@ -145,11 +145,11 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) void {...@@ -145,11 +145,11 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) void {
145 if (actual) |actual_payload| {145 if (actual) |actual_payload| {
146 expectEqual(expected_payload, actual_payload);146 expectEqual(expected_payload, actual_payload);
147 } else {147 } else {
148 std.debug.panic("expected {}, found null", .{expected_payload});148 std.debug.panic("expected {any}, found null", .{expected_payload});
149 }149 }
150 } else {150 } else {
151 if (actual) |actual_payload| {151 if (actual) |actual_payload| {
152 std.debug.panic("expected null, found {}", .{actual_payload});152 std.debug.panic("expected null, found {any}", .{actual_payload});
153 }153 }
154 }154 }
155 },155 },
...@@ -159,11 +159,11 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) void {...@@ -159,11 +159,11 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) void {
159 if (actual) |actual_payload| {159 if (actual) |actual_payload| {
160 expectEqual(expected_payload, actual_payload);160 expectEqual(expected_payload, actual_payload);
161 } else |actual_err| {161 } else |actual_err| {
162 std.debug.panic("expected {}, found {}", .{ expected_payload, actual_err });162 std.debug.panic("expected {any}, found {}", .{ expected_payload, actual_err });
163 }163 }
164 } else |expected_err| {164 } else |expected_err| {
165 if (actual) |actual_payload| {165 if (actual) |actual_payload| {
166 std.debug.panic("expected {}, found {}", .{ expected_err, actual_payload });166 std.debug.panic("expected {}, found {any}", .{ expected_err, actual_payload });
167 } else |actual_err| {167 } else |actual_err| {
168 expectEqual(expected_err, actual_err);168 expectEqual(expected_err, actual_err);
169 }169 }
...@@ -279,7 +279,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const...@@ -279,7 +279,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
279 var i: usize = 0;279 var i: usize = 0;
280 while (i < expected.len) : (i += 1) {280 while (i < expected.len) : (i += 1) {
281 if (!std.meta.eql(expected[i], actual[i])) {281 if (!std.meta.eql(expected[i], actual[i])) {
282 std.debug.panic("index {} incorrect. expected {}, found {}", .{ i, expected[i], actual[i] });282 std.debug.panic("index {} incorrect. expected {any}, found {any}", .{ i, expected[i], actual[i] });
283 }283 }
284 }284 }
285}285}
src/Module.zig+1-1
...@@ -2400,7 +2400,7 @@ fn getAnonTypeName(self: *Module, scope: *Scope, base_token: std.zig.ast.TokenIn...@@ -2400,7 +2400,7 @@ fn getAnonTypeName(self: *Module, scope: *Scope, base_token: std.zig.ast.TokenIn
2400 else => unreachable,2400 else => unreachable,
2401 };2401 };
2402 const loc = tree.tokenLocationLoc(0, tree.token_locs[base_token]);2402 const loc = tree.tokenLocationLoc(0, tree.token_locs[base_token]);
2403 return std.fmt.allocPrint(self.gpa, "{}:{}:{}", .{ base_name, loc.line, loc.column });2403 return std.fmt.allocPrint(self.gpa, "{s}:{}:{}", .{ base_name, loc.line, loc.column });
2404}2404}
24052405
2406fn getNextAnonNameIndex(self: *Module) usize {2406fn getNextAnonNameIndex(self: *Module) usize {
src/codegen.zig+1-1
...@@ -2223,7 +2223,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2223,7 +2223,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2223 writeInt(u32, try self.code.addManyAsArray(4), Instruction.cmp(.al, reg, op).toU32());2223 writeInt(u32, try self.code.addManyAsArray(4), Instruction.cmp(.al, reg, op).toU32());
2224 break :blk .ne;2224 break :blk .ne;
2225 },2225 },
2226 else => return self.fail(inst.base.src, "TODO implement condbr {} when condition is {}", .{ self.target.cpu.arch, @tagName(cond) }),2226 else => return self.fail(inst.base.src, "TODO implement condbr {} when condition is {s}", .{ self.target.cpu.arch, @tagName(cond) }),
2227 };2227 };
22282228
2229 const reloc = Reloc{2229 const reloc = Reloc{
src/zir_sema.zig+1-1
...@@ -1832,7 +1832,7 @@ fn zirBitwise(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*In...@@ -1832,7 +1832,7 @@ fn zirBitwise(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*In
1832 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;1832 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
18331833
1834 if (!is_int) {1834 if (!is_int) {
1835 return mod.fail(scope, inst.base.src, "invalid operands to binary bitwise expression: '{}' and '{}'", .{ @tagName(lhs.ty.zigTypeTag()), @tagName(rhs.ty.zigTypeTag()) });1835 return mod.fail(scope, inst.base.src, "invalid operands to binary bitwise expression: '{s}' and '{s}'", .{ @tagName(lhs.ty.zigTypeTag()), @tagName(rhs.ty.zigTypeTag()) });
1836 }1836 }
18371837
1838 if (casted_lhs.value()) |lhs_val| {1838 if (casted_lhs.value()) |lhs_val| {
test/cli.zig+4-4
...@@ -51,9 +51,9 @@ fn unwrapArg(arg: UnwrapArgError![]u8) UnwrapArgError![]u8 {...@@ -51,9 +51,9 @@ fn unwrapArg(arg: UnwrapArgError![]u8) UnwrapArgError![]u8 {
51}51}
5252
53fn printCmd(cwd: []const u8, argv: []const []const u8) void {53fn printCmd(cwd: []const u8, argv: []const []const u8) void {
54 std.debug.warn("cd {} && ", .{cwd});54 std.debug.warn("cd {s} && ", .{cwd});
55 for (argv) |arg| {55 for (argv) |arg| {
56 std.debug.warn("{} ", .{arg});56 std.debug.warn("{s} ", .{arg});
57 }57 }
58 std.debug.warn("\n", .{});58 std.debug.warn("\n", .{});
59}59}
...@@ -75,14 +75,14 @@ fn exec(cwd: []const u8, expect_0: bool, argv: []const []const u8) !ChildProcess...@@ -75,14 +75,14 @@ fn exec(cwd: []const u8, expect_0: bool, argv: []const []const u8) !ChildProcess
75 if ((code != 0) == expect_0) {75 if ((code != 0) == expect_0) {
76 std.debug.warn("The following command exited with error code {}:\n", .{code});76 std.debug.warn("The following command exited with error code {}:\n", .{code});
77 printCmd(cwd, argv);77 printCmd(cwd, argv);
78 std.debug.warn("stderr:\n{}\n", .{result.stderr});78 std.debug.warn("stderr:\n{s}\n", .{result.stderr});
79 return error.CommandFailed;79 return error.CommandFailed;
80 }80 }
81 },81 },
82 else => {82 else => {
83 std.debug.warn("The following command terminated unexpectedly:\n", .{});83 std.debug.warn("The following command terminated unexpectedly:\n", .{});
84 printCmd(cwd, argv);84 printCmd(cwd, argv);
85 std.debug.warn("stderr:\n{}\n", .{result.stderr});85 std.debug.warn("stderr:\n{s}\n", .{result.stderr});
86 return error.CommandFailed;86 return error.CommandFailed;
87 },87 },
88 }88 }
test/standalone/cat/main.zig+1-1
...@@ -41,6 +41,6 @@ pub fn main() !void {...@@ -41,6 +41,6 @@ pub fn main() !void {
41}41}
4242
43fn usage(exe: []const u8) !void {43fn usage(exe: []const u8) !void {
44 warn("Usage: {} [FILE]...\n", .{exe});44 warn("Usage: {s} [FILE]...\n", .{exe});
45 return error.Invalid;45 return error.Invalid;
46}46}