mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 14:25:16 +00:00
stage2: error union and non-error set/union peer cast resolution
This commit is contained in:
parent
38aae2cb7c
commit
b4ce855788
73
src/Sema.zig
73
src/Sema.zig
@ -17814,8 +17814,8 @@ fn resolvePeerTypes(
|
||||
err_set_ty = try err_set_ty.?.errorSetMerge(sema.arena, candidate_ty);
|
||||
continue;
|
||||
},
|
||||
.ErrorUnion => {
|
||||
if (chosen_ty_tag == .ErrorSet) {
|
||||
.ErrorUnion => switch (chosen_ty_tag) {
|
||||
.ErrorSet => {
|
||||
if (err_set_ty.?.isAnyError()) {
|
||||
chosen = candidate;
|
||||
chosen_i = candidate_i + 1;
|
||||
@ -17854,9 +17854,9 @@ fn resolvePeerTypes(
|
||||
chosen = candidate;
|
||||
chosen_i = candidate_i + 1;
|
||||
continue;
|
||||
}
|
||||
},
|
||||
|
||||
if (chosen_ty_tag == .ErrorUnion) {
|
||||
.ErrorUnion => {
|
||||
const chosen_payload_ty = chosen_ty.errorUnionPayload();
|
||||
const candidate_payload_ty = candidate_ty.errorUnionPayload();
|
||||
|
||||
@ -17926,30 +17926,57 @@ fn resolvePeerTypes(
|
||||
err_set_ty = try chosen_set_ty.errorSetMerge(sema.arena, candidate_ty);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
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) {
|
||||
.Pointer => {
|
||||
const payload_ty = candidate_ty.errorUnionPayload();
|
||||
if (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;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
else => {
|
||||
// Chosen coercing into payload type
|
||||
// Then merge error sets (if any)
|
||||
const payload_ty = candidate_ty.errorUnionPayload();
|
||||
if ((try sema.coerceInMemoryAllowed(block, payload_ty, chosen_ty, false, target, src, src)) == .ok) {
|
||||
chosen = candidate;
|
||||
chosen_i = candidate_i + 1;
|
||||
|
||||
convert_to_slice = false; // it already is a slice
|
||||
if (err_set_ty) |ty| {
|
||||
const cand_set_ty = candidate_ty.errorUnionSet();
|
||||
if (cand_set_ty.castTag(.error_set_inferred)) |inferred| {
|
||||
try sema.resolveInferredErrorSet(inferred.data);
|
||||
}
|
||||
if (cand_set_ty.isAnyError()) {
|
||||
err_set_ty = cand_set_ty;
|
||||
continue;
|
||||
}
|
||||
if (ty.isAnyError()) continue;
|
||||
|
||||
// If the prev pointer is const then we need to const
|
||||
if (chosen_child_ty.isConstPtr())
|
||||
make_the_slice_const = true;
|
||||
err_set_ty = try err_set_ty.?.errorSetMerge(sema.arena, cand_set_ty);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
.Pointer => {
|
||||
if (candidate_ty.ptrSize() == .C) {
|
||||
@ -18115,6 +18142,12 @@ fn resolvePeerTypes(
|
||||
continue;
|
||||
}
|
||||
},
|
||||
.ErrorUnion => {
|
||||
const payload_ty = chosen_ty.errorUnionPayload();
|
||||
if ((try sema.coerceInMemoryAllowed(block, payload_ty, candidate_ty, false, target, src, src)) == .ok) {
|
||||
continue;
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
|
||||
@ -705,6 +705,37 @@ test "peer type resolution: error union and error set" {
|
||||
}
|
||||
}
|
||||
|
||||
test "peer type resolution: error union after non-error" {
|
||||
const a: u32 = undefined;
|
||||
const b: error{ One, Two }!u32 = undefined;
|
||||
|
||||
// note: order of error set members doesn't member, may want to sort
|
||||
|
||||
{
|
||||
const ty = @TypeOf(a, b);
|
||||
const info = @typeInfo(ty);
|
||||
try expect(info == .ErrorUnion);
|
||||
try expect(info.ErrorUnion.payload == u32);
|
||||
|
||||
const error_set_info = @typeInfo(info.ErrorUnion.error_set);
|
||||
try expect(error_set_info.ErrorSet.?.len == 2);
|
||||
try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One"));
|
||||
try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Two"));
|
||||
}
|
||||
|
||||
{
|
||||
const ty = @TypeOf(b, a);
|
||||
const info = @typeInfo(ty);
|
||||
try expect(info == .ErrorUnion);
|
||||
try expect(info.ErrorUnion.payload == u32);
|
||||
|
||||
const error_set_info = @typeInfo(info.ErrorUnion.error_set);
|
||||
try expect(error_set_info.ErrorSet.?.len == 2);
|
||||
try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One"));
|
||||
try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Two"));
|
||||
}
|
||||
}
|
||||
|
||||
test "peer cast *[0]T to E![]const T" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user