Skip to content

Commit

Permalink
add a fastpath to forall_exists_equal in subtyping (#23995)
Browse files Browse the repository at this point in the history
fixes #22688, fixes #23908
  • Loading branch information
JeffBezanson authored Oct 10, 2017
1 parent 1cb8071 commit 19bce95
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 20 deletions.
4 changes: 2 additions & 2 deletions base/random/RNGs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,8 @@ rand(r::MersenneTwister, I::FloatInterval) = rand_generic(r, I)

#### integers

rand(r::MersenneTwister,
::Type{T}) where {T<:Union{Bool,Int8,UInt8,Int16,UInt16,Int32,UInt32}} =
rand(r::MersenneTwister, T::Union{Type{Bool}, Type{Int8}, Type{UInt8}, Type{Int16}, Type{UInt16},
Type{Int32}, Type{UInt32}}) =
rand_ui52_raw(r) % T

function rand(r::MersenneTwister, ::Type{UInt64})
Expand Down
54 changes: 37 additions & 17 deletions src/subtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -959,29 +959,49 @@ 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;

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));
e->Runions.depth = 0;
e->Runions.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.more = 0;

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 +1010,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 +1023,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 +1038,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 +1092,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 +1105,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
1 change: 0 additions & 1 deletion test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5454,7 +5454,6 @@ t4 = vcat(A23567, t2, t3)
@test t4[11:15] == A23567

for U in unboxedunions
Base.unionlen(U) > 5 && continue # larger values cause subtyping to crash
local U
for N in (1, 2, 3, 4)
A = Array{U}(ntuple(x->0, N)...)
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 19bce95

Please sign in to comment.