Skip to content

Commit

Permalink
add a fastpath to forall_exists_equal in subtyping
Browse files Browse the repository at this point in the history
fixes #22688, fixes #23908
  • Loading branch information
JeffBezanson committed Oct 5, 2017
1 parent 92fa0f3 commit 4580788
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 18 deletions.
52 changes: 34 additions & 18 deletions src/subtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -959,29 +959,45 @@ static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param)
return x == y || jl_egal(x, y);
}

static int forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param);

static int forall_exists_equal(jl_value_t *x, jl_value_t *y, jl_stenv_t *e)
{
if (obviously_egal(x, y)) return 1;

jl_unionstate_t oldLunions = e->Lunions;
memset(e->Lunions.stack, 0, sizeof(e->Lunions.stack));
int lastset = 0;
int sub;
while (1) {
e->Lunions.more = 0;
e->Lunions.depth = 0;
sub = subtype(x, y, e, 2);
int set = e->Lunions.more;
if (!sub || !set)
break;
for (int i = set; i <= lastset; i++)
statestack_set(&e->Lunions, i, 0);
lastset = set - 1;
statestack_set(&e->Lunions, lastset, 1);

if (!jl_has_free_typevars(x) || !jl_has_free_typevars(y)) {
jl_unionstate_t oldRunions = e->Runions;
memset(e->Runions.stack, 0, sizeof(e->Runions.stack));

sub = forall_exists_subtype(x, y, e, 2);

e->Runions = oldRunions;
}
else {
int lastset = 0;
while (1) {
e->Lunions.more = 0;
e->Lunions.depth = 0;
sub = subtype(x, y, e, 2);
int set = e->Lunions.more;
if (!sub || !set)
break;
for (int i = set; i <= lastset; i++)
statestack_set(&e->Lunions, i, 0);
lastset = set - 1;
statestack_set(&e->Lunions, lastset, 1);
}
}

e->Lunions = oldLunions;
return sub && subtype(y, x, e, 0);
}

static int exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, jl_value_t *saved, jl_savedenv_t *se)
static int exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, jl_value_t *saved, jl_savedenv_t *se, int param)
{
memset(e->Runions.stack, 0, sizeof(e->Runions.stack));
int lastset = 0;
Expand All @@ -990,7 +1006,7 @@ static int exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, jl_value_
e->Runions.more = 0;
e->Lunions.depth = 0;
e->Lunions.more = 0;
if (subtype(x, y, e, 0))
if (subtype(x, y, e, param))
return 1;
restore_env(e, saved, se);
int set = e->Runions.more;
Expand All @@ -1003,7 +1019,7 @@ static int exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, jl_value_
}
}

static int forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e)
static int forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param)
{
// The depth recursion has the following shape, after simplification:
// ∀₁
Expand All @@ -1018,7 +1034,7 @@ static int forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e)
int lastset = 0;
int sub;
while (1) {
sub = exists_subtype(x, y, e, saved, &se);
sub = exists_subtype(x, y, e, saved, &se, param);
int set = e->Lunions.more;
if (!sub || !set)
break;
Expand Down Expand Up @@ -1072,7 +1088,7 @@ JL_DLLEXPORT int jl_subtype_env(jl_value_t *x, jl_value_t *y, jl_value_t **env,
if (envsz == 0 && (y == (jl_value_t*)jl_any_type || x == jl_bottom_type || x == y))
return 1;
init_stenv(&e, env, envsz);
return forall_exists_subtype(x, y, &e);
return forall_exists_subtype(x, y, &e, 0);
}

static int subtype_in_env(jl_value_t *x, jl_value_t *y, jl_stenv_t *e)
Expand All @@ -1085,7 +1101,7 @@ static int subtype_in_env(jl_value_t *x, jl_value_t *y, jl_stenv_t *e)
e2.envsz = e->envsz;
e2.envout = e->envout;
e2.envidx = e->envidx;
return forall_exists_subtype(x, y, &e2);
return forall_exists_subtype(x, y, &e2, 0);
}

JL_DLLEXPORT int jl_subtype(jl_value_t *x, jl_value_t *y)
Expand Down
18 changes: 18 additions & 0 deletions test/subtype.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1184,3 +1184,21 @@ let
triangular(::Type{<:AbstractArray}) = Any
@test triangular(Array{Array{T, 1}, 1} where T) === Any
end

# issue #23908
@test Array{Union{Int128, Int16, Int32, Int8}, 1} <: Array{Union{Int128, Int32, Int8, _1}, 1} where _1
let A = Pair{Void, Pair{Array{Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}, 1}, Void}},
B = Pair{Void, Pair{Array{Union{Int8, UInt128, UInt16, UInt32, UInt64, UInt8, _1}, 1}, Void}} where _1
@test A <: B
@test !(B <: A)
end

# issue #22688
let X = Ref{Tuple{Array{Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}, 1}}}
@test !(X <: Ref{Tuple{Array{Union{Int8, UInt128, UInt16, UInt32, UInt64, UInt8, S}}}} where S)
@test X <: Ref{Tuple{Array{Union{Int8, UInt128, UInt16, UInt32, UInt64, UInt8, S}, 1}}} where S
end
let X = Ref{Tuple{Array{Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}, 1}, Array{Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}, 1}}},
Y = Ref{Tuple{Array{Union{Int8, UInt128, UInt16, UInt32, UInt64, UInt8, S}, 1}, Array{Union{Int8, UInt128, UInt16, UInt32, UInt64, UInt8, T}, 1}}} where S where T
@test X <: Y
end

0 comments on commit 4580788

Please sign in to comment.