Skip to content

[ty] remove special handling for Any() in match class patterns#23011

Merged
sharkdp merged 1 commit intoastral-sh:mainfrom
abhijeetbodas2001:apb-none-match
Feb 2, 2026
Merged

[ty] remove special handling for Any() in match class patterns#23011
sharkdp merged 1 commit intoastral-sh:mainfrom
abhijeetbodas2001:apb-none-match

Conversation

@abhijeetbodas2001
Copy link
Contributor

@abhijeetbodas2001 abhijeetbodas2001 commented Feb 1, 2026

Summary

Any does not support isinstance checks and cannot be used in class patterns. If the arm with Any() is hit, it will raise an error at runtime:

[nav] In [1]: from typing import Any
         ...:
         ...: X = Any
         ...:
         ...: def f(obj: object):
         ...:     match obj:
         ...:         case int():
         ...:             ...
         ...:         case X():
         ...:             ...

[ins] In [2]: f("")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[2], line 1
----> 1 f("")

Cell In[1], line 9, in f(obj)
      7 case int():
      8     ...
----> 9 case X():
     10     ...

# << snipped for brevity >>

TypeError: typing.Any cannot be used with isinstance()

Because this fails at runtime, we should ideally raise a diagnostic on seeing Any() in a match pattern. That could potentially be done as part of astral-sh/ty#2592. But for now, this PR only removes the special support that we have.

The special-case handling does not reduce any diagnostics on jax as of today either.

Test Plan

Removed tests :)

@astral-sh-bot
Copy link

astral-sh-bot bot commented Feb 1, 2026

Typing conformance results

No changes detected ✅

@astral-sh-bot
Copy link

astral-sh-bot bot commented Feb 1, 2026

mypy_primer results

