From 84673c26a6cbbfef68b7539c0f8a9566e5c7d667 Mon Sep 17 00:00:00 2001 From: Christoph Tyralla Date: Sun, 29 Dec 2024 15:29:29 +0100 Subject: [PATCH] Reject promotions when checking against protocols. Fixes #18359 --- mypy/subtypes.py | 2 +- test-data/unit/check-type-promotion.test | 16 ++++++++++++++++ test-data/unit/fixtures/primitives.pyi | 1 + 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/mypy/subtypes.py b/mypy/subtypes.py index a26aaf798b58f..666bdebed7429 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -499,7 +499,7 @@ def visit_instance(self, left: Instance) -> bool: return True if type_state.is_cached_negative_subtype_check(self._subtype_kind, left, right): return False - if not self.subtype_context.ignore_promotions: + if not self.subtype_context.ignore_promotions and not right.type.is_protocol: for base in left.type.mro: if base._promote and any( self._is_subtype(p, self.right) for p in base._promote diff --git a/test-data/unit/check-type-promotion.test b/test-data/unit/check-type-promotion.test index d98d0c60e1644..1b69174a45454 100644 --- a/test-data/unit/check-type-promotion.test +++ b/test-data/unit/check-type-promotion.test @@ -187,3 +187,19 @@ if isinstance(x, (float, complex)): else: reveal_type(x) # N: Revealed type is "builtins.int" [builtins fixtures/primitives.pyi] + +[case testRejectPromotionsForProtocols] +from typing import Protocol + +class H(Protocol): + def hex(self, /) -> str: ... + +f: H = 1.0 +o: H = object() # E: Incompatible types in assignment (expression has type "object", variable has type "H") +c: H = 1j # E: Incompatible types in assignment (expression has type "complex", variable has type "H") +i: H = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "H") +b: H = False # E: Incompatible types in assignment (expression has type "bool", variable has type "H") + +class N(float): ... +n: H = N() +[builtins fixtures/primitives.pyi] diff --git a/test-data/unit/fixtures/primitives.pyi b/test-data/unit/fixtures/primitives.pyi index e7d3e12bd5e6a..fc220a4e2ee0c 100644 --- a/test-data/unit/fixtures/primitives.pyi +++ b/test-data/unit/fixtures/primitives.pyi @@ -22,6 +22,7 @@ class int: class float: def __float__(self) -> float: pass def __add__(self, x: float) -> float: pass + def hex(self) -> str: pass class complex: def __add__(self, x: complex) -> complex: pass class bool(int): pass