authorgravatar for inkryption07@gmail.comInKryption <inkryption07@gmail.com> 2022-07-25 15:29:07+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-26 11:25:49-07:00
loga0d3a87ce15a9f68047dc900109f5b76184d046f
tree5fb7b787347a7061bc072e76787983c82698b00d
parent1a16b7214d88261f0e38b7ca4d15bcd76caaec4c

std.fmt: require specifier for unwrapping ?T and E!T


14 files changed, 70 insertions(+), 45 deletions(-)

doc/langref.html.in+4-4
......@@ -574,7 +574,7 @@ pub fn main() void {
574574 var optional_value: ?[]const u8 = null;
575575 assert(optional_value == null);
576576
577 print("\noptional 1\ntype: {s}\nvalue: {s}\n", .{
577 print("\noptional 1\ntype: {s}\nvalue: {?s}\n", .{
578578 @typeName(@TypeOf(optional_value)),
579579 optional_value,
580580 });
......@@ -582,7 +582,7 @@ pub fn main() void {
582582 optional_value = "hi";
583583 assert(optional_value != null);
584584
585 print("\noptional 2\ntype: {s}\nvalue: {s}\n", .{
585 print("\noptional 2\ntype: {s}\nvalue: {?s}\n", .{
586586 @typeName(@TypeOf(optional_value)),
587587 optional_value,
588588 });
......@@ -590,14 +590,14 @@ pub fn main() void {
590590 // error union
591591 var number_or_error: anyerror!i32 = error.ArgNotFound;
592592
593 print("\nerror union 1\ntype: {s}\nvalue: {}\n", .{
593 print("\nerror union 1\ntype: {s}\nvalue: {!}\n", .{
594594 @typeName(@TypeOf(number_or_error)),
595595 number_or_error,
596596 });
597597
598598 number_or_error = 1234;
599599
600 print("\nerror union 2\ntype: {s}\nvalue: {}\n", .{
600 print("\nerror union 2\ntype: {s}\nvalue: {!}\n", .{
601601 @typeName(@TypeOf(number_or_error)),
602602 number_or_error,
603603 });
lib/std/build.zig+2-2
......@@ -751,7 +751,7 @@ pub const Builder = struct {
751751 \\Available CPU features for architecture '{s}':
752752 \\
753753 , .{
754 diags.unknown_feature_name,
754 diags.unknown_feature_name.?,
755755 @tagName(diags.arch.?),
756756 });
757757 for (diags.arch.?.allFeaturesList()) |feature| {
......@@ -765,7 +765,7 @@ pub const Builder = struct {
765765 \\Unknown OS: '{s}'
766766 \\Available operating systems:
767767 \\
768 , .{diags.os_name});
768 , .{diags.os_name.?});
769769 inline for (std.meta.fields(std.Target.Os.Tag)) |field| {
770770 log.err(" {s}", .{field.name});
771771 }
lib/std/crypto/phc_encoding.zig+1-1
......@@ -216,7 +216,7 @@ fn serializeTo(params: anytype, out: anytype) !void {
216216
217217 var has_params = false;
218218 inline for (comptime meta.fields(HashResult)) |p| {
219 if (!(mem.eql(u8, p.name, "alg_id") or
219 if (comptime !(mem.eql(u8, p.name, "alg_id") or
220220 mem.eql(u8, p.name, "alg_version") or
221221 mem.eql(u8, p.name, "hash") or
222222 mem.eql(u8, p.name, "salt")))
lib/std/fmt.zig+33-11
......@@ -60,8 +60,10 @@ pub const FormatOptions = struct {
6060/// - `o`: output integer value in octal notation
6161/// - `c`: output integer as an ASCII character. Integer type must have 8 bits at max.
6262/// - `u`: output integer as an UTF-8 sequence. Integer type must have 21 bits at max.
63/// - `?`: output optional value as either the unwrapped value, or `null`; may be followed by a format specifier for the underlying value.
64/// - `!`: output error union value as either the unwrapped value, or the formatted error value; may be followed by a format specifier for the underlying value.
6365/// - `*`: output the address of the value instead of the value itself.
64/// - `any`: output a value of any type using its default format
66/// - `any`: output a value of any type using its default format.
6567///
6668/// If a formatted user type contains a function of the type
6769/// ```
......@@ -438,12 +440,20 @@ fn defaultSpec(comptime T: type) [:0]const u8 {
438440 .Many, .C => return "*",
439441 .Slice => return ANY,
440442 },
441 .Optional => |info| return defaultSpec(info.child),
443 .Optional => |info| return "?" ++ defaultSpec(info.child),
444 .ErrorUnion => |info| return "!" ++ defaultSpec(info.payload),
442445 else => {},
443446 }
444447 return "";
445448}
446449
450fn stripOptionalOrErrorUnionSpec(comptime fmt: []const u8) []const u8 {
451 return if (std.mem.eql(u8, fmt[1..], ANY))
452 ANY
453 else
454 fmt[1..];
455}
456
447457pub fn formatType(
448458 value: anytype,
449459 comptime fmt: []const u8,
......@@ -451,12 +461,18 @@ pub fn formatType(
451461 writer: anytype,
452462 max_depth: usize,
453463) @TypeOf(writer).Error!void {
454 const actual_fmt = comptime if (std.mem.eql(u8, fmt, ANY)) defaultSpec(@TypeOf(value)) else fmt;
464 const T = @TypeOf(value);
465 const actual_fmt = comptime if (std.mem.eql(u8, fmt, ANY))
466 defaultSpec(@TypeOf(value))
467 else if (fmt.len != 0 and (fmt[0] == '?' or fmt[0] == '!')) switch (@typeInfo(T)) {
468 .Optional, .ErrorUnion => fmt,
469 else => stripOptionalOrErrorUnionSpec(fmt),
470 } else fmt;
471
455472 if (comptime std.mem.eql(u8, actual_fmt, "*")) {
456473 return formatAddress(value, options, writer);
457474 }
458475
459 const T = @TypeOf(value);
460476 if (comptime std.meta.trait.hasFn("format")(T)) {
461477 return try value.format(actual_fmt, options, writer);
462478 }
......@@ -472,17 +488,23 @@ pub fn formatType(
472488 return formatBuf(if (value) "true" else "false", options, writer);
473489 },
474490 .Optional => {
491 if (actual_fmt.len == 0 or actual_fmt[0] != '?')
492 @compileError("cannot format optional without a specifier (i.e. {?} or {any})");
493 const remaining_fmt = comptime stripOptionalOrErrorUnionSpec(actual_fmt);
475494 if (value) |payload| {
476 return formatType(payload, actual_fmt, options, writer, max_depth);
495 return formatType(payload, remaining_fmt, options, writer, max_depth);
477496 } else {
478497 return formatBuf("null", options, writer);
479498 }
480499 },
481500 .ErrorUnion => {
501 if (actual_fmt.len == 0 or actual_fmt[0] != '!')
502 @compileError("cannot format error union without a specifier (i.e. {!} or {any})");
503 const remaining_fmt = comptime stripOptionalOrErrorUnionSpec(actual_fmt);
482504 if (value) |payload| {
483 return formatType(payload, actual_fmt, options, writer, max_depth);
505 return formatType(payload, remaining_fmt, options, writer, max_depth);
484506 } else |err| {
485 return formatType(err, actual_fmt, options, writer, max_depth);
507 return formatType(err, remaining_fmt, options, writer, max_depth);
486508 }
487509 },
488510 .ErrorSet => {
......@@ -1977,11 +1999,11 @@ test "escaped braces" {
19771999test "optional" {
19782000 {
19792001 const value: ?i32 = 1234;
1980 try expectFmt("optional: 1234\n", "optional: {}\n", .{value});
2002 try expectFmt("optional: 1234\n", "optional: {?}\n", .{value});
19812003 }
19822004 {
19832005 const value: ?i32 = null;
1984 try expectFmt("optional: null\n", "optional: {}\n", .{value});
2006 try expectFmt("optional: null\n", "optional: {?}\n", .{value});
19852007 }
19862008 {
19872009 const value = @intToPtr(?*i32, 0xf000d000);
......@@ -1992,11 +2014,11 @@ test "optional" {
19922014test "error" {
19932015 {
19942016 const value: anyerror!i32 = 1234;
1995 try expectFmt("error union: 1234\n", "error union: {}\n", .{value});
2017 try expectFmt("error union: 1234\n", "error union: {!}\n", .{value});
19962018 }
19972019 {
19982020 const value: anyerror!i32 = error.InvalidChar;
1999 try expectFmt("error union: error.InvalidChar\n", "error union: {}\n", .{value});
2021 try expectFmt("error union: error.InvalidChar\n", "error union: {!}\n", .{value});
20002022 }
20012023}
20022024
lib/std/x/os/net.zig+1-1
......@@ -544,7 +544,7 @@ test "ip: convert to and from ipv6" {
544544 try testing.expect(IPv4.localhost.mapToIPv6().mapsToIPv4());
545545
546546 try testing.expect(IPv4.localhost.toIPv6().toIPv4() == null);
547 try testing.expectFmt("127.0.0.1", "{}", .{IPv4.localhost.mapToIPv6().toIPv4()});
547 try testing.expectFmt("127.0.0.1", "{?}", .{IPv4.localhost.mapToIPv6().toIPv4()});
548548}
549549
550550test "ipv4: parse & format" {
src/Cache.zig+1-1
......@@ -747,7 +747,7 @@ pub const Manifest = struct {
747747 file.stat.inode,
748748 file.stat.mtime,
749749 &encoded_digest,
750 file.path,
750 file.path.?,
751751 });
752752 }
753753
src/Compilation.zig+1-1
......@@ -1465,7 +1465,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
14651465 .handle = artifact_dir,
14661466 .path = try options.local_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}),
14671467 };
1468 log.debug("zig_cache_artifact_directory='{s}' use_stage1={}", .{
1468 log.debug("zig_cache_artifact_directory='{?s}' use_stage1={}", .{
14691469 zig_cache_artifact_directory.path, use_stage1,
14701470 });
14711471
src/link/MachO.zig+9-9
......@@ -363,7 +363,7 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
363363
364364 // Create dSYM bundle.
365365 const dir = options.module.?.zig_cache_artifact_directory;
366 log.debug("creating {s}.dSYM bundle in {s}", .{ emit.sub_path, dir.path });
366 log.debug("creating {s}.dSYM bundle in {?s}", .{ emit.sub_path, dir.path });
367367
368368 const d_sym_path = try fmt.allocPrint(
369369 allocator,
......@@ -2378,7 +2378,7 @@ fn writeAtomsOneShot(self: *MachO) !void {
23782378 break :blk math.cast(usize, size) orelse return error.Overflow;
23792379 } else 0;
23802380
2381 log.debug(" (adding ATOM(%{d}, '{s}') from object({d}) to buffer)", .{
2381 log.debug(" (adding ATOM(%{d}, '{s}') from object({?d}) to buffer)", .{
23822382 atom.sym_index,
23832383 atom.getName(self),
23842384 atom.file,
......@@ -2911,7 +2911,7 @@ fn createTentativeDefAtoms(self: *MachO) !void {
29112911 const sym = self.getSymbolPtr(global);
29122912 if (!sym.tentative()) continue;
29132913
2914 log.debug("creating tentative definition for ATOM(%{d}, '{s}') in object({d})", .{
2914 log.debug("creating tentative definition for ATOM(%{d}, '{s}') in object({?d})", .{
29152915 global.sym_index, self.getSymbolName(global), global.file,
29162916 });
29172917
......@@ -3694,7 +3694,7 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
36943694 };
36953695 const name = self.strtab.get(name_str_index);
36963696
3697 log.debug("allocating symbol indexes for {s}", .{name});
3697 log.debug("allocating symbol indexes for {?s}", .{name});
36983698
36993699 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);
37003700 const sym_index = try self.allocateSymbol();
......@@ -3734,7 +3734,7 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
37343734 );
37353735 const addr = try self.allocateAtom(atom, code.len, required_alignment, match);
37363736
3737 log.debug("allocated atom for {s} at 0x{x}", .{ name, addr });
3737 log.debug("allocated atom for {?s} at 0x{x}", .{ name, addr });
37383738 log.debug(" (required alignment 0x{x})", .{required_alignment});
37393739
37403740 errdefer self.freeAtom(atom, match, true);
......@@ -7040,7 +7040,7 @@ fn logSymtab(self: *MachO) void {
70407040 @divTrunc(sym.n_desc, macho.N_SYMBOL_RESOLVER)
70417041 else
70427042 sym.n_sect;
7043 log.debug(" %{d}: {s} @{x} in {s}({d}), {s}", .{
7043 log.debug(" %{d}: {?s} @{x} in {s}({d}), {s}", .{
70447044 sym_id,
70457045 self.strtab.get(sym.n_strx),
70467046 sym.n_value,
......@@ -7053,7 +7053,7 @@ fn logSymtab(self: *MachO) void {
70537053 log.debug("globals table:", .{});
70547054 for (self.globals.keys()) |name, id| {
70557055 const value = self.globals.values()[id];
7056 log.debug(" {s} => %{d} in object({d})", .{ name, value.sym_index, value.file });
7056 log.debug(" {s} => %{d} in object({?d})", .{ name, value.sym_index, value.file });
70577057 }
70587058
70597059 log.debug("GOT entries:", .{});
......@@ -7068,7 +7068,7 @@ fn logSymtab(self: *MachO) void {
70687068 self.getSymbolName(entry.target),
70697069 });
70707070 } else {
7071 log.debug(" {d}@{x} => local(%{d}) in object({d}) {s}", .{
7071 log.debug(" {d}@{x} => local(%{d}) in object({?d}) {s}", .{
70727072 i,
70737073 atom_sym.n_value,
70747074 entry.target.sym_index,
......@@ -7137,7 +7137,7 @@ fn logAtoms(self: *MachO) void {
71377137pub fn logAtom(self: *MachO, atom: *const Atom) void {
71387138 const sym = atom.getSymbol(self);
71397139 const sym_name = atom.getName(self);
7140 log.debug(" ATOM(%{d}, '{s}') @ {x} (sizeof({x}), alignof({x})) in object({d}) in sect({d})", .{
7140 log.debug(" ATOM(%{d}, '{s}') @ {x} (sizeof({x}), alignof({x})) in object({?d}) in sect({d})", .{
71417141 atom.sym_index,
71427142 sym_name,
71437143 sym.n_value,
src/link/MachO/Atom.zig+3-3
......@@ -541,7 +541,7 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {
541541 const arch = macho_file.base.options.target.cpu.arch;
542542 switch (arch) {
543543 .aarch64 => {
544 log.debug(" RELA({s}) @ {x} => %{d} in object({d})", .{
544 log.debug(" RELA({s}) @ {x} => %{d} in object({?d})", .{
545545 @tagName(@intToEnum(macho.reloc_type_arm64, rel.@"type")),
546546 rel.offset,
547547 rel.target.sym_index,
......@@ -549,7 +549,7 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {
549549 });
550550 },
551551 .x86_64 => {
552 log.debug(" RELA({s}) @ {x} => %{d} in object({d})", .{
552 log.debug(" RELA({s}) @ {x} => %{d} in object({?d})", .{
553553 @tagName(@intToEnum(macho.reloc_type_x86_64, rel.@"type")),
554554 rel.offset,
555555 rel.target.sym_index,
......@@ -579,7 +579,7 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {
579579 log.debug(" | atomless target '{s}'", .{target_name});
580580 break :blk atomless_sym.n_value;
581581 };
582 log.debug(" | target ATOM(%{d}, '{s}') in object({d})", .{
582 log.debug(" | target ATOM(%{d}, '{s}') in object({?d})", .{
583583 target_atom.sym_index,
584584 target_atom.getName(macho_file),
585585 target_atom.file,
src/link/Wasm.zig+1-1
......@@ -1629,7 +1629,7 @@ fn setupMemory(self: *Wasm) !void {
16291629 return error.MemoryTooBig;
16301630 }
16311631 self.memories.limits.max = @intCast(u32, max_memory / page_size);
1632 log.debug("Maximum memory pages: {d}", .{self.memories.limits.max});
1632 log.debug("Maximum memory pages: {?d}", .{self.memories.limits.max});
16331633 }
16341634}
16351635
src/link/Wasm/Object.zig+1-1
......@@ -548,7 +548,7 @@ fn Parser(comptime ReaderType: type) type {
548548 .index = try leb.readULEB128(u32, reader),
549549 .addend = if (rel_type_enum.addendIsPresent()) try leb.readULEB128(u32, reader) else null,
550550 };
551 log.debug("Found relocation: type({s}) offset({d}) index({d}) addend({d})", .{
551 log.debug("Found relocation: type({s}) offset({d}) index({d}) addend({?d})", .{
552552 @tagName(relocation.relocation_type),
553553 relocation.offset,
554554 relocation.index,
src/main.zig+5-3
......@@ -3168,7 +3168,7 @@ fn parseCrossTargetOrReportFatalError(
31683168 @tagName(diags.arch.?), help_text.items,
31693169 });
31703170 }
3171 fatal("Unknown CPU feature: '{s}'", .{diags.unknown_feature_name});
3171 fatal("Unknown CPU feature: '{s}'", .{diags.unknown_feature_name.?});
31723172 },
31733173 else => |e| return e,
31743174 };
......@@ -3496,7 +3496,8 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, enable_cache: bool, stage
34963496 } else {
34973497 const out_zig_path = try fs.path.join(arena, &[_][]const u8{ "o", &digest, translated_zig_basename });
34983498 const zig_file = comp.local_cache_directory.handle.openFile(out_zig_path, .{}) catch |err| {
3499 fatal("unable to open cached translated zig file '{s}{s}{s}': {s}", .{ comp.local_cache_directory.path, fs.path.sep_str, out_zig_path, @errorName(err) });
3499 const path = comp.local_cache_directory.path orelse ".";
3500 fatal("unable to open cached translated zig file '{s}{s}{s}': {s}", .{ path, fs.path.sep_str, out_zig_path, @errorName(err) });
35003501 };
35013502 defer zig_file.close();
35023503 try io.getStdOut().writeFileAll(zig_file, .{});
......@@ -3626,7 +3627,8 @@ pub fn cmdInit(
36263627 .Exe => "init-exe",
36273628 };
36283629 var template_dir = zig_lib_directory.handle.openDir(template_sub_path, .{}) catch |err| {
3629 fatal("unable to open zig project template directory '{s}{s}{s}': {s}", .{ zig_lib_directory.path, s, template_sub_path, @errorName(err) });
3630 const path = zig_lib_directory.path orelse ".";
3631 fatal("unable to open zig project template directory '{s}{s}{s}': {s}", .{ path, s, template_sub_path, @errorName(err) });
36303632 };
36313633 defer template_dir.close();
36323634
src/register_manager.zig+1-1
......@@ -301,7 +301,7 @@ pub fn RegisterManager(
301301 /// register.
302302 pub fn getReg(self: *Self, reg: Register, inst: ?Air.Inst.Index) AllocateRegistersError!void {
303303 const index = indexOfRegIntoTracked(reg) orelse return;
304 log.debug("getReg {} for inst {}", .{ reg, inst });
304 log.debug("getReg {} for inst {?}", .{ reg, inst });
305305 self.markRegAllocated(reg);
306306
307307 if (inst) |tracked_inst|
src/translate_c.zig+7-6
......@@ -2765,7 +2765,7 @@ fn transInitListExpr(
27652765 qual_type,
27662766 ));
27672767 } else {
2768 const type_name = c.str(qual_type.getTypeClassName());
2768 const type_name = try c.str(qual_type.getTypeClassName());
27692769 return fail(c, error.UnsupportedType, source_loc, "unsupported initlist type: '{s}'", .{type_name});
27702770 }
27712771}
......@@ -4812,11 +4812,11 @@ fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clan
48124812 });
48134813 },
48144814 .BitInt, .ExtVector => {
4815 const type_name = c.str(ty.getTypeClassName());
4815 const type_name = try c.str(ty.getTypeClassName());
48164816 return fail(c, error.UnsupportedType, source_loc, "TODO implement translation of type: '{s}'", .{type_name});
48174817 },
48184818 else => {
4819 const type_name = c.str(ty.getTypeClassName());
4819 const type_name = try c.str(ty.getTypeClassName());
48204820 return fail(c, error.UnsupportedType, source_loc, "unsupported type: '{s}'", .{type_name});
48214821 },
48224822 }
......@@ -5052,8 +5052,8 @@ fn finishTransFnProto(
50525052}
50535053
50545054fn warn(c: *Context, scope: *Scope, loc: clang.SourceLocation, comptime format: []const u8, args: anytype) !void {
5055 const args_prefix = .{c.locStr(loc)};
5056 const value = try std.fmt.allocPrint(c.arena, "// {s}: warning: " ++ format, args_prefix ++ args);
5055 const str = try c.locStr(loc);
5056 const value = try std.fmt.allocPrint(c.arena, "// {s}: warning: " ++ format, .{str} ++ args);
50575057 try scope.appendNode(try Tag.warning.create(c.arena, value));
50585058}
50595059
......@@ -5073,7 +5073,8 @@ pub fn failDecl(c: *Context, loc: clang.SourceLocation, name: []const u8, compti
50735073 // pub const name = @compileError(msg);
50745074 const fail_msg = try std.fmt.allocPrint(c.arena, format, args);
50755075 try addTopLevelDecl(c, name, try Tag.fail_decl.create(c.arena, .{ .actual = name, .mangled = fail_msg }));
5076 const location_comment = try std.fmt.allocPrint(c.arena, "// {s}", .{c.locStr(loc)});
5076 const str = try c.locStr(loc);
5077 const location_comment = try std.fmt.allocPrint(c.arena, "// {s}", .{str});
50775078 try c.global_scope.nodes.append(try Tag.warning.create(c.arena, location_comment));
50785079}
50795080