You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This PR propagates `Conditional`s inter-procedurally when a
`Conditional` at return site imposes a constraint on the call arguments.
When inference exits local frame and the return type is annotated as
`Conditional`, it will be converted into `InterConditional` object,
which is implemented in `Core` and can be directly put into the global
cache. Finally after going back to caller frame, `InterConditional` will
be re-converted into `Conditional` in the context of the caller frame.
So now some simple "is-wrapper" functions will propagate its constraint
as expected, e.g.:
```julia
isaint(a) = isa(a, Int)
@test Base.return_types((Any,)) do a
isaint(a) && return a # a::Int
return 0
end == [Int]
```
This PR also tweaks `isnothing` and `ismissing` so that there is no
longer any inferrability penalties to use them instead of
`x === nothing` or `x === missing` e.g.:
```julia
@test Base.return_types((Union{Nothing,Int},)) do a
isnothing(a) && return 0
return a # a::Int
end == [Int]
```
(and now we don't need something like #38636)
There're certain limitations around. One of the biggest ones would be
that it can propagate constrains only on a single argument, and it fails
to back-propagate constrains when there're multiple conditions on
different slots, e.g. `Meta.isexpr` can't still propagate its type
constraint to the caller:
```julia
@test_broken Base.return_types((Any,)) do x
Meta.isexpr(x, :call) && return x # still x::Any but ideally x::Expr
return nothing
end == [Nothing,Expr]
```
(and because of this reason, this PR can't close#37342)
0 commit comments