Skip to content

Commit 679d9b4

Browse files
N5N3kpamnany
authored andcommitted
Subtype: enable more Tuple related fast path. (JuliaLang#58196)
Fix the subtyping hang found in JuliaLang#58115 (comment)
1 parent 37cdbd8 commit 679d9b4

File tree

2 files changed

+33
-9
lines changed

2 files changed

+33
-9
lines changed

src/subtype.c

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,7 +1012,8 @@ static int forall_exists_equal(jl_value_t *x, jl_value_t *y, jl_stenv_t *e);
10121012

10131013
static int subtype_tuple_varargs(
10141014
jl_vararg_t *vtx, jl_vararg_t *vty,
1015-
size_t vx, size_t vy,
1015+
jl_value_t *lastx, jl_value_t *lasty,
1016+
size_t vx, size_t vy, size_t x_reps,
10161017
jl_stenv_t *e, int param)
10171018
{
10181019
jl_value_t *xp0 = jl_unwrap_vararg(vtx); jl_value_t *xp1 = jl_unwrap_vararg_num(vtx);
@@ -1063,12 +1064,30 @@ static int subtype_tuple_varargs(
10631064
}
10641065
}
10651066
}
1066-
1067-
// in Vararg{T1} <: Vararg{T2}, need to check subtype twice to
1068-
// simulate the possibility of multiple arguments, which is needed
1069-
// to implement the diagonal rule correctly.
1070-
if (!subtype(xp0, yp0, e, param)) return 0;
1071-
if (!subtype(xp0, yp0, e, 1)) return 0;
1067+
int x_same = vx > 1 || (lastx && obviously_egal(xp0, lastx));
1068+
int y_same = vy > 1 || (lasty && obviously_egal(yp0, lasty));
1069+
// keep track of number of consecutive identical subtyping
1070+
x_reps = y_same && x_same ? x_reps + 1 : 1;
1071+
if (x_reps > 2) {
1072+
// an identical type on the left doesn't need to be compared to the same
1073+
// element type on the right more than twice.
1074+
}
1075+
else if (x_same && e->Runions.depth == 0 && y_same &&
1076+
!jl_has_free_typevars(xp0) && !jl_has_free_typevars(yp0)) {
1077+
// fast path for repeated elements
1078+
}
1079+
else if ((e->Runions.depth == 0 ? !jl_has_free_typevars(xp0) : jl_is_concrete_type(xp0)) && !jl_has_free_typevars(yp0)) {
1080+
// fast path for separable sub-formulas
1081+
if (!jl_subtype(xp0, yp0))
1082+
return 0;
1083+
}
1084+
else {
1085+
// in Vararg{T1} <: Vararg{T2}, need to check subtype twice to
1086+
// simulate the possibility of multiple arguments, which is needed
1087+
// to implement the diagonal rule correctly.
1088+
if (!subtype(xp0, yp0, e, param)) return 0;
1089+
if (x_reps < 2 && !subtype(xp0, yp0, e, 1)) return 0;
1090+
}
10721091

10731092
constrain_length:
10741093
if (!yp1) {
@@ -1192,7 +1211,8 @@ static int subtype_tuple_tail(jl_datatype_t *xd, jl_datatype_t *yd, int8_t R, jl
11921211
return subtype_tuple_varargs(
11931212
(jl_vararg_t*)xi,
11941213
(jl_vararg_t*)yi,
1195-
vx, vy, e, param);
1214+
lastx, lasty,
1215+
vx, vy, x_reps, e, param);
11961216
}
11971217

11981218
if (j >= ly)
@@ -1213,7 +1233,7 @@ static int subtype_tuple_tail(jl_datatype_t *xd, jl_datatype_t *yd, int8_t R, jl
12131233
(yi == lastx && !vx && vy && jl_is_concrete_type(xi)))) {
12141234
// fast path for repeated elements
12151235
}
1216-
else if (e->Runions.depth == 0 && !jl_has_free_typevars(xi) && !jl_has_free_typevars(yi)) {
1236+
else if ((e->Runions.depth == 0 ? !jl_has_free_typevars(xi) : jl_is_concrete_type(xi)) && !jl_has_free_typevars(yi)) {
12171237
// fast path for separable sub-formulas
12181238
if (!jl_subtype(xi, yi))
12191239
return 0;

test/subtype.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2597,3 +2597,7 @@ let S = Type{T53371{A, B, C, D, E}} where {A, B<:R53371{A}, C<:R53371{A}, D<:R53
25972597
T = Type{T53371{A, B, C, D, E} where {A, B<:R53371{A}, C<:R53371{A}, D<:R53371{A}, E<:R53371{A}}}
25982598
@test !(S <: T)
25992599
end
2600+
2601+
#issue 58115
2602+
@test Tuple{Tuple{Vararg{Tuple{Vararg{Tuple{Vararg{Tuple{Vararg{Tuple{Vararg{ Union{Tuple{}, Tuple{Tuple{}}}}}}}}}}}}} , Tuple{}} <:
2603+
Tuple{Tuple{Vararg{Tuple{Vararg{Tuple{Vararg{Tuple{Vararg{Tuple{Vararg{Tuple{Vararg{Union{Tuple{}, Tuple{Tuple{}}}}}}}}}}}}}}}, Tuple{}}

0 commit comments

Comments
 (0)