diff --git a/src/Sema.zig b/src/Sema.zig index 62523a6a01..a03db84d2c 100644 --- a/src/Sema.zig +++ b/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 diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 0ddbf6458a..e37f1fb974 100644 --- a/test/behavior/cast.zig +++ b/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);