Skip to content

Commit

Permalink
fix isa tfunc for type kinds
Browse files Browse the repository at this point in the history
previously, isa_tfunc(DataType, Type{...}) might return Const(false)

(cherry picked from commit cd959a2, PR #22779)
  • Loading branch information
vtjnash committed Sep 13, 2017
1 parent 4b967d4 commit 873152b
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 11 deletions.
26 changes: 15 additions & 11 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -353,13 +353,15 @@ isType(t::ANY) = isa(t, DataType) && (t::DataType).name === _Type_name
# true if Type is inlineable as constant (is a singleton)
isconstType(t::ANY) = isType(t) && (isleaftype(t.parameters[1]) || t.parameters[1] === Union{})

iskindtype(t::ANY) = (t === DataType || t === UnionAll || t === Union || t === typeof(Bottom))

const IInf = typemax(Int) # integer infinity
const n_ifunc = reinterpret(Int32,arraylen)+1
const t_ifunc = Array{Tuple{Int,Int,Any},1}(n_ifunc)
const t_ffunc_key = Array{Function,1}(0)
const t_ffunc_val = Array{Tuple{Int,Int,Any},1}(0)
const n_ifunc = reinterpret(Int32, arraylen) + 1
const t_ifunc = Array{Tuple{Int, Int, Any}, 1}(n_ifunc)
const t_ffunc_key = Array{Any, 1}(0)
const t_ffunc_val = Array{Tuple{Int, Int, Any}, 1}(0)
function add_tfunc(f::IntrinsicFunction, minarg::Int, maxarg::Int, tfunc::ANY)
t_ifunc[reinterpret(Int32,f)+1] = (minarg, maxarg, tfunc)
t_ifunc[reinterpret(Int32, f) + 1] = (minarg, maxarg, tfunc)
end
function add_tfunc(f::Function, minarg::Int, maxarg::Int, tfunc::ANY)
push!(t_ffunc_key, f)
Expand Down Expand Up @@ -630,7 +632,7 @@ add_tfunc(isa, 2, 2,
if t !== Any && !has_free_typevars(t)
if v t
return Const(true)
elseif isa(v, Const) || isa(v, Conditional) || isleaftype(v)
elseif isa(v, Const) || isa(v, Conditional) || (isleaftype(v) && !iskindtype(v))
return Const(false)
end
end
Expand Down Expand Up @@ -1171,20 +1173,20 @@ function builtin_tfunction(f::ANY, argtypes::Array{Any,1},
end
if isa(f, IntrinsicFunction)
iidx = Int(reinterpret(Int32, f::IntrinsicFunction)) + 1
if !isassigned(t_ifunc, iidx)
# unknown/unhandled intrinsic (most fall in this category since most return an unboxed value)
if iidx < 0 || iidx > length(t_ifunc)
# invalid intrinsic
return Any
end
tf = t_ifunc[iidx]
else
fidx = findfirst(t_ffunc_key, f::Function)
fidx = findfirst(t_ffunc_key, f)
if fidx == 0
# unknown/unhandled builtin or anonymous function
# unknown/unhandled builtin function
return Any
end
tf = t_ffunc_val[fidx]
end
tf = tf::Tuple{Real, Real, Any}
tf = tf::Tuple{Int, Int, Any}
if !(tf[1] <= length(argtypes) <= tf[2])
# wrong # of args
return Bottom
Expand Down Expand Up @@ -5488,6 +5490,8 @@ let fs = Any[typeinf_ext, typeinf_loop, typeinf_edge, occurs_outside_getfield, p
if isassigned(t_ifunc, i)
x = t_ifunc[i]
push!(fs, x[3])
else
println(STDERR, "WARNING: tfunc missing for ", reinterpret(IntrinsicFunction, Int32(i)))
end
end
for f in fs
Expand Down
33 changes: 33 additions & 0 deletions test/inference.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

# tests for Core.Inference correctness and precision
import Core.Inference: Const, Conditional,

# issue 9770
@noinline x9770() = false
Expand Down Expand Up @@ -851,3 +852,35 @@ let niter = 0
end
@test niter == 4
end

let isa_tfunc = Core.Inference.t_ffunc_val[
findfirst(Core.Inference.t_ffunc_key, isa)][3]
@test isa_tfunc(Array, Const(AbstractArray)) === Const(true)
@test isa_tfunc(Array, Type{AbstractArray}) === Const(true)
@test isa_tfunc(Array, Type{AbstractArray{Int}}) == Bool
@test isa_tfunc(Array{Real}, Type{AbstractArray{Int}}) === Bool # could be improved
@test isa_tfunc(Array{Real, 2}, Const(AbstractArray{Real, 2})) === Const(true)
@test isa_tfunc(Array{Real, 2}, Const(AbstractArray{Int, 2})) === Const(false)
@test isa_tfunc(DataType, Int) === Bool # could be improved
@test isa_tfunc(DataType, Const(Type{Int})) === Bool
@test isa_tfunc(DataType, Const(Type{Array})) === Bool
@test isa_tfunc(UnionAll, Const(Type{Int})) === Bool # could be improved
@test isa_tfunc(UnionAll, Const(Type{Array})) === Bool
@test isa_tfunc(Union, Const(Union{Float32, Float64})) === Bool
@test isa_tfunc(Union, Type{Union}) === Const(true)
@test isa_tfunc(typeof(Union{}), Const(Int)) === Bool # any result is ok
@test isa_tfunc(typeof(Union{}), Const(Union{})) === Bool # could be improved
@test isa_tfunc(typeof(Union{}), typeof(Union{})) === Bool # could be improved
@test isa_tfunc(typeof(Union{}), Union{}) === Bool # could be improved
@test isa_tfunc(typeof(Union{}), Type{typeof(Union{})}) === Const(true)
@test isa_tfunc(typeof(Union{}), Const(typeof(Union{}))) === Const(true)
let c = Conditional(Core.SlotNumber(0), Const(Union{}), Const(Union{}))
@test isa_tfunc(c, Const(Bool)) === Const(true)
@test isa_tfunc(c, Type{Bool}) === Const(true)
@test isa_tfunc(c, Const(Real)) === Const(true)
@test isa_tfunc(c, Type{Real}) === Const(true)
@test isa_tfunc(c, Const(Signed)) === Const(false)
@test isa_tfunc(c, Type{Complex}) === Const(false)
@test isa_tfunc(c, Type{Complex{T}} where T) === Const(false)
end
end

0 comments on commit 873152b

Please sign in to comment.