Commit 1480c42806
Changed files (8)
lib
lib/std/build.zig
@@ -739,7 +739,7 @@ pub const Builder = struct {
return args.default_target;
},
else => |e| {
- warn("Unable to parse target '{}': {s}\n\n", .{ triple, @errorName(e) });
+ warn("Unable to parse target '{s}': {s}\n\n", .{ triple, @errorName(e) });
self.markInvalidUserInput();
return args.default_target;
},
lib/std/fmt.zig
@@ -69,6 +69,7 @@ pub const FormatOptions = struct {
/// - `c`: output integer as an ASCII character. Integer type must have 8 bits at max.
/// - `u`: output integer as an UTF-8 sequence. Integer type must have 21 bits at max.
/// - `*`: output the address of the value instead of the value itself.
+/// - `any`: output a value of any type using its default format
///
/// If a formatted user type contains a function of the type
/// ```
@@ -387,17 +388,32 @@ pub fn formatAddress(value: anytype, options: FormatOptions, writer: anytype) @T
return;
}
},
- .Array => |info| {
- try writer.writeAll(@typeName(info.child) ++ "@");
- try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, writer);
- return;
- },
else => {},
}
@compileError("Cannot format non-pointer type " ++ @typeName(T) ++ " with * specifier");
}
+// This ANY const is a workaround for: https://github.com/ziglang/zig/issues/7948
+const ANY = "any";
+
+fn defaultSpec(comptime T: type) [:0]const u8 {
+ switch (@typeInfo(T)) {
+ .Array => |_| return ANY,
+ .Pointer => |ptr_info| switch (ptr_info.size) {
+ .One => switch (@typeInfo(ptr_info.child)) {
+ .Array => |_| return "*",
+ else => {},
+ },
+ .Many, .C => return "*",
+ .Slice => return ANY,
+ },
+ .Optional => |info| return defaultSpec(info.child),
+ else => {},
+ }
+ return "";
+}
+
pub fn formatType(
value: anytype,
comptime fmt: []const u8,
@@ -405,18 +421,19 @@ pub fn formatType(
writer: anytype,
max_depth: usize,
) @TypeOf(writer).Error!void {
- if (comptime std.mem.eql(u8, fmt, "*")) {
+ const actual_fmt = comptime if (std.mem.eql(u8, fmt, ANY)) defaultSpec(@TypeOf(value)) else fmt;
+ if (comptime std.mem.eql(u8, actual_fmt, "*")) {
return formatAddress(value, options, writer);
}
const T = @TypeOf(value);
if (comptime std.meta.trait.hasFn("format")(T)) {
- return try value.format(fmt, options, writer);
+ return try value.format(actual_fmt, options, writer);
}
switch (@typeInfo(T)) {
.ComptimeInt, .Int, .ComptimeFloat, .Float => {
- return formatValue(value, fmt, options, writer);
+ return formatValue(value, actual_fmt, options, writer);
},
.Void => {
return formatBuf("void", options, writer);
@@ -426,16 +443,16 @@ pub fn formatType(
},
.Optional => {
if (value) |payload| {
- return formatType(payload, fmt, options, writer, max_depth);
+ return formatType(payload, actual_fmt, options, writer, max_depth);
} else {
return formatBuf("null", options, writer);
}
},
.ErrorUnion => {
if (value) |payload| {
- return formatType(payload, fmt, options, writer, max_depth);
+ return formatType(payload, actual_fmt, options, writer, max_depth);
} else |err| {
- return formatType(err, fmt, options, writer, max_depth);
+ return formatType(err, actual_fmt, options, writer, max_depth);
}
},
.ErrorSet => {
@@ -461,7 +478,7 @@ pub fn formatType(
}
try writer.writeAll("(");
- try formatType(@enumToInt(value), fmt, options, writer, max_depth);
+ try formatType(@enumToInt(value), actual_fmt, options, writer, max_depth);
try writer.writeAll(")");
},
.Union => |info| {
@@ -475,7 +492,7 @@ pub fn formatType(
try writer.writeAll(" = ");
inline for (info.fields) |u_field| {
if (value == @field(UnionTagType, u_field.name)) {
- try formatType(@field(value, u_field.name), fmt, options, writer, max_depth - 1);
+ try formatType(@field(value, u_field.name), ANY, options, writer, max_depth - 1);
}
}
try writer.writeAll(" }");
@@ -497,48 +514,54 @@ pub fn formatType(
}
try writer.writeAll(f.name);
try writer.writeAll(" = ");
- try formatType(@field(value, f.name), fmt, options, writer, max_depth - 1);
+ try formatType(@field(value, f.name), ANY, options, writer, max_depth - 1);
}
try writer.writeAll(" }");
},
.Pointer => |ptr_info| switch (ptr_info.size) {
.One => switch (@typeInfo(ptr_info.child)) {
.Array => |info| {
+ if (actual_fmt.len == 0)
+ @compileError("cannot format array ref without a specifier (i.e. {s} or {*})");
if (info.child == u8) {
- if (fmt.len > 0 and comptime mem.indexOfScalar(u8, "sxXeEzZ", fmt[0]) != null) {
- return formatText(value, fmt, options, writer);
+ if (comptime mem.indexOfScalar(u8, "sxXeEzZ", actual_fmt[0]) != null) {
+ return formatText(value, actual_fmt, options, writer);
}
}
- return format(writer, "{s}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value) });
+ @compileError("Unknown format string: '" ++ actual_fmt ++ "'");
},
.Enum, .Union, .Struct => {
- return formatType(value.*, fmt, options, writer, max_depth);
+ return formatType(value.*, actual_fmt, options, writer, max_depth);
},
else => return format(writer, "{s}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value) }),
},
.Many, .C => {
+ if (actual_fmt.len == 0)
+ @compileError("cannot format pointer without a specifier (i.e. {s} or {*})");
if (ptr_info.sentinel) |sentinel| {
- return formatType(mem.span(value), fmt, options, writer, max_depth);
+ return formatType(mem.span(value), actual_fmt, options, writer, max_depth);
}
if (ptr_info.child == u8) {
- if (fmt.len > 0 and comptime mem.indexOfScalar(u8, "sxXeEzZ", fmt[0]) != null) {
- return formatText(mem.span(value), fmt, options, writer);
+ if (comptime mem.indexOfScalar(u8, "sxXeEzZ", actual_fmt[0]) != null) {
+ return formatText(mem.span(value), actual_fmt, options, writer);
}
}
- return format(writer, "{s}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value) });
+ @compileError("Unknown format string: '" ++ actual_fmt ++ "'");
},
.Slice => {
+ if (actual_fmt.len == 0)
+ @compileError("cannot format slice without a specifier (i.e. {s} or {any})");
if (max_depth == 0) {
return writer.writeAll("{ ... }");
}
if (ptr_info.child == u8) {
- if (fmt.len > 0 and comptime mem.indexOfScalar(u8, "sxXeEzZ", fmt[0]) != null) {
- return formatText(value, fmt, options, writer);
+ if (comptime mem.indexOfScalar(u8, "sxXeEzZ", actual_fmt[0]) != null) {
+ return formatText(value, actual_fmt, options, writer);
}
}
try writer.writeAll("{ ");
for (value) |elem, i| {
- try formatType(elem, fmt, options, writer, max_depth - 1);
+ try formatType(elem, actual_fmt, options, writer, max_depth - 1);
if (i != value.len - 1) {
try writer.writeAll(", ");
}
@@ -547,17 +570,19 @@ pub fn formatType(
},
},
.Array => |info| {
+ if (actual_fmt.len == 0)
+ @compileError("cannot format array without a specifier (i.e. {s} or {any})");
if (max_depth == 0) {
return writer.writeAll("{ ... }");
}
if (info.child == u8) {
- if (fmt.len > 0 and comptime mem.indexOfScalar(u8, "sxXeEzZ", fmt[0]) != null) {
- return formatText(&value, fmt, options, writer);
+ if (comptime mem.indexOfScalar(u8, "sxXeEzZ", actual_fmt[0]) != null) {
+ return formatText(&value, actual_fmt, options, writer);
}
}
try writer.writeAll("{ ");
for (value) |elem, i| {
- try formatType(elem, fmt, options, writer, max_depth - 1);
+ try formatType(elem, actual_fmt, options, writer, max_depth - 1);
if (i < value.len - 1) {
try writer.writeAll(", ");
}
@@ -568,7 +593,7 @@ pub fn formatType(
try writer.writeAll("{ ");
var i: usize = 0;
while (i < info.len) : (i += 1) {
- try formatValue(value[i], fmt, options, writer);
+ try formatValue(value[i], actual_fmt, options, writer);
if (i < info.len - 1) {
try writer.writeAll(", ");
}
@@ -1668,7 +1693,7 @@ test "slice" {
{
var int_slice = [_]u32{ 1, 4096, 391891, 1111111111 };
var runtime_zero: usize = 0;
- try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {}", .{int_slice[runtime_zero..]});
+ try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {any}", .{int_slice[runtime_zero..]});
try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {d}", .{int_slice[runtime_zero..]});
try expectFmt("int: { 1, 1000, 5fad3, 423a35c7 }", "int: {x}", .{int_slice[runtime_zero..]});
try expectFmt("int: { 00001, 01000, 5fad3, 423a35c7 }", "int: {x:0>5}", .{int_slice[runtime_zero..]});
lib/std/testing.zig
@@ -29,7 +29,7 @@ pub var zig_exe_path: []const u8 = undefined;
/// and then aborts when actual_error_union is not expected_error.
pub fn expectError(expected_error: anyerror, actual_error_union: anytype) void {
if (actual_error_union) |actual_payload| {
- std.debug.panic("expected error.{s}, found {}", .{ @errorName(expected_error), actual_payload });
+ std.debug.panic("expected error.{s}, found {any}", .{ @errorName(expected_error), actual_payload });
} else |actual_error| {
if (expected_error != actual_error) {
std.debug.panic("expected error.{s}, found error.{s}", .{
@@ -88,7 +88,7 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) void {
},
.Slice => {
if (actual.ptr != expected.ptr) {
- std.debug.panic("expected slice ptr {}, found {}", .{ expected.ptr, actual.ptr });
+ std.debug.panic("expected slice ptr {*}, found {*}", .{ expected.ptr, actual.ptr });
}
if (actual.len != expected.len) {
std.debug.panic("expected slice len {}, found {}", .{ expected.len, actual.len });
@@ -145,11 +145,11 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) void {
if (actual) |actual_payload| {
expectEqual(expected_payload, actual_payload);
} else {
- std.debug.panic("expected {}, found null", .{expected_payload});
+ std.debug.panic("expected {any}, found null", .{expected_payload});
}
} else {
if (actual) |actual_payload| {
- std.debug.panic("expected null, found {}", .{actual_payload});
+ std.debug.panic("expected null, found {any}", .{actual_payload});
}
}
},
@@ -159,11 +159,11 @@ pub fn expectEqual(expected: anytype, actual: @TypeOf(expected)) void {
if (actual) |actual_payload| {
expectEqual(expected_payload, actual_payload);
} else |actual_err| {
- std.debug.panic("expected {}, found {}", .{ expected_payload, actual_err });
+ std.debug.panic("expected {any}, found {}", .{ expected_payload, actual_err });
}
} else |expected_err| {
if (actual) |actual_payload| {
- std.debug.panic("expected {}, found {}", .{ expected_err, actual_payload });
+ std.debug.panic("expected {}, found {any}", .{ expected_err, actual_payload });
} else |actual_err| {
expectEqual(expected_err, actual_err);
}
@@ -279,7 +279,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
var i: usize = 0;
while (i < expected.len) : (i += 1) {
if (!std.meta.eql(expected[i], actual[i])) {
- std.debug.panic("index {} incorrect. expected {}, found {}", .{ i, expected[i], actual[i] });
+ std.debug.panic("index {} incorrect. expected {any}, found {any}", .{ i, expected[i], actual[i] });
}
}
}
src/codegen.zig
@@ -2223,7 +2223,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
writeInt(u32, try self.code.addManyAsArray(4), Instruction.cmp(.al, reg, op).toU32());
break :blk .ne;
},
- else => return self.fail(inst.base.src, "TODO implement condbr {} when condition is {}", .{ self.target.cpu.arch, @tagName(cond) }),
+ else => return self.fail(inst.base.src, "TODO implement condbr {} when condition is {s}", .{ self.target.cpu.arch, @tagName(cond) }),
};
const reloc = Reloc{
src/Module.zig
@@ -2400,7 +2400,7 @@ fn getAnonTypeName(self: *Module, scope: *Scope, base_token: std.zig.ast.TokenIn
else => unreachable,
};
const loc = tree.tokenLocationLoc(0, tree.token_locs[base_token]);
- return std.fmt.allocPrint(self.gpa, "{}:{}:{}", .{ base_name, loc.line, loc.column });
+ return std.fmt.allocPrint(self.gpa, "{s}:{}:{}", .{ base_name, loc.line, loc.column });
}
fn getNextAnonNameIndex(self: *Module) usize {
src/zir_sema.zig
@@ -1832,7 +1832,7 @@ fn zirBitwise(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*In
const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
if (!is_int) {
- return mod.fail(scope, inst.base.src, "invalid operands to binary bitwise expression: '{}' and '{}'", .{ @tagName(lhs.ty.zigTypeTag()), @tagName(rhs.ty.zigTypeTag()) });
+ return mod.fail(scope, inst.base.src, "invalid operands to binary bitwise expression: '{s}' and '{s}'", .{ @tagName(lhs.ty.zigTypeTag()), @tagName(rhs.ty.zigTypeTag()) });
}
if (casted_lhs.value()) |lhs_val| {
test/standalone/cat/main.zig
@@ -41,6 +41,6 @@ pub fn main() !void {
}
fn usage(exe: []const u8) !void {
- warn("Usage: {} [FILE]...\n", .{exe});
+ warn("Usage: {s} [FILE]...\n", .{exe});
return error.Invalid;
}
test/cli.zig
@@ -51,9 +51,9 @@ fn unwrapArg(arg: UnwrapArgError![]u8) UnwrapArgError![]u8 {
}
fn printCmd(cwd: []const u8, argv: []const []const u8) void {
- std.debug.warn("cd {} && ", .{cwd});
+ std.debug.warn("cd {s} && ", .{cwd});
for (argv) |arg| {
- std.debug.warn("{} ", .{arg});
+ std.debug.warn("{s} ", .{arg});
}
std.debug.warn("\n", .{});
}
@@ -75,14 +75,14 @@ fn exec(cwd: []const u8, expect_0: bool, argv: []const []const u8) !ChildProcess
if ((code != 0) == expect_0) {
std.debug.warn("The following command exited with error code {}:\n", .{code});
printCmd(cwd, argv);
- std.debug.warn("stderr:\n{}\n", .{result.stderr});
+ std.debug.warn("stderr:\n{s}\n", .{result.stderr});
return error.CommandFailed;
}
},
else => {
std.debug.warn("The following command terminated unexpectedly:\n", .{});
printCmd(cwd, argv);
- std.debug.warn("stderr:\n{}\n", .{result.stderr});
+ std.debug.warn("stderr:\n{s}\n", .{result.stderr});
return error.CommandFailed;
},
}