diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 577576a4e5f8..7c205eb89dfe 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1668,16 +1668,17 @@ def check_callable_call( # An Enum() call that failed SemanticAnalyzerPass2.check_enum_call(). return callee.ret_type, callee - if ( - callee.is_type_obj() - and callee.type_object().is_protocol - # Exception for Type[...] - and not callee.from_type_type - ): + if callee.is_type_obj() and callee.type_object().is_protocol: + protocol_name = callee.type_object().name self.chk.fail( - message_registry.CANNOT_INSTANTIATE_PROTOCOL.format(callee.type_object().name), - context, + message_registry.CANNOT_INSTANTIATE_PROTOCOL.format(protocol_name), context ) + if callee.from_type_type: + self.chk.note( + f'Consider using "Callable[..., {protocol_name}]" ' + f'instead of "type[{protocol_name}]"', + context, + ) elif ( callee.is_type_obj() and callee.type_object().is_abstract diff --git a/test-data/unit/check-protocols.test b/test-data/unit/check-protocols.test index 0367be3dde65..e00f727ec710 100644 --- a/test-data/unit/check-protocols.test +++ b/test-data/unit/check-protocols.test @@ -1603,7 +1603,8 @@ class C: pass def f(cls: Type[P]) -> P: - return cls() # OK + return cls() # E: Cannot instantiate protocol class "P" \ + # N: Consider using "Callable[..., P]" instead of "type[P]" def g() -> P: return P() # E: Cannot instantiate protocol class "P" @@ -1625,7 +1626,8 @@ class C: pass def f(cls: Type[P]) -> P: - return cls() # OK + return cls() # E: Cannot instantiate protocol class "P" \ + # N: Consider using "Callable[..., P]" instead of "type[P]" Alias = P GoodAlias = C @@ -1646,14 +1648,16 @@ class C: pass var: Type[P] -var() +var() # E: Cannot instantiate protocol class "P" \ + # N: Consider using "Callable[..., P]" instead of "type[P]" if int(): var = P # E: Can only assign concrete classes to a variable of type "Type[P]" var = B # OK var = C # OK var_old = None # type: Type[P] # Old syntax for variable annotations -var_old() +var_old() # E: Cannot instantiate protocol class "P" \ + # N: Consider using "Callable[..., P]" instead of "type[P]" if int(): var_old = P # E: Can only assign concrete classes to a variable of type "Type[P]" var_old = B # OK @@ -1669,7 +1673,8 @@ class Logger: class C(Protocol): @classmethod def action(cls) -> None: - cls() #OK for classmethods + cls() # E: Cannot instantiate protocol class "C" \ + # N: Consider using "Callable[..., C]" instead of "type[C]" Logger.log(cls) #OK for classmethods [builtins fixtures/classmethod.pyi] diff --git a/test-data/unit/check-selftype.test b/test-data/unit/check-selftype.test index fa853ac48e5a..e97fa7d81657 100644 --- a/test-data/unit/check-selftype.test +++ b/test-data/unit/check-selftype.test @@ -1023,7 +1023,8 @@ T = TypeVar('T', bound=HasX) class Meta(type): def do_x(cls: Type[T]) -> T: cls.x - return cls() + return cls() # E: Cannot instantiate protocol class "HasX" \ + # N: Consider using "Callable[..., HasX]" instead of "type[HasX]" class Good(metaclass=Meta): x: int