Skip to content

Commit 4ef8313

Browse files
Merge pull request #37233 from JuliaLang/mh/va-tfuncs
Better Vararg handling in tfuncs
2 parents 4ab5293 + 180db15 commit 4ef8313

File tree

2 files changed

+79
-37
lines changed

2 files changed

+79
-37
lines changed

base/compiler/tfuncs.jl

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ function nfields_tfunc(@nospecialize(x))
390390
end
391391
add_tfunc(nfields, 1, 1, nfields_tfunc, 1)
392392
add_tfunc(Core._expr, 1, INT_INF, (@nospecialize args...)->Expr, 100)
393+
add_tfunc(svec, 0, INT_INF, (@nospecialize args...)->SimpleVector, 20)
393394
function typevar_tfunc(@nospecialize(n), @nospecialize(lb_arg), @nospecialize(ub_arg))
394395
lb = Union{}
395396
ub = Any
@@ -1093,6 +1094,9 @@ function apply_type_tfunc(@nospecialize(headtypetype), @nospecialize args...)
10931094
else
10941095
return Type
10951096
end
1097+
if !isempty(args) && isvarargtype(args[end])
1098+
return Type
1099+
end
10961100
largs = length(args)
10971101
if headtype === Union
10981102
largs == 0 && return Const(Bottom)
@@ -1297,6 +1301,26 @@ function tuple_tfunc(atypes::Vector{Any})
12971301
return anyinfo ? PartialStruct(typ, atypes) : typ
12981302
end
12991303

1304+
function arrayref_tfunc(@nospecialize(boundscheck), @nospecialize(a), @nospecialize i...)
1305+
a = widenconst(a)
1306+
if a <: Array
1307+
if isa(a, DataType) && (isa(a.parameters[1], Type) || isa(a.parameters[1], TypeVar))
1308+
# TODO: the TypeVar case should not be needed here
1309+
a = a.parameters[1]
1310+
return isa(a, TypeVar) ? a.ub : a
1311+
elseif isa(a, UnionAll) && !has_free_typevars(a)
1312+
unw = unwrap_unionall(a)
1313+
if isa(unw, DataType)
1314+
return rewrap_unionall(unw.parameters[1], a)
1315+
end
1316+
end
1317+
end
1318+
return Any
1319+
end
1320+
add_tfunc(arrayref, 3, INT_INF, arrayref_tfunc, 20)
1321+
add_tfunc(const_arrayref, 3, INT_INF, arrayref_tfunc, 20)
1322+
add_tfunc(arrayset, 4, INT_INF, (@nospecialize(boundscheck), @nospecialize(a), @nospecialize(v), @nospecialize i...)->a, 20)
1323+
13001324
function array_type_undefable(@nospecialize(a))
13011325
if isa(a, Union)
13021326
return array_type_undefable(a.a) || array_type_undefable(a.b)
@@ -1387,41 +1411,8 @@ end
13871411

