Skip to content

Fix descriptor access for complex generics#21506

Open
JiwaniZakir wants to merge 2 commits into
python:masterfrom
JiwaniZakir:fix/issue-21505
Open

Fix descriptor access for complex generics#21506
JiwaniZakir wants to merge 2 commits into
python:masterfrom
JiwaniZakir:fix/issue-21505

Conversation

@JiwaniZakir
Copy link
Copy Markdown

When mypy resolved a descriptor's __get__ return type in analyze_descriptor_access (mypy/checkmember.py), it first called bind_self to produce a bound-method type and then checked the call with only (instance, owner) arguments. This failed for descriptors whose __get__ carries a Self-like type variable that also appears in the instance parameter, because bind_self could 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__ annotates self with a type variable shared with instance, run mypy on it, and confirm the inferred return type is correct rather than Any or an error.

Fixes #21505

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
@github-actions
Copy link
Copy Markdown
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]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Descriptor access fails for complex generics

1 participant