From 6547da8f97b94453fb08f582c2c7ce4eb1782a80 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 6 Mar 2022 21:25:45 -0700 Subject: [PATCH] Sema: handle peer type resolution of optional slices --- src/Sema.zig | 30 +++++++++++++++++++++++++----- test/behavior/slice.zig | 12 +++++++----- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index fb7209ae0e..b0bf3c4a23 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -18383,6 +18383,24 @@ fn resolvePeerTypes( continue; } }, + .Optional => { + var opt_child_buf: Type.Payload.ElemType = undefined; + const chosen_ptr_ty = chosen_ty.optionalChild(&opt_child_buf); + if (chosen_ptr_ty.zigTypeTag() == .Pointer) { + const chosen_info = chosen_ptr_ty.ptrInfo().data; + + seen_const = seen_const or !chosen_info.mutable or !cand_info.mutable; + + // *[N]T to ?![*]T + // *[N]T to ?![]T + if (cand_info.size == .One and + cand_info.pointee_type.zigTypeTag() == .Array and + (chosen_info.size == .Many or chosen_info.size == .Slice)) + { + continue; + } + } + }, .ErrorUnion => { const chosen_ptr_ty = chosen_ty.errorUnionPayload(); if (chosen_ptr_ty.zigTypeTag() == .Pointer) { @@ -18406,15 +18424,17 @@ fn resolvePeerTypes( .Optional => { var opt_child_buf: Type.Payload.ElemType = undefined; const opt_child_ty = candidate_ty.optionalChild(&opt_child_buf); - if ((try sema.coerceInMemoryAllowed(block, opt_child_ty, chosen_ty, false, target, src, src)) == .ok) { - chosen = candidate; - chosen_i = candidate_i + 1; - continue; - } if ((try sema.coerceInMemoryAllowed(block, chosen_ty, opt_child_ty, false, target, src, src)) == .ok) { + seen_const = seen_const or opt_child_ty.isConstPtr(); any_are_null = true; continue; } + + seen_const = seen_const or chosen_ty.isConstPtr(); + any_are_null = false; + chosen = candidate; + chosen_i = candidate_i + 1; + continue; }, else => {}, } diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index 740eaefc90..f5421f9159 100644 --- a/test/behavior/slice.zig +++ b/test/behavior/slice.zig @@ -333,17 +333,15 @@ test "obtaining a null terminated slice" { } test "empty array to slice" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - const S = struct { fn doTheTest() !void { const empty: []align(16) u8 = &[_]u8{}; const align_1: []align(1) u8 = empty; const align_4: []align(4) u8 = empty; const align_16: []align(16) u8 = empty; - try expectEqual(1, @typeInfo(@TypeOf(align_1)).Pointer.alignment); - try expectEqual(4, @typeInfo(@TypeOf(align_4)).Pointer.alignment); - try expectEqual(16, @typeInfo(@TypeOf(align_16)).Pointer.alignment); + try expect(1 == @typeInfo(@TypeOf(align_1)).Pointer.alignment); + try expect(4 == @typeInfo(@TypeOf(align_4)).Pointer.alignment); + try expect(16 == @typeInfo(@TypeOf(align_16)).Pointer.alignment); } }; @@ -478,6 +476,10 @@ test "slice syntax resulting in pointer-to-array" { var array: [2]u8 = [2]u8{ 1, 2 }; var slice: ?[]u8 = &array; comptime try expect(@TypeOf(&array, slice) == ?[]u8); + if (builtin.zig_backend != .stage1) { + // stage1 is not passing this case + comptime try expect(@TypeOf(slice, &array) == ?[]u8); + } comptime try expect(@TypeOf(slice.?[0..2]) == *[2]u8); }