Skip to content

Commit

Permalink
only infer concrete union-split signatures to cut down on inference
Browse files Browse the repository at this point in the history
reduce O(n^2) behavior of `jl_recache_types`

improve soundness of inferred typevar bounds in subtyping

these help #24383
  • Loading branch information
JeffBezanson committed Oct 30, 2017
1 parent 5478834 commit c3f5f5f
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 4 deletions.
5 changes: 4 additions & 1 deletion base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,10 @@ function _methods_by_ftype(t::ANY, lim::Int, world::UInt, min::Array{UInt,1}, ma
end
end
if 1 < nu <= 64
return _methods_by_ftype(Any[tp...], t, length(tp), lim, [], world, min, max)
ms = _methods_by_ftype(Any[tp...], t, length(tp), lim, [], world, min, max)
if all(m->isleaftype(m[1]), ms)
return ms
end
end
# XXX: the following can return incorrect answers that the above branch would have corrected
return ccall(:jl_matching_methods, Any, (Any, Cint, Cint, UInt, Ptr{UInt}, Ptr{UInt}), t, lim, 0, world, min, max)
Expand Down
5 changes: 3 additions & 2 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -3035,6 +3035,8 @@ static jl_datatype_t *jl_recache_type(jl_datatype_t *dt, size_t start, jl_value_
t = dt;
}
assert(t->uid != 0);
if (t == dt && v == NULL)
return t;
// delete / replace any other usages of this type in the backref list
// with the newly constructed object
size_t i = start;
Expand Down Expand Up @@ -3087,8 +3089,7 @@ static void jl_recache_types(void)
if (jl_is_datatype(o)) {
dt = (jl_datatype_t*)o;
v = dt->instance;
assert(dt->uid == -1);
t = jl_recache_type(dt, i + 2, NULL);
t = dt->uid == -1 ? jl_recache_type(dt, i + 2, NULL) : dt;
}
else {
dt = (jl_datatype_t*)jl_typeof(o);
Expand Down
4 changes: 3 additions & 1 deletion src/subtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,9 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8
jl_value_t *oldval = e->envout[e->envidx];
// if we try to assign different variable values (due to checking
// multiple union members), consider the value unknown.
if (!oldval || !jl_is_typevar(oldval) || !jl_is_long(val))
if (oldval && jl_is_typevar(oldval))
e->envout[e->envidx] = (jl_value_t*)u->var;
else
e->envout[e->envidx] = val;
// TODO: substitute the value (if any) of this variable into previous envout entries
}
Expand Down
11 changes: 11 additions & 0 deletions test/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -952,3 +952,14 @@ g23024(TT::Tuple{DataType}) = f23024(TT[1], v23024)
@test Base.return_types(f23024, (DataType, Any)) == Any[Int]
@test Base.return_types(g23024, (Tuple{DataType},)) == Any[Int]
@test g23024((UInt8,)) === 2

# approximate static parameters due to unions
inference_test_copy(a::T) where {T<:Array} = ccall(:jl_array_copy, Ref{T}, (Any,), a)
let T1 = Array{Float64}, T2 = Array{_1,2} where _1
rt = Base.return_types(inference_test_copy, (Union{T1,T2},))[1]
@test rt >: T1 && rt >: T2

el(x::T) where {T} = eltype(T)
rt = Base.return_types(el, (Union{T1,Array{Float32,2}},))[1]
@test rt >: Union{Type{Float64}, Type{Float32}}
end

0 comments on commit c3f5f5f

Please sign in to comment.