Skip to content

Commit

Permalink
fix #38888, pessimistic sparam inference with concrete upper bound (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Dec 18, 2020
1 parent 17de527 commit a88c435
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 1 deletion.
32 changes: 31 additions & 1 deletion base/compiler/utilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,45 @@ end
const nonfunction_mt = typename(SimpleVector).mt

function get_compileable_sig(method::Method, @nospecialize(atypes), sparams::SimpleVector)
isa(atypes, DataType) || return Nothing
isa(atypes, DataType) || return nothing
mt = ccall(:jl_method_table_for, Any, (Any,), atypes)
mt === nothing && return nothing
return ccall(:jl_normalize_to_compilable_sig, Any, (Any, Any, Any, Any),
mt, atypes, sparams, method)
end

# eliminate UnionAll vars that might be degenerate due to having identical bounds,
# or a concrete upper bound and appearing covariantly.
function subst_trivial_bounds(@nospecialize(atypes))
if !isa(atypes, UnionAll)
return atypes
end
v = atypes.var
if isconcretetype(v.ub) || v.lb === v.ub
return subst_trivial_bounds(atypes{v.ub})
end
return UnionAll(v, subst_trivial_bounds(atypes.body))
end

# If removing trivial vars from atypes results in an equivalent type, use that
# instead. Otherwise we can get a case like issue #38888, where a signature like
# f(x::S) where S<:Int
# gets cached and matches a concrete dispatch case.
function normalize_typevars(method::Method, @nospecialize(atypes), sparams::SimpleVector)
at2 = subst_trivial_bounds(atypes)
if at2 !== atypes && at2 == atypes
atypes = at2
sp_ = ccall(:jl_type_intersection_with_env, Any, (Any, Any), at2, method.sig)::SimpleVector
sparams = sp_[2]::SimpleVector
end
return atypes, sparams
end

# get a handle to the unique specialization object representing a particular instantiation of a call
function specialize_method(method::Method, @nospecialize(atypes), sparams::SimpleVector, preexisting::Bool=false, compilesig::Bool=false)
if isa(atypes, UnionAll)
atypes, sparams = normalize_typevars(method, atypes, sparams)
end
if compilesig
new_atypes = get_compileable_sig(method, atypes, sparams)
new_atypes === nothing && return nothing
Expand Down
10 changes: 10 additions & 0 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2979,3 +2979,13 @@ gVarargInt(x::Int) = 1
gVarargInt(x) = 2
fVarargInt(::Tuple{Vararg{Int, N}}) where {N} = Val{gVarargInt(N)}()
@test only(Base.return_types(fVarargInt, Tuple{Tuple{Vararg{Int}}})) == Val{1}

# issue #38888
struct S38888{T}
S38888(x::S) where {S<:Int} = new{S}()
S38888(x::S, y) where {S2<:Int,S<:S2} = new{S}()
end
f38888() = S38888(Base.inferencebarrier(3))
@test f38888() isa S38888
g38888() = S38888(Base.inferencebarrier(3), nothing)
@test g38888() isa S38888

0 comments on commit a88c435

Please sign in to comment.