Skip to content

[ty] Fix subtyping of invariant generics specialized with Any#20650

Merged
AlexWaygood merged 2 commits intomainfrom
alex/non-fully-static-subtyping
Oct 1, 2025
Merged

[ty] Fix subtyping of invariant generics specialized with Any#20650
AlexWaygood merged 2 commits intomainfrom
alex/non-fully-static-subtyping

Conversation

@AlexWaygood
Copy link
Member

@AlexWaygood AlexWaygood commented Sep 30, 2025

Summary

Currently we consider list[Any] a subtype of list[Any]. But we shouldn't, for the same reason that we shouldn't consider Any a subtype of Any: the two Anys might materialize to different types.

The reason why we make this mistake on main is that we (correctly) consider list[Any] to be equivalent to list[Any], but then incorrectly assume that if T is equivalent to S then T will necessarily be a subtype of S.

Test Plan

  • Added mdtests that fail on main.
  • Ran QUICKCHECK_TESTS=1000000 cargo test --release -p ty_python_semantic -- --ignored types::property_tests::stable

@AlexWaygood AlexWaygood added bug Something isn't working ty Multi-file analysis & type inference labels Sep 30, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Sep 30, 2025

Diagnostic diff on typing conformance tests

No changes detected when running ty on typing conformance tests ✅

@github-actions
Copy link
Contributor

github-actions bot commented Sep 30, 2025

mypy_primer results

Changes were detected when running on open source projects
mongo-python-driver (https://github.com/mongodb/mongo-python-driver)
- bson/json_util.py:1015:9: error[invalid-assignment] Method `__setitem__` of type `bound method dict[int, (Any, JSONOptions, /) -> Any].__setitem__(key: int, value: (Any, JSONOptions, /) -> Any, /) -> None` cannot be called with a key of type `object` and a value of type `((Any, JSONOptions, /) -> Any) | ((obj: Any, dummy0: Any) -> Any) | ((obj: Binary, json_options: JSONOptions) -> dict[Unknown, Unknown]) | ((obj: datetime, json_options: JSONOptions) -> dict[Unknown, Unknown]) | ((obj: Any, json_options: JSONOptions) -> dict[Unknown, Unknown]) | ((obj: int | float, json_options: JSONOptions) -> Any) | ((obj: int, json_options: JSONOptions) -> Any) | ((obj: UUID, json_options: JSONOptions) -> dict[Unknown, Unknown]) | ((obj: Int64, json_options: JSONOptions) -> Any) | ((obj: Code, json_options: JSONOptions) -> dict[Unknown, Unknown]) | ((obj: DBRef, json_options: JSONOptions) -> dict[Unknown, Unknown]) | ((dummy0: Any, dummy1: Any) -> dict[Unknown, Unknown]) | ((obj: ObjectId, dummy0: Any) -> dict[Unknown, Unknown]) | ((obj: Timestamp, dummy0: Any) -> dict[Unknown, Unknown])` on object of type `dict[int, (Any, JSONOptions, /) -> Any]`
+ bson/json_util.py:1015:9: error[invalid-assignment] Method `__setitem__` of type `bound method dict[int, (Any, JSONOptions, /) -> Any].__setitem__(key: int, value: (Any, JSONOptions, /) -> Any, /) -> None` cannot be called with a key of type `object` and a value of type `((Any, JSONOptions, /) -> Any) | ((obj: Any, dummy0: Any) -> Any) | ((obj: bytes, json_options: JSONOptions) -> dict[Unknown, Unknown]) | ((obj: datetime, json_options: JSONOptions) -> dict[Unknown, Unknown]) | ((obj: Any, json_options: JSONOptions) -> dict[Unknown, Unknown]) | ((obj: int | float, json_options: JSONOptions) -> Any) | ((obj: int, json_options: JSONOptions) -> Any) | ((obj: UUID, json_options: JSONOptions) -> dict[Unknown, Unknown]) | ((obj: Binary, json_options: JSONOptions) -> dict[Unknown, Unknown]) | ((obj: Int64, json_options: JSONOptions) -> Any) | ((obj: Code, json_options: JSONOptions) -> dict[Unknown, Unknown]) | ((obj: DBRef, json_options: JSONOptions) -> dict[Unknown, Unknown]) | ((dummy0: Any, dummy1: Any) -> dict[Unknown, Unknown]) | ((obj: ObjectId, dummy0: Any) -> dict[Unknown, Unknown]) | ((obj: Timestamp, dummy0: Any) -> dict[Unknown, Unknown])` on object of type `dict[int, (Any, JSONOptions, /) -> Any]`

static-frame (https://github.com/static-frame/static-frame)
- static_frame/test/property/strategies.py:927:17: error[invalid-argument-type] Argument to function `get_index_hierarchy` is incorrect: Expected `(...) -> IndexHierarchy`, found `bound method type[Index[Any]].from_labels(labels: Iterable[Unknown], *, /, name: Unknown = None) -> Index[Any]`
+ static_frame/test/property/strategies.py:927:17: error[invalid-argument-type] Argument to function `get_index_hierarchy` is incorrect: Expected `(...) -> IndexHierarchy`, found `(bound method type[Index[Any]].from_labels(labels: Iterable[Unknown], *, /, name: Unknown = None) -> Index[Any]) | (bound method <class 'Index'>.from_labels(labels: Iterable[Unknown], *, /, name: Unknown = None) -> Index[Any])`

jax (https://github.com/google/jax)
- jax/_src/interpreters/partial_eval.py:2513:15: warning[possibly-missing-attribute] Attribute `frame` on type `Trace[Unknown] | Unknown` may be missing
+ jax/_src/interpreters/partial_eval.py:2513:15: warning[possibly-missing-attribute] Attribute `frame` on type `Trace[Unknown] | Unknown | DynamicJaxprTrace` may be missing
No memory usage changes detected ✅

@codspeed-hq
Copy link

codspeed-hq bot commented Sep 30, 2025

CodSpeed WallTime Performance Report

Merging #20650 will improve performances by 68.52%

Comparing alex/non-fully-static-subtyping (e790951) with main (d9473a2)

Summary

⚡ 1 improvement
✅ 7 untouched

Benchmarks breakdown

Benchmark BASE HEAD Change
small[freqtrade] 9.2 s 5.5 s +68.52%

@AlexWaygood AlexWaygood enabled auto-merge (squash) October 1, 2025 10:02
@AlexWaygood AlexWaygood merged commit 20eb5b5 into main Oct 1, 2025
38 checks passed
@AlexWaygood AlexWaygood deleted the alex/non-fully-static-subtyping branch October 1, 2025 10:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants