From c3f5f5f8b8c352edef997dfd601912eac56293f9 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sun, 29 Oct 2017 17:21:44 -0400 Subject: [PATCH] only infer concrete union-split signatures to cut down on inference reduce O(n^2) behavior of `jl_recache_types` improve soundness of inferred typevar bounds in subtyping these help #24383 --- base/reflection.jl | 5 ++++- src/dump.c | 5 +++-- src/subtype.c | 4 +++- test/inference.jl | 11 +++++++++++ 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/base/reflection.jl b/base/reflection.jl index e322a22dfe020..1417e0da6a824 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -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) diff --git a/src/dump.c b/src/dump.c index 0b9d3e228da5e..c49bc2168e79f 100644 --- a/src/dump.c +++ b/src/dump.c @@ -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; @@ -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); diff --git a/src/subtype.c b/src/subtype.c index b636d77bba83d..724dd308d2121 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -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 } diff --git a/test/inference.jl b/test/inference.jl index d6111ac96dad9..2b95305fd7cd2 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -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