aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index e5c38c8450..7326fd9bc6 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -17100,6 +17100,18 @@ fn resolvePeerTypes(
const chosen_ty = sema.typeOf(chosen);
if (candidate_ty.eql(chosen_ty))
continue;
+
+ // If the candidate can coerce into our chosen type, we're done.
+ // If the chosen type can coerce into the candidate, use that.
+ if ((try sema.coerceInMemoryAllowed(block, chosen_ty, candidate_ty, false, target, src, src)) == .ok) {
+ continue;
+ }
+ if ((try sema.coerceInMemoryAllowed(block, candidate_ty, chosen_ty, false, target, src, src)) == .ok) {
+ chosen = candidate;
+ chosen_i = candidate_i + 1;
+ continue;
+ }
+
const candidate_ty_tag = candidate_ty.zigTypeTag();
const chosen_ty_tag = chosen_ty.zigTypeTag();
@@ -17180,6 +17192,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) {
@@ -17192,6 +17228,80 @@ fn resolvePeerTypes(
}
}
+ // *[N]T to [*]T
+ if (candidate_ty.ptrSize() == .Many and
+ chosen_ty_tag == .Pointer and
+ chosen_ty.ptrSize() == .One and
+ chosen_ty.childType().zigTypeTag() == .Array)
+ {
+ chosen = candidate;
+ chosen_i = candidate_i + 1;
+
+ convert_to_slice = false;
+
+ if (chosen_ty.childType().isConstPtr() and !candidate_ty.childType().isConstPtr())
+ make_the_slice_const = true;
+
+ continue;
+ }
+
+ // *[N]T to [*]T (prev is many pointer)
+ if (candidate_ty.ptrSize() == .One and
+ candidate_ty.childType().zigTypeTag() == .Array and
+ chosen_ty_tag == .Pointer and
+ chosen_ty.ptrSize() == .Many)
+ {
+ if (candidate_ty.childType().isConstPtr() and !chosen_ty.childType().isConstPtr())
+ make_the_slice_const = true;
+
+ continue;
+ }
+
+ // *[N]T to []T (prev is slice)
+ // *[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 = 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
+
+ // If the pointer is const then we need to const
+ if (candidate_ty.childType().isConstPtr())
+ make_the_slice_const = true;
+
+ continue;
+ }
+ }
+
+ // *[N]T to []T (current is slice)
+ if (chosen_ty_tag == .Pointer and
+ chosen_ty.ptrSize() == .One and
+ chosen_ty.childType().zigTypeTag() == .Array and
+ candidate_ty.isSlice())
+ {
+ const chosen_child_ty = chosen_ty.childType();
+ const chosen_elem_ty = chosen_child_ty.elemType2();
+ const candidate_elem_ty = candidate_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;
+ }
+ }
+
// *[N]T and *[M]T
// verify both are pointers to known lengths
if (chosen_ty_tag == .Pointer and
@@ -17329,6 +17439,13 @@ fn resolvePeerTypes(
return Type.ptr(sema.arena, info.data);
}
+ if (make_the_slice_const) {
+ // turn []T => []const T
+ var info = chosen_ty.ptrInfo();
+ info.data.mutable = false;
+ return Type.ptr(sema.arena, info.data);
+ }
+
return chosen_ty;
}