Skip to content

Commit b77b8c0

Browse files
committed
Disallow calling type on Protocol
Fixes #16919, fixes #16890
1 parent 1f200dd commit b77b8c0

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

mypy/checkexpr.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1802,9 +1802,11 @@ def check_callable_call(
18021802

18031803
if (
18041804
callee.is_type_obj()
1805-
and (len(arg_types) == 1)
1805+
and len(arg_types) == 1
18061806
and is_equivalent(callee.ret_type, self.named_type("builtins.type"))
18071807
):
1808+
if isinstance(arg_types[0], Instance) and arg_types[0].type.is_protocol:
1809+
self.msg.fail("Calling type() on a protocol class is unsound", context)
18081810
callee = callee.copy_modified(ret_type=TypeType.make_normalized(arg_types[0]))
18091811

18101812
if callable_node:

test-data/unit/check-protocols.test

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4215,3 +4215,21 @@ def g4(a: Input[bytes], b: Output[str]) -> None:
42154215
f(a, b) # E: Cannot infer type argument 1 of "f"
42164216

42174217
[builtins fixtures/tuple.pyi]
4218+
4219+
[case testTypeCallOnProtocol]
4220+
from typing import Protocol
4221+
4222+
import mod
4223+
4224+
class P(Protocol):
4225+
def foo(self) -> None: ...
4226+
4227+
a: P = mod
4228+
value = type(a) # E: Calling type() on a protocol class is unsound
4229+
reveal_type(value) # N: Revealed type is "Type[__main__.P]"
4230+
reveal_type(value.foo) # N: Revealed type is "def (self: __main__.P)"
4231+
4232+
[file mod.py]
4233+
def foo() -> None: ...
4234+
4235+
[builtins fixtures/tuple.pyi]

0 commit comments

Comments
 (0)