Skip to content

Commit 9e14600

Browse files
committed
subtype: add repeating/separable fast path into subtype_vararg
fix JuliaLang#58115
1 parent ff0a931 commit 9e14600

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

src/subtype.c

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

10701070
static int subtype_tuple_varargs(
10711071
jl_vararg_t *vtx, jl_vararg_t *vty,
1072-
size_t vx, size_t vy,
1072+
jl_value_t *lastx, jl_value_t *lasty,
1073+
size_t vx, size_t vy, size_t x_reps,
10731074
jl_stenv_t *e, int param)
10741075
{
10751076
jl_value_t *xp0 = jl_unwrap_vararg(vtx); jl_value_t *xp1 = jl_unwrap_vararg_num(vtx);
@@ -1111,12 +1112,30 @@ static int subtype_tuple_varargs(
11111112
}
11121113
}
11131114
}
1114-
1115-
// in Vararg{T1} <: Vararg{T2}, need to check subtype twice to
1116-
// simulate the possibility of multiple arguments, which is needed
1117-
// to implement the diagonal rule correctly.
1118-
if (!subtype(xp0, yp0, e, param)) return 0;
1119-
if (!subtype(xp0, yp0, e, 1)) return 0;
1115+
int x_same = vx > 1 || (lastx && obviously_egal(xp0, lastx));
1116+
int y_same = vy > 1 || (lasty && obviously_egal(yp0, lasty));
1117+
// keep track of number of consecutive identical subtyping
1118+
x_reps = y_same && x_same ? x_reps + 1 : 1;
1119+
if (x_reps > 2) {
1120+
// an identical type on the left doesn't need to be compared to the same
1121+
// element type on the right more than twice.
1122+
}
1123+
else if (x_same && e->Runions.depth == 0 && y_same &&
1124+
!jl_has_free_typevars(xp0) && !jl_has_free_typevars(yp0)) {
1125+
// fast path for repeated elements
1126+
}
1127+
else if (e->Runions.depth == 0 && !jl_has_free_typevars(xp0) && !jl_has_free_typevars(yp0)) {
1128+
// fast path for separable sub-formulas
1129+
if (!jl_subtype(xp0, yp0))
1130+
return 0;
1131+
}
1132+
else {
1133+
// in Vararg{T1} <: Vararg{T2}, need to check subtype twice to
1134+
// simulate the possibility of multiple arguments, which is needed
1135+
// to implement the diagonal rule correctly.
1136+
if (!subtype(xp0, yp0, e, param)) return 0;
1137+
if (x_reps < 2 && !subtype(xp0, yp0, e, 1)) return 0;
1138+
}
11201139

11211140
constrain_length:
11221141
if (!yp1) {
@@ -1246,7 +1265,8 @@ static int subtype_tuple_tail(jl_datatype_t *xd, jl_datatype_t *yd, int8_t R, jl
12461265
return subtype_tuple_varargs(
12471266
(jl_vararg_t*)xi,
12481267
(jl_vararg_t*)yi,
1249-
vx, vy, e, param);
1268+
lastx, lasty,
1269+
vx, vy, x_reps, e, param);
12501270
}
12511271

12521272
if (j >= ly)

test/subtype.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2782,3 +2782,7 @@ let Tvar1 = TypeVar(:Tvar1), Tvar2 = TypeVar(:Tvar2)
27822782
V2 = UnionAll(Tvar2, Union{(@eval($(Symbol(:T58129, k)){$Tvar2}) for k in 1:100)...})
27832783
@test Set{<:V2} <: AbstractSet{<:V1}
27842784
end
2785+
2786+
#issue 58115
2787+
@test Tuple{Tuple{Vararg{Tuple{Vararg{Tuple{Vararg{Tuple{Vararg{Tuple{Vararg{ Union{Tuple{}, Tuple{Tuple{}}}}}}}}}}}}} , Tuple{}} <:
2788+
Tuple{Tuple{Vararg{Tuple{Vararg{Tuple{Vararg{Tuple{Vararg{Tuple{Vararg{Tuple{Vararg{Union{Tuple{}, Tuple{Tuple{}}}}}}}}}}}}}}}, Tuple{}}

0 commit comments

Comments
 (0)