Resolve unbound class generics to any - #3442
Open
RomanSpector wants to merge 2 commits into
Open
Conversation
A generic class can be referenced without arguments — `---@type Box` instead of `Box<string>`. Its fields kept the parameter itself as their type, shown as `<T>`: a type no value can ever have. Every mention of such a class without arguments then became unusable, which in practice rules out making an existing widely-used class generic. Unbound parameters now resolve to `any`, so those places behave exactly as before the class gained a parameter. Where arguments are given they still win. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
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.
A generic class can be referenced without arguments. Its fields kept the parameter itself as their type, displayed as
<T>— a type no value can ever have:Why this matters beyond cosmetics
It effectively rules out adding a parameter to an existing, widely used class. Consider a store that holds elements of many kinds and hands them to code that knows exactly what it works with:
Turning
ElementintoElement<T>is exactly the right move for the consumers — a toggle wantsElement<boolean>, a slider wantsElement<number>. But every place that legitimately does not care about the parameter — the store, the registry, the traversal helpers, theregistersignature — suddenly deals in<T>. In a codebase of any size that is dozens of mentions, and the only escape is writingElement<any>in each of them: noise that says nothing and has to be maintained forever.The alternative workaround is worse: declaring a second, "typed" subclass purely to carry the parameter, duplicating a class for no reason other than to satisfy the checker.
What this changes
Unbound parameters resolve to
any, so those places behave exactly as before the class gained a parameter, while explicit arguments still win:This holds for methods as well, not only fields, and matches what writing
Repository<any>by hand already does today.Why
anyand notunknownunknownreads as "inference failed" and is reported byno-unknown; here nothing failed — the parameter was simply never bound, and the value genuinely can be anything.anyalso keeps the promise that adding a parameter to a class does not change how existing code is checked.Worth noting for symmetry: an unbound parameter of a generic function still yields
unknown, so the two are not aligned. If you would rather have both behave the same, say which way and I will follow.Other uses this opens up
Gradual typing of an existing hierarchy — add the parameter to a base class today, annotate consumers one by one, and untouched code keeps working. Container-like classes (
Queue<T>,Cache<T>,Result<T>) can be referenced generically in plumbing and precisely at the point of use.