907
907
function limit_type_size (@nospecialize (t), @nospecialize (compare), @nospecialize (source), allowed_tuplelen:: Int )
908
908
source = svec (unwrap_unionall (compare), unwrap_unionall (source))
909
909
source[1 ] === source[2 ] && (source = svec (source[1 ]))
910
- type_more_complex (t, compare, source, TUPLE_COMPLEXITY_LIMIT_DEPTH, allowed_tuplelen) || return t
911
- r = _limit_type_size (t, compare, source, allowed_tuplelen)
910
+ type_more_complex (t, compare, source, 1 , TUPLE_COMPLEXITY_LIMIT_DEPTH, allowed_tuplelen) || return t
911
+ r = _limit_type_size (t, compare, source, 1 , allowed_tuplelen)
912
912
@assert t <: r
913
913
# @assert r === _limit_type_size(r, t, source) # this monotonicity constraint is slightly stronger than actually required,
914
914
# since we only actually need to demonstrate that repeated application would reaches a fixed point,
918
918
919
919
sym_isless (a:: Symbol , b:: Symbol ) = ccall (:strcmp , Int32, (Ptr{UInt8}, Ptr{UInt8}), a, b) < 0
920
920
921
- function type_more_complex (@nospecialize (t), @nospecialize (c), sources:: SimpleVector , tupledepth:: Int , allowed_tuplelen:: Int )
921
+ function type_more_complex (@nospecialize (t), @nospecialize (c), sources:: SimpleVector , depth :: Int , tupledepth:: Int , allowed_tuplelen:: Int )
922
922
# detect cases where the comparison is trivial
923
923
if t === c
924
924
return false
@@ -928,7 +928,7 @@ function type_more_complex(@nospecialize(t), @nospecialize(c), sources::SimpleVe
928
928
return false # fastpath: unparameterized types are always finite
929
929
elseif tupledepth > 0 && isa (unwrap_unionall (t), DataType) && isa (c, Type) && c != = Union{} && c <: t
930
930
return false # t is already wider than the comparison in the type lattice
931
- elseif tupledepth > 0 && is_derived_type_from_any (unwrap_unionall (t), sources)
931
+ elseif tupledepth > 0 && is_derived_type_from_any (unwrap_unionall (t), sources, depth )
932
932
return false # t isn't something new
933
933
end
934
934
# peel off wrappers
@@ -942,19 +942,20 @@ function type_more_complex(@nospecialize(t), @nospecialize(c), sources::SimpleVe
942
942
end
943
943
# rules for various comparison types
944
944
if isa (c, TypeVar)
945
+ tupledepth = 1 # allow replacing a TypeVar with a concrete value (since we know the UnionAll must be in covariant position)
945
946
if isa (t, TypeVar)
946
947
return ! (t. lb === Union{} || t. lb === c. lb) || # simplify lb towards Union{}
947
- type_more_complex (t. ub, c. ub, sources, tupledepth, 0 )
948
+ type_more_complex (t. ub, c. ub, sources, depth + 1 , tupledepth, 0 )
948
949
end
949
950
c. lb === Union{} || return true
950
- return type_more_complex (t, c. ub, sources, max (tupledepth, 1 ) , 0 ) # allow replacing a TypeVar with a concrete value
951
+ return type_more_complex (t, c. ub, sources, depth, tupledepth , 0 )
951
952
elseif isa (c, Union)
952
953
if isa (t, Union)
953
- return type_more_complex (t. a, c. a, sources, tupledepth, allowed_tuplelen) ||
954
- type_more_complex (t. b, c. b, sources, tupledepth, allowed_tuplelen)
954
+ return type_more_complex (t. a, c. a, sources, depth, tupledepth, allowed_tuplelen) ||
955
+ type_more_complex (t. b, c. b, sources, depth, tupledepth, allowed_tuplelen)
955
956
end
956
- return type_more_complex (t, c. a, sources, tupledepth, allowed_tuplelen) &&
957
- type_more_complex (t, c. b, sources, tupledepth, allowed_tuplelen)
957
+ return type_more_complex (t, c. a, sources, depth, tupledepth, allowed_tuplelen) &&
958
+ type_more_complex (t, c. b, sources, depth, tupledepth, allowed_tuplelen)
958
959
elseif isa (t, Int) && isa (c, Int)
959
960
return t != = 1 # alternatively, could use !(0 <= t < c)
960
961
end
@@ -987,34 +988,41 @@ function type_more_complex(@nospecialize(t), @nospecialize(c), sources::SimpleVe
987
988
end
988
989
end
989
990
end
990
- type_more_complex (tPi, cPi, sources, tupledepth, 0 ) && return true
991
+ type_more_complex (tPi, cPi, sources, depth + 1 , tupledepth, 0 ) && return true
991
992
end
992
993
return false
993
994
elseif isvarargtype (c)
994
- return type_more_complex (t, unwrapva (c), sources, tupledepth, 0 )
995
+ return type_more_complex (t, unwrapva (c), sources, depth, tupledepth, 0 )
995
996
end
996
997
if isType (t) # allow taking typeof any source type anywhere as Type{...}, as long as it isn't nesting Type{Type{...}}
997
998
tt = unwrap_unionall (t. parameters[1 ])
998
999
if isa (tt, DataType) && ! isType (tt)
999
- is_derived_type_from_any (tt, sources) || return true
1000
+ is_derived_type_from_any (tt, sources, depth ) || return true
1000
1001
return false
1001
1002
end
1002
1003
end
1003
1004
end
1004
1005
return true
1005
1006
end
1006
1007
1007
- function is_derived_type (@nospecialize (t), @nospecialize (c)) # try to find `type` somewhere in `comparison` type
1008
- t === c && return true
1008
+ # try to find `type` somewhere in `comparison` type
1009
+ # at a minimum nesting depth of `mindepth`
1010
+ function is_derived_type (@nospecialize (t), @nospecialize (c), mindepth:: Int )
1011
+ if mindepth > 0
1012
+ mindepth -= 1
1013
+ end
1014
+ if t === c
1015
+ return mindepth == 0
1016
+ end
1009
1017
if isa (c, TypeVar)
1010
1018
# see if it is replacing a TypeVar upper bound with something simpler
1011
- return is_derived_type (t, c. ub)
1019
+ return is_derived_type (t, c. ub, mindepth )
1012
1020
elseif isa (c, Union)
1013
1021
# see if it is one of the elements of the union
1014
- return is_derived_type (t, c. a) || is_derived_type (t, c. b)
1022
+ return is_derived_type (t, c. a, mindepth + 1 ) || is_derived_type (t, c. b, mindepth + 1 )
1015
1023
elseif isa (c, UnionAll)
1016
1024
# see if it is derived from the body
1017
- return is_derived_type (t, c. body)
1025
+ return is_derived_type (t, c. body, mindepth )
1018
1026
elseif isa (c, DataType)
1019
1027
if isa (t, DataType)
1020
1028
# see if it is one of the supertypes of a parameter
@@ -1027,7 +1035,7 @@ function is_derived_type(@nospecialize(t), @nospecialize(c)) # try to find `type
1027
1035
# see if it was extracted from a type parameter
1028
1036
cP = c. parameters
1029
1037
for p in cP
1030
- is_derived_type (t, p) && return true
1038
+ is_derived_type (t, p, mindepth ) && return true
1031
1039
end
1032
1040
if isleaftype (c) && isbits (c)
1033
1041
# see if it was extracted from a fieldtype
@@ -1038,21 +1046,22 @@ function is_derived_type(@nospecialize(t), @nospecialize(c)) # try to find `type
1038
1046
# it cannot have a reference cycle in the type graph
1039
1047
cF = c. types
1040
1048
for f in cF
1041
- is_derived_type (t, f) && return true
1049
+ is_derived_type (t, f, mindepth ) && return true
1042
1050
end
1043
1051
end
1044
1052
end
1045
1053
return false
1046
1054
end
1047
1055
1048
- function is_derived_type_from_any (@nospecialize (t), sources:: SimpleVector )
1056
+ function is_derived_type_from_any (@nospecialize (t), sources:: SimpleVector , mindepth :: Int )
1049
1057
for s in sources
1050
- is_derived_type (t, s) && return true
1058
+ is_derived_type (t, s, mindepth ) && return true
1051
1059
end
1052
1060
return false
1053
1061
end
1054
1062
1055
- function _limit_type_size (@nospecialize (t), @nospecialize (c), sources:: SimpleVector , allowed_tuplelen:: Int ) # type vs. comparison which was derived from source
1063
+ # type vs. comparison or which was derived from source
1064
+ function _limit_type_size (@nospecialize (t), @nospecialize (c), sources:: SimpleVector , depth:: Int , allowed_tuplelen:: Int )
1056
1065
if t === c
1057
1066
return t # quick egal test
1058
1067
elseif t === Union{}
@@ -1061,7 +1070,7 @@ function _limit_type_size(@nospecialize(t), @nospecialize(c), sources::SimpleVec
1061
1070
return t # fast path: unparameterized are always simple
1062
1071
elseif isa (unwrap_unionall (t), DataType) && isa (c, Type) && c != = Union{} && c <: t
1063
1072
return t # t is already wider than the comparison in the type lattice
1064
- elseif is_derived_type_from_any (unwrap_unionall (t), sources)
1073
+ elseif is_derived_type_from_any (unwrap_unionall (t), sources, depth )
1065
1074
return t # t isn't something new
1066
1075
end
1067
1076
if isa (t, TypeVar)
@@ -1072,8 +1081,8 @@ function _limit_type_size(@nospecialize(t), @nospecialize(c), sources::SimpleVec
1072
1081
end
1073
1082
elseif isa (t, Union)
1074
1083
if isa (c, Union)
1075
- a = _limit_type_size (t. a, c. a, sources, allowed_tuplelen)
1076
- b = _limit_type_size (t. b, c. b, sources, allowed_tuplelen)
1084
+ a = _limit_type_size (t. a, c. a, sources, depth, allowed_tuplelen)
1085
+ b = _limit_type_size (t. b, c. b, sources, depth, allowed_tuplelen)
1077
1086
return Union{a, b}
1078
1087
end
1079
1088
elseif isa (t, UnionAll)
@@ -1082,11 +1091,11 @@ function _limit_type_size(@nospecialize(t), @nospecialize(c), sources::SimpleVec
1082
1091
cv = c. var
1083
1092
if tv. ub === cv. ub
1084
1093
if tv. lb === cv. lb
1085
- return UnionAll (tv, _limit_type_size (t. body, c. body, sources, allowed_tuplelen))
1094
+ return UnionAll (tv, _limit_type_size (t. body, c. body, sources, depth + 1 , allowed_tuplelen))
1086
1095
end
1087
1096
ub = tv. ub
1088
1097
else
1089
- ub = _limit_type_size (tv. ub, cv. ub, sources, 0 )
1098
+ ub = _limit_type_size (tv. ub, cv. ub, sources, depth + 1 , 0 )
1090
1099
end
1091
1100
if tv. lb === cv. lb
1092
1101
lb = tv. lb
@@ -1095,21 +1104,21 @@ function _limit_type_size(@nospecialize(t), @nospecialize(c), sources::SimpleVec
1095
1104
lb = Bottom
1096
1105
end
1097
1106
v2 = TypeVar (tv. name, lb, ub)
1098
- return UnionAll (v2, _limit_type_size (t{v2}, c{v2}, sources, allowed_tuplelen))
1107
+ return UnionAll (v2, _limit_type_size (t{v2}, c{v2}, sources, depth + 1 , allowed_tuplelen))
1099
1108
end
1100
- tbody = _limit_type_size (t. body, c, sources, allowed_tuplelen)
1109
+ tbody = _limit_type_size (t. body, c, sources, depth + 1 , allowed_tuplelen)
1101
1110
tbody === t. body && return t
1102
1111
return UnionAll (t. var, tbody)
1103
1112
elseif isa (c, UnionAll)
1104
1113
# peel off non-matching wrapper of comparison
1105
- return _limit_type_size (t, c. body, sources, allowed_tuplelen)
1114
+ return _limit_type_size (t, c. body, sources, depth, allowed_tuplelen)
1106
1115
elseif isa (t, DataType)
1107
1116
if isa (c, DataType)
1108
1117
tP = t. parameters
1109
1118
cP = c. parameters
1110
1119
if t. name === c. name && ! isempty (cP)
1111
1120
if isvarargtype (t)
1112
- VaT = _limit_type_size (tP[1 ], cP[1 ], sources, 0 )
1121
+ VaT = _limit_type_size (tP[1 ], cP[1 ], sources, depth + 1 , 0 )
1113
1122
N = tP[2 ]
1114
1123
if isa (N, TypeVar) || N === cP[2 ]
1115
1124
return Vararg{VaT, N}
@@ -1136,19 +1145,19 @@ function _limit_type_size(@nospecialize(t), @nospecialize(c), sources::SimpleVec
1136
1145
else
1137
1146
cPi = Any
1138
1147
end
1139
- Q[i] = _limit_type_size (Q[i], cPi, sources, 0 )
1148
+ Q[i] = _limit_type_size (Q[i], cPi, sources, depth + 1 , 0 )
1140
1149
end
1141
1150
return Tuple{Q... }
1142
1151
end
1143
1152
elseif isvarargtype (c)
1144
1153
# Tuple{Vararg{T}} --> Tuple{T} is OK
1145
- return _limit_type_size (t, cP[1 ], sources, 0 )
1154
+ return _limit_type_size (t, cP[1 ], sources, depth, 0 )
1146
1155
end
1147
1156
end
1148
1157
if isType (t) # allow taking typeof as Type{...}, but ensure it doesn't start nesting
1149
1158
tt = unwrap_unionall (t. parameters[1 ])
1150
1159
if isa (tt, DataType) && ! isType (tt)
1151
- is_derived_type_from_any (tt, sources) && return t
1160
+ is_derived_type_from_any (tt, sources, depth ) && return t
1152
1161
end
1153
1162
end
1154
1163
if isvarargtype (t)
@@ -1864,43 +1873,23 @@ function abstract_call_method(method::Method, @nospecialize(f), @nospecialize(si
1864
1873
end
1865
1874
1866
1875
if limited
1867
- newsig = sig
1868
1876
sigtuple = unwrap_unionall (sig):: DataType
1869
1877
msig = unwrap_unionall (method. sig):: DataType
1870
- max_spec_len = length (msig. parameters) + 1
1878
+ spec_len = length (msig. parameters) + 1
1871
1879
ls = length (sigtuple. parameters)
1872
1880
if method === sv. linfo. def
1873
1881
# direct self-recursion permits much greater use of reducers
1874
1882
# without using non-local state (just the total edge)
1875
1883
# here we assume that complexity(specTypes) :>= complexity(sig)
1876
1884
comparison = sv. linfo. specTypes
1877
1885
l_comparison = length (unwrap_unionall (comparison). parameters)
1878
- max_spec_len = max (max_spec_len , l_comparison)
1886
+ spec_len = max (spec_len , l_comparison)
1879
1887
else
1880
1888
comparison = method. sig
1881
1889
end
1882
- if method. isva && ls > max_spec_len
1883
- # limit length based on size of definition signature.
1884
- # for example, given function f(T, Any...), limit to 3 arguments
1885
- # instead of the default (MAX_TUPLETYPE_LEN)
1886
- fst = sigtuple. parameters[max_spec_len]
1887
- allsame = true
1888
- # allow specializing on longer arglists if all the trailing
1889
- # arguments are the same, since there is no exponential
1890
- # blowup in this case.
1891
- for i = (max_spec_len + 1 ): ls
1892
- if sigtuple. parameters[i] != fst
1893
- allsame = false
1894
- break
1895
- end
1896
- end
1897
- if ! allsame
1898
- sigtuple = limit_tuple_type_n (sigtuple, max_spec_len)
1899
- newsig = rewrap_unionall (sigtuple, newsig)
1900
- end
1901
- end
1902
- # see if the type is still too big, and limit it further if still required
1903
- newsig = limit_type_size (newsig, comparison, sv. linfo. specTypes, max_spec_len)
1890
+ # see if the type is too big, and limit it if required
1891
+ newsig = limit_type_size (sig, comparison, sv. linfo. specTypes, spec_len)
1892
+
1904
1893
if newsig != = sig
1905
1894
if ! sv. limited
1906
1895
# continue inference, but limit parameter complexity to ensure (quick) convergence
@@ -1937,6 +1926,7 @@ function abstract_call_method(method::Method, @nospecialize(f), @nospecialize(si
1937
1926
end
1938
1927
sparams = recomputed[2 ]:: SimpleVector
1939
1928
end
1929
+
1940
1930
rt, edge = typeinf_edge (method, sig, sparams, sv)
1941
1931
edge != = nothing && add_backedge! (edge:: MethodInstance , sv)
1942
1932
return rt
0 commit comments