Skip to content

fix: report unreachable match case after earlier sibling pattern - #5515

Closed
bniladridas wants to merge 1 commit into
meta:mainfrom
bniladridas:investigate/3338-match-subsumption-v3
Closed

bniladridas wants to merge 1 commit into
meta:mainfrom
bniladridas:investigate/3338-match-subsumption-v3

Conversation

@bniladridas

@bniladridas bniladridas commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #3338.

Any was short-circuited in match-case reachability, so case bool() after case int() was never reported. Narrowing by the current class pattern first, then applying earlier unguarded case negations, reuses the existing narrowing and subtraction path: Any becomes bool, then bool minus int is Never.

This supersedes the closed #5201 approach. It removes the second sibling-subsumption check, the separate class extraction, and the prev_case_ops vector. The binder passes one earlier negation separately, and reachability applies the current pattern before that negation.

Scope

  • detect match case branch subclass #3338 is limited to Any. object keeps the existing early return because structural patterns such as tuples can narrow object to Never spuriously.
  • Partial class patterns are covered for the no-false-positive case, for example case A(x=1) does not subsume case B(). Existing reachability also does not report duplicate partial-class patterns on precise subjects, so positive detection is tracked separately in Report unreachable duplicate partial-class match cases #5516.
  • One projected NarrowOp is cloned because Binding::Narrow and the reachability metadata own separate copies. No vector or class-extraction clone remains.

Test Plan

  • cargo test -p pyrefly pattern_match --quiet: 113 passed, 0 failed.

  • cargo clippy -p pyrefly --lib -- -D warnings: passed.

  • python3 test.py --no-test --no-tensor-shapes --no-conformance --no-jsonschema --no-extension: passed.

  • cargo test -p pyrefly --quiet -- --skip test::cycles::deep_phi_chain_term_expr: 10244 passed, 0 failed, 3 ignored on the rebased origin/main at 10226ec1. That test overflows the default 10 MiB debug stack on clean current origin/main too, so it is unrelated; it passes with PYREFLY_STACK_SIZE=67108864.

  • New regression covers Any int then bool, subclass-first order, guarded predecessor, duplicate literal, Or-pattern, object no-report, and partial-class no-false-positive.

  • I am a human, and I fully understand the code I am submitting.

Narrow by the current case pattern before applying earlier unguarded case negations. This lets an Any subject become its current class first, so subtracting an earlier superclass produces Never and the case is reported unreachable.

Keep object subjects on the existing early return because structural patterns can narrow object to Never spuriously. The check is limited to the Any case tracked by meta#3338.

Signed-off-by: Niladri Das <125604915+bniladridas@users.noreply.github.com>
@meta-codesync

meta-codesync Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

This pull request has been imported. If you are a Meta employee, you can view this in D129509393. (Because this pull request was imported automatically, there will not be any future comments.)

@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown

Diff from mypy_primer, showing the effect of this PR on open source code:

============================================================
SUMMARY
============================================================
Total: +5 new errors, -0 fixed errors
By preset: +5/-0 (default), +5/-0 (strict)

Projects with changes (1):
  pytensor: +5 -0
============================================================

FULL DIFF DETAILS
------------------------------------------------------------

pytensor (https://github.com/pymc-devs/pytensor)
+ ERROR pytensor/link/numba/dispatch/sparse/variable.py:340:9-341:49: Case pattern can never match subject of type `Unknown` [unreachable-match-case]
+ ERROR pytensor/link/numba/dispatch/sparse/variable.py:362:9-363:49: Case pattern can never match subject of type `Unknown` [unreachable-match-case]
+ ERROR pytensor/link/numba/dispatch/sparse/variable.py:428:9-429:49: Case pattern can never match subject of type `Unknown` [unreachable-match-case]
+ ERROR pytensor/link/numba/dispatch/sparse/variable.py:571:9-584:28: Case pattern can never match subject of type `Unknown` [unreachable-match-case]
+ ERROR pytensor/link/numba/dispatch/sparse/variable.py:626:9-649:27: Case pattern can never match subject of type `Unknown` [unreachable-match-case]

@rchen152 rchen152 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review automatically exported from Phabricator review in Meta.

@rchen152

rchen152 commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Thanks for reworking this!

@meta-codesync

meta-codesync Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

This pull request has been merged in fd8a152.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

detect match case branch subclass

2 participants