Skip to content

[ty] Infer types for names bound in match patterns - #25637

Merged
charliermarsh merged 0 commit into
charlie/class-pattern-exhaustivenessfrom
charlie/pattern-as
Jun 13, 2026
Merged

[ty] Infer types for names bound in match patterns#25637
charliermarsh merged 0 commit into
charlie/class-pattern-exhaustivenessfrom
charlie/pattern-as

Conversation

@charliermarsh

@charliermarsh charliermarsh commented Jun 4, 2026

Copy link
Copy Markdown
Member

Summary

This PR teaches ty to infer types for names introduced by match patterns.

def f(x: object) -> None:
    match x:
        case [int() as item, _]:
            reveal_type(item)  # revealed: int

Previously, these bindings used a placeholder type. Rather than adding a separate inference path for every pattern form, we extend the existing match-pattern model to describe the names produced by a successful match. The same analysis that determines which values can reach a case now determines what each name refers to.

This covers captures, as patterns, starred sequence captures, and or alternatives. Because binding inference and match narrowing share one model, the resulting types stay consistent across nested patterns, case ordering, unions, generics, and type aliases. The inferred types are also available to hover, go-to-type, and inlay hints.

@astral-sh-bot astral-sh-bot Bot added the ty Multi-file analysis & type inference label Jun 4, 2026
@astral-sh-bot

astral-sh-bot Bot commented Jun 4, 2026

Copy link
Copy Markdown

Typing conformance results

No changes detected ✅

Current numbers
The percentage of diagnostics emitted that were expected errors held steady at 94.36%. The percentage of expected errors that received a diagnostic held steady at 88.82%. The number of fully passing files held steady at 93/134.

@astral-sh-bot

astral-sh-bot Bot commented Jun 4, 2026

Copy link
Copy Markdown

Memory usage report

Memory usage unchanged ✅

@astral-sh-bot

astral-sh-bot Bot commented Jun 4, 2026

Copy link
Copy Markdown

ecosystem-analyzer results

