From b1eb831aba6eec78f367053200007c867817e811 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Wed, 1 Apr 2020 01:44:14 +1100 Subject: [PATCH 1/2] std: fix mem.span* when an optional pointer is passed --- lib/std/mem.zig | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/std/mem.zig b/lib/std/mem.zig index d4d0a83f4..f54eb03d6 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -559,10 +559,14 @@ test "Span" { /// When there is both a sentinel and an array length or slice length, the /// length value is used instead of the sentinel. pub fn span(ptr: var) Span(@TypeOf(ptr)) { - const Result = Span(@TypeOf(ptr)); - if (@typeInfo(@TypeOf(ptr)) == .Optional and ptr == null) { - return null; + if (@typeInfo(@TypeOf(ptr)) == .Optional) { + if (ptr) |non_null| { + return span(non_null); + } else { + return null; + } } + const Result = Span(@TypeOf(ptr)); const l = len(ptr); if (@typeInfo(Result).Pointer.sentinel) |s| { return ptr[0..l :s]; @@ -576,16 +580,21 @@ test "span" { const ptr = @as([*:3]u16, array[0..2 :3]); testing.expect(eql(u16, span(ptr), &[_]u16{ 1, 2 })); testing.expect(eql(u16, span(&array), &[_]u16{ 1, 2, 3, 4, 5 })); + testing.expectEqual(@as(?[:0]u16, null), span(@as(?[*:0]u16, null))); } /// Same as `span`, except when there is both a sentinel and an array /// length or slice length, scans the memory for the sentinel value /// rather than using the length. pub fn spanZ(ptr: var) Span(@TypeOf(ptr)) { - const Result = Span(@TypeOf(ptr)); - if (@typeInfo(@TypeOf(ptr)) == .Optional and ptr == null) { - return null; + if (@typeInfo(@TypeOf(ptr)) == .Optional) { + if (ptr) |non_null| { + return spanZ(non_null); + } else { + return null; + } } + const Result = Span(@TypeOf(ptr)); const l = lenZ(ptr); if (@typeInfo(Result).Pointer.sentinel) |s| { return ptr[0..l :s]; @@ -599,6 +608,7 @@ test "spanZ" { const ptr = @as([*:3]u16, array[0..2 :3]); testing.expect(eql(u16, spanZ(ptr), &[_]u16{ 1, 2 })); testing.expect(eql(u16, spanZ(&array), &[_]u16{ 1, 2, 3, 4, 5 })); + testing.expectEqual(@as(?[:0]u16, null), spanZ(@as(?[*:0]u16, null))); } /// Takes a pointer to an array, an array, a sentinel-terminated pointer, From 3cf302a71d50114c44cedbe0114e513063b93302 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Wed, 1 Apr 2020 01:25:25 +1100 Subject: [PATCH 2/2] Tidy up some mem.spanZ use-sites now that null is accepted --- lib/std/debug.zig | 2 +- lib/std/os.zig | 2 +- src-self-hosted/stage2.zig | 7 +++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 35c13809f..11d808a17 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -1254,7 +1254,7 @@ pub const DebugInfo = struct { if (context.address >= seg_start and context.address < seg_end) { // Android libc uses NULL instead of an empty string to mark the // main program - context.name = if (info.dlpi_name) |dlpi_name| mem.spanZ(dlpi_name) else ""; + context.name = mem.spanZ(info.dlpi_name) orelse ""; context.base_address = info.dlpi_addr; // Stop the iteration return error.Found; diff --git a/lib/std/os.zig b/lib/std/os.zig index e9e3b449f..48d82797b 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -1078,7 +1078,7 @@ pub fn execvpe_expandArg0( mem.set(?[*:0]u8, argv_buf, null); defer { for (argv_buf) |arg| { - const arg_buf = if (arg) |ptr| mem.spanZ(ptr) else break; + const arg_buf = mem.spanZ(arg) orelse break; allocator.free(arg_buf); } allocator.free(argv_buf); diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index fcf963409..d9b763912 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -689,12 +689,11 @@ fn stage2CrossTarget( mcpu_oz: ?[*:0]const u8, dynamic_linker_oz: ?[*:0]const u8, ) !CrossTarget { - const zig_triple = if (zig_triple_oz) |zig_triple_z| mem.spanZ(zig_triple_z) else "native"; - const mcpu = if (mcpu_oz) |mcpu_z| mem.spanZ(mcpu_z) else null; - const dynamic_linker = if (dynamic_linker_oz) |dl_z| mem.spanZ(dl_z) else null; + const mcpu = mem.spanZ(mcpu_oz); + const dynamic_linker = mem.spanZ(dynamic_linker_oz); var diags: CrossTarget.ParseOptions.Diagnostics = .{}; const target: CrossTarget = CrossTarget.parse(.{ - .arch_os_abi = zig_triple, + .arch_os_abi = mem.spanZ(zig_triple_oz) orelse "native", .cpu_features = mcpu, .dynamic_linker = dynamic_linker, .diagnostics = &diags,