Fix descriptor access for complex generics#21506
Open
JiwaniZakir wants to merge 2 commits into
Open
Conversation
Use the unbound __get__ type and call it with all three arguments (self, instance, owner) so that type inference can jointly solve all type variables. The previous approach called bind_self first and then passed only two arguments, which failed when the __get__ self annotation contained type variables shared with the instance parameter.
get_method returns FuncBase | Decorator; unwrap Decorator.func before passing to function_type (which expects FuncBase). Annotate dunder_get_type as Type so the transform_callee_type (-> Type) assignment is compatible. Fixes python#21505
Contributor
|
Diff from mypy_primer, showing the effect of this PR on open source code: steam.py (https://github.com/Gobot1234/steam.py)
- steam/chat.py:402: error: Argument 2 to "__get__" of "classproperty" has incompatible type "type[Chat[ChatMessageT, ClanT, GroupT]]"; expected "type[Never]" [arg-type]
+ steam/chat.py:402: error: Argument 3 to "__get__" of "classproperty" has incompatible type "type[Chat[ChatMessageT, ClanT, GroupT]]"; expected "type[Never]" [arg-type]
- steam/chat.py:589: error: Argument 2 to "__get__" of "classproperty" has incompatible type "type[ChatGroup[MemberT, ChatT, ChatGroupTypeT]]"; expected "type[Never]" [arg-type]
+ steam/chat.py:589: error: Argument 3 to "__get__" of "classproperty" has incompatible type "type[ChatGroup[MemberT, ChatT, ChatGroupTypeT]]"; expected "type[Never]" [arg-type]
- steam/chat.py:608: error: Argument 2 to "__get__" of "classproperty" has incompatible type "type[ChatGroup[MemberT, ChatT, ChatGroupTypeT]]"; expected "type[Never]" [arg-type]
+ steam/chat.py:608: error: Argument 3 to "__get__" of "classproperty" has incompatible type "type[ChatGroup[MemberT, ChatT, ChatGroupTypeT]]"; expected "type[Never]" [arg-type]
- steam/chat.py:643: error: Argument 2 to "__get__" of "classproperty" has incompatible type "type[ChatGroup[MemberT, ChatT, ChatGroupTypeT]]"; expected "type[Never]" [arg-type]
+ steam/chat.py:643: error: Argument 3 to "__get__" of "classproperty" has incompatible type "type[ChatGroup[MemberT, ChatT, ChatGroupTypeT]]"; expected "type[Never]" [arg-type]
- steam/chat.py:688: error: Argument 2 to "__get__" of "classproperty" has incompatible type "type[ChatGroup[MemberT, ChatT, ChatGroupTypeT]]"; expected "type[Never]" [arg-type]
+ steam/chat.py:688: error: Argument 3 to "__get__" of "classproperty" has incompatible type "type[ChatGroup[MemberT, ChatT, ChatGroupTypeT]]"; expected "type[Never]" [arg-type]
- steam/chat.py:696: error: Argument 2 to "__get__" of "classproperty" has incompatible type "type[ChatGroup[MemberT, ChatT, ChatGroupTypeT]]"; expected "type[Never]" [arg-type]
+ steam/chat.py:696: error: Argument 3 to "__get__" of "classproperty" has incompatible type "type[ChatGroup[MemberT, ChatT, ChatGroupTypeT]]"; expected "type[Never]" [arg-type]
- steam/chat.py:869: error: Argument 2 to "__get__" of "classproperty" has incompatible type "type[ChatGroup[MemberT, ChatT, ChatGroupTypeT]]"; expected "type[Never]" [arg-type]
+ steam/chat.py:869: error: Argument 3 to "__get__" of "classproperty" has incompatible type "type[ChatGroup[MemberT, ChatT, ChatGroupTypeT]]"; expected "type[Never]" [arg-type]
- steam/state.py:1473: error: Argument 2 to "__get__" of "classproperty" has incompatible type "type[GroupChannel]"; expected "type[Never]" [arg-type]
+ steam/state.py:1473: error: Argument 3 to "__get__" of "classproperty" has incompatible type "type[GroupChannel]"; expected "type[Never]" [arg-type]
- steam/state.py:1473: error: Argument 2 to "__get__" of "classproperty" has incompatible type "type[ClanChannel]"; expected "type[Never]" [arg-type]
+ steam/state.py:1473: error: Argument 3 to "__get__" of "classproperty" has incompatible type "type[ClanChannel]"; expected "type[Never]" [arg-type]
- steam/state.py:1512: error: Argument 2 to "__get__" of "classproperty" has incompatible type "type[GroupChannel]"; expected "type[Never]" [arg-type]
+ steam/state.py:1512: error: Argument 3 to "__get__" of "classproperty" has incompatible type "type[GroupChannel]"; expected "type[Never]" [arg-type]
- steam/state.py:1512: error: Argument 2 to "__get__" of "classproperty" has incompatible type "type[ClanChannel]"; expected "type[Never]" [arg-type]
+ steam/state.py:1512: error: Argument 3 to "__get__" of "classproperty" has incompatible type "type[ClanChannel]"; expected "type[Never]" [arg-type]
- steam/state.py:2280: error: Argument 2 to "__get__" of "classproperty" has incompatible type "type[Commentable]"; expected "type[Never]" [arg-type]
+ steam/state.py:2280: error: Argument 3 to "__get__" of "classproperty" has incompatible type "type[Commentable]"; expected "type[Never]" [arg-type]
- steam/state.py:2292: error: Argument 2 to "__get__" of "classproperty" has incompatible type "type[Commentable]"; expected "type[Never]" [arg-type]
+ steam/state.py:2292: error: Argument 3 to "__get__" of "classproperty" has incompatible type "type[Commentable]"; expected "type[Never]" [arg-type]
- steam/state.py:2307: error: Argument 2 to "__get__" of "classproperty" has incompatible type "type[OwnerT]"; expected "type[Never]" [arg-type]
+ steam/state.py:2307: error: Argument 3 to "__get__" of "classproperty" has incompatible type "type[OwnerT]"; expected "type[Never]" [arg-type]
- steam/state.py:2331: error: Argument 2 to "__get__" of "classproperty" has incompatible type "type[Commentable]"; expected "type[Never]" [arg-type]
+ steam/state.py:2331: error: Argument 3 to "__get__" of "classproperty" has incompatible type "type[Commentable]"; expected "type[Never]" [arg-type]
- steam/state.py:2342: error: Argument 2 to "__get__" of "classproperty" has incompatible type "type[Commentable]"; expected "type[Never]" [arg-type]
+ steam/state.py:2342: error: Argument 3 to "__get__" of "classproperty" has incompatible type "type[Commentable]"; expected "type[Never]" [arg-type]
- steam/state.py:2438: error: Argument 2 to "__get__" of "classproperty" has incompatible type "type[Awardable[int]]"; expected "type[Never]" [arg-type]
+ steam/state.py:2438: error: Argument 3 to "__get__" of "classproperty" has incompatible type "type[Awardable[int]]"; expected "type[Never]" [arg-type]
- steam/state.py:2451: error: Argument 2 to "__get__" of "classproperty" has incompatible type "type[Awardable[int]]"; expected "type[Never]" [arg-type]
+ steam/state.py:2451: error: Argument 3 to "__get__" of "classproperty" has incompatible type "type[Awardable[int]]"; expected "type[Never]" [arg-type]
operator (https://github.com/canonical/operator)
- ops/_private/harness.py:429: error: Argument 1 to "__get__" of "ObjectEvents" has incompatible type "None"; expected "Object" [arg-type]
+ ops/_private/harness.py:429: error: Argument 2 to "__get__" of "ObjectEvents" has incompatible type "None"; expected "Object" [arg-type]
|
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.
When mypy resolved a descriptor's
__get__return type inanalyze_descriptor_access(mypy/checkmember.py), it first calledbind_selfto produce a bound-method type and then checked the call with only(instance, owner)arguments. This failed for descriptors whose__get__carries aSelf-like type variable that also appears in theinstanceparameter, becausebind_selfcould not unify those variables against complex callable types, producing incorrect or missing inferred types.The fix replaces that two-step approach with a single call using the raw unbound function type and three positional arguments
(self, instance, owner), letting the type-inference engine solve all type variables jointly in one pass.To verify, write a descriptor class whose
__get__annotatesselfwith a type variable shared withinstance, runmypyon it, and confirm the inferred return type is correct rather thanAnyor an error.Fixes #21505