Skip to content

Comments

[ty] Allow if type(x) is Y narrowing for types other than class-literal types#22729

Merged
AlexWaygood merged 1 commit intomainfrom
alex/type-t-narrow
Jan 20, 2026
Merged

[ty] Allow if type(x) is Y narrowing for types other than class-literal types#22729
AlexWaygood merged 1 commit intomainfrom
alex/type-t-narrow

Conversation

@AlexWaygood
Copy link
Member

Summary

Fixes astral-sh/ty#2565.

This PR adds support for if type(x) is Y narrowing where Y is a subclass-of type, type-alias type, or typevar type.

Test Plan

mdtests

@AlexWaygood AlexWaygood added the ty Multi-file analysis & type inference label Jan 19, 2026
@astral-sh-bot
Copy link

astral-sh-bot bot commented Jan 19, 2026

Typing conformance results

No changes detected ✅

@astral-sh-bot
Copy link

astral-sh-bot bot commented Jan 19, 2026

mypy_primer results

Changes were detected when running on open source projects
yarl (https://github.com/aio-libs/yarl)
- yarl/_url.py:379:20: error[invalid-return-type] Return type does not match returned value: expected `URL`, found `str | SplitResult | URL | UndefinedType`
- Found 46 diagnostics
+ Found 45 diagnostics

scrapy (https://github.com/scrapy/scrapy)
- tests/test_downloader_handlers.py:344:16: warning[possibly-missing-attribute] Attribute `encoding` may be missing on object of type `Unknown | Response`
- tests/test_downloader_handlers.py:352:16: warning[possibly-missing-attribute] Attribute `encoding` may be missing on object of type `Unknown | Response`
+ tests/test_downloader_handlers.py:344:16: error[unresolved-attribute] Object of type `Response` has no attribute `encoding`
+ tests/test_downloader_handlers.py:352:16: error[unresolved-attribute] Object of type `Response` has no attribute `encoding`
- tests/test_downloader_handlers.py:372:16: warning[possibly-missing-attribute] Attribute `encoding` may be missing on object of type `Unknown | Response`
+ tests/test_downloader_handlers.py:372:16: error[unresolved-attribute] Object of type `Response` has no attribute `encoding`

tornado (https://github.com/tornadoweb/tornado)
- tornado/gen.py:255:62: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `None | Awaitable[Unknown] | list[Awaitable[Unknown]] | dict[Any, Awaitable[Unknown]] | Future[Unknown]`, found `_T@next | _T@next | _VT@next`
+ tornado/gen.py:255:62: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `None | Awaitable[Unknown] | list[Awaitable[Unknown]] | dict[Any, Awaitable[Unknown]] | Future[Unknown]`, found `_T@next | _VT@next | _T@next`

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

prefect (https://github.com/PrefectHQ/prefect)
- src/integrations/prefect-dbt/prefect_dbt/core/settings.py:94:28: error[invalid-assignment] Object of type `T@resolve_block_document_references | int | dict[str, Any] | ... omitted 4 union elements` is not assignable to `dict[str, Any]`
+ src/integrations/prefect-dbt/prefect_dbt/core/settings.py:94:28: error[invalid-assignment] Object of type `T@resolve_block_document_references | dict[str, Any]` is not assignable to `dict[str, Any]`
- src/integrations/prefect-dbt/prefect_dbt/core/settings.py:99:28: error[invalid-assignment] Object of type `int | T@resolve_variables | float | ... omitted 4 union elements` is not assignable to `dict[str, Any]`
+ src/integrations/prefect-dbt/prefect_dbt/core/settings.py:99:28: error[invalid-assignment] Object of type `T@resolve_variables | dict[str, Any]` is not assignable to `dict[str, Any]`
- src/prefect/cli/deploy/_core.py:86:21: error[invalid-assignment] Object of type `T@resolve_block_document_references | int | dict[str, Any] | ... omitted 4 union elements` is not assignable to `dict[str, Any]`
+ src/prefect/cli/deploy/_core.py:86:21: error[invalid-assignment] Object of type `T@resolve_block_document_references | dict[str, Any]` is not assignable to `dict[str, Any]`
- src/prefect/cli/deploy/_core.py:87:21: error[invalid-assignment] Object of type `int | T@resolve_variables | float | ... omitted 4 union elements` is not assignable to `dict[str, Any]`
+ src/prefect/cli/deploy/_core.py:87:21: error[invalid-assignment] Object of type `T@resolve_variables` is not assignable to `dict[str, Any]`
- src/prefect/deployments/steps/core.py:137:38: error[invalid-argument-type] Argument is incorrect: Expected `T@resolve_variables`, found `T@resolve_block_document_references | int | dict[str, Any] | ... omitted 4 union elements`
+ src/prefect/deployments/steps/core.py:137:38: error[invalid-argument-type] Argument is incorrect: Expected `T@resolve_variables`, found `T@resolve_block_document_references | dict[str, Any]`
- src/prefect/utilities/templating.py:320:13: error[invalid-assignment] Invalid subscript assignment with key of type `object` and value of type `T@resolve_block_document_references | int | dict[str, Any] | ... omitted 4 union elements` on object of type `dict[str, Any]`
+ src/prefect/utilities/templating.py:320:13: error[invalid-assignment] Invalid subscript assignment with key of type `object` and value of type `T@resolve_block_document_references | dict[str, Any]` on object of type `dict[str, Any]`
- src/prefect/utilities/templating.py:323:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_block_document_references | dict[str, Any]`, found `list[T@resolve_block_document_references | int | dict[str, Any] | ... omitted 5 union elements]`
+ src/prefect/utilities/templating.py:323:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_block_document_references | dict[str, Any]`, found `list[T@resolve_block_document_references | dict[str, Any] | Unknown]`
- src/prefect/utilities/templating.py:437:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_variables`, found `dict[object, int | T@resolve_variables | float | ... omitted 5 union elements]`
+ src/prefect/utilities/templating.py:437:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_variables`, found `dict[object, T@resolve_variables | Unknown]`
- src/prefect/utilities/templating.py:442:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_variables`, found `list[int | T@resolve_variables | float | ... omitted 5 union elements]`
+ src/prefect/utilities/templating.py:442:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_variables`, found `list[T@resolve_variables | Unknown]`
- src/prefect/workers/base.py:232:13: error[invalid-argument-type] Argument is incorrect: Expected `T@resolve_variables`, found `T@resolve_block_document_references | int | dict[str, Any] | ... omitted 4 union elements`
+ src/prefect/workers/base.py:232:13: error[invalid-argument-type] Argument is incorrect: Expected `T@resolve_variables`, found `T@resolve_block_document_references | dict[str, Any]`
- src/prefect/workers/base.py:234:20: error[invalid-argument-type] Argument expression after ** must be a mapping type: Found `int | T@resolve_variables | float | ... omitted 4 union elements`
+ src/prefect/workers/base.py:234:20: error[invalid-argument-type] Argument expression after ** must be a mapping type: Found `T@resolve_variables`

ibis (https://github.com/ibis-project/ibis)
- ibis/common/patterns.py:658:37: error[unresolved-attribute] Object of type `Pattern` has no attribute `type`
- Found 4606 diagnostics
+ Found 4605 diagnostics

static-frame (https://github.com/static-frame/static-frame)
- static_frame/core/index.py:580:16: error[invalid-return-type] Return type does not match returned value: expected `InterGetItemLocReduces[TVContainer_co@loc, TVDtype@Index]`, found `InterGetItemLocReduces[Bottom[Series[Any, Any]] | Any, TVDtype@Index]`
+ static_frame/core/index.py:580:16: error[invalid-return-type] Return type does not match returned value: expected `InterGetItemLocReduces[TVContainer_co@loc, TVDtype@Index]`, found `InterGetItemLocReduces[Any | Bottom[Series[Any, Any]], TVDtype@Index]`
- static_frame/core/node_selector.py:526:16: error[invalid-return-type] Return type does not match returned value: expected `InterGetItemLocReduces[TVContainer_co@InterfaceSelectQuartet, Any]`, found `InterGetItemLocReduces[Bottom[Series[Any, Any]] | Unknown, Any]`
+ static_frame/core/node_selector.py:526:16: error[invalid-return-type] Return type does not match returned value: expected `InterGetItemLocReduces[TVContainer_co@InterfaceSelectQuartet, Any]`, found `InterGetItemLocReduces[Unknown | Bottom[Series[Any, Any]], Any]`

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, _R@ignore_variance | int | float | datetime, _P@ignore_variance, _R@ignore_variance | int | float | datetime]`
- Found 14492 diagnostics
+ Found 14491 diagnostics

No memory usage changes detected ✅

@astral-sh-bot
Copy link

astral-sh-bot bot commented Jan 19, 2026

ecosystem-analyzer results

Lint rule Added Removed Changed
invalid-return-type 1 1 2
unresolved-attribute 3 1 0
possibly-missing-attribute 0 3 0
invalid-argument-type 0 0 1
Total 4 5 3

Full report with detailed diff (timing results)

@AlexWaygood
Copy link
Member Author

The ecosystem report shows false positives going away on ibis and yarl

@AlexWaygood AlexWaygood merged commit af886b0 into main Jan 20, 2026
54 checks passed
@AlexWaygood AlexWaygood deleted the alex/type-t-narrow branch January 20, 2026 08:23
carljm added a commit that referenced this pull request Jan 20, 2026
* main: (149 commits)
  Preserve required parentheses in lambda bodies (#22747)
  [`flake8-simplify`] Make fix unsafe if it deletes comments (`SIM911`) (#22661)
  [`refurb`] Make fix unsafe if it deletes comments (`FURB145`) (#22670)
  [`ruff`] Make fix unsafe if it deletes comments (`RUF020`) (#22664)
  [ty] Add README for `ty_completion_bench` CLI tool
  [ty] Update completion eval
  [ty] Collect completions into a max-heap
  [ty] Truncate imports and qualifications derived from completions
  [ty] Get rid of high-level completion deduplication
  [ty] Refactor how we sort completions
  [ty] Optimize collection of "all symbols"
  [ty] Speed up completions by tweaking sorts
  [ty] Add new `ty_completion_bench` for ad hoc benchmarking
  gitignore: ignore scratch directories in completion eval truth directory
  [`pyupgrade`] Allow shadowing non-builtin bindings (`UP029`) (#22749)
  [ty] Emit invalid type form for stringified annotations (#22752)
  [ty] Allow `if type(x) is Y` narrowing for types other than class-literal types (#22729)
  [ty] Add basic support for overloads in `ParamSpec` (#21946)
  [`ruff`] Make fix unsafe if it deletes comments (`RUF019`) (#22663)
  [`flake8-bugbear`] Make fix unsafe if it deletes comments (`B014`) (#22659)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ecosystem-analyzer ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

type(x) is t doesn't work for t: type[T]

2 participants