Skip to content

Commit

Permalink
typeintersect: more organized innervar wrapping
Browse files Browse the repository at this point in the history
  • Loading branch information
N5N3 committed Mar 5, 2024
1 parent 6219dee commit dd459af
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 6 deletions.
42 changes: 38 additions & 4 deletions src/subtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -3018,7 +3018,8 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
}

if (vb->innervars != NULL) {
for (size_t i = 0; i < jl_array_nrows(vb->innervars); i++) {
size_t len = jl_array_nrows(vb->innervars), count = 0;
for (size_t i = 0; i < len; i++) {
jl_tvar_t *var = (jl_tvar_t*)jl_array_ptr_ref(vb->innervars, i);
// the `btemp->prev` walk is only giving a sort of post-order guarantee (since we are
// iterating 2 trees at once), so once we set `wrap`, there might remain other branches
Expand All @@ -3033,10 +3034,43 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
if (wrap->innervars == NULL)
wrap->innervars = jl_alloc_array_1d(jl_array_any_type, 0);
jl_array_ptr_1d_push(wrap->innervars, (jl_value_t*)var);
jl_array_ptr_set(vb->innervars, i, (jl_value_t*)NULL);
}
else if (res != jl_bottom_type) {
if (jl_has_typevar(res, var))
res = jl_type_unionall((jl_tvar_t*)var, res);
}
for (size_t i = 0; i < len; i++) {
jl_tvar_t *var = (jl_tvar_t*)jl_array_ptr_ref(vb->innervars, i);
if (var) {
if (count < i)
jl_array_ptr_set(vb->innervars, count, (jl_value_t*)var);
count++;
}
}
if (count != len)
jl_array_del_end(vb->innervars, len - count);
if (res != jl_bottom_type) {
while (count > 1) {
int changed = 0;
// Now need to re-sort the vb->innervars using the partial-ordering predicate `jl_has_typevar`.
// If this is slow, we could possibly switch to a simpler graph sort than this triple loop, such as Tarjan's SCC.
// But for now we use a variant on selection sort for partial-orders.
for (size_t i = 0; i < count - 1; i++) {
jl_tvar_t *vari = (jl_tvar_t*)jl_array_ptr_ref(vb->innervars, i);
for (size_t j = i+1; j < count; j++) {
jl_tvar_t *varj = (jl_tvar_t*)jl_array_ptr_ref(vb->innervars, j);
if (jl_has_typevar(varj->lb, vari) || jl_has_typevar(varj->ub, vari)) {
jl_array_ptr_set(vb->innervars, j, (jl_value_t*)vari);
jl_array_ptr_set(vb->innervars, i, (jl_value_t*)varj);
changed = 1;
break;
}
}
if (changed) break;
}
if (!changed) break;
}
for (size_t i = 0; i < count; i++) {
jl_tvar_t *var = (jl_tvar_t*)jl_array_ptr_ref(vb->innervars, i);
res = jl_type_unionall(var, res);
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions test/subtype.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1216,8 +1216,7 @@ let a = Tuple{T1,T1} where T1,
end
let a = Val{Tuple{T1,T1}} where T1,
b = Val{Tuple{Val{S2},S6}} where S2 where S6
# @testintersect(a, b, Val{Tuple{Val{T},Val{T}}} where T)
@test_broken !Base.has_free_typevars(typeintersect(b, a))
@testintersect(a, b, Val{Tuple{Val{T},Val{T}}} where T)
end
let a = Tuple{Float64,T3,T4} where T4 where T3,
b = Tuple{S2,Tuple{S3},S3} where S2 where S3
Expand Down

0 comments on commit dd459af

Please sign in to comment.