Skip to content

Protocol type object is not resolved correctly with overload #15666

Closed as not planned

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

Activity

  1. ippeiukai commented on Jul 18, 2023

    @ippeiukai
    Author

    I've learnt this is actually as spec'ed in PEP 544.
    https://peps.python.org/pep-0544/#type-and-class-objects-vs-protocols

    However, some inconsistencies remain problematic. I will create new issues for them.

    • pure abstract case being error
    • assert_type not picking up error
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