Skip to content

Commit

Permalink
Subtype: skip more identical check for X::Tuple <: Y::Tuple
Browse files Browse the repository at this point in the history
Should improve the performance where `Y` has fixed length.

Fix the example from JuliaLang#39967.
The root cause there is a exponential growth in Left union.
Fortunately, we won't encounter this problem for concrete `X`,
as there's no 0-depth `Union`.
  • Loading branch information
N5N3 committed Feb 5, 2023
1 parent 36d035c commit 3d0278b
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 12 deletions.
20 changes: 8 additions & 12 deletions src/subtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -1081,7 +1081,7 @@ static int subtype_tuple_tail(jl_datatype_t *xd, jl_datatype_t *yd, int8_t R, jl
{
size_t lx = jl_nparams(xd);
size_t ly = jl_nparams(yd);
size_t i = 0, j = 0, vx = 0, vy = 0, x_reps = 0;
size_t i = 0, j = 0, vx = 0, vy = 0, x_reps = 1;
jl_value_t *lastx = NULL, *lasty = NULL;
jl_value_t *xi = NULL, *yi = NULL;

Expand Down Expand Up @@ -1131,21 +1131,17 @@ static int subtype_tuple_tail(jl_datatype_t *xd, jl_datatype_t *yd, int8_t R, jl
return !!vx;

xi = vx ? jl_unwrap_vararg(xi) : xi;
int x_same = lastx && jl_egal(xi, lastx);
if (vy) {
yi = jl_unwrap_vararg(yi);
// keep track of number of consecutive identical types compared to Vararg
if (x_same)
x_reps++;
else
x_reps = 1;
}
yi = vy ? jl_unwrap_vararg(yi) : yi;
int x_same = vx > 1 || (lastx && obviously_egal(xi, lastx));
int y_same = vy > 1 || (lasty && obviously_egal(yi, lasty));
// keep track of number of consecutive identical subtyping
x_reps = y_same && x_same ? x_reps + 1 : 1;
if (x_reps > 2) {
// an identical type on the left doesn't need to be compared to a Vararg
// an identical type on the left doesn't need to be compared to the same
// element type on the right more than twice.
}
else if (x_same && e->Runions.depth == 0 &&
((yi == lasty && !jl_has_free_typevars(xi) && !jl_has_free_typevars(yi)) ||
((y_same && !jl_has_free_typevars(xi) && !jl_has_free_typevars(yi)) ||
(yi == lastx && !vx && vy && jl_is_concrete_type(xi)))) {
// fast path for repeated elements
}
Expand Down
3 changes: 3 additions & 0 deletions test/subtype.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2426,6 +2426,9 @@ end

@test !(Tuple{Any, Any, Any} <: Tuple{Any, Vararg{T}} where T)

# issue #39967
@test (NTuple{27, T} where {S, T<:Union{Array, Array{S}}}) <: Tuple{Array, Array, Vararg{AbstractArray, 25}}

abstract type MyAbstract47877{C}; end
struct MyType47877{A,B} <: MyAbstract47877{A} end
let A = Tuple{Type{T}, T} where T,
Expand Down

0 comments on commit 3d0278b

Please sign in to comment.