Changes were detected when running on open source projects
pydantic (https://github.com/pydantic/pydantic)
- pydantic/_internal/_core_metadata.py:87:54: error[invalid-assignment] Invalid assignment to key "pydantic_js_extra" with declared type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | ((dict[str, Divergent], type[Any], /) -> None)` on TypedDict `CoreMetadata`: value of type `dict[object, object]`
+ pydantic/_internal/_core_metadata.py:87:54: error[invalid-assignment] Invalid assignment to key "pydantic_js_extra" with declared type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | ((dict[str, int | float | str | ... omitted 3 union elements], type[Any], /) -> None)` on TypedDict `CoreMetadata`: value of type `dict[object, object]`
- pydantic/fields.py:949:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:949:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:989:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:989:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1032:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1032:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1072:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1072:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1115:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1115:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1154:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1154:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1194:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1194:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1573:13: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`, found `Top[dict[Unknown, Unknown]] | (((dict[str, Divergent], /) -> None) & ~Top[dict[Unknown, Unknown]]) | None`
+ pydantic/fields.py:1573:13: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`, found `Top[dict[Unknown, Unknown]] | (((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) & ~Top[dict[Unknown, Unknown]]) | None`

prefect (https://github.com/PrefectHQ/prefect)
- src/prefect/deployments/runner.py:1017:70: warning[possibly-missing-attribute] Attribute `__name__` may be missing on object of type `Unknown | ((...) -> Any)`
+ src/prefect/deployments/runner.py:1017:70: warning[possibly-missing-attribute] Attribute `__name__` may be missing on object of type `Unknown | (((...) -> Any) & ((*args: object, **kwargs: object) -> object))`
- src/prefect/flow_engine.py:997:32: error[invalid-await] `Unknown | R@FlowRunEngine | Coroutine[Any, Any, R@FlowRunEngine]` is not awaitable
- src/prefect/flow_engine.py:1596:24: error[invalid-await] `Unknown | R@AsyncFlowRunEngine | Coroutine[Any, Any, R@AsyncFlowRunEngine]` is not awaitable
- src/prefect/flow_engine.py:1677:43: error[invalid-argument-type] Argument to function `next` is incorrect: Expected `SupportsNext[Unknown]`, found `Unknown | R@run_generator_flow_sync`
- src/prefect/flow_engine.py:1685:21: warning[possibly-missing-attribute] Attribute `throw` may be missing on object of type `Unknown | R@run_generator_flow_sync`
- src/prefect/flow_engine.py:1719:44: warning[possibly-missing-attribute] Attribute `__anext__` may be missing on object of type `Unknown | R@run_generator_flow_async`
- src/prefect/flow_engine.py:1726:25: warning[possibly-missing-attribute] Attribute `throw` may be missing on object of type `Unknown | R@run_generator_flow_async`
- src/prefect/flows.py:285:34: error[unresolved-attribute] Object of type `(**P@Flow) -> R@Flow` has no attribute `__name__`
+ src/prefect/flows.py:285:34: error[unresolved-attribute] Object of type `((**P@Flow) -> R@Flow) & ((*args: object, **kwargs: object) -> object)` has no attribute `__name__`
- src/prefect/flows.py:403:68: error[unresolved-attribute] Object of type `(**P@Flow) -> R@Flow` has no attribute `__name__`
+ src/prefect/flows.py:403:68: error[unresolved-attribute] Object of type `((**P@Flow) -> R@Flow) & ((*args: object, **kwargs: object) -> object)` has no attribute `__name__`
- src/prefect/flows.py:1945:21: error[no-matching-overload] No overload of function `run_coro_as_sync` matches arguments
+ src/prefect/flows.py:1885:53: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- Found 5371 diagnostics
+ Found 5365 diagnostics

scikit-build-core (https://github.com/scikit-build/scikit-build-core)
- src/scikit_build_core/build/wheel.py:99:20: error[no-matching-overload] No overload of bound method `__init__` matches arguments
- Found 47 diagnostics
+ Found 46 diagnostics

core (https://github.com/home-assistant/core)
- homeassistant/util/variance.py:47:12: error[invalid-return-type] Return type does not match returned value: expected `(**_P@ignore_variance) -> _R@ignore_variance`, found `_Wrapped[_P@ignore_variance, int | _R@ignore_variance | float | datetime, _P@ignore_variance, _R@ignore_variance | int | float | datetime]`
- Found 14514 diagnostics
+ Found 14513 diagnostics

No memory usage changes detected ✅

@abhijeetbodas2001 abhijeetbodas2001 changed the title [ty] [DRAFT] remove special Any handling for match class patterns [ty] remove special handling for Any() in match class patterns Feb 1, 2026
@ntBre ntBre added the ty Multi-file analysis & type inference label Feb 1, 2026
Comment on lines -121 to -146
## Class patterns where the class pattern does not resolve to a class

In general this does not allow for narrowing, but we make an exception for `Any`. This is to support
[real ecosystem code](https://github.com/jax-ml/jax/blob/d2ce04b6c3d03ae18b145965b8b8b92e09e8009c/jax/_src/pallas/mosaic_gpu/lowering.py#L3372-L3387)
found in `jax`.

```py
from typing import Any

X = Any

def f(obj: object):
match obj:
case int():
reveal_type(obj) # revealed: int
case X():
reveal_type(obj) # revealed: Any & ~int

def g(obj: object, Y: Any):
match obj:
case int():
reveal_type(obj) # revealed: int
case Y():
reveal_type(obj) # revealed: Any & ~int
```

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

@sharkdp sharkdp left a comment

Choose a reason for hiding this comment

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

This looks good to me, thank you!

I'll keep the referenced ticket open for now, because I think it makes sense to introduce a new diagnostic.

@sharkdp sharkdp merged commit 9e0189b into astral-sh:main Feb 2, 2026
49 checks passed
@abhijeetbodas2001 abhijeetbodas2001 deleted the apb-none-match branch February 2, 2026 14:01
carljm added a commit that referenced this pull request Feb 2, 2026
* main: (48 commits)
  add info for non_octal permissions (#22972)
  Fix empty body rule rendering (#23039)
  [ty] Infer `ParamSpec` from class constructors for callable protocols (#22853)
  Update NPM Development dependencies (#23030)
  Update CodSpeedHQ/action action to v4.8.2 (#23029)
  [ty] remove special handling for `Any()` in match class patterns (#23011)
  Update Rust crate get-size2 to v0.7.4 (#23022)
  Update Rust crate insta to v1.46.1 (#23023)
  Update taiki-e/install-action action to v2.67.11 (#23033)
  Update Rust crate colored to v3.1.1 (#23031)
  Update cargo-bins/cargo-binstall action to v1.17.3 (#23028)
  Update Rust crate uuid to v1.20.0 (#23032)
  [ty] Avoid using `.node()` for detecting `Self` (#23000)
  Update Rust crate proc-macro2 to v1.0.106 (#23024)
  Update actions/setup-python action to v6.2.0 (#23027)
  [ty] fix query cycles in decorated function with parameter defaults (#23014)
  Update Rust crate quote to v1.0.44 (#23025)
  Update Rust crate thiserror to v2.0.18 (#23026)
  Update Rust crate filetime to v0.2.27 (#23021)
  Update Rust crate clearscreen to v4.0.3 (#23020)
  ...
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.

3 participants