@@ -89,7 +89,8 @@ function abstract_call_gf_by_type(@nospecialize(f), argtypes::Vector{Any}, @nosp
89
89
this_rt === Any && break
90
90
end
91
91
else
92
- this_rt, edgecycle, edge = abstract_call_method (method, sig, match[2 ]:: SimpleVector , sv)
92
+ this_rt, edgecycle1, edge = abstract_call_method (method, sig, match[2 ]:: SimpleVector , sv)
93
+ edgecycle |= edgecycle1:: Bool
93
94
if edge != = nothing
94
95
push! (edges, edge)
95
96
end
@@ -170,53 +171,58 @@ function abstract_call_method_with_const_args(@nospecialize(rettype), @nospecial
170
171
method. isva && (nargs -= 1 )
171
172
length (argtypes) >= nargs || return Any
172
173
haveconst = false
174
+ allconst = true
175
+ # see if any or all of the arguments are constant and propagating constants may be worthwhile
173
176
for a in argtypes
174
177
a = widenconditional (a)
175
- if has_nontrivial_const_info (a)
176
- haveconst = const_prop_profitable (a)
177
- haveconst && break
178
+ if allconst && ! isa (a, Const) && ! isconstType (a) && ! isa (a, PartialStruct)
179
+ allconst = false
180
+ end
181
+ if ! haveconst && has_nontrivial_const_info (a) && const_prop_profitable (a)
182
+ haveconst = true
183
+ end
184
+ if haveconst && ! allconst
185
+ break
178
186
end
179
187
end
180
188
haveconst || improvable_via_constant_propagation (rettype) || return Any
181
189
sig = match[1 ]
182
190
sparams = match[2 ]:: SimpleVector
183
- code = code_for_method (method, sig, sparams, sv. params. world)
184
- code === nothing && return Any
185
- code = code:: MethodInstance
186
- # decide if it's likely to be worthwhile
187
- declared_inline = isdefined (method, :source ) && ccall (:jl_ast_flag_inlineable , Bool, (Any,), method. source)
188
- cache_inlineable = declared_inline
189
- if isdefined (code, :inferred ) && ! cache_inlineable
190
- cache_inf = code. inferred
191
- if ! (cache_inf === nothing )
192
- cache_src_inferred = ccall (:jl_ast_flag_inferred , Bool, (Any,), cache_inf)
193
- cache_src_inlineable = ccall (:jl_ast_flag_inlineable , Bool, (Any,), cache_inf)
194
- cache_inlineable = cache_src_inferred && cache_src_inlineable
195
- end
191
+ force_inference = allconst || sv. params. aggressive_constant_propagation
192
+ if istopfunction (f, :getproperty ) || istopfunction (f, :setproperty! )
193
+ force_inference = true
196
194
end
197
- if ! cache_inlineable && ! sv. params. aggressive_constant_propagation
198
- tm = _topmod (sv)
199
- if ! istopfunction (f, :getproperty ) && ! istopfunction (f, :setproperty! )
200
- # in this case, see if all of the arguments are constants
201
- for a in argtypes
202
- a = widenconditional (a)
203
- if ! isa (a, Const) && ! isconstType (a) && ! isa (a, PartialStruct)
204
- return Any
205
- end
195
+ mi = specialize_method (method, sig, sparams, ! force_inference)
196
+ mi === nothing && return Any
197
+ mi = mi:: MethodInstance
198
+ # decide if it's likely to be worthwhile
199
+ if ! force_inference
200
+ code = inf_for_methodinstance (mi, sv. params. world)
201
+ declared_inline = isdefined (method, :source ) && ccall (:jl_ast_flag_inlineable , Bool, (Any,), method. source)
202
+ cache_inlineable = declared_inline
203
+ if isdefined (code, :inferred ) && ! cache_inlineable
204
+ cache_inf = code. inferred
205
+ if ! (cache_inf === nothing )
206
+ cache_src_inferred = ccall (:jl_ast_flag_inferred , Bool, (Any,), cache_inf)
207
+ cache_src_inlineable = ccall (:jl_ast_flag_inlineable , Bool, (Any,), cache_inf)
208
+ cache_inlineable = cache_src_inferred && cache_src_inlineable
206
209
end
207
210
end
211
+ if ! cache_inlineable
212
+ return Any
213
+ end
208
214
end
209
- inf_result = cache_lookup (code , argtypes, sv. params. cache)
215
+ inf_result = cache_lookup (mi , argtypes, sv. params. cache)
210
216
if inf_result === nothing
211
- inf_result = InferenceResult (code , argtypes)
217
+ inf_result = InferenceResult (mi , argtypes)
212
218
frame = InferenceState (inf_result, #= cache=# false , sv. params)
213
219
frame. limited = true
214
220
frame. parent = sv
215
221
push! (sv. params. cache, inf_result)
216
222
typeinf (frame) || return Any
217
223
end
218
224
result = inf_result. result
219
- isa (result, InferenceState) && return Any # TODO : is this recursive constant inference?
225
+ isa (result, InferenceState) && return Any # TODO : unexpected, is this recursive constant inference?
220
226
add_backedge! (inf_result. linfo, sv)
221
227
return result
222
228
end
@@ -237,7 +243,7 @@ function abstract_call_method(method::Method, @nospecialize(sig), sparams::Simpl
237
243
# necessary in order to retrieve this field from the generated `CodeInfo`, if it exists.
238
244
# The other `CodeInfo`s we inspect will already have this field inflated, so we just
239
245
# access it directly instead (to avoid regeneration).
240
- method2 = method_for_inference_heuristics (method, sig, sparams, sv . params . world ) # Union{Method, Nothing}
246
+ method2 = method_for_inference_heuristics (method, sig, sparams) # Union{Method, Nothing}
241
247
sv_method2 = sv. src. method_for_inference_limit_heuristics # limit only if user token match
242
248
sv_method2 isa Method || (sv_method2 = nothing ) # Union{Method, Nothing}
243
249
while ! (infstate === nothing )
0 commit comments