Commit 1019181982

Mitchell Hashimoto <mitchell.hashimoto@gmail.com>
2022-02-25 22:33:11
stage2: *[N]T and E![]T
1 parent 117ef22
Changed files (2)
src
test
behavior
src/Sema.zig
@@ -17073,6 +17073,30 @@ fn resolvePeerTypes(
                 },
                 else => {},
             },
+            .ErrorUnion => {
+                const payload_ty = candidate_ty.errorUnionPayload();
+                if (chosen_ty_tag == .Pointer and
+                    chosen_ty.ptrSize() == .One and
+                    chosen_ty.childType().zigTypeTag() == .Array and
+                    payload_ty.isSlice())
+                {
+                    const chosen_child_ty = chosen_ty.childType();
+                    const chosen_elem_ty = chosen_child_ty.elemType2();
+                    const candidate_elem_ty = payload_ty.elemType2();
+                    if ((try sema.coerceInMemoryAllowed(block, candidate_elem_ty, chosen_elem_ty, false, target, src, src)) == .ok) {
+                        chosen = candidate;
+                        chosen_i = candidate_i + 1;
+
+                        convert_to_slice = false; // it already is a slice
+
+                        // If the prev pointer is const then we need to const
+                        if (chosen_child_ty.isConstPtr())
+                            make_the_slice_const = true;
+
+                        continue;
+                    }
+                }
+            },
             .Pointer => {
                 if (candidate_ty.ptrSize() == .C) {
                     if (chosen_ty_tag == .Int or chosen_ty_tag == .ComptimeInt) {
@@ -17086,11 +17110,15 @@ fn resolvePeerTypes(
                 }
 
                 // *[N]T to []T (prev is slice)
-                if (chosen_ty.isSlice() and
+                // *[N]T to E![]T
+                if ((chosen_ty.isSlice() or (chosen_ty_tag == .ErrorUnion and chosen_ty.errorUnionPayload().isSlice())) and
                     candidate_ty.ptrSize() == .One and
                     candidate_ty.childType().zigTypeTag() == .Array)
                 {
-                    const chosen_elem_ty = chosen_ty.elemType2();
+                    const chosen_elem_ty = switch (chosen_ty_tag) {
+                        .ErrorUnion => chosen_ty.errorUnionPayload().elemType2(),
+                        else => chosen_ty.elemType2(),
+                    };
                     const candidate_elem_ty = candidate_ty.childType().elemType2();
                     if ((try sema.coerceInMemoryAllowed(block, candidate_elem_ty, chosen_elem_ty, false, target, src, src)) == .ok) {
                         convert_to_slice = false; // it already is a slice
test/behavior/cast.zig
@@ -358,8 +358,6 @@ fn testCastIntToErr(err: anyerror) !void {
 }
 
 test "peer resolve array and const slice" {
-    if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
-
     try testPeerResolveArrayConstSlice(true);
     comptime try testPeerResolveArrayConstSlice(true);
 }
@@ -492,8 +490,6 @@ fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
 }
 
 test "single-item pointer of array to slice to unknown length pointer" {
-    if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
-
     try testCastPtrOfArrayToSliceAndPtr();
     comptime try testCastPtrOfArrayToSliceAndPtr();
 }
@@ -607,18 +603,16 @@ test "peer type resolution: unreachable, error set, unreachable" {
 }
 
 test "peer cast *[0]T to E![]const T" {
-    if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
-
     var buffer: [5]u8 = "abcde".*;
     var buf: anyerror![]const u8 = buffer[0..];
     var b = false;
     var y = if (b) &[0]u8{} else buf;
+    var z = if (!b) buf else &[0]u8{};
     try expect(mem.eql(u8, "abcde", y catch unreachable));
+    try expect(mem.eql(u8, "abcde", z catch unreachable));
 }
 
 test "peer cast *[0]T to []const T" {
-    if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
-
     var buffer: [5]u8 = "abcde".*;
     var buf: []const u8 = buffer[0..];
     var b = false;
@@ -744,8 +738,6 @@ test "peer type resolution implicit cast to variable type" {
 }
 
 test "variable initialization uses result locations properly with regards to the type" {
-    if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
-
     var b = true;
     const x: i32 = if (b) 1 else 2;
     try expect(x == 1);