diff --git a/doc/langref.html.in b/doc/langref.html.in index 13c7da4a8a..81ccd58261 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -574,7 +574,7 @@ pub fn main() void { var optional_value: ?[]const u8 = null; assert(optional_value == null); - print("\noptional 1\ntype: {s}\nvalue: {s}\n", .{ + print("\noptional 1\ntype: {s}\nvalue: {?s}\n", .{ @typeName(@TypeOf(optional_value)), optional_value, }); @@ -582,7 +582,7 @@ pub fn main() void { optional_value = "hi"; assert(optional_value != null); - print("\noptional 2\ntype: {s}\nvalue: {s}\n", .{ + print("\noptional 2\ntype: {s}\nvalue: {?s}\n", .{ @typeName(@TypeOf(optional_value)), optional_value, }); @@ -590,14 +590,14 @@ pub fn main() void { // error union var number_or_error: anyerror!i32 = error.ArgNotFound; - print("\nerror union 1\ntype: {s}\nvalue: {}\n", .{ + print("\nerror union 1\ntype: {s}\nvalue: {!}\n", .{ @typeName(@TypeOf(number_or_error)), number_or_error, }); number_or_error = 1234; - print("\nerror union 2\ntype: {s}\nvalue: {}\n", .{ + print("\nerror union 2\ntype: {s}\nvalue: {!}\n", .{ @typeName(@TypeOf(number_or_error)), number_or_error, }); diff --git a/lib/std/build.zig b/lib/std/build.zig index 83e30b278f..e20f793209 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -750,7 +750,7 @@ pub const Builder = struct { \\Available CPU features for architecture '{s}': \\ , .{ - diags.unknown_feature_name, + diags.unknown_feature_name.?, @tagName(diags.arch.?), }); for (diags.arch.?.allFeaturesList()) |feature| { @@ -764,7 +764,7 @@ pub const Builder = struct { \\Unknown OS: '{s}' \\Available operating systems: \\ - , .{diags.os_name}); + , .{diags.os_name.?}); inline for (std.meta.fields(std.Target.Os.Tag)) |field| { log.err(" {s}", .{field.name}); } diff --git a/lib/std/crypto/phc_encoding.zig b/lib/std/crypto/phc_encoding.zig index 69324dc5b3..a3796dc436 100644 --- a/lib/std/crypto/phc_encoding.zig +++ b/lib/std/crypto/phc_encoding.zig @@ -216,7 +216,7 @@ fn serializeTo(params: anytype, out: anytype) !void { var has_params = false; inline for (comptime meta.fields(HashResult)) |p| { - if (!(mem.eql(u8, p.name, "alg_id") or + if (comptime !(mem.eql(u8, p.name, "alg_id") or mem.eql(u8, p.name, "alg_version") or mem.eql(u8, p.name, "hash") or mem.eql(u8, p.name, "salt"))) diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index a506d8f395..52f0cb4841 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -60,8 +60,10 @@ pub const FormatOptions = struct { /// - `o`: output integer value in octal notation /// - `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 optional value as either the unwrapped value, or `null`; may be followed by a format specifier for the underlying value. +/// - `!`: 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. /// - `*`: output the address of the value instead of the value itself. -/// - `any`: output a value of any type using its default format +/// - `any`: output a value of any type using its default format. /// /// If a formatted user type contains a function of the type /// ``` @@ -438,12 +440,20 @@ fn defaultSpec(comptime T: type) [:0]const u8 { .Many, .C => return "*", .Slice => return ANY, }, - .Optional => |info| return defaultSpec(info.child), + .Optional => |info| return "?" ++ defaultSpec(info.child), + .ErrorUnion => |info| return "!" ++ defaultSpec(info.payload), else => {}, } return ""; } +fn stripOptionalOrErrorUnionSpec(comptime fmt: []const u8) []const u8 { + return if (std.mem.eql(u8, fmt[1..], ANY)) + ANY + else + fmt[1..]; +} + pub fn formatType( value: anytype, comptime fmt: []const u8, @@ -451,12 +461,18 @@ pub fn formatType( writer: anytype, max_depth: usize, ) @TypeOf(writer).Error!void { - const actual_fmt = comptime if (std.mem.eql(u8, fmt, ANY)) defaultSpec(@TypeOf(value)) else fmt; + const T = @TypeOf(value); + const actual_fmt = comptime if (std.mem.eql(u8, fmt, ANY)) + defaultSpec(@TypeOf(value)) + else if (fmt.len != 0 and (fmt[0] == '?' or fmt[0] == '!')) switch (@typeInfo(T)) { + .Optional, .ErrorUnion => fmt, + else => stripOptionalOrErrorUnionSpec(fmt), + } 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(actual_fmt, options, writer); } @@ -472,17 +488,23 @@ pub fn formatType( return formatBuf(if (value) "true" else "false", options, writer); }, .Optional => { + if (actual_fmt.len == 0 or actual_fmt[0] != '?') + @compileError("cannot format optional without a specifier (i.e. {?} or {any})"); + const remaining_fmt = comptime stripOptionalOrErrorUnionSpec(actual_fmt); if (value) |payload| { - return formatType(payload, actual_fmt, options, writer, max_depth); + return formatType(payload, remaining_fmt, options, writer, max_depth); } else { return formatBuf("null", options, writer); } }, .ErrorUnion => { + if (actual_fmt.len == 0 or actual_fmt[0] != '!') + @compileError("cannot format error union without a specifier (i.e. {!} or {any})"); + const remaining_fmt = comptime stripOptionalOrErrorUnionSpec(actual_fmt); if (value) |payload| { - return formatType(payload, actual_fmt, options, writer, max_depth); + return formatType(payload, remaining_fmt, options, writer, max_depth); } else |err| { - return formatType(err, actual_fmt, options, writer, max_depth); + return formatType(err, remaining_fmt, options, writer, max_depth); } }, .ErrorSet => { @@ -1977,11 +1999,11 @@ test "escaped braces" { test "optional" { { const value: ?i32 = 1234; - try expectFmt("optional: 1234\n", "optional: {}\n", .{value}); + try expectFmt("optional: 1234\n", "optional: {?}\n", .{value}); } { const value: ?i32 = null; - try expectFmt("optional: null\n", "optional: {}\n", .{value}); + try expectFmt("optional: null\n", "optional: {?}\n", .{value}); } { const value = @intToPtr(?*i32, 0xf000d000); @@ -1992,11 +2014,11 @@ test "optional" { test "error" { { const value: anyerror!i32 = 1234; - try expectFmt("error union: 1234\n", "error union: {}\n", .{value}); + try expectFmt("error union: 1234\n", "error union: {!}\n", .{value}); } { const value: anyerror!i32 = error.InvalidChar; - try expectFmt("error union: error.InvalidChar\n", "error union: {}\n", .{value}); + try expectFmt("error union: error.InvalidChar\n", "error union: {!}\n", .{value}); } } diff --git a/lib/std/x/os/net.zig b/lib/std/x/os/net.zig index d9eb910b79..d8af2b3577 100644 --- a/lib/std/x/os/net.zig +++ b/lib/std/x/os/net.zig @@ -544,7 +544,7 @@ test "ip: convert to and from ipv6" { try testing.expect(IPv4.localhost.mapToIPv6().mapsToIPv4()); try testing.expect(IPv4.localhost.toIPv6().toIPv4() == null); - try testing.expectFmt("127.0.0.1", "{}", .{IPv4.localhost.mapToIPv6().toIPv4()}); + try testing.expectFmt("127.0.0.1", "{?}", .{IPv4.localhost.mapToIPv6().toIPv4()}); } test "ipv4: parse & format" { diff --git a/src/Cache.zig b/src/Cache.zig index 0d4b51492d..829d903e5a 100644 --- a/src/Cache.zig +++ b/src/Cache.zig @@ -747,7 +747,7 @@ pub const Manifest = struct { file.stat.inode, file.stat.mtime, &encoded_digest, - file.path, + file.path.?, }); } diff --git a/src/Compilation.zig b/src/Compilation.zig index 5204910193..300a02a881 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1465,7 +1465,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .handle = artifact_dir, .path = try options.local_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}), }; - log.debug("zig_cache_artifact_directory='{s}' use_stage1={}", .{ + log.debug("zig_cache_artifact_directory='{?s}' use_stage1={}", .{ zig_cache_artifact_directory.path, use_stage1, }); diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 0f2cbfa844..b90bc8bdee 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -363,7 +363,7 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO { // Create dSYM bundle. const dir = options.module.?.zig_cache_artifact_directory; - log.debug("creating {s}.dSYM bundle in {s}", .{ emit.sub_path, dir.path }); + log.debug("creating {s}.dSYM bundle in {?s}", .{ emit.sub_path, dir.path }); const d_sym_path = try fmt.allocPrint( allocator, diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 41ee8392ec..30e2192268 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -1629,7 +1629,7 @@ fn setupMemory(self: *Wasm) !void { return error.MemoryTooBig; } self.memories.limits.max = @intCast(u32, max_memory / page_size); - log.debug("Maximum memory pages: {d}", .{self.memories.limits.max}); + log.debug("Maximum memory pages: {?d}", .{self.memories.limits.max}); } } diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig index 9dba838d27..a1308ec045 100644 --- a/src/link/Wasm/Object.zig +++ b/src/link/Wasm/Object.zig @@ -548,7 +548,7 @@ fn Parser(comptime ReaderType: type) type { .index = try leb.readULEB128(u32, reader), .addend = if (rel_type_enum.addendIsPresent()) try leb.readULEB128(u32, reader) else null, }; - log.debug("Found relocation: type({s}) offset({d}) index({d}) addend({d})", .{ + log.debug("Found relocation: type({s}) offset({d}) index({d}) addend({?d})", .{ @tagName(relocation.relocation_type), relocation.offset, relocation.index, diff --git a/src/main.zig b/src/main.zig index 27682003f2..c9b9d1c0af 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3168,7 +3168,7 @@ fn parseCrossTargetOrReportFatalError( @tagName(diags.arch.?), help_text.items, }); } - fatal("Unknown CPU feature: '{s}'", .{diags.unknown_feature_name}); + fatal("Unknown CPU feature: '{s}'", .{diags.unknown_feature_name.?}); }, else => |e| return e, }; @@ -3496,7 +3496,8 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, enable_cache: bool, stage } else { const out_zig_path = try fs.path.join(arena, &[_][]const u8{ "o", &digest, translated_zig_basename }); const zig_file = comp.local_cache_directory.handle.openFile(out_zig_path, .{}) catch |err| { - 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) }); + const path = comp.local_cache_directory.path orelse "."; + fatal("unable to open cached translated zig file '{s}{s}{s}': {s}", .{ path, fs.path.sep_str, out_zig_path, @errorName(err) }); }; defer zig_file.close(); try io.getStdOut().writeFileAll(zig_file, .{}); @@ -3626,7 +3627,8 @@ pub fn cmdInit( .Exe => "init-exe", }; var template_dir = zig_lib_directory.handle.openDir(template_sub_path, .{}) catch |err| { - fatal("unable to open zig project template directory '{s}{s}{s}': {s}", .{ zig_lib_directory.path, s, template_sub_path, @errorName(err) }); + const path = zig_lib_directory.path orelse "."; + fatal("unable to open zig project template directory '{s}{s}{s}': {s}", .{ path, s, template_sub_path, @errorName(err) }); }; defer template_dir.close(); diff --git a/src/register_manager.zig b/src/register_manager.zig index 0bd9ef62e9..0ab9d103b8 100644 --- a/src/register_manager.zig +++ b/src/register_manager.zig @@ -301,7 +301,7 @@ pub fn RegisterManager( /// register. pub fn getReg(self: *Self, reg: Register, inst: ?Air.Inst.Index) AllocateRegistersError!void { const index = indexOfRegIntoTracked(reg) orelse return; - log.debug("getReg {} for inst {}", .{ reg, inst }); + log.debug("getReg {} for inst {?}", .{ reg, inst }); self.markRegAllocated(reg); if (inst) |tracked_inst| diff --git a/src/translate_c.zig b/src/translate_c.zig index 53481c8f5d..a64d00829a 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -2765,7 +2765,7 @@ fn transInitListExpr( qual_type, )); } else { - const type_name = c.str(qual_type.getTypeClassName()); + const type_name = try c.str(qual_type.getTypeClassName()); return fail(c, error.UnsupportedType, source_loc, "unsupported initlist type: '{s}'", .{type_name}); } } @@ -4812,11 +4812,11 @@ fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clan }); }, .BitInt, .ExtVector => { - const type_name = c.str(ty.getTypeClassName()); + const type_name = try c.str(ty.getTypeClassName()); return fail(c, error.UnsupportedType, source_loc, "TODO implement translation of type: '{s}'", .{type_name}); }, else => { - const type_name = c.str(ty.getTypeClassName()); + const type_name = try c.str(ty.getTypeClassName()); return fail(c, error.UnsupportedType, source_loc, "unsupported type: '{s}'", .{type_name}); }, } @@ -5052,8 +5052,8 @@ fn finishTransFnProto( } fn warn(c: *Context, scope: *Scope, loc: clang.SourceLocation, comptime format: []const u8, args: anytype) !void { - const args_prefix = .{c.locStr(loc)}; - const value = try std.fmt.allocPrint(c.arena, "// {s}: warning: " ++ format, args_prefix ++ args); + const str = try c.locStr(loc); + const value = try std.fmt.allocPrint(c.arena, "// {s}: warning: " ++ format, .{str} ++ args); try scope.appendNode(try Tag.warning.create(c.arena, value)); } @@ -5073,7 +5073,8 @@ pub fn failDecl(c: *Context, loc: clang.SourceLocation, name: []const u8, compti // pub const name = @compileError(msg); const fail_msg = try std.fmt.allocPrint(c.arena, format, args); try addTopLevelDecl(c, name, try Tag.fail_decl.create(c.arena, .{ .actual = name, .mangled = fail_msg })); - const location_comment = try std.fmt.allocPrint(c.arena, "// {s}", .{c.locStr(loc)}); + const str = try c.locStr(loc); + const location_comment = try std.fmt.allocPrint(c.arena, "// {s}", .{str}); try c.global_scope.nodes.append(try Tag.warning.create(c.arena, location_comment)); }