Skip to content

Commit 02f27c2

Browse files
committed
typeintersect: more organized innervar wrapping
1 parent a556af2 commit 02f27c2

File tree

2 files changed

+42
-7
lines changed

2 files changed

+42
-7
lines changed

src/subtype.c

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2849,7 +2849,7 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
28492849

28502850
// I. Handle indirect innervars (make them behave like direct innervars).
28512851
// 1) record if btemp->lb/ub has indirect innervars.
2852-
// 2) substitute `vb->var` with `varval`/`varval`
2852+
// 2) substitute `vb->var` with `varval`/`newvar`
28532853
// note: We only store the innervar in the outmost `varbinding`,
28542854
// thus we must check all inner env to ensure the recording/substitution
28552855
// is complete
@@ -2913,6 +2913,7 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
29132913
}
29142914
envind++;
29152915
}
2916+
// FIXME: innervar that depend on `ivar` should also be updated.
29162917
}
29172918
}
29182919
}
@@ -3028,7 +3029,8 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
30283029
}
30293030

30303031
if (vb->innervars != NULL) {
3031-
for (size_t i = 0; i < jl_array_nrows(vb->innervars); i++) {
3032+
size_t len = jl_array_nrows(vb->innervars), count = 0;
3033+
for (size_t i = 0; i < len; i++) {
30323034
jl_tvar_t *var = (jl_tvar_t*)jl_array_ptr_ref(vb->innervars, i);
30333035
// the `btemp->prev` walk is only giving a sort of post-order guarantee (since we are
30343036
// iterating 2 trees at once), so once we set `wrap`, there might remain other branches
@@ -3042,11 +3044,45 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
30423044
if (wrap) {
30433045
if (wrap->innervars == NULL)
30443046
wrap->innervars = jl_alloc_array_1d(jl_array_any_type, 0);
3047+
// FIXME: `var`'s dependence should also be pushed into `wrap->innervars`.
30453048
jl_array_ptr_1d_push(wrap->innervars, (jl_value_t*)var);
3049+
jl_array_ptr_set(vb->innervars, i, (jl_value_t*)NULL);
30463050
}
3047-
else if (res != jl_bottom_type) {
3048-
if (jl_has_typevar(res, var))
3049-
res = jl_type_unionall((jl_tvar_t*)var, res);
3051+
}
3052+
for (size_t i = 0; i < len; i++) {
3053+
jl_tvar_t *var = (jl_tvar_t*)jl_array_ptr_ref(vb->innervars, i);
3054+
if (var) {
3055+
if (count < i)
3056+
jl_array_ptr_set(vb->innervars, count, (jl_value_t*)var);
3057+
count++;
3058+
}
3059+
}
3060+
if (count != len)
3061+
jl_array_del_end(vb->innervars, len - count);
3062+
if (res != jl_bottom_type) {
3063+
while (count > 1) {
3064+
int changed = 0;
3065+
// Now need to re-sort the vb->innervars using the partial-ordering predicate `jl_has_typevar`.
3066+
// If this is slow, we could possibly switch to a simpler graph sort than this triple loop, such as Tarjan's SCC.
3067+
// But for now we use a variant on selection sort for partial-orders.
3068+
for (size_t i = 0; i < count - 1; i++) {
3069+
jl_tvar_t *vari = (jl_tvar_t*)jl_array_ptr_ref(vb->innervars, i);
3070+
for (size_t j = i+1; j < count; j++) {
3071+
jl_tvar_t *varj = (jl_tvar_t*)jl_array_ptr_ref(vb->innervars, j);
3072+
if (jl_has_typevar(varj->lb, vari) || jl_has_typevar(varj->ub, vari)) {
3073+
jl_array_ptr_set(vb->innervars, j, (jl_value_t*)vari);
3074+
jl_array_ptr_set(vb->innervars, i, (jl_value_t*)varj);
3075+
changed = 1;
3076+
break;
3077+
}
3078+
}
3079+
if (changed) break;
3080+
}
3081+
if (!changed) break;
3082+
}
3083+
for (size_t i = 0; i < count; i++) {
3084+
jl_tvar_t *var = (jl_tvar_t*)jl_array_ptr_ref(vb->innervars, i);
3085+
res = jl_type_unionall(var, res);
30503086
}
30513087
}
30523088
}

test/subtype.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,8 +1216,7 @@ let a = Tuple{T1,T1} where T1,
12161216
end
12171217
let a = Val{Tuple{T1,T1}} where T1,
12181218
b = Val{Tuple{Val{S2},S6}} where S2 where S6
1219-
# @testintersect(a, b, Val{Tuple{Val{T},Val{T}}} where T)
1220-
@test_broken !Base.has_free_typevars(typeintersect(b, a))
1219+
@testintersect(a, b, Val{Tuple{Val{T},Val{T}}} where T)
12211220
end
12221221
let a = Tuple{Float64,T3,T4} where T4 where T3,
12231222
b = Tuple{S2,Tuple{S3},S3} where S2 where S3

0 commit comments

Comments
 (0)