Skip to content

Commit 61cbe0c

Browse files
authored
Fix couple inconsistencies in protocols vs TypeType (#19267)
1 parent 75f7a25 commit 61cbe0c

File tree

4 files changed

+37
-6
lines changed

4 files changed

+37
-6
lines changed

mypy/checker.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7190,7 +7190,7 @@ def check_subtype(
71907190
if (
71917191
isinstance(supertype, Instance)
71927192
and supertype.type.is_protocol
7193-
and isinstance(subtype, (CallableType, Instance, TupleType, TypedDictType))
7193+
and isinstance(subtype, (CallableType, Instance, TupleType, TypedDictType, TypeType))
71947194
):
71957195
self.msg.report_protocol_problems(subtype, supertype, context, parent_error=error)
71967196
if isinstance(supertype, CallableType) and isinstance(subtype, Instance):

mypy/messages.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3090,9 +3090,14 @@ def get_bad_protocol_flags(
30903090
assert right.type.is_protocol
30913091
all_flags: list[tuple[str, set[int], set[int]]] = []
30923092
for member in right.type.protocol_members:
3093-
if find_member(member, left, left):
3094-
item = (member, get_member_flags(member, left), get_member_flags(member, right))
3095-
all_flags.append(item)
3093+
if find_member(member, left, left, class_obj=class_obj):
3094+
all_flags.append(
3095+
(
3096+
member,
3097+
get_member_flags(member, left, class_obj=class_obj),
3098+
get_member_flags(member, right),
3099+
)
3100+
)
30963101
bad_flags = []
30973102
for name, subflags, superflags in all_flags:
30983103
if (

mypy/subtypes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,8 +1319,8 @@ def find_member(
13191319
is_lvalue=is_lvalue,
13201320
is_super=False,
13211321
is_operator=is_operator,
1322-
original_type=itype,
1323-
self_type=subtype,
1322+
original_type=TypeType.make_normalized(itype) if class_obj else itype,
1323+
self_type=TypeType.make_normalized(subtype) if class_obj else subtype,
13241324
context=Context(), # all errors are filtered, but this is a required argument
13251325
chk=type_checker,
13261326
suppress_errors=True,

test-data/unit/check-protocols.test

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4552,6 +4552,32 @@ t = Test(Mock())
45524552
reveal_type(t) # N: Revealed type is "__main__.Test[Any]"
45534553
[builtins fixtures/dict.pyi]
45544554

4555+
[case testProtocolClassObjectDescriptor]
4556+
from typing import Any, Protocol, overload
4557+
4558+
class Desc:
4559+
@overload
4560+
def __get__(self, instance: None, owner: Any) -> Desc: ...
4561+
@overload
4562+
def __get__(self, instance: object, owner: Any) -> int: ...
4563+
def __get__(self, instance, owner):
4564+
pass
4565+
4566+
class HasDesc(Protocol):
4567+
attr: Desc
4568+
4569+
class HasInt(Protocol):
4570+
attr: int
4571+
4572+
class C:
4573+
attr = Desc()
4574+
4575+
x: HasInt = C()
4576+
y: HasDesc = C
4577+
z: HasInt = C # E: Incompatible types in assignment (expression has type "type[C]", variable has type "HasInt") \
4578+
# N: Following member(s) of "C" have conflicts: \
4579+
# N: attr: expected "int", got "Desc"
4580+
45554581
[case testProtocolErrorReportingNoDuplicates]
45564582
from typing import Callable, Protocol, TypeVar
45574583

0 commit comments

Comments
 (0)