From bd07ef4f97f3ab00d56719eb7c38bfce2ea43344 Mon Sep 17 00:00:00 2001
From: Jeff Bezanson
Date: Thu, 14 Feb 2019 11:18:54 -0500
Subject: [PATCH] improve precision of typeof_tfunc a bit (#31043)
---
base/compiler/tfuncs.jl | 41 ++++++++++++++++++++++++++++++++------
test/compiler/inference.jl | 8 ++++++++
2 files changed, 43 insertions(+), 6 deletions(-)
diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl
index dd2a2de41606c..8cab5eaab4ffb 100644
--- a/base/compiler/tfuncs.jl
+++ b/base/compiler/tfuncs.jl
@@ -409,6 +409,23 @@ add_tfunc(pointerref, 3, 3,
end, 4)
add_tfunc(pointerset, 4, 4, (@nospecialize(a), @nospecialize(v), @nospecialize(i), @nospecialize(align)) -> a, 5)
+# more accurate typeof_tfunc for vararg tuples abstract only in length
+function typeof_concrete_vararg(@nospecialize(t))
+ np = length(t.parameters)
+ for i = 1:np
+ p = t.parameters[i]
+ if i == np && isvarargtype(p)
+ pp = unwrap_unionall(p)
+ if isconcretetype(pp.parameters[1]) && pp.parameters[2] isa TypeVar
+ return rewrap_unionall(Type{Tuple{t.parameters[1:np-1]..., pp}}, p)
+ end
+ elseif !isconcretetype(p)
+ break
+ end
+ end
+ return nothing
+end
+
function typeof_tfunc(@nospecialize(t))
isa(t, Const) && return Const(typeof(t.val))
t = widenconst(t)
@@ -416,15 +433,17 @@ function typeof_tfunc(@nospecialize(t))
tp = t.parameters[1]
if issingletontype(tp)
return Const(typeof(tp))
- else
- return Type
end
elseif isa(t, DataType)
- if isconcretetype(t) || isvarargtype(t)
+ if isconcretetype(t)
return Const(t)
elseif t === Any
return DataType
else
+ if t.name === Tuple.name
+ tt = typeof_concrete_vararg(t)
+ tt === nothing || return tt
+ end
return Type{<:t}
end
elseif isa(t, Union)
@@ -434,10 +453,20 @@ function typeof_tfunc(@nospecialize(t))
elseif isa(t, TypeVar) && !(Any <: t.ub)
return typeof_tfunc(t.ub)
elseif isa(t, UnionAll)
- return rewrap_unionall(widenconst(typeof_tfunc(unwrap_unionall(t))), t)
- else
- return DataType # typeof(anything)::DataType
+ u = unwrap_unionall(t)
+ if isa(u, DataType) && !u.abstract
+ if u.name === Tuple.name
+ uu = typeof_concrete_vararg(u)
+ if uu !== nothing
+ return rewrap_unionall(uu, t)
+ end
+ else
+ return rewrap_unionall(Type{u}, t)
+ end
+ end
+ return rewrap_unionall(widenconst(typeof_tfunc(u)), t)
end
+ return DataType # typeof(anything)::DataType
end
add_tfunc(typeof, 1, 1, typeof_tfunc, 0)
diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl
index 114e278093d55..bf1b496860c45 100644
--- a/test/compiler/inference.jl
+++ b/test/compiler/inference.jl
@@ -1346,6 +1346,14 @@ let PT = PartialTuple(Tuple{Int64,UInt64}, Any[Const(10, false), UInt64])
end
@test sizeof_nothrow(Const(Tuple)) === false
+using Core.Compiler: typeof_tfunc
+@test typeof_tfunc(Tuple{Vararg{Int}}) == Type{Tuple{Vararg{Int,N}}} where N
+@test typeof_tfunc(Tuple{Any}) == Type{<:Tuple{Any}}
+@test typeof_tfunc(Type{Array}) === DataType
+@test typeof_tfunc(Type{<:Array}) === DataType
+@test typeof_tfunc(Array{Int}) == Type{Array{Int,N}} where N
+@test typeof_tfunc(AbstractArray{Int}) == Type{<:AbstractArray{Int,N}} where N
+
function f23024(::Type{T}, ::Int) where T
1 + 1
end