Skip to content

Type-narrowing based on instance type #19671

@nenb

Description

@nenb

Bug Report

I would like to do a form of type narrowing based on the instance type. Minimal example in the script below.

mypy tells me that my script is not a valid pattern though. Is this true, or is it a bug?

To Reproduce

from typing import overload, Protocol, Self

class HasOverride(Protocol):
    override: bool

class A():
       
    @overload
    def fake_method(self: HasOverride) -> "A":
        ...
    
    @overload
    def fake_method(self) -> Self:
        ...
        
    def fake_method(self) -> Self | "A":
        if hasattr(self, 'override'):
            return A()
        return self
    
class B(A):  # fake_method should return B
    pass

class C(A):  # fake_method should return A
    override = True

Expected Behavior

mypy 1.16.0 raises the following error:

error: Overloaded function implementation cannot satisfy signature 1 due to inconsistencies in how they use type variables [misc]

pyright 1.1.403 does not raise an error.

It seems reasonable to me to allow this pattern, which is why I am opening this as a bug report.

If this is in fact desired behaviour, I would be very grateful for an explanation and, if possible, a suggested alternative pattern (I'm a bit desperate!).

Actual Behavior

Your Environment

  • Mypy version used: 1.16.0 (but have also repeated on 1.17.1)
  • Mypy command-line flags: just mypy (from a clean environment I pip installed mypy and then ran `mypy on the script above)
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: 3.11.13

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions