Skip to content

Protocol type object is not resolved correctly with overload #15666

Closed as not planned
@ippeiukai

Description

@ippeiukai

Bug Report

Function overloads that take type as argument does not match Protocol subclass objects.

This bug prevents use of Protocol classes with DI container like python-inject.
https://github.com/ivankorobkov/python-inject/blob/05ad3e87bb179ce56cabb272bd5f75cca2880f7c/inject/__init__.py#L394-L402

To Reproduce

from abc import ABCMeta, abstractmethod
from typing import Any, cast, NewType, overload, Protocol, runtime_checkable, TypeVar
from typing_extensions import assert_type

T = TypeVar( "T")


@overload
def get_instance(t: type[T]) -> T: ...
@overload
def get_instance(t: Any) -> object: ...

def get_instance(t):
    return cast(Any, object())  # dummy (e.g. should implement a DI container)


# normal class
class C:
    def foo(self) -> str:
        return ''

assert_type(C, type[C])


# abstract class
class A(metaclass=ABCMeta):
    def foo(self) -> str:
        return ''

assert_type(A, type[A])


# pure abstract class
class PA(metaclass=ABCMeta):
    @abstractmethod
    def foo(self) -> str:
        ...

assert_type(PA, type[PA])


# Protocol type
class P(Protocol):
    def foo(self) -> str:
        ...

assert_type(P, type[P])


# runtime-checkable Protocol type
@runtime_checkable
class RP(Protocol):
    def foo(self) -> str:
        ...

assert_type(RP, type[RP])


# NewType
NT = NewType("NT", PA)

assert_type(NT, type[NT])


c = get_instance(C)
assert_type(c, C)

a = get_instance(A)
assert_type(a, A)

pa = get_instance(PA)
assert_type(pa, PA)  # error: Expression is of type "object", not "PA"  [assert-type]

p = get_instance(P)
assert_type(p, P)  # error: Expression is of type "object", not "P"  [assert-type]

rp = get_instance(RP)
assert_type(rp, RP)  # error: Expression is of type "object", not "RP"  [assert-type]

nt = get_instance(NT)
assert_type(nt, NT)

Expected Behavior

There should be no type checking error.
Protocol class P should match type[P] in overloads.

Actual Behavior

Type checking errors are raised for Protocol types.
Protocol class P does match type[P] in overloads.

Your Environment

  • Mypy version used: 1.4.1
  • Mypy command-line flags:
  • Mypy configuration options from mypy.ini (and other config files):
  • Python version used: 3.10.9 with typing-extensions 4.3.0

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