Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #38888, pessimistic sparam inference with concrete upper bound #38899

Merged
merged 1 commit into from
Dec 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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