Skip to content

Improve return type inferrability of in for homogeneous tuples#61526

Open
aviatesk wants to merge 2 commits intomasterfrom
avi/tuple-in-inferrability
Open

Improve return type inferrability of in for homogeneous tuples#61526
aviatesk wants to merge 2 commits intomasterfrom
avi/tuple-in-inferrability

Conversation

@aviatesk
Copy link
Copy Markdown
Member

@aviatesk aviatesk commented Apr 7, 2026

Overload _in_tuple for Tuple{Vararg{T}} so that, when the element type T is known not to intersect Missing, the return type is pinned as Bool rather than Union{Bool,Missing}.

This is motivated by JET(LS), which reports diagnostics when a non-Bool value appears in a branch condition. Without this change, straightforward code like:

function get_valid_flags(xs::Vector{String})
    flags = tuple(xs...)
    "flag" in flags ? flags : nothing  # non-boolean `Missing` found in boolean context (1/2 union split)
end

because the inferred return type of
::String in ::Tuple{Vararg{String}} is currently Union{Bool,Missing}, even though elements are all String and it's trivially clear that it never returns missing.

Implementation notes:

  • Rather than adding a new in method for Tuple{Vararg{T}}, this overloads _in_tuple instead. Adding a separate ::Any in ::Tuple{Vararg{T}} method would increase the number of methods matching x::Any in itr::Tuple from 3 to 4, potentially degrading inferrability at abstract call sites.
  • The additional hasintersect(T, Missing) would no runtime cost: the added _in_tuple is only compiled for concrete T, and in that case the typeintersect result will be statically inlined.

aviatesk and others added 2 commits April 8, 2026 02:12
Overload `_in_tuple` for `Tuple{Vararg{T}}` so that, when the element
type `T` is known not to intersect `Missing`, the return type is pinned
as `Bool` rather than `Union{Bool,Missing}`.

This is motivated by JET(LS), which reports diagnostics when a
non-`Bool` value appears in a branch condition. Without this change,
straightforward code like:

```julia
function get_valid_flags(xs::Vector{String})
    flags = tuple(xs...)
    "flag" in flags ? flags : nothing  # non-boolean `Missing` found in boolean context (1/2 union split)
end
```
because the inferred return type of
`::String in ::Tuple{Vararg{String}}` is currently
`Union{Bool,Missing}`, even though elements are all `String` and it's
trivially clear that it never returns `missing`.

Implementation notes:
- Rather than adding a new `in` method for `Tuple{Vararg{T}}`, this
  overloads `_in_tuple` instead. Adding a separate
  `::Any in ::Tuple{Vararg{T}}` method would increase the number of
  methods matching `x::Any in itr::Tuple` from 3 to 4, potentially
  degrading inferrability at abstract call sites.
- The additional `hasintersect(T, Missing)` would no runtime cost: the
  added `_in_tuple` is only compiled for concrete `T`, and in that case
  the `typeintersect` result will be statically inlined.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant