Skip to content

Commit e42a427

Browse files
committed
ignore promotions
1 parent 7062598 commit e42a427

2 files changed

Lines changed: 40 additions & 9 deletions

File tree

mypy/checker.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6719,13 +6719,15 @@ def narrow_type_by_identity_equality(
67196719

67206720
if is_target_for_value_narrowing(get_proper_type(target_type)):
67216721
if_map, else_map = conditional_types_to_typemaps(
6722-
operands[i], *conditional_types(expanded_expr_type, [target])
6722+
operands[i],
6723+
*conditional_types(expanded_expr_type, [target], ignore_promotions=False),
67236724
)
67246725
all_if_maps.append(if_map)
67256726
all_else_maps.append(else_map)
67266727
else:
67276728
if_map, else_map = conditional_types_to_typemaps(
6728-
operands[i], *conditional_types(expr_type, [target])
6729+
operands[i],
6730+
*conditional_types(expr_type, [target], ignore_promotions=False),
67296731
)
67306732
# For value targets, it is safe to narrow in the negative case.
67316733
# e.g. if (x: Literal[5] | None) != (y: Literal[5]), we can narrow x to None
@@ -6756,7 +6758,8 @@ def narrow_type_by_identity_equality(
67566758
target = TypeRange(target_type, is_upper_bound=False)
67576759
if is_target_for_value_narrowing(get_proper_type(target_type)):
67586760
if_map, else_map = conditional_types_to_typemaps(
6759-
operands[i], *conditional_types(expr_type, [target])
6761+
operands[i],
6762+
*conditional_types(expr_type, [target], ignore_promotions=False),
67606763
)
67616764
if else_map:
67626765
all_else_maps.append(else_map)
@@ -6786,7 +6789,10 @@ def narrow_type_by_identity_equality(
67866789
expr_type = coerce_to_literal(expr_type)
67876790
expr_type = try_expanding_sum_type_to_union(expr_type, None)
67886791
if_map, else_map = conditional_types_to_typemaps(
6789-
operands[i], *conditional_types(expr_type, [target], default=expr_type)
6792+
operands[i],
6793+
*conditional_types(
6794+
expr_type, [target], default=expr_type, ignore_promotions=False
6795+
),
67906796
)
67916797
or_if_maps.append(if_map)
67926798
if is_value_target:
@@ -8244,6 +8250,7 @@ def conditional_types(
82448250
default: None = None,
82458251
*,
82468252
consider_runtime_isinstance: bool = True,
8253+
ignore_promotions: bool = True,
82478254
) -> tuple[Type | None, Type | None]: ...
82488255

82498256

@@ -8254,6 +8261,7 @@ def conditional_types(
82548261
default: Type,
82558262
*,
82568263
consider_runtime_isinstance: bool = True,
8264+
ignore_promotions: bool = True,
82578265
) -> tuple[Type, Type]: ...
82588266

82598267

@@ -8263,6 +8271,7 @@ def conditional_types(
82638271
default: Type | None = None,
82648272
*,
82658273
consider_runtime_isinstance: bool = True,
8274+
ignore_promotions: bool = True,
82668275
) -> tuple[Type | None, Type | None]:
82678276
"""Takes in the current type and a proposed type of an expression.
82688277
@@ -8321,14 +8330,14 @@ def conditional_types(
83218330
return proposed_type, default
83228331
if not any(type_range.is_upper_bound for type_range in proposed_type_ranges):
83238332
# concrete subtype
8324-
if is_proper_subtype(current_type, proposed_type, ignore_promotions=True):
8333+
if is_proper_subtype(current_type, proposed_type, ignore_promotions=ignore_promotions):
83258334
return default, UninhabitedType()
83268335

83278336
# structural subtypes
83288337
if (
83298338
isinstance(proposed_type, CallableType)
83308339
or (isinstance(proposed_type, Instance) and proposed_type.type.is_protocol)
8331-
) and is_subtype(current_type, proposed_type, ignore_promotions=True):
8340+
) and is_subtype(current_type, proposed_type, ignore_promotions=ignore_promotions):
83328341
# Note: It's possible that current_type=`Any | Proto` while proposed_type=`Proto`
83338342
# so we cannot return `Never` for the else branch
83348343
remainder = restrict_subtype_away(
@@ -8337,7 +8346,7 @@ def conditional_types(
83378346
consider_runtime_isinstance=consider_runtime_isinstance,
83388347
)
83398348
return default, remainder
8340-
if not is_overlapping_types(current_type, proposed_type, ignore_promotions=True):
8349+
if not is_overlapping_types(current_type, proposed_type, ignore_promotions=ignore_promotions):
83418350
# Expression is never of any type in proposed_type_ranges
83428351
return UninhabitedType(), default
83438352
# we can only restrict when the type is precise, not bounded

test-data/unit/check-narrowing.test

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3264,18 +3264,40 @@ def bar(y: Any):
32643264

32653265

32663266
[case testNarrowingConstrainedTypeVarType]
3267-
from __future__ import annotations
3267+
# flags: --strict-equality --warn-unreachable
32683268
from typing import TypeVar, Any, Type
32693269

32703270
TargetType = TypeVar("TargetType", int, float, str)
32713271

32723272
def convert_type(target_type: Type[TargetType]) -> TargetType:
32733273
if target_type == str:
32743274
return str()
3275-
if target_type == int:
3275+
if target_type == int:s
32763276
return int()
32773277
if target_type == float:
32783278
return float()
32793279
raise
3280+
[builtins fixtures/primitives.pyi]
3281+
3282+
3283+
[case testNarrowingEqualityWithPromotions]
3284+
# flags: --strict-equality --warn-unreachable
3285+
from __future__ import annotations
3286+
from typing import Literal
3287+
3288+
def f1(number: float, i: int):
3289+
if number == i:
3290+
reveal_type(number) # N: Revealed type is "builtins.int"
3291+
3292+
def f2(number: float, five: Literal[5]):
3293+
if number == five:
3294+
reveal_type(number) # N: Revealed type is "Literal[5]"
3295+
3296+
class Custom:
3297+
def __eq__(self, other: object) -> bool: return True
32803298

3299+
def f3(number: float, x: Custom | int):
3300+
if number == x:
3301+
reveal_type(number) # N: Revealed type is "builtins.float"
3302+
reveal_type(x) # N: Revealed type is "__main__.Custom | builtins.int"
32813303
[builtins fixtures/primitives.pyi]

0 commit comments

Comments
 (0)