Skip to content

Short-circuit empty branches in function and list emptiness checks - #16032

Merged
josevalim merged 1 commit into
mainfrom
jv-optimize-fun-phi
Oct 29, 2026
Merged

josevalim merged 1 commit into
mainfrom
jv-optimize-fun-phi

Conversation

@josevalim

Copy link
Copy Markdown
Member

Similar to #15619, avoid exploring branches whose result is already known.

In phi, a branch whose refined return type (ret ∧ return) or refined argument (arg ∖ type) is empty is true, as empty types are never refined back, so we return true without recursing over the remaining positives.

In list_line_empty?, subtype_seen?/3 already computes the difference between the last types, so compute it once instead of computing it again and re-checking its emptiness when the subtype check fails.

Timings per subtype?/2 call, before and after:

Case Before After
fun, 5 arrows with none() args (holds) 114µs 6.7µs
fun, 5 arrows with none() args (fails) 58µs 4.4µs
non_empty_list, 4 negatives cover the tail 1.62µs 1.49µs
non_empty_list, partial cover 1.27µs 1.13µs

Assisted-by: Claude Code:claude-opus-5-5

  • Describe here the reasons behind the pull request.
  • Make sure you have read the CONTRIBUTING.md file.
  • Make sure any relevant documentation and tests have been added/updated.
  • Do not submit Draft pull requests unless previously asked/agreed.

@josevalim
josevalim requested a review from gldubc October 28, 2026 14:57
@josevalim josevalim closed this Oct 28, 2026
@josevalim josevalim reopened this Oct 28, 2026
Similar to #15619, avoid exploring branches whose result is already known.

In phi, a branch whose refined return type (ret ∧ return) or refined
argument (arg ∖ type) is empty is true, as empty types are never refined
back, so we return true without recursing over the remaining positives.

In list_line_empty?, subtype_seen?/3 already computes the difference
between the last types, so compute it once instead of computing it again
and re-checking its emptiness when the subtype check fails.

Timings per subtype?/2 call, before and after:

| Case                                        | Before  | After  |
|---------------------------------------------|---------|--------|
| fun, 5 arrows with none() args (holds)      | 114µs   | 6.7µs  |
| fun, 5 arrows with none() args (fails)      | 58µs    | 4.4µs  |
| non_empty_list, 4 negatives cover the tail  | 1.62µs  | 1.49µs |
| non_empty_list, partial cover               | 1.27µs  | 1.13µs |

Assisted-by: Claude Code:claude-opus-5-5
@josevalim
josevalim force-pushed the jv-optimize-fun-phi branch from c4e635b to e4867f4 Compare October 28, 2026 16:14
@josevalim
josevalim merged commit 3fca4d0 into main Oct 29, 2026
26 checks passed
@josevalim
josevalim deleted the jv-optimize-fun-phi branch October 29, 2026 17:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants