Skip to content

Commit 7a65218

Browse files
committed
improve exct modeling for opaque closure calls
1 parent bfeaa27 commit 7a65218

File tree

2 files changed

+25
-10
lines changed

2 files changed

+25
-10
lines changed

base/compiler/abstractinterpretation.jl

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
4242
arginfo::ArgInfo, si::StmtInfo, @nospecialize(atype),
4343
sv::AbsIntState, max_methods::Int)
4444
𝕃ₚ, 𝕃ᵢ = ipo_lattice(interp), typeinf_lattice(interp)
45-
ₚ, ₚ, = partialorder(𝕃ₚ), join(𝕃ₚ), join(𝕃ᵢ)
45+
ₚ, ₚ, ₚ, = partialorder(𝕃ₚ), strictneqpartialorder(𝕃ₚ), join(𝕃ₚ), join(𝕃ᵢ)
4646
argtypes = arginfo.argtypes
4747
matches = find_method_matches(interp, argtypes, atype; max_methods)
4848
if isa(matches, FailedMethodMatch)
@@ -97,7 +97,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
9797
else
9898
add_remark!(interp, sv, "[constprop] Discarded because the result was wider than inference")
9999
end
100-
if !(exct ₚ const_call_result.exct)
100+
if const_call_result.exct exct
101101
exct = const_call_result.exct
102102
(; const_result, edge) = const_call_result
103103
else
@@ -154,7 +154,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
154154
end
155155
# Treat the exception type separately. Currently, constprop often cannot determine the exception type
156156
# because consistent-cy does not apply to exceptions.
157-
if !(this_exct const_call_result.exct)
157+
if const_call_result.exct this_exct
158158
this_exct = const_call_result.exct
159159
(; const_result, edge) = const_call_result
160160
else
@@ -2342,10 +2342,10 @@ function abstract_call_opaque_closure(interp::AbstractInterpreter,
23422342
hasintersect(sig, ocsig) || return CallMeta(Union{}, Union{MethodError,TypeError}, EFFECTS_THROWS, NoCallInfo())
23432343
ocmethod = closure.source::Method
23442344
result = abstract_call_method(interp, ocmethod, sig, Core.svec(), false, si, sv)
2345-
(; rt, edge, effects, volatile_inf_result) = result
2345+
(; rt, exct, edge, effects, volatile_inf_result) = result
23462346
match = MethodMatch(sig, Core.svec(), ocmethod, sig <: ocsig)
23472347
𝕃ₚ = ipo_lattice(interp)
2348-
= (𝕃ₚ)
2348+
, = partialorder(𝕃ₚ), strictneqpartialorder(𝕃ₚ)
23492349
const_result = volatile_inf_result
23502350
if !result.edgecycle
23512351
const_call_result = abstract_call_method_with_const_args(interp, result,
@@ -2354,20 +2354,23 @@ function abstract_call_opaque_closure(interp::AbstractInterpreter,
23542354
if const_call_result.rt ₚ rt
23552355
(; rt, effects, const_result, edge) = const_call_result
23562356
end
2357+
if const_call_result.exct ₚ exct
2358+
(; exct, const_result, edge) = const_call_result
2359+
end
23572360
end
23582361
end
23592362
if check # analyze implicit type asserts on argument and return type
2360-
ftt = closure.typ
2361-
(aty, rty) = (unwrap_unionall(ftt)::DataType).parameters
2362-
rty = rewrap_unionall(rty isa TypeVar ? rty.lb : rty, ftt)
2363-
if !(rt ₚ rty && tuple_tfunc(𝕃ₚ, arginfo.argtypes[2:end]) rewrap_unionall(aty, ftt))
2363+
rty = (unwrap_unionall(tt)::DataType).parameters[2]
2364+
rty = rewrap_unionall(rty isa TypeVar ? rty.ub : rty, tt)
2365+
if !(rt ₚ rty && sig ₚ ocsig)
23642366
effects = Effects(effects; nothrow=false)
2367+
exct = tmerge(𝕃ₚ, exct, TypeError)
23652368
end
23662369
end
23672370
rt = from_interprocedural!(interp, rt, sv, arginfo, match.spec_types)
23682371
info = OpaqueClosureCallInfo(match, const_result)
23692372
edge !== nothing && add_backedge!(sv, edge)
2370-
return CallMeta(rt, Any, effects, info)
2373+
return CallMeta(rt, exct, effects, info)
23712374
end
23722375

23732376
function most_general_argtypes(closure::PartialOpaque)

test/compiler/inference.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6097,3 +6097,15 @@ end >: MethodError
60976097
f = issue55627_make_oc()
60986098
return f(1), f('1')
60996099
end >: TypeError
6100+
6101+
# `exct` modeling for opaque closure
6102+
oc_exct_1() = Base.Experimental.@opaque function (x)
6103+
return x < 0 ? throw(x) : x
6104+
end
6105+
@test Base.infer_exception_type((Int,)) do x
6106+
oc_exct_1()(x)
6107+
end == Int
6108+
oc_exct_2() = Base.Experimental.@opaque Tuple{Number}->Number (x) -> '1'
6109+
@test Base.infer_exception_type((Int,)) do x
6110+
oc_exct_2()(x)
6111+
end == TypeError

0 commit comments

Comments
 (0)