Skip to content
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
20 changes: 8 additions & 12 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -778,10 +778,7 @@ function precise_container_type(interp::AbstractInterpreter, @nospecialize(itft)
if isa(tti, DataType) && tti.name === NamedTuple_typename
# A NamedTuple iteration is the same as the iteration of its Tuple parameter:
# compute a new `tti == unwrap_unionall(tti0)` based on that Tuple type
tti = tti.parameters[2]
while isa(tti, TypeVar)
tti = tti.ub
end
tti = unwraptv(tti.parameters[2])
tti0 = rewrap_unionall(tti, tti0)
end
if isa(tti, Union)
Expand Down Expand Up @@ -1153,7 +1150,8 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, fargs::U
end
end
end
return isa(rt, TypeVar) ? rt.ub : rt
@assert !isa(rt, TypeVar) "unhandled TypeVar"
return rt
end

function abstract_call_unionall(argtypes::Vector{Any})
Expand Down Expand Up @@ -1405,7 +1403,7 @@ function sp_type_rewrap(@nospecialize(T), linfo::MethodInstance, isreturn::Bool)
spsig = linfo.def.sig
if isa(spsig, UnionAll)
if !isempty(linfo.sparam_vals)
sparam_vals = Any[isa(v, Core.TypeofVararg) ? TypeVar(:N, Union{}, Any) :
sparam_vals = Any[isvarargtype(v) ? TypeVar(:N, Union{}, Any) :
v for v in linfo.sparam_vals]
T = ccall(:jl_instantiate_type_in_env, Any, (Any, Any, Ptr{Any}), T, spsig, sparam_vals)
isref && isreturn && T === Any && return Bottom # catch invalid return Ref{T} where T = Any
Expand All @@ -1419,10 +1417,7 @@ function sp_type_rewrap(@nospecialize(T), linfo::MethodInstance, isreturn::Bool)
end
end
end
while isa(T, TypeVar)
T = T.ub
end
return T
return unwraptv(T)
end

function abstract_eval_cfunction(interp::AbstractInterpreter, e::Expr, vtypes::VarTable, sv::InferenceState)
Expand Down Expand Up @@ -1632,7 +1627,7 @@ function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e),
else
t = abstract_eval_value_expr(interp, e, vtypes, sv)
end
@assert !isa(t, TypeVar)
@assert !isa(t, TypeVar) "unhandled TypeVar"
if isa(t, DataType) && isdefined(t, :instance)
# replace singleton types with their equivalent Const object
t = Const(t.instance)
Expand Down Expand Up @@ -1717,7 +1712,8 @@ function widenreturn(@nospecialize(rt), @nospecialize(bestguess), nslots::Int, s
fields = copy(rt.fields)
haveconst = false
for i in 1:length(fields)
a = widenreturn(fields[i], bestguess, nslots, slottypes, changes)
a = fields[i]
a = isvarargtype(a) ? a : widenreturn(a, bestguess, nslots, slottypes, changes)
if !haveconst && has_const_info(a)
# TODO: consider adding && const_prop_profitable(a) here?
haveconst = true
Expand Down
4 changes: 1 addition & 3 deletions base/compiler/bootstrap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ let
# remove any TypeVars from the intersection
typ = Any[m.spec_types.parameters...]
for i = 1:length(typ)
if isa(typ[i], TypeVar)
typ[i] = typ[i].ub
end
typ[i] = unwraptv(typ[i])
end
typeinf_type(interp, m.method, Tuple{typ...}, m.sparams)
end
Expand Down
3 changes: 2 additions & 1 deletion base/compiler/compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ using Core.Intrinsics, Core.IR

import Core: print, println, show, write, unsafe_write, stdout, stderr,
_apply_iterate, svec, apply_type, Builtin, IntrinsicFunction,
MethodInstance, CodeInstance, MethodMatch, PartialOpaque
MethodInstance, CodeInstance, MethodMatch, PartialOpaque,
TypeofVararg

const getproperty = Core.getfield
const setproperty! = Core.setfield!
Expand Down
25 changes: 18 additions & 7 deletions base/compiler/inferenceresult.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ end
function most_general_argtypes(method::Union{Method, Nothing}, @nospecialize(specTypes),
isva::Bool, withfirst::Bool = true)
toplevel = method === nothing
linfo_argtypes = Any[unwrap_unionall(specTypes).parameters...]
linfo_argtypes = Any[(unwrap_unionall(specTypes)::DataType).parameters...]
nargs::Int = toplevel ? 0 : method.nargs
if !withfirst
# For opaque closure, the closure environment is processed elsewhere
Expand Down Expand Up @@ -78,8 +78,8 @@ function most_general_argtypes(method::Union{Method, Nothing}, @nospecialize(spe
else
vargtype_elements = Any[]
for p in linfo_argtypes[nargs:linfo_argtypes_length]
p = isvarargtype(p) ? unconstrain_vararg_length(p) : p
push!(vargtype_elements, rewrap(p, specTypes))
p = unwraptv(isvarargtype(p) ? unconstrain_vararg_length(p) : p)
push!(vargtype_elements, elim_free_typevars(rewrap(p, specTypes)))
end
for i in 1:length(vargtype_elements)
atyp = vargtype_elements[i]
Expand Down Expand Up @@ -111,16 +111,14 @@ function most_general_argtypes(method::Union{Method, Nothing}, @nospecialize(spe
atyp = unwrapva(atyp)
tail_index -= 1
end
while isa(atyp, TypeVar)
atyp = atyp.ub
end
atyp = unwraptv(atyp)
if isa(atyp, DataType) && isdefined(atyp, :instance)
# replace singleton types with their equivalent Const object
atyp = Const(atyp.instance)
elseif isconstType(atyp)
atyp = Const(atyp.parameters[1])
else
atyp = rewrap(atyp, specTypes)
atyp = elim_free_typevars(rewrap(atyp, specTypes))
end
i == n && (lastatype = atyp)
cache_argtypes[i] = atyp
Expand All @@ -134,6 +132,19 @@ function most_general_argtypes(method::Union{Method, Nothing}, @nospecialize(spe
cache_argtypes
end

# eliminate free `TypeVar`s in order to make the life much easier down the road:
# at runtime only `Type{...}::DataType` can contain invalid type parameters, and other
# malformed types here are user-constructed type arguments given at an inference entry
# so this function will replace only the malformed `Type{...}::DataType` with `Type`
# and simply replace other possibilities with `Any`
function elim_free_typevars(@nospecialize t)
if has_free_typevars(t)
return isType(t) ? Type : Any
else
return t
end
end

function matching_cache_argtypes(linfo::MethodInstance, ::Nothing, va_override::Bool)
mthd = isa(linfo.def, Method) ? linfo.def::Method : nothing
cache_argtypes = most_general_argtypes(mthd, linfo.specTypes,
Expand Down
2 changes: 1 addition & 1 deletion base/compiler/inferencestate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ function sptypes_from_meth_instance(linfo::MethodInstance)
ty = UnionAll(tv, Type{tv})
end
end
elseif isa(v, Core.TypeofVararg)
elseif isvarargtype(v)
ty = Int
else
ty = Const(v)
Expand Down
6 changes: 2 additions & 4 deletions base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,7 @@ end

function validate_sparams(sparams::SimpleVector)
for i = 1:length(sparams)
(isa(sparams[i], TypeVar) || isa(sparams[i], Core.TypeofVararg)) && return false
(isa(sparams[i], TypeVar) || isvarargtype(sparams[i])) && return false
end
return true
end
Expand Down Expand Up @@ -873,9 +873,7 @@ function is_valid_type_for_apply_rewrite(@nospecialize(typ), params::Optimizatio
typ = widenconst(typ)
if isa(typ, DataType) && typ.name === NamedTuple_typename
typ = typ.parameters[2]
while isa(typ, TypeVar)
typ = typ.ub
end
typ = unwraptv(typ)
end
isa(typ, DataType) || return false
if typ.name === Tuple.name
Expand Down
41 changes: 22 additions & 19 deletions base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -549,11 +549,9 @@ function typeof_tfunc(@nospecialize(t))
return Type{<:t}
end
elseif isa(t, Union)
a = widenconst(typeof_tfunc(t.a))
b = widenconst(typeof_tfunc(t.b))
a = widenconst(_typeof_tfunc(t.a))
b = widenconst(_typeof_tfunc(t.b))
return Union{a, b}
elseif isa(t, TypeVar) && !(Any === t.ub)
return typeof_tfunc(t.ub)
elseif isa(t, UnionAll)
u = unwrap_unionall(t)
if isa(u, DataType) && !isabstracttype(u)
Expand All @@ -570,6 +568,13 @@ function typeof_tfunc(@nospecialize(t))
end
return DataType # typeof(anything)::DataType
end
# helper function of `typeof_tfunc`, which accepts `TypeVar`
function _typeof_tfunc(@nospecialize(t))
if isa(t, TypeVar)
return t.ub !== Any ? _typeof_tfunc(t.ub) : DataType
end
return typeof_tfunc(t)
end
add_tfunc(typeof, 1, 1, typeof_tfunc, 1)

function typeassert_tfunc(@nospecialize(v), @nospecialize(t))
Expand Down Expand Up @@ -865,10 +870,7 @@ function getfield_tfunc(@nospecialize(s00), @nospecialize(name))
elseif Symbol ⊑ name
name = Int
end
_ts = s.parameters[2]
while isa(_ts, TypeVar)
_ts = _ts.ub
end
_ts = unwraptv(s.parameters[2])
_ts = rewrap_unionall(_ts, s00)
if !(_ts <: Tuple)
return Any
Expand Down Expand Up @@ -1268,7 +1270,7 @@ function apply_type_tfunc(@nospecialize(headtypetype), @nospecialize args...)
return Any
end
if !isempty(args) && isvarargtype(args[end])
return isvarargtype(headtype) ? Core.TypeofVararg : Type
return isvarargtype(headtype) ? TypeofVararg : Type
end
largs = length(args)
if headtype === Union
Expand Down Expand Up @@ -1329,7 +1331,7 @@ function apply_type_tfunc(@nospecialize(headtypetype), @nospecialize args...)
canconst &= !has_free_typevars(aip1)
push!(tparams, aip1)
elseif isa(ai, Const) && (isa(ai.val, Type) || isa(ai.val, TypeVar) ||
valid_tparam(ai.val) || (istuple && isa(ai.val, Core.TypeofVararg)))
valid_tparam(ai.val) || (istuple && isvarargtype(ai.val)))
push!(tparams, ai.val)
elseif isa(ai, PartialTypeVar)
canconst = false
Expand Down Expand Up @@ -1395,11 +1397,11 @@ function apply_type_tfunc(@nospecialize(headtypetype), @nospecialize args...)
catch ex
# type instantiation might fail if one of the type parameters
# doesn't match, which could happen if a type estimate is too coarse
return isvarargtype(headtype) ? Core.TypeofVararg : Type{<:headtype}
return isvarargtype(headtype) ? TypeofVararg : Type{<:headtype}
end
!uncertain && canconst && return Const(appl)
if isvarargtype(appl)
return Core.TypeofVararg
return TypeofVararg
end
if istuple
return Type{<:appl}
Expand Down Expand Up @@ -1439,12 +1441,15 @@ function tuple_tfunc(atypes::Vector{Any})
if has_struct_const_info(x)
anyinfo = true
else
atypes[i] = x = widenconst(x)
if !isvarargtype(x)
x = widenconst(x)
end
atypes[i] = x
end
if isa(x, Const)
params[i] = typeof(x.val)
else
x = widenconst(x)
x = isvarargtype(x) ? x : widenconst(x)
if isType(x)
anyinfo = true
xparam = x.parameters[1]
Expand All @@ -1467,10 +1472,8 @@ end
function arrayref_tfunc(@nospecialize(boundscheck), @nospecialize(a), @nospecialize i...)
a = widenconst(a)
if a <: Array
if isa(a, DataType) && (isa(a.parameters[1], Type) || isa(a.parameters[1], TypeVar))
# TODO: the TypeVar case should not be needed here
a = a.parameters[1]
return isa(a, TypeVar) ? a.ub : a
if isa(a, DataType) && isa(a.parameters[1], Type)
return a.parameters[1]
elseif isa(a, UnionAll) && !has_free_typevars(a)
unw = unwrap_unionall(a)
if isa(unw, DataType)
Expand Down Expand Up @@ -1632,7 +1635,7 @@ function builtin_tfunction(interp::AbstractInterpreter, @nospecialize(f), argtyp
if length(argtypes) - 1 == tf[2]
argtypes = argtypes[1:end-1]
else
vatype = argtypes[end]::Core.TypeofVararg
vatype = argtypes[end]::TypeofVararg
argtypes = argtypes[1:end-1]
while length(argtypes) < tf[1]
push!(argtypes, unwrapva(vatype))
Expand Down
9 changes: 2 additions & 7 deletions base/compiler/typeinfer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -959,7 +959,6 @@ function typeinf_ext_toplevel(interp::AbstractInterpreter, linfo::MethodInstance
return src
end


function return_type(@nospecialize(f), @nospecialize(t))
world = ccall(:jl_get_tls_world_age, UInt, ())
return ccall(:jl_call_in_typeinf_world, Any, (Ptr{Ptr{Cvoid}}, Cint), Any[_return_type, f, t, world], 4)
Expand All @@ -971,14 +970,10 @@ function _return_type(interp::AbstractInterpreter, @nospecialize(f), @nospeciali
rt = Union{}
if isa(f, Builtin)
rt = builtin_tfunction(interp, f, Any[t.parameters...], nothing)
if isa(rt, TypeVar)
rt = rt.ub
else
rt = widenconst(rt)
end
rt = widenconst(rt)
else
for match in _methods(f, t, -1, get_world_counter(interp))::Vector
match = match::Core.MethodMatch
match = match::MethodMatch
ty = typeinf_type(interp, match.method, match.spec_types, match.sparams)
ty === nothing && return Any
rt = tmerge(rt, ty)
Expand Down
4 changes: 2 additions & 2 deletions base/compiler/typelattice.jl
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,8 @@ widenconst(c::PartialTypeVar) = TypeVar
widenconst(t::PartialStruct) = t.typ
widenconst(t::PartialOpaque) = t.typ
widenconst(t::Type) = t
widenconst(t::TypeVar) = t
widenconst(t::Core.TypeofVararg) = t
widenconst(t::TypeVar) = error("unhandled TypeVar")
widenconst(t::TypeofVararg) = error("unhandled Vararg")
widenconst(t::LimitedAccuracy) = error("unhandled LimitedAccuracy")

issubstate(a::VarState, b::VarState) = (a.typ ⊑ b.typ && a.undef <= b.undef)
Expand Down
Loading