@@ -125,19 +125,16 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
125
125
splitsigs = switchtupleunion (sig)
126
126
for sig_n in splitsigs
127
127
result = abstract_call_method (interp, method, sig_n, svec (), multiple_matches, sv)
128
- rt = result. rt
129
- edge = result. edge
128
+ (; rt, edge, effects) = result
130
129
edge != = nothing && push! (edges, edge)
131
130
this_argtypes = isa (matches, MethodMatches) ? argtypes : matches. applicable_argtypes[i]
132
131
this_arginfo = ArgInfo (fargs, this_argtypes)
133
132
const_call_result = abstract_call_method_with_const_args (interp, result,
134
133
f, this_arginfo, match, sv)
135
- effects = result. edge_effects
136
134
const_result = nothing
137
135
if const_call_result != = nothing
138
- const_rt = const_call_result. rt
139
- if const_rt ⊑ rt
140
- rt = const_rt
136
+ if const_call_result. rt ⊑ rt
137
+ rt = const_call_result. rt
141
138
(; effects, const_result) = const_call_result
142
139
end
143
140
end
@@ -167,17 +164,16 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
167
164
end
168
165
169
166
result = abstract_call_method (interp, method, sig, match. sparams, multiple_matches, sv)
170
- this_conditional = ignorelimited ( result. rt)
171
- this_rt = widenwrappedconditional (result . rt)
172
- edge = result . edge
167
+ (; rt, edge, effects) = result
168
+ this_conditional = ignorelimited ( rt)
169
+ this_rt = widenwrappedconditional (rt)
173
170
edge != = nothing && push! (edges, edge)
174
171
# try constant propagation with argtypes for this match
175
172
# this is in preparation for inlining, or improving the return result
176
173
this_argtypes = isa (matches, MethodMatches) ? argtypes : matches. applicable_argtypes[i]
177
174
this_arginfo = ArgInfo (fargs, this_argtypes)
178
175
const_call_result = abstract_call_method_with_const_args (interp, result,
179
176
f, this_arginfo, match, sv)
180
- effects = result. edge_effects
181
177
const_result = nothing
182
178
if const_call_result != = nothing
183
179
this_const_conditional = ignorelimited (const_call_result. rt)
@@ -606,7 +602,8 @@ function abstract_call_method(interp::AbstractInterpreter, method::Method, @nosp
606
602
sparams = recomputed[2 ]:: SimpleVector
607
603
end
608
604
609
- (; rt, edge, edge_effects) = typeinf_edge (interp, method, sig, sparams, sv)
605
+ (; rt, edge, effects) = typeinf_edge (interp, method, sig, sparams, sv)
606
+
610
607
if edge === nothing
611
608
edgecycle = edgelimited = true
612
609
end
@@ -615,16 +612,17 @@ function abstract_call_method(interp::AbstractInterpreter, method::Method, @nosp
615
612
# may have been tainted due to recursion at this point even if it's overridden
616
613
if is_effect_overridden (sv, :terminates_globally )
617
614
# this frame is known to terminate
618
- edge_effects = Effects (edge_effects , terminates= ALWAYS_TRUE)
615
+ effects = Effects (effects , terminates= ALWAYS_TRUE)
619
616
elseif is_effect_overridden (method, :terminates_globally )
620
617
# this edge is known to terminate
621
- edge_effects = Effects (edge_effects ; terminates= ALWAYS_TRUE)
618
+ effects = Effects (effects ; terminates= ALWAYS_TRUE)
622
619
elseif edgecycle
623
620
# Some sort of recursion was detected. Even if we did not limit types,
624
621
# we cannot guarantee that the call will terminate
625
- edge_effects = Effects (edge_effects ; terminates= TRISTATE_UNKNOWN)
622
+ effects = Effects (effects ; terminates= TRISTATE_UNKNOWN)
626
623
end
627
- return MethodCallResult (rt, edgecycle, edgelimited, edge, edge_effects)
624
+
625
+ return MethodCallResult (rt, edgecycle, edgelimited, edge, effects)
628
626
end
629
627
630
628
function edge_matches_sv (frame:: InferenceState , method:: Method , @nospecialize (sig), sparams:: SimpleVector , hardlimit:: Bool , sv:: InferenceState )
@@ -700,13 +698,13 @@ struct MethodCallResult
700
698
edgecycle:: Bool
701
699
edgelimited:: Bool
702
700
edge:: Union{Nothing,MethodInstance}
703
- edge_effects :: Effects
701
+ effects :: Effects
704
702
function MethodCallResult (@nospecialize (rt),
705
703
edgecycle:: Bool ,
706
704
edgelimited:: Bool ,
707
705
edge:: Union{Nothing,MethodInstance} ,
708
- edge_effects :: Effects )
709
- return new (rt, edgecycle, edgelimited, edge, edge_effects )
706
+ effects :: Effects )
707
+ return new (rt, edgecycle, edgelimited, edge, effects )
710
708
end
711
709
end
712
710
@@ -751,10 +749,10 @@ function concrete_eval_eligible(interp::AbstractInterpreter,
751
749
@nospecialize (f), result:: MethodCallResult , arginfo:: ArgInfo , sv:: InferenceState )
752
750
# disable concrete-evaluation if this function call is tainted by some overlayed
753
751
# method since currently there is no direct way to execute overlayed methods
754
- isoverlayed (method_table (interp)) && ! is_nonoverlayed (result. edge_effects ) && return false
752
+ isoverlayed (method_table (interp)) && ! is_nonoverlayed (result. effects ) && return false
755
753
return f != = nothing &&
756
754
result. edge != = nothing &&
757
- is_foldable (result. edge_effects ) &&
755
+ is_foldable (result. effects ) &&
758
756
is_all_const_arg (arginfo)
759
757
end
760
758
@@ -785,7 +783,7 @@ function concrete_eval_call(interp::AbstractInterpreter,
785
783
Core. _call_in_world_total (world, f, args... )
786
784
catch
787
785
# The evaulation threw. By :consistent-cy, we're guaranteed this would have happened at runtime
788
- return ConstCallResults (Union{}, ConcreteResult (result. edge:: MethodInstance , result. edge_effects ), result. edge_effects )
786
+ return ConstCallResults (Union{}, ConcreteResult (result. edge:: MethodInstance , result. effects ), result. effects )
789
787
end
790
788
if is_inlineable_constant (value) || call_result_unused (sv)
791
789
# If the constant is not inlineable, still do the const-prop, since the
@@ -929,7 +927,7 @@ function const_prop_entry_heuristic(interp::AbstractInterpreter, result::MethodC
929
927
return false
930
928
else
931
929
if isa (rt, Const)
932
- if result. edge_effects . nothrow != = ALWAYS_TRUE
930
+ if result. effects . nothrow != = ALWAYS_TRUE
933
931
# Could still be improved to Bottom (or at least could see the effects improved)
934
932
return true
935
933
end
@@ -1596,8 +1594,8 @@ function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgIn
1596
1594
method = match. method
1597
1595
tienv = ccall (:jl_type_intersection_with_env , Any, (Any, Any), nargtype, method. sig):: SimpleVector
1598
1596
ti = tienv[1 ]; env = tienv[2 ]:: SimpleVector
1599
- (; rt, edge) = result = abstract_call_method (interp, method, ti, env, false , sv)
1600
- effects = result. edge_effects
1597
+ result = abstract_call_method (interp, method, ti, env, false , sv)
1598
+ (; rt, edge, effects) = result
1601
1599
edge != = nothing && add_backedge! (edge:: MethodInstance , sv)
1602
1600
match = MethodMatch (ti, env, method, argtype <: method.sig )
1603
1601
res = nothing
@@ -1746,9 +1744,11 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
1746
1744
return abstract_call_gf_by_type (interp, f, arginfo, atype, sv, max_methods)
1747
1745
end
1748
1746
1749
- function abstract_call_opaque_closure (interp:: AbstractInterpreter , closure:: PartialOpaque , arginfo:: ArgInfo , sv:: InferenceState )
1747
+ function abstract_call_opaque_closure (interp:: AbstractInterpreter ,
1748
+ closure:: PartialOpaque , arginfo:: ArgInfo , sv:: InferenceState , check:: Bool = true )
1750
1749
sig = argtypes_to_type (arginfo. argtypes)
1751
- (; rt, edge, edge_effects) = result = abstract_call_method (interp, closure. source, sig, Core. svec (), false , sv)
1750
+ result = abstract_call_method (interp, closure. source, sig, Core. svec (), false , sv)
1751
+ (; rt, edge, effects) = result
1752
1752
edge != = nothing && add_backedge! (edge, sv)
1753
1753
tt = closure. typ
1754
1754
sigT = (unwrap_unionall (tt):: DataType ). parameters[1 ]
@@ -1759,12 +1759,21 @@ function abstract_call_opaque_closure(interp::AbstractInterpreter, closure::Part
1759
1759
nothing , arginfo, match, sv)
1760
1760
if const_call_result != = nothing
1761
1761
if const_call_result. rt ⊑ rt
1762
- (; rt, const_result) = const_call_result
1762
+ (; rt, effects, const_result) = const_call_result
1763
1763
end
1764
1764
end
1765
1765
end
1766
1766
info = OpaqueClosureCallInfo (match, const_result)
1767
- return CallMeta (from_interprocedural! (rt, sv, arginfo, match. spec_types), edge_effects, info)
1767
+ if check # analyze implicit type asserts on argument and return type
1768
+ ftt = closure. typ
1769
+ (aty, rty) = (unwrap_unionall (ftt):: DataType ). parameters
1770
+ rty = rewrap_unionall (rty isa TypeVar ? rty. lb : rty, ftt)
1771
+ if ! (rt ⊑ rty && tuple_tfunc (arginfo. argtypes[2 : end ]) ⊑ rewrap_unionall (aty, ftt))
1772
+ effects = Effects (effects; nothrow= TRISTATE_UNKNOWN)
1773
+ end
1774
+ end
1775
+ rt = from_interprocedural! (rt, sv, arginfo, match. spec_types)
1776
+ return CallMeta (rt, effects, info)
1768
1777
end
1769
1778
1770
1779
function most_general_argtypes (closure:: PartialOpaque )
@@ -1786,22 +1795,8 @@ function abstract_call(interp::AbstractInterpreter, arginfo::ArgInfo,
1786
1795
if isa (ft, PartialOpaque)
1787
1796
newargtypes = copy (argtypes)
1788
1797
newargtypes[1 ] = ft. env
1789
- body_call = abstract_call_opaque_closure (interp, ft, ArgInfo (arginfo. fargs, newargtypes), sv)
1790
- # Analyze implicit type asserts on argument and return type
1791
- ftt = ft. typ
1792
- (at, rt) = (unwrap_unionall (ftt):: DataType ). parameters
1793
- if isa (rt, TypeVar)
1794
- rt = rewrap_unionall (rt. lb, ftt)
1795
- else
1796
- rt = rewrap_unionall (rt, ftt)
1797
- end
1798
- nothrow = body_call. rt ⊑ rt
1799
- if nothrow
1800
- nothrow = tuple_tfunc (newargtypes[2 : end ]) ⊑ rewrap_unionall (at, ftt)
1801
- end
1802
- return CallMeta (body_call. rt, Effects (body_call. effects,
1803
- nothrow = nothrow ? TRISTATE_UNKNOWN : body_call. effects. nothrow),
1804
- body_call. info)
1798
+ return abstract_call_opaque_closure (interp,
1799
+ ft, ArgInfo (arginfo. fargs, newargtypes), sv, #= check=# true )
1805
1800
elseif (uft = unwrap_unionall (widenconst (ft)); isa (uft, DataType) && uft. name === typename (Core. OpaqueClosure))
1806
1801
return CallMeta (rewrap_unionall ((uft:: DataType ). parameters[2 ], widenconst (ft)), Effects (), false )
1807
1802
elseif f === nothing
@@ -2027,7 +2022,7 @@ function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e),
2027
2022
argtypes = most_general_argtypes (t)
2028
2023
pushfirst! (argtypes, t. env)
2029
2024
callinfo = abstract_call_opaque_closure (interp, t,
2030
- ArgInfo (nothing , argtypes), sv)
2025
+ ArgInfo (nothing , argtypes), sv, #= check =# false )
2031
2026
sv. stmt_info[sv. currpc] = OpaqueClosureCreateInfo (callinfo)
2032
2027
end
2033
2028
end
0 commit comments