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