authorgravatar for mitchell.hashimoto@gmail.comMitchell Hashimoto <mitchell.hashimoto@gmail.com> 2022-02-22 13:34:51-08:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-02-24 08:50:26+02:00
log65c04759709a64d1ad0529623bab804b97c02cbc
treee6f5af3f35fd68eaf65ff356843c012760383976
parentffb7ac6755230264b35b236a440e21381040ad3b

stage2: peer type resolution *[N]T and *[M]T to []const T


2 files changed, 58 insertions(+), 2 deletions(-)

src/Sema.zig+58
......@@ -16858,6 +16858,8 @@ fn resolvePeerTypes(
1685816858
1685916859 var chosen = instructions[0];
1686016860 var any_are_null = false;
16861 var make_the_slice_const = false;
16862 var convert_to_slice = false;
1686116863 var chosen_i: usize = 0;
1686216864 for (instructions[1..]) |candidate, candidate_i| {
1686316865 const candidate_ty = sema.typeOf(candidate);
......@@ -16955,6 +16957,46 @@ fn resolvePeerTypes(
1695516957 continue;
1695616958 }
1695716959 }
16960
16961 // *[N]T and *[M]T
16962 // verify both are pointers to known lengths
16963 if (chosen_ty_tag == .Pointer and
16964 chosen_ty.ptrSize() == .One and
16965 candidate_ty.ptrSize() == .One)
16966 {
16967 // verify both pointers are two arrays
16968 const chosen_child_ty = chosen_ty.childType();
16969 const candidate_child_ty = candidate_ty.childType();
16970 if (chosen_child_ty.zigTypeTag() == .Array and candidate_child_ty.zigTypeTag() == .Array) {
16971 // If there is a sentinel, it must match
16972 if (chosen_child_ty.sentinel()) |chosen_sentinel| {
16973 if (candidate_child_ty.sentinel()) |candidate_sentinel| {
16974 if (!chosen_sentinel.eql(candidate_sentinel, chosen_child_ty)) {
16975 continue;
16976 }
16977 } else {
16978 continue;
16979 }
16980 }
16981
16982 // If we can cerce the element types, then we can do this.
16983 const chosen_elem_ty = chosen_child_ty.elemType2();
16984 const candidate_elem_ty = candidate_child_ty.elemType2();
16985 if ((try sema.coerceInMemoryAllowed(block, candidate_elem_ty, chosen_elem_ty, false, target, src, src)) == .ok) {
16986 chosen = candidate;
16987 chosen_i = candidate_i + 1;
16988
16989 convert_to_slice = true;
16990
16991 // If one of the pointers is to const data, the slice
16992 // must also be const.
16993 if (candidate_child_ty.isConstPtr() or chosen_child_ty.isConstPtr())
16994 make_the_slice_const = true;
16995
16996 continue;
16997 }
16998 }
16999 }
1695817000 },
1695917001 .Optional => {
1696017002 var opt_child_buf: Type.Payload.ElemType = undefined;
......@@ -17037,6 +17079,22 @@ fn resolvePeerTypes(
1703717079 }
1703817080 }
1703917081
17082 if (convert_to_slice) {
17083 // turn *[N]T => []T
17084 const chosen_child_ty = chosen_ty.childType();
17085 var info = chosen_ty.ptrInfo();
17086 info.data.sentinel = chosen_child_ty.sentinel();
17087 info.data.size = .Slice;
17088 info.data.mutable = chosen_child_ty.isConstPtr() or make_the_slice_const;
17089 info.data.pointee_type = switch (chosen_child_ty.tag()) {
17090 .array => chosen_child_ty.elemType2(),
17091 .array_u8, .array_u8_sentinel_0 => Type.initTag(.u8),
17092 else => unreachable,
17093 };
17094
17095 return Type.ptr(sema.arena, info.data);
17096 }
17097
1704017098 return chosen_ty;
1704117099}
1704217100
test/behavior/cast.zig-2
......@@ -777,8 +777,6 @@ test "peer type resolve string lit with sentinel-terminated mutable slice" {
777777}
778778
779779test "peer type resolve array pointers, one of them const" {
780 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
781
782780 var array1: [4]u8 = undefined;
783781 const array2: [5]u8 = undefined;
784782 comptime try expect(@TypeOf(&array1, &array2) == []const u8);