Skip to content

Commit ac6151a

Browse files
authored
Reject promotions when checking against protocols. (#18360)
Fixes #18359 Fixes #18257 The change is simple but may be way too general. Making it more precise should be straightforward, but I want to see the Mypy Primer results and hear other opinions first.
1 parent b9056f9 commit ac6151a

File tree

3 files changed

+18
-1
lines changed

3 files changed

+18
-1
lines changed

mypy/subtypes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ def visit_instance(self, left: Instance) -> bool:
499499
return True
500500
if type_state.is_cached_negative_subtype_check(self._subtype_kind, left, right):
501501
return False
502-
if not self.subtype_context.ignore_promotions:
502+
if not self.subtype_context.ignore_promotions and not right.type.is_protocol:
503503
for base in left.type.mro:
504504
if base._promote and any(
505505
self._is_subtype(p, self.right) for p in base._promote

test-data/unit/check-type-promotion.test

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,19 @@ if isinstance(x, (float, complex)):
187187
else:
188188
reveal_type(x) # N: Revealed type is "builtins.int"
189189
[builtins fixtures/primitives.pyi]
190+
191+
[case testRejectPromotionsForProtocols]
192+
from typing import Protocol
193+
194+
class H(Protocol):
195+
def hex(self, /) -> str: ...
196+
197+
f: H = 1.0
198+
o: H = object() # E: Incompatible types in assignment (expression has type "object", variable has type "H")
199+
c: H = 1j # E: Incompatible types in assignment (expression has type "complex", variable has type "H")
200+
i: H = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "H")
201+
b: H = False # E: Incompatible types in assignment (expression has type "bool", variable has type "H")
202+
203+
class N(float): ...
204+
n: H = N()
205+
[builtins fixtures/primitives.pyi]

test-data/unit/fixtures/primitives.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class int:
2222
class float:
2323
def __float__(self) -> float: pass
2424
def __add__(self, x: float) -> float: pass
25+
def hex(self) -> str: pass
2526
class complex:
2627
def __add__(self, x: complex) -> complex: pass
2728
class bool(int): pass

0 commit comments

Comments
 (0)