Open
Conversation
Typing conformance resultsNo changes detected ✅ |
|
|
| Lint rule | Added | Removed | Changed |
|---|---|---|---|
call-top-callable |
121 | 0 | 0 |
invalid-argument-type |
24 | 1 | 40 |
unresolved-attribute |
30 | 0 | 18 |
unused-type-ignore-comment |
0 | 24 | 0 |
unknown-argument |
19 | 0 | 0 |
invalid-return-type |
3 | 0 | 15 |
call-non-callable |
16 | 1 | 0 |
missing-argument |
12 | 0 | 0 |
invalid-assignment |
6 | 0 | 3 |
too-many-positional-arguments |
6 | 0 | 0 |
unsupported-operator |
1 | 0 | 5 |
index-out-of-bounds |
5 | 0 | 0 |
no-matching-overload |
3 | 0 | 0 |
not-iterable |
0 | 0 | 1 |
type-assertion-failure |
1 | 0 | 0 |
| Total | 247 | 26 | 82 |
Implement proper handling for calling intersection types. Previously, calling an intersection type would return a `@Todo` type that suppressed errors but provided no useful type information. Now, when calling an intersection type: - We try to call each positive element with the given arguments - Elements where the call fails (wrong arguments, not callable, etc.) are discarded - If at least one element succeeds, the call is valid - The return type is the intersection of return types from successful elements - If all elements fail, an appropriate error is reported This approach means that if an intersection contains both a callable with a known signature and a `Top[Callable[..., object]]` (from narrowing by `callable()`), the call will succeed using the element with the known signature, avoiding spurious `call-top-callable` errors. Fixes astral-sh/ty#1858
3dae02a to
f39370a
Compare
When calling an intersection type where all callable elements reject the specific call arguments, we now show an error for each failing element (similar to how unions work) instead of a single generic "not callable" error. This is achieved by: - Not filtering out failed elements when ALL elements fail - Returning BindingError instead of NotCallable to trigger individual diagnostics - Adding IntersectionDiagnostic struct and CompoundDiagnostic trait - Modifying report_diagnostics to iterate over intersection elements
More diagnostics are now emitted due to showing individual errors when all intersection elements fail a call.
When all intersection elements fail a call, we now use a priority hierarchy to determine which errors to show: 1. NotCallable (lowest) - object has no __call__ method 2. TopCallable - object is a top callable with unknown signature 3. BindingError (highest) - specific errors like invalid-argument-type Only errors from the highest priority category are shown. This prevents noise from less-specific errors when more informative errors are available. For example, if an intersection has one element that fails with invalid-argument-type and another that's not callable, we only show the invalid-argument-type error since it's more specific and actionable.
Refactors the `Bindings` structure to use a two-level representation: - Outer level: union elements (each can be a single callable or an intersection) - Inner level: bindings within an intersection element This enables proper handling of types like `(A & B) | C` when calling, where `A & B` is an intersection that was narrowed by `callable()`. Key changes: - Add `BindingsElement` struct to represent a single union element (which may contain multiple bindings for intersections) - Update `from_union` to preserve intersection structure instead of flattening - Update `from_intersection` to create a single element with multiple bindings - Update `return_type`, `check_types_impl`, and `report_diagnostics` to handle the two-level structure - Add test for union-of-intersections case The priority hierarchy for intersection call errors is preserved: when all bindings in an intersection fail, only the highest-priority error type is reported (BindingError > TopCallable > NotCallable).
Resolves conflicts between the two-level Bindings structure and main's new Type match cases for property descriptors, dataclass transformers, and other features.
06c217d to
f72e874
Compare
This PR fixes false `invalid-await` errors for patterns like:
```python
if inspect.isawaitable(x):
await x # x has type Unknown & Awaitable[object]
```
Changes:
1. Add intersection handling to `generator_return_type()` so that await
operations on intersection types work correctly. When awaiting an
intersection, we iterate over positive elements, collect return types
from awaitable elements, and intersect them together. Non-awaitable
elements are skipped; only if all elements fail to be awaitable do we
report an error.
2. Add intersection handling to `try_call_dunder_with_policy()` to call
dunder methods on each intersection element separately and combine the
results. This avoids intersecting bound methods (which often collapses
to Never) and instead intersects the return types.
Added tests for:
- Awaiting `Unknown & Awaitable[object]` returns `Unknown`
- Awaiting intersection of two Coroutine types
- Awaiting intersection with non-awaitable elements skips those elements
- Awaiting intersection where all elements are non-awaitable produces error
f72e874 to
01b1937
Compare
carljm
commented
Jan 12, 2026
When multiple bindings in an intersection (or multiple elements in a union) return argument forms from type checking (e.g., during argument type expansion), we should merge them to properly detect conflicting forms, rather than overwriting with the last one.
Use error priority to select the appropriate error kind when all bindings fail, rather than handling intersection and single-binding cases separately. This addresses review comments 2 and 3 from PR #22469.
Update the doc comment to clarify that Bindings represents a union of callables (possibly size one), where each element is an intersection (possibly size one). This addresses review comment 5 from PR #22469.
…allable() - Add is_callable() method to BindingsElement for clearer element-level checks - Update report_diagnostics to iterate over elements instead of flattened bindings - Add documentation to iter() and iter_mut() clarifying they flatten the structure This addresses review comments 6 and 7 from PR #22469.
Simplify the call site by moving the is_intersection() and as_result().is_ok() checks inside retain_successful(). This addresses review comment 8 from PR #22469.
When an intersection fails inside a union, report errors with both union and intersection context: - Add LayeredDiagnostic that combines both contexts - Show the correct intersection type (not the full union) - Include test with snapshot diagnostics demonstrating the layered output This addresses review comment 9 from PR #22469.
* main: (76 commits) [ty] Improve the check for `NewType`s with generic bases (#22961) [ty] Ban legacy `TypeVar` bounds or constraints from containing type variables (#22949) Bump the typing conformance suite pin (#22960) [ty] Emit an error if a TypeVarTuple is used to subscript `Generic` or `Protocol` without being unpacked (#22952) [ty] Reduce false positives when subscripting classes generic over `TypeVarTuple`s (#22950) [ty] Detect invalid attempts to subclass `Protocol[]` and `Generic[]` simultaneously (#22948) Fix suppression indentation matching (#22903) Remove hidden `--output-format` warning (#22944) [ty] Validate signatures of dataclass `__post_init__` methods (#22730) [ty] extend special-cased `numbers` diagnostic to `invalid-argument-type` errors (#22938) [ty] Avoid false positive for `not-iterable` with no-positive intersection types (#22089) [ty] Preserve pure negation types in descriptor protocol (#22907) [ty] add special-case diagnostic for `numbers` module (#22931) [ty] Move the location of more `invalid-overload` diagnostics (#22933) [ty] Fix unary and comparison operators for TypeVars with union bounds (#22925) [ty] Rule Selection: ignore/warn/select all rules (unless subsequently overriden) (#22832) [ty] Fix TypedDict construction from existing TypedDict values (#22904) [ty] fix bug in string annotations and clean up diagnostics (#22913) [ty] Improve support for goto-type, goto-declaration, hover, and highlighting of string annotations (#22878) [ty] Rename old typing imports to new on `unresolved-reference`. (#22827) ...
* 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) ...
* main: (209 commits) [ty] Defer base inference for functional `type(...)` classes (#22792) flake8-executable: allow global flags in uv shebangs (EXE003) (#22582) [ty] Add `replace-imports-with-any` option (#23122) Update html comments in mdtests (#23269) Apply ruff formatting to mdtests (#22935) [ty] Exclude test-related symbols from non-first-party packages in auto-import completions [ty] Refactor `CursorTest` helper to support site-packages [ty] Qualify inlay hint edit symbol when possibly referencing another variable (#23265) [ty] Avoid `UnionBuilder` overhead when creating a new union from the filtered elements of an existing union (#22352) [ty] Refactor TypedDict key assignment validation (#23262) [ty] Improve Python environment path documentation (#23256) [ty] loop control flow analysis using loop header definitions Prepare for 0.15.1 (#23253) Remove docker-run-action (#23254) [ty] Allow discovering dependencies in system Python environments (#22994) Ensure pending suppression diagnostics are reported (#23242) [`isort`] support for configurable import section heading comments (#23151) [ty] Fix method calls on subclasses of `Any` (#23248) [ty] Fix bound method access on `None` (#23246) Make range suppression test snapshot actually useful (#23251) ...
Memory usage reportSummary
Significant changesClick to expand detailed breakdownprefect
sphinx
trio
flake8
|
AlexWaygood
requested changes
Feb 15, 2026
Member
AlexWaygood
left a comment
There was a problem hiding this comment.
Awesome!
This is a test-only review so far. There are a few tests that don't test what they say they're testing.
crates/ty_python_semantic/resources/mdtest/dataclasses/dataclass_transform.md
Show resolved
Hide resolved
crates/ty_python_semantic/resources/mdtest/intersection_types.md
Outdated
Show resolved
Hide resolved
crates/ty_python_semantic/resources/mdtest/intersection_types.md
Outdated
Show resolved
Hide resolved
crates/ty_python_semantic/resources/mdtest/intersection_types.md
Outdated
Show resolved
Hide resolved
crates/ty_python_semantic/resources/mdtest/intersection_types.md
Outdated
Show resolved
Hide resolved
AlexWaygood
reviewed
Feb 15, 2026
crates/ty_python_semantic/resources/mdtest/intersection_types.md
Outdated
Show resolved
Hide resolved
AlexWaygood
reviewed
Feb 15, 2026
Member
AlexWaygood
left a comment
There was a problem hiding this comment.
(still not a complete review -- will pick it back up tomorrow!)
carljm
commented
Feb 16, 2026
Contributor
Author
carljm
left a comment
There was a problem hiding this comment.
Thanks for the review!
| # Diagnostics | ||
|
|
||
| ``` | ||
| error[invalid-argument-type]: Argument to bound method `__call__` is incorrect |
Contributor
Author
There was a problem hiding this comment.
This looks verbose in this contrived example, but I think in real code it's pretty unlikely to call a union containing an intersection where all elements of the union and the intersection all fail the call, and all elements of the intersection have the same "priority" error. And if that did happen, you might well want to know the details on each failed element.
crates/ty_python_semantic/resources/mdtest/dataclasses/dataclass_transform.md
Show resolved
Hide resolved
crates/ty_python_semantic/resources/mdtest/intersection_types.md
Outdated
Show resolved
Hide resolved
crates/ty_python_semantic/resources/mdtest/intersection_types.md
Outdated
Show resolved
Hide resolved
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes astral-sh/ty#1858
Handle calls to intersection types. Previously, calling an intersection type would return a
@Todotype that suppressed errors but provided no useful type information.Now, when calling an intersection type:
Ecosystem review only revealed existing known issues or correct behaviors newly exposed by actually processing intersection calls and getting precise return types instead of Todo types