Skip to content

Commit dd39282

Browse files
committed
Fix couple inconsistencies in protocols vs TypeType
1 parent fe91422 commit dd39282

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, code=msg.code)
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
@@ -3109,9 +3109,14 @@ def get_bad_protocol_flags(
31093109
assert right.type.is_protocol
31103110
all_flags: list[tuple[str, set[int], set[int]]] = []
31113111
for member in right.type.protocol_members:
3112-
if find_member(member, left, left):
3113-
item = (member, get_member_flags(member, left), get_member_flags(member, right))
3114-
all_flags.append(item)
3112+
if find_member(member, left, left, class_obj=class_obj):
3113+
all_flags.append(
3114+
(
3115+
member,
3116+
get_member_flags(member, left, class_obj=class_obj),
3117+
get_member_flags(member, right),
3118+
)
3119+
)
31153120
bad_flags = []
31163121
for name, subflags, superflags in all_flags:
31173122
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
@@ -4551,3 +4551,29 @@ class Test(Generic[T]):
45514551
t = Test(Mock())
45524552
reveal_type(t) # N: Revealed type is "__main__.Test[Any]"
45534553
[builtins fixtures/dict.pyi]
4554+
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"

0 commit comments

Comments
 (0)