Skip to content

Commit afa72b9

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

File tree

2 files changed

+26
-2
lines changed

2 files changed

+26
-2
lines changed

mypy/checkexpr.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1802,10 +1802,15 @@ 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-
callee = callee.copy_modified(ret_type=TypeType.make_normalized(arg_types[0]))
1808+
proper_arg = get_proper_type(arg_types[0])
1809+
if isinstance(proper_arg, Instance) and proper_arg.type.is_protocol:
1810+
self.msg.fail("Calling type() on a protocol class is unsound", context)
1811+
callee = callee.copy_modified(ret_type=self.named_type("builtins.object"))
1812+
else:
1813+
callee = callee.copy_modified(ret_type=TypeType.make_normalized(arg_types[0]))
18091814

18101815
if callable_node:
18111816
# Store the inferred callable type.

test-data/unit/check-protocols.test

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4215,3 +4215,22 @@ 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 "builtins.object"
4230+
reveal_type(value.foo) # E: "object" has no attribute "foo" \
4231+
# N: Revealed type is "Any"
4232+
4233+
[file mod.py]
4234+
def foo() -> None: ...
4235+
4236+
[builtins fixtures/tuple.pyi]

0 commit comments

Comments
 (0)