Skip to content

Inconsistent errors when reassigning Union[list|Callable] in subclass #12126

Closed

Description

@MathiasSven

To Reproduce

from typing import Callable, Any, TypeVar

T = TypeVar('T', bound='BaseClass')  # Alternative Example

class BaseClass:
    def default_example(self) -> list[int]:
         return [1, 2, 3]
    
    example: Callable[[Any], list[int]] | list[int] = default_example

class ChildClassA(BaseClass):
    example: list[int] = [1, 2, 3]
    
class ChildClassB(BaseClass):
    example = lambda self: [1,2,3]

class ChildClassC(BaseClass):
    def default_example(self) -> list[int]:
         return [1, 2, 3]
    example = default_example

class ChildClassD(BaseClass):
    def example(self) -> list[int]:
         return [1, 2, 3]

Behavior

Given that ChildClassB and ChildClassC passes with no issues, I would expect ChildClassD to also pass, however mypy raises the error:

main.py:23: error: Signature of "example" incompatible with supertype "BaseClass"

This seems to be unexpected as ChildClassC and ChildClassD should be equivalent. From my understanding it should also be equal to ChildClassB but it uses a lambda function so I suppose it is not the same.

Also if we change the annotation on BaseClass.example to example: Callable[[T], list[int]] | list[int] (swapping Any to bounded T) then both ChildClassC and ``ChildClassB` raise an error:

main.py:20: error: Incompatible types in assignment (expression has type "Callable[[ChildClassC], List[int]]", base class "Class" defined the type as "Union[Callable[[T], List[int]], List[int]]")
main.py:23: error: Signature of "example" incompatible with supertype "BaseClass"

From what I understand this is intended, however in that case shouldn't ChildClassB also fail?

Environment

  • Mypy version used: 0.931
  • Mypy command-line flags: --strict
  • Python version used: 3.10

Activity

  1. changed the title [-]Inconsistent errors when reassigning `Union[ list | callable ]` in subclass[/-] [+]Inconsistent errors when reassigning `Union[list|Callable]` in subclass[/+] on Feb 4, 2022
  2. ilevkivskyi commented on Mar 31, 2025

    @ilevkivskyi
    Member

    Actually I think this one should stay open. Although it now gives errors more consistently, it is not the best we can do. If we have a union of callable with non-callable, we need to handle bind_self() separately on both items of the union.

  3. ilevkivskyi commented on Apr 3, 2025

    @ilevkivskyi
    Member

    OK, on current master it should work without errors if you will use ClassVar in the explicit annotations you have (according to PEP 526 an explicit annotation in class body automatically makes a variable an instance variable).

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

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