13881412
function builtin_tfunction(interp::AbstractInterpreter, @nospecialize(f), argtypes::Array{Any,1},
13891413
sv::Union{InferenceState,Nothing})
1390-
isva = !isempty(argtypes) && isvarargtype(argtypes[end])
13911414
if f === tuple
13921415
return tuple_tfunc(argtypes)
1393-
elseif f === svec
1394-
return SimpleVector
1395-
elseif f === arrayset
1396-
if length(argtypes) < 4
1397-
isva && return Any
1398-
return Bottom
1399-
end
1400-
return argtypes[2]
1401-
elseif f === arrayref || f === const_arrayref
1402-
if length(argtypes) < 3
1403-
isva && return Any
1404-
return Bottom
1405-
end
1406-
a = widenconst(argtypes[2])
1407-
if a <: Array
1408-
if isa(a, DataType) && (isa(a.parameters[1], Type) || isa(a.parameters[1], TypeVar))
1409-
# TODO: the TypeVar case should not be needed here
1410-
a = a.parameters[1]
1411-
return isa(a, TypeVar) ? a.ub : a
1412-
elseif isa(a, UnionAll) && !has_free_typevars(a)
1413-
unw = unwrap_unionall(a)
1414-
if isa(unw, DataType)
1415-
return rewrap_unionall(unw.parameters[1], a)
1416-
end
1417-
end
1418-
end
1419-
return Any
1420-
elseif f === Core._expr
1421-
if length(argtypes) < 1 && !isva
1422-
return Bottom
1423-
end
1424-
return Expr
14251416
elseif f === invoke
14261417
if length(argtypes) > 1 && sv !== nothing && (isa(argtypes[1], Const) || isa(argtypes[1], Type))
14271418
if isa(argtypes[1], Const)
@@ -1443,9 +1434,6 @@ function builtin_tfunction(interp::AbstractInterpreter, @nospecialize(f), argtyp
14431434
end
14441435
return Any
14451436
end
1446-
if isva
1447-
return Any
1448-
end
14491437
if isa(f, IntrinsicFunction)
14501438
if is_pure_intrinsic_infer(f) && _all(@nospecialize(a) -> isa(a, Const), argtypes)
14511439
argvals = anymap(a::Const -> a.val, argtypes)
@@ -1469,7 +1457,24 @@ function builtin_tfunction(interp::AbstractInterpreter, @nospecialize(f), argtyp
14691457
tf = T_FFUNC_VAL[fidx]
14701458
end
14711459
tf = tf::Tuple{Int, Int, Any}
1472-
if !(tf[1] <= length(argtypes) <= tf[2])
1460+
if !isempty(argtypes) && isvarargtype(argtypes[end])
1461+
if length(argtypes) - 1 > tf[2]
1462+
# definitely too many arguments
1463+
return Bottom
1464+
end
1465+
if length(argtypes) - 1 == tf[2]
1466+
argtypes = argtypes[1:end-1]
1467+
else
1468+
vatype = argtypes[end]
1469+
argtypes = argtypes[1:end-1]
1470+
while length(argtypes) < tf[1]
1471+
push!(argtypes, unwrapva(vatype))
1472+
end
1473+
if length(argtypes) < tf[2]
1474+
push!(argtypes, unconstrain_vararg_length(vatype))
1475+
end
1476+
end
1477+
elseif !(tf[1] <= length(argtypes) <= tf[2])
14731478
# wrong # of args
14741479
return Bottom
14751480
end

test/compiler/inference.jl

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2776,3 +2776,40 @@ for badf in [getfield_const_typename_bad1, getfield_const_typename_bad2]
27762776
@test code[end] === Core.ReturnNode()
27772777
@test_throws TypeError badf()
27782778
end
2779+
2780+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(sizeof), Vararg{DataType}}) == Int
2781+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(sizeof), DataType, Vararg}) == Int
2782+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(sizeof), DataType, Any, Vararg}) == Union{}
2783+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(===), Vararg}) == Bool
2784+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(===), Any, Vararg}) == Bool
2785+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(===), Any, Any, Vararg}) == Bool
2786+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(===), Any, Any, Any, Vararg}) == Union{}
2787+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(setfield!), Vararg{Symbol}}) == Symbol
2788+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(setfield!), Any, Vararg{Symbol}}) == Symbol
2789+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(setfield!), Any, Symbol, Vararg{Integer}}) == Integer
2790+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(setfield!), Any, Symbol, Integer, Vararg}) == Integer
2791+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(setfield!), Any, Symbol, Integer, Any, Vararg}) == Union{}
2792+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(Core._expr), Vararg}) == Expr
2793+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(Core._expr), Any, Vararg}) == Expr
2794+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(Core._expr), Any, Any, Vararg}) == Expr
2795+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(applicable), Vararg}) == Bool
2796+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(applicable), Any, Vararg}) == Bool
2797+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(applicable), Any, Any, Vararg}) == Bool
2798+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(applicable), Any, Any, Any, Vararg}) == Bool
2799+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(getfield), Tuple{Int}, Vararg}) == Int
2800+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(getfield), Tuple{Int}, Any, Vararg}) == Int
2801+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(getfield), Tuple{Int}, Any, Any, Vararg}) == Int
2802+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(getfield), Any, Any, Any, Any, Vararg}) == Union{}
2803+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(fieldtype), Vararg}) == Type
2804+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(fieldtype), Any, Vararg}) == Type
2805+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(fieldtype), Any, Any, Vararg}) == Type
2806+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(fieldtype), Any, Any, Any, Vararg}) == Type
2807+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(fieldtype), Any, Any, Any, Any, Vararg}) == Union{}
2808+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(Core.apply_type), Vararg}) == Type
2809+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(Core.apply_type), Any, Vararg}) == Type
2810+
@test Core.Compiler.return_type(apply26826, Tuple{typeof(Core.apply_type), Any, Any, Vararg}) == Type
2811+
f_apply_cglobal(args...) = cglobal(args...)
2812+
@test Core.Compiler.return_type(f_apply_cglobal, Tuple{Vararg{Type{Int}}}) == Ptr
2813+
@test Core.Compiler.return_type(f_apply_cglobal, Tuple{Any, Vararg{Type{Int}}}) == Ptr
2814+
@test Core.Compiler.return_type(f_apply_cglobal, Tuple{Any, Type{Int}, Vararg{Type{Int}}}) == Ptr{Int}
2815+
@test Core.Compiler.return_type(f_apply_cglobal, Tuple{Any, Type{Int}, Type{Int}, Vararg{Type{Int}}}) == Union{}

0 commit comments

Comments
 (0)