Lint rule Added Removed Changed
invalid-argument-type 11 0 0
type-assertion-failure 0 0 4
invalid-return-type 1 0 0
Total 12 0 4
Raw diff (16 changes)
cwltool (https://github.com/common-workflow-language/cwltool)
+ cwltool/secrets.py:46:40 error[invalid-argument-type] Argument to bound method `SecretStore.has_secret` is incorrect: Expected `int | str | float | ... omitted 4 union elements`, found `object`
+ cwltool/secrets.py:50:40 error[invalid-argument-type] Argument to bound method `SecretStore.has_secret` is incorrect: Expected `int | str | float | ... omitted 4 union elements`, found `object`
+ cwltool/secrets.py:62:24 error[invalid-return-type] Return type does not match returned value: expected `int | str | float | ... omitted 4 union elements`, found `dict[object, int | str | float | ... omitted 4 union elements]`
+ cwltool/secrets.py:62:42 error[invalid-argument-type] Argument to bound method `SecretStore.retrieve` is incorrect: Expected `int | str | float | ... omitted 4 union elements`, found `object`
+ cwltool/secrets.py:64:39 error[invalid-argument-type] Argument to bound method `SecretStore.retrieve` is incorrect: Expected `int | str | float | ... omitted 4 union elements`, found `object`
+ cwltool/process.py:507:44 error[invalid-argument-type] Argument to function `var_spool_cwl_detector` is incorrect: Expected `int | str | float | ... omitted 5 union elements`, found `object`
+ cwltool/process.py:510:44 error[invalid-argument-type] Argument to function `var_spool_cwl_detector` is incorrect: Expected `int | str | float | ... omitted 5 union elements`, found `object`

jax (https://github.com/google/jax)
+ jax/_src/pallas/mosaic_gpu/lowering.py:1630:55 error[invalid-argument-type] Argument to bound method `UnswizzleRef.commute_reshape` is incorrect: Expected `ShapedArray`, found `AbstractValue`
- jax/experimental/mosaic/gpu/constraints.py:1019:7 error[type-assertion-failure] Type `@Todo` is not equivalent to `Never`
+ jax/experimental/mosaic/gpu/constraints.py:1019:7 error[type-assertion-failure] Type `(Equals & ~AlwaysTrue) | (Relayout & ~AlwaysTrue) | (NotOfType & ~AlwaysTrue) | ... omitted 5 union elements` is not equivalent to `Never`
- jax/experimental/mosaic/gpu/constraints.py:1057:11 error[type-assertion-failure] Type `@Todo` is not equivalent to `Never`
+ jax/experimental/mosaic/gpu/constraints.py:1057:11 error[type-assertion-failure] Type `(Reduce & ~Variable & ~RegisterLayout & ~SMEMTransforms & ~TMEMLayout) | (Reshape & ~Variable & ~RegisterLayout & ~SMEMTransforms & ~TMEMLayout) | (Transpose & ~Variable & ~RegisterLayout & ~SMEMTransforms & ~TMEMLayout) | (CollapseShape & ~Variable & ~RegisterLayout & ~SMEMTransforms & ~TMEMLayout)` is not equivalent to `Never`
- jax/experimental/mosaic/gpu/constraints.py:1083:11 error[type-assertion-failure] Type `@Todo` is not equivalent to `Never`
+ jax/experimental/mosaic/gpu/constraints.py:1083:11 error[type-assertion-failure] Type `(Equals & ~AlwaysTrue) | (Relayout & ~AlwaysTrue) | (NotOfType & ~AlwaysTrue) | ... omitted 5 union elements` is not equivalent to `Never`

mitmproxy (https://github.com/mitmproxy/mitmproxy)
- test/mitmproxy/addons/test_dns_resolver.py:155:17 error[type-assertion-failure] Type `@Todo` is not equivalent to `Never`
+ test/mitmproxy/addons/test_dns_resolver.py:155:17 error[type-assertion-failure] Type `tuple[Literal["nxdomain.example.com", "no-a-records.example.com", "no-network.example.com", "txt.example.com", "ipv4.example.com", "ipv6.example.com"], Literal["nameservers", "no-nameservers"], Literal["hosts", "no-hosts"]] & ~<Protocol with members '__getitem__', '__len__'> & ~<Protocol with members '__getitem__', '__len__'> & ~<Protocol with members '__getitem__', '__len__'> & ~<Protocol with members '__getitem__', '__len__'> & ~<Protocol with members '__getitem__', '__len__'> & ~<Protocol with members '__getitem__', '__len__'> & ~<Protocol with members '__getitem__', '__len__'> & ~<Protocol with members '__getitem__', '__len__'> & ~<Protocol with members '__getitem__', '__len__'> & ~<Protocol with members '__getitem__', '__len__'>` is not equivalent to `Never`

schema_salad (https://github.com/common-workflow-language/schema_salad)
+ src/schema_salad/dotnet_codegen.py:509:45 error[invalid-argument-type] Argument to function `DotNetCodeGen.safe_name` is incorrect: Expected `str`, found `(dict[str, Any] & ~Top[MutableSequence[Unknown]]) | (str & ~Top[MutableSequence[Unknown]])`
+ src/schema_salad/java_codegen.py:571:45 error[invalid-argument-type] Argument to function `JavaCodeGen.safe_name` is incorrect: Expected `str`, found `(dict[str, Any] & ~Top[MutableSequence[Unknown]]) | (str & ~Top[MutableSequence[Unknown]])`
+ src/schema_salad/python_codegen.py:490:40 error[invalid-argument-type] Argument to function `PythonCodeGen.safe_name` is incorrect: Expected `str`, found `(dict[str, Any] & ~Top[MutableSequence[Unknown]]) | (str & ~Top[MutableSequence[Unknown]])`
+ src/schema_salad/typescript_codegen.py:444:40 error[invalid-argument-type] Argument to function `TypeScriptCodeGen.safe_name` is incorrect: Expected `str`, found `(dict[str, Any] & ~Top[MutableSequence[Unknown]]) | (str & ~Top[MutableSequence[Unknown]])`

Full report with detailed diff (timing results)

@charliermarsh
charliermarsh force-pushed the charlie/pattern-match branch 3 times, most recently from afa86eb to 210840d Compare June 6, 2026 18:27
Base automatically changed from charlie/pattern-match to main June 6, 2026 18:41
@charliermarsh
charliermarsh force-pushed the charlie/pattern-as branch 5 times, most recently from 8e04b0c to 10670ee Compare June 11, 2026 14:16
@charliermarsh charliermarsh changed the title [ty] Narrow match pattern bindings [ty] Infer types for names bound in match patterns Jun 12, 2026
@charliermarsh
charliermarsh force-pushed the charlie/pattern-as branch 2 times, most recently from 0d076f1 to 2f25c16 Compare June 12, 2026 18:19
@charliermarsh
charliermarsh changed the base branch from main to charlie/revive-equality-narrowing June 12, 2026 18:20
@charliermarsh
charliermarsh force-pushed the charlie/revive-equality-narrowing branch from 12a1bb9 to 990ec4d Compare June 12, 2026 19:09
@charliermarsh
charliermarsh force-pushed the charlie/revive-equality-narrowing branch from 990ec4d to 63ffaef Compare June 12, 2026 19:50
@charliermarsh
charliermarsh changed the base branch from charlie/revive-equality-narrowing to charlie/class-pattern-exhaustiveness June 12, 2026 20:00
@charliermarsh
charliermarsh force-pushed the charlie/class-pattern-exhaustiveness branch from 4089f69 to 6e8f960 Compare June 12, 2026 20:25
@charliermarsh
charliermarsh force-pushed the charlie/pattern-as branch 3 times, most recently from dce4b3e to b5bb66e Compare June 13, 2026 00:51
@charliermarsh
charliermarsh force-pushed the charlie/class-pattern-exhaustiveness branch from adacb47 to ef39e10 Compare June 13, 2026 01:33
@charliermarsh
charliermarsh merged commit 5721b8d into charlie/class-pattern-exhaustiveness Jun 13, 2026
@charliermarsh
charliermarsh force-pushed the charlie/class-pattern-exhaustiveness branch from 34884d1 to 5835e48 Compare June 13, 2026 02:52
@charliermarsh
charliermarsh deleted the charlie/pattern-as branch June 13, 2026 02:52
@charliermarsh
charliermarsh restored the charlie/pattern-as branch June 13, 2026 02:53
@charliermarsh

Copy link
Copy Markdown
Member Author

Superseded by #25940 after the branch stack was reordered. GitHub marked this PR as merged when its former base became a descendant of this branch.

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

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant