Skip to content
Closed
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
30 changes: 26 additions & 4 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,13 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
fullmatch = Bool[]
if splitunions
splitsigs = switchtupleunion(atype)
split_argtypes = switchtupleunion(argtypes)
applicable = Any[]
# arrays like `argtypes`, including constants, for each match
applicable_argtypes = Vector{Any}[]
infos = MethodMatchInfo[]
for sig_n in splitsigs
for j in 1:length(splitsigs)
sig_n = splitsigs[j]
mt = ccall(:jl_method_table_for, Any, (Any,), sig_n)
if mt === nothing
add_remark!(interp, sv, "Could not identify method table for call")
Expand All @@ -45,6 +49,9 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
end
push!(infos, MethodMatchInfo(matches))
append!(applicable, matches)
for _ in 1:length(matches)
push!(applicable_argtypes, split_argtypes[j])
end
valid_worlds = intersect(valid_worlds, matches.valid_worlds)
thisfullmatch = _any(match->(match::MethodMatch).fully_covers, matches)
found = false
Expand Down Expand Up @@ -80,6 +87,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
info = MethodMatchInfo(matches)
applicable = matches.matches
valid_worlds = matches.valid_worlds
applicable_argtypes = nothing
end
update_valid_age!(sv, valid_worlds)
applicable = applicable::Array{Any,1}
Expand Down Expand Up @@ -136,6 +144,9 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
if this_rt !== Bottom
if nonbot === 0
nonbot = i
elseif nonbot === -1
elseif method === (applicable[nonbot]::MethodMatch).method
# another entry from the same method, due to union splitting
else
nonbot = -1
end
Expand All @@ -147,12 +158,23 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
# try constant propagation if only 1 method is inferred to non-Bottom
# this is in preparation for inlining, or improving the return result
is_unused = call_result_unused(sv)
if nonbot > 0 && seen == napplicable && (!edgecycle || !is_unused) && isa(rettype, Type) && InferenceParams(interp).ipo_constant_propagation
if nonbot > 0 && seen == napplicable && (!edgecycle || !is_unused) &&
(isa(rettype, Type) || isa(rettype, PartialStruct)) && InferenceParams(interp).ipo_constant_propagation
# if there's a possibility we could constant-propagate a better result
# (hopefully without doing too much work), try to do that now
# TODO: it feels like this could be better integrated into abstract_call_method / typeinf_edge
const_rettype = abstract_call_method_with_const_args(interp, rettype, f, argtypes, applicable[nonbot]::MethodMatch, sv, edgecycle)
if const_rettype ⊑ rettype
const_rettype = Bottom
for i in 1:napplicable
mm = applicable[i]::MethodMatch
if i === nonbot || mm.method === (applicable[nonbot]::MethodMatch).method
this_argtypes = applicable_argtypes === nothing ? argtypes : applicable_argtypes[i]
one_rettype = abstract_call_method_with_const_args(interp, rettype, f, this_argtypes, mm, sv, edgecycle)
const_rettype = tmerge(const_rettype, one_rettype)
const_rettype ⊑ rettype || (const_rettype = Any)
const_rettype === Any && break
end
end
if const_rettype !== Any
# use the better result, if it's a refinement of rettype
rettype = const_rettype
end
Expand Down
10 changes: 8 additions & 2 deletions base/compiler/typeutils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,16 @@ function switchtupleunion(@nospecialize(ty))
return _switchtupleunion(Any[tparams...], length(tparams), [], ty)
end

switchtupleunion(t::Vector{Any}) = _switchtupleunion(t, length(t), [], nothing)

function _switchtupleunion(t::Vector{Any}, i::Int, tunion::Vector{Any}, @nospecialize(origt))
if i == 0
tpl = rewrap_unionall(Tuple{t...}, origt)
push!(tunion, tpl)
if origt === nothing
push!(tunion, t)
Copy link
Member

@aviatesk aviatesk Jan 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
push!(tunion, t)
push!(tunion, copy(t))

I think we need to copy t here, otherwise it will be mutated at t[i] = ti in recursion.

else
tpl = rewrap_unionall(Tuple{t...}, origt)
push!(tunion, tpl)
end
else
ti = t[i]
if isa(ti, Union)
Expand Down
2 changes: 1 addition & 1 deletion base/namedtuple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ firstindex(t::NamedTuple) = 1
lastindex(t::NamedTuple) = nfields(t)
getindex(t::NamedTuple, i::Int) = getfield(t, i)
getindex(t::NamedTuple, i::Symbol) = getfield(t, i)
indexed_iterate(t::NamedTuple, i::Int, state=1) = (getfield(t, i), i+1)
indexed_iterate(t::NamedTuple, i::Int, state=1) = (@_inline_meta; (getfield(t, i), i+1))
isempty(::NamedTuple{()}) = true
isempty(::NamedTuple) = false
empty(::NamedTuple) = NamedTuple()
Expand Down
2 changes: 1 addition & 1 deletion base/pair.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Pair, =>

eltype(p::Type{Pair{A, B}}) where {A, B} = Union{A, B}
iterate(p::Pair, i=1) = i > 2 ? nothing : (getfield(p, i), i + 1)
indexed_iterate(p::Pair, i::Int, state=1) = (getfield(p, i), i + 1)
indexed_iterate(p::Pair, i::Int, state=1) = (@_inline_meta; (getfield(p, i), i + 1))

hash(p::Pair, h::UInt) = hash(p.second, hash(p.first, h))

Expand Down
2 changes: 1 addition & 1 deletion base/stream.jl
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ function alloc_request(buffer::IOBuffer, recommended_size::UInt)
ensureroom(buffer, Int(recommended_size))
ptr = buffer.append ? buffer.size + 1 : buffer.ptr
nb = min(length(buffer.data), buffer.maxsize) - ptr + 1
return (pointer(buffer.data, ptr), nb)
return (Ptr{Cvoid}(pointer(buffer.data, ptr)), nb)
end

notify_filled(buffer::IOBuffer, nread::Int, base::Ptr{Cvoid}, len::UInt) = notify_filled(buffer, nread)
Expand Down
2 changes: 1 addition & 1 deletion stdlib/Sockets/src/Sockets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ function recvfrom(sock::UDPSocket)
end
end

alloc_buf_hook(sock::UDPSocket, size::UInt) = (Libc.malloc(size), size) # size is always 64k from libuv
alloc_buf_hook(sock::UDPSocket, size::UInt) = (Libc.malloc(size), Int(size)) # size is always 64k from libuv

function uv_recvcb(handle::Ptr{Cvoid}, nread::Cssize_t, buf::Ptr{Cvoid}, addr::Ptr{Cvoid}, flags::Cuint)
sock = @handle_as handle UDPSocket
Expand Down
11 changes: 11 additions & 0 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2813,3 +2813,14 @@ f_apply_cglobal(args...) = cglobal(args...)
@test Core.Compiler.return_type(f_apply_cglobal, Tuple{Any, Vararg{Type{Int}}}) == Ptr
@test Core.Compiler.return_type(f_apply_cglobal, Tuple{Any, Type{Int}, Vararg{Type{Int}}}) == Ptr{Int}
@test Core.Compiler.return_type(f_apply_cglobal, Tuple{Any, Type{Int}, Type{Int}, Vararg{Type{Int}}}) == Union{}

# issue #37610
function f37610(a, i)
y = iterate(a, i)
if y !== nothing
(k, v), st = y
return k, v
end
return y
end
@test Base.return_types(f37610, (typeof(("foo" => "bar", "baz" => nothing)), Int)) == Any[Union{Nothing, Tuple{String, Union{Nothing, String}}}]