python / python/mypy

Calling a method of Union of two classes with class's attribute results in incompatible type error

Open
#8,355 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature priority-2-low
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

Honestly didn't know how to name this issue...

Issue type: Bug
Problematic code:

from typing import Union

class UserTypeA: ...
class UserTypeB: ...

class A:
    def permissions_for(self, user: UserTypeA) -> bool: ...
    
    @property
    def me(self) -> UserTypeA: ...

class B:
    def permissions_for(self, user: UserTypeB) -> bool: ...
    
    @property
    def me(self) -> UserTypeB: ...


def func(x: Union[A, B]) -> bool:
    return x.permissions_for(x.me)

Error message:

main.py:20: error: Argument 1 to "permissions_for" of "A" has incompatible type "Union[UserTypeA, UserTypeB]"; expected "UserTypeA"
main.py:20: error: Argument 1 to "permissions_for" of "B" has incompatible type "Union[UserTypeA, UserTypeB]"; expected "UserTypeB"

Expected behaviour:
No error as x.me matches the type expected by x.permissions_for - if instance of A is passed x.me will have type UserTypeA and x.permissions_for will expect UserTypeA and same for instance of B.

Also, if func looks like this, the errors are gone so if mypy could infer this without isinstance it would be great:

def func(x: Union[A, B]) -> bool:
    if isinstance(x, A):
        return x.permissions_for(x.me)
    else:
        return x.permissions_for(x.me)

Python version:: 3.8.1
Mypy version: 0.761, occurs on master as well
Mypy flags: No flags

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the minimal example in main.py with mypy 0.761 or current master, focusing on the Union[A, B] call through x.permissions_for(x.me). Done means func type-checks without isinstance when each class's property matches its method parameter, while genuinely incompatible calls remain errors.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
devtools
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.