output-position widening for invariant builtin containers - #14
Draft
KotlinIsland wants to merge 1 commit into
Draft
output-position widening for invariant builtin containers#14KotlinIsland wants to merge 1 commit into
KotlinIsland wants to merge 1 commit into
Conversation
KotlinIsland
force-pushed
the
typeshed-expected-type
branch
3 times, most recently
from
July 14, 2026 06:10
b9b65a8 to
15868d0
Compare
fresh-copy methods of invariant containers (list/set/dict) return a brand new object the caller owns, so widening its element type at the call site is sound — but `list[int]` isn't a `list[int | None]`, so today `a.copy()` can't be assigned to a wider specialization. encode the fix as a `Never`-defaulted output type parameter unioned into each invariant return position: `def copy[Widen = Never](self) -> list[Element | Widen]`. with an expected type it solves to the widening; without one it defaults to `Never` and collapses back, so inference is unchanged. new `output-widening` typeshed patch (post-pep695 pass, keyed on `in out` variance so covariant frozenset/tuple are left alone) + regenerated builtins.byi. it widens only methods reached by an ordinary call — `copy`, `set.union`/`difference`/`intersection`/`symmetric_difference` — where the caller's expected type already flows into inference. operator dunders (`__add__`, `__getitem__`, ...) are deliberately not widened: making their returns widen would require bidirectional inference on every binary op and subscript, which is far too expensive on real code (it times out xarray).
KotlinIsland
force-pushed
the
typeshed-expected-type
branch
from
July 14, 2026 07:22
15868d0 to
76d8da1
Compare
KotlinIsland
marked this pull request as draft
July 14, 2026 07:42
KotlinIsland
force-pushed
the
main
branch
8 times, most recently
from
July 22, 2026 08:38
0a30a5b to
a2564b5
Compare
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.
fresh-copy methods of invariant containers (list/set/dict) return a brand new object the caller owns, so widening its element type at the call site is sound — but
list[int]isn't alist[int | None], so todaycopy/+/*/ set+dict algebra can't be assigned to a wider specialization.encode the fix as a
Never-defaulted output type parameter unioned into each invariant return position:def copy[Widen = Never](self) -> list[Element | Widen]. with an expected type it solves to the widening; without one it defaults toNeverand collapses back, so inference is unchanged.output-wideningtypeshed patch (post-pep695 pass, keyed onin outvariance so covariant frozenset/tuple are left alone) + regenerated builtins.byi