Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 54512be

Browse files
committed
another approach
1 parent 635a82b commit 54512be

2 files changed

Lines changed: 30 additions & 18 deletions

File tree

mypy/checker.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6720,14 +6720,14 @@ def narrow_type_by_identity_equality(
67206720
if is_target_for_value_narrowing(get_proper_type(target_type)):
67216721
if_map, else_map = conditional_types_to_typemaps(
67226722
operands[i],
6723-
*conditional_types(expanded_expr_type, [target], ignore_promotions=False),
6723+
*conditional_types(expanded_expr_type, [target], consider_promotion_overlap=True),
67246724
)
67256725
all_if_maps.append(if_map)
67266726
all_else_maps.append(else_map)
67276727
else:
67286728
if_map, else_map = conditional_types_to_typemaps(
67296729
operands[i],
6730-
*conditional_types(expr_type, [target], ignore_promotions=False),
6730+
*conditional_types(expr_type, [target], consider_promotion_overlap=True),
67316731
)
67326732
# For value targets, it is safe to narrow in the negative case.
67336733
# e.g. if (x: Literal[5] | None) != (y: Literal[5]), we can narrow x to None
@@ -6759,7 +6759,7 @@ def narrow_type_by_identity_equality(
67596759
if is_target_for_value_narrowing(get_proper_type(target_type)):
67606760
if_map, else_map = conditional_types_to_typemaps(
67616761
operands[i],
6762-
*conditional_types(expr_type, [target], ignore_promotions=False),
6762+
*conditional_types(expr_type, [target], consider_promotion_overlap=True),
67636763
)
67646764
if else_map:
67656765
all_else_maps.append(else_map)
@@ -6791,7 +6791,7 @@ def narrow_type_by_identity_equality(
67916791
if_map, else_map = conditional_types_to_typemaps(
67926792
operands[i],
67936793
*conditional_types(
6794-
expr_type, [target], default=expr_type, ignore_promotions=False
6794+
expr_type, [target], default=expr_type, consider_promotion_overlap=True
67956795
),
67966796
)
67976797
or_if_maps.append(if_map)
@@ -8250,7 +8250,7 @@ def conditional_types(
82508250
default: None = None,
82518251
*,
82528252
consider_runtime_isinstance: bool = True,
8253-
ignore_promotions: bool = True,
8253+
consider_promotion_overlap: bool = False,
82548254
) -> tuple[Type | None, Type | None]: ...
82558255

82568256

@@ -8261,7 +8261,7 @@ def conditional_types(
82618261
default: Type,
82628262
*,
82638263
consider_runtime_isinstance: bool = True,
8264-
ignore_promotions: bool = True,
8264+
consider_promotion_overlap: bool = False,
82658265
) -> tuple[Type, Type]: ...
82668266

82678267

@@ -8271,7 +8271,7 @@ def conditional_types(
82718271
default: Type | None = None,
82728272
*,
82738273
consider_runtime_isinstance: bool = True,
8274-
ignore_promotions: bool = True,
8274+
consider_promotion_overlap: bool = False,
82758275
) -> tuple[Type | None, Type | None]:
82768276
"""Takes in the current type and a proposed type of an expression.
82778277
@@ -8311,7 +8311,7 @@ def conditional_types(
83118311
proposed_type_ranges,
83128312
default=union_item,
83138313
consider_runtime_isinstance=consider_runtime_isinstance,
8314-
ignore_promotions=ignore_promotions,
8314+
consider_promotion_overlap=consider_promotion_overlap,
83158315
)
83168316
for union_item in get_proper_types(proper_type.items)
83178317
]
@@ -8331,14 +8331,14 @@ def conditional_types(
83318331
return proposed_type, default
83328332
if not any(type_range.is_upper_bound for type_range in proposed_type_ranges):
83338333
# concrete subtype
8334-
if is_proper_subtype(current_type, proposed_type, ignore_promotions=ignore_promotions):
8334+
if is_proper_subtype(current_type, proposed_type, ignore_promotions=True):
83358335
return default, UninhabitedType()
83368336

83378337
# structural subtypes
83388338
if (
83398339
isinstance(proposed_type, CallableType)
83408340
or (isinstance(proposed_type, Instance) and proposed_type.type.is_protocol)
8341-
) and is_subtype(current_type, proposed_type, ignore_promotions=ignore_promotions):
8341+
) and is_subtype(current_type, proposed_type, ignore_promotions=True):
83428342
# Note: It's possible that current_type=`Any | Proto` while proposed_type=`Proto`
83438343
# so we cannot return `Never` for the else branch
83448344
remainder = restrict_subtype_away(
@@ -8347,9 +8347,11 @@ def conditional_types(
83478347
consider_runtime_isinstance=consider_runtime_isinstance,
83488348
)
83498349
return default, remainder
8350-
if not is_overlapping_types(current_type, proposed_type, ignore_promotions=ignore_promotions):
8350+
if not is_overlapping_types(current_type, proposed_type, ignore_promotions=not consider_promotion_overlap):
83518351
# Expression is never of any type in proposed_type_ranges
83528352
return UninhabitedType(), default
8353+
if consider_promotion_overlap and not is_overlapping_types(current_type, proposed_type, ignore_promotions=True):
8354+
return default, default
83538355
# we can only restrict when the type is precise, not bounded
83548356
proposed_precise_type = UnionType.make_union(
83558357
[type_range.item for type_range in proposed_type_ranges if not type_range.is_upper_bound]

test-data/unit/check-narrowing.test

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3287,28 +3287,38 @@ from typing import Literal
32873287

32883288
def f1(number: float, i: int):
32893289
if number == i:
3290-
reveal_type(number) # N: Revealed type is "builtins.int"
3290+
reveal_type(number) # N: Revealed type is "builtins.float"
3291+
reveal_type(i) # N: Revealed type is "builtins.int"
32913292

32923293
def f2(number: float, five: Literal[5]):
32933294
if number == five:
3294-
reveal_type(number) # N: Revealed type is "Literal[5]"
3295+
reveal_type(number) # N: Revealed type is "builtins.float"
3296+
reveal_type(five) # N: Revealed type is "Literal[5]"
32953297

3296-
def f3(number: float | None, i: int):
3298+
def f3(number: float | int, five: Literal[5]):
3299+
if number == five:
3300+
reveal_type(number) # N: Revealed type is "builtins.float | Literal[5]"
3301+
reveal_type(five) # N: Revealed type is "Literal[5]"
3302+
3303+
def f4(number: float | None, i: int):
32973304
if number == i:
3298-
reveal_type(number) # N: Revealed type is "builtins.int"
3305+
reveal_type(number) # N: Revealed type is "builtins.float"
3306+
reveal_type(i) # N: Revealed type is "builtins.int"
32993307

3300-
def f4(number: float | int, i: int):
3308+
def f5(number: float | int, i: int):
33013309
if number == i:
33023310
reveal_type(number) # N: Revealed type is "builtins.float | builtins.int"
3311+
reveal_type(i) # N: Revealed type is "builtins.int"
33033312

3304-
def f5(number: float | complex, i: int):
3313+
def f6(number: float | complex, i: int):
33053314
if number == i:
33063315
reveal_type(number) # N: Revealed type is "builtins.float | builtins.complex"
3316+
reveal_type(i) # N: Revealed type is "builtins.int"
33073317

33083318
class Custom:
33093319
def __eq__(self, other: object) -> bool: return True
33103320

3311-
def f6(number: float, x: Custom | int):
3321+
def f7(number: float, x: Custom | int):
33123322
if number == x:
33133323
reveal_type(number) # N: Revealed type is "builtins.float"
33143324
reveal_type(x) # N: Revealed type is "__main__.Custom | builtins.int"

0 commit comments

Comments
 (0)