Skip to content

Incorrect returned type of access descriptors on unions of types #16603

Closed
@md384

Description

@md384

Bug Report

Mypy will return the incorrect type for access descriptors on unions of types. It returns the types of the attributes on the instance of the type rather than the type itself.

See sqlalchemy/sqlalchemy#9419 for a concrete example with sqlalchemy.

To Reproduce

# Ideally, a small sample program that demonstrates the problem.
# Or even better, a reproducible playground link https://mypy-play.net/ (use the "Gist" button)

from typing import overload, Generic, Any, TypeVar, List, Optional, Union, Type

_T_co = TypeVar("_T_co", bound=Any, covariant=True)

class Mapped(Generic[_T_co]):
    def __init__(self, value: _T_co):
        self.value = value

    @overload
    def __get__(
        self, instance: None, owner: Any
    ) -> List[_T_co]:
        ...

    @overload
    def __get__(self, instance: object, owner: Any) -> _T_co:
        ...

    def __get__(
        self, instance: Optional[object], owner: Any
    ) -> Union[List[_T_co], _T_co]:
        return self.value

class A:
    field_1: Mapped[int] = Mapped(1)
    field_2: Mapped[str] = Mapped('1')

class B:
    field_1: Mapped[int] = Mapped(2)
    field_2: Mapped[str] = Mapped('2')

Expected Behavior

mix: Union[Type[A], Type[B]] = A
reveal_type(mix)  # N: Revealed type is "Union[Type[__main__.A], Type[__main__.B]]"
reveal_type(mix.field_1)  # N: Revealed type is "builtins.list[builtins.int]"
reveal_type(mix().field_1)  # N: Revealed type is "builtins.int"

Actual Behavior

mix: Union[Type[A], Type[B]] = A
reveal_type(mix)  # N: Revealed type is "Union[Type[__main__.A], Type[__main__.B]]"
reveal_type(mix.field_1)  # N: Revealed type is "builtins.int"
reveal_type(mix().field_1)  # N: Revealed type is "builtins.int"

reveal_type(mix.field_1) is incorrectly builtins.int, should be builtins.list[builtins.int].

Your Environment

  • Mypy version used: master (1.7)
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: 3.11

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions