Skip to content

Cannot access custom property of union type #9053

Closed
@nielsbuwen

Description

@nielsbuwen

Hi, i may have found a false-positive in mypy,

Example

Below is a simplified version of a custom property we use. In my understanding the interfaces of A and B are compatible.

from typing import Union, Callable, Type


# similar to a get-only property
class MyProperty:
    def __init__(self, func: Callable[['B'], int]) -> None:
        self.func = func

    def __get__(self, instance: 'B', owner: Type['B']) -> int:
        return self.func(instance)


# This class has an attribute 'x'
class A:
    def __init__(self) -> None:
        self.x = 123


# This class has a property 'x'
class B:
    @MyProperty
    def x(self) -> int:
        return 456


def foo(a: Union[A, B]) -> int:
    return a.x  # mypy detects an error here

Actual Behavior

Running mypy --strict test.py yields an error

test.py:25: error: Argument 1 to "__get__" of "MyProperty" has incompatible type "Union[A, B]"; expected "B"
test.py:25: error: Argument 2 to "__get__" of "MyProperty" has incompatible type "Union[Type[A], Type[B]]"; expected "Type[B]"
Found 2 errors in 1 file (checked 1 source file)

It looks like mypy thinks that instances of type A also use the property which is not true.

Expected Behavior

The expected behavior would be that mypy accepts the code without an error.

Versions

I am using python==3.8.1 and mypy==0.790+dev.6ee562a8f3e69ac134f8c501b79b3712c9e24bbd

Notes

Replacing the @MyProperty with @property or @functools.cached_property works as expected. Changing foo to acceppt either A or B also works as expected.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions