Skip to content

Commit

Permalink
Disallow calling type on Protocol
Browse files Browse the repository at this point in the history
Fixes #16919, fixes #16890
  • Loading branch information
hauntsaninja committed Nov 3, 2024
1 parent 1f200dd commit 3d3a3be
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 1 deletion.
5 changes: 4 additions & 1 deletion mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -1802,9 +1802,12 @@ def check_callable_call(

if (
callee.is_type_obj()
and (len(arg_types) == 1)
and len(arg_types) == 1
and is_equivalent(callee.ret_type, self.named_type("builtins.type"))
):
proper_arg = get_proper_type(arg_types[0])
if isinstance(proper_arg, Instance) and proper_arg.type.is_protocol:
self.msg.fail("Calling type() on a protocol class is unsound", context)
callee = callee.copy_modified(ret_type=TypeType.make_normalized(arg_types[0]))

if callable_node:
Expand Down
18 changes: 18 additions & 0 deletions test-data/unit/check-protocols.test
Original file line number Diff line number Diff line change
Expand Up @@ -4215,3 +4215,21 @@ def g4(a: Input[bytes], b: Output[str]) -> None:
f(a, b) # E: Cannot infer type argument 1 of "f"

[builtins fixtures/tuple.pyi]

[case testTypeCallOnProtocol]
from typing import Protocol

import mod

class P(Protocol):
def foo(self) -> None: ...

a: P = mod
value = type(a) # E: Calling type() on a protocol class is unsound
reveal_type(value) # N: Revealed type is "Type[__main__.P]"
reveal_type(value.foo) # N: Revealed type is "def (self: __main__.P)"

[file mod.py]
def foo() -> None: ...

[builtins fixtures/tuple.pyi]

0 comments on commit 3d3a3be

Please sign in to comment.