Commit 6547da8f97

Andrew Kelley <andrew@ziglang.org>
2022-03-07 05:25:45
Sema: handle peer type resolution of optional slices
1 parent 76d810c
Changed files (2)
src
test
behavior
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 => {},
         }
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);
         }