Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove TypeType exception for protocol instantiation #18346

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 10 additions & 5 deletions test-data/unit/check-protocols.test
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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
Expand All @@ -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
Expand All @@ -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]

Expand Down
3 changes: 2 additions & 1 deletion test-data/unit/check-selftype.test
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading