Skip to content

Commit b435a03

Browse files
committed
Use union types instead of join in binder
1 parent 1eb9d4c commit b435a03

File tree

5 files changed

+31
-80
lines changed

5 files changed

+31
-80
lines changed

mypy/binder.py

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
from typing_extensions import TypeAlias as _TypeAlias
88

99
from mypy.erasetype import remove_instance_last_known_values
10-
from mypy.join import join_simple
1110
from mypy.literals import Key, literal, literal_hash, subkeys
1211
from mypy.nodes import Expression, IndexExpr, MemberExpr, NameExpr, RefExpr, TypeInfo, Var
1312
from mypy.subtypes import is_same_type, is_subtype
13+
from mypy.typeops import make_simplified_union
1414
from mypy.types import (
1515
AnyType,
1616
Instance,
@@ -237,27 +237,25 @@ def update_from_options(self, frames: list[Frame]) -> bool:
237237
):
238238
type = AnyType(TypeOfAny.from_another_any, source_any=declaration_type)
239239
else:
240-
for other in resulting_values[1:]:
241-
assert other is not None
242-
type = join_simple(self.declarations[key], type, other.type)
243-
# Try simplifying resulting type for unions involving variadic tuples.
244-
# Technically, everything is still valid without this step, but if we do
245-
# not do this, this may create long unions after exiting an if check like:
246-
# x: tuple[int, ...]
247-
# if len(x) < 10:
248-
# ...
249-
# We want the type of x to be tuple[int, ...] after this block (if it is
250-
# still equivalent to such type).
251-
if isinstance(type, UnionType):
252-
type = collapse_variadic_union(type)
253-
if isinstance(type, ProperType) and isinstance(type, UnionType):
254-
# Simplify away any extra Any's that were added to the declared
255-
# type when popping a frame.
256-
simplified = UnionType.make_union(
257-
[t for t in type.items if not isinstance(get_proper_type(t), AnyType)]
258-
)
259-
if simplified == self.declarations[key]:
260-
type = simplified
240+
type = make_simplified_union([t.type for t in resulting_values])
241+
# Try simplifying resulting type for unions involving variadic tuples.
242+
# Technically, everything is still valid without this step, but if we do
243+
# not do this, this may create long unions after exiting an if check like:
244+
# x: tuple[int, ...]
245+
# if len(x) < 10:
246+
# ...
247+
# We want the type of x to be tuple[int, ...] after this block (if it is
248+
# still equivalent to such type).
249+
if isinstance(type, UnionType):
250+
type = collapse_variadic_union(type)
251+
if isinstance(type, ProperType) and isinstance(type, UnionType):
252+
# Simplify away any extra Any's that were added to the declared
253+
# type when popping a frame.
254+
simplified = UnionType.make_union(
255+
[t for t in type.items if not isinstance(get_proper_type(t), AnyType)]
256+
)
257+
if simplified == self.declarations[key]:
258+
type = simplified
261259
if current_value is None or not is_same_type(type, current_value[0]):
262260
self._put(key, type, from_assignment=True)
263261
changed = True

mypy/join.py

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -183,55 +183,6 @@ def join_instances_via_supertype(self, t: Instance, s: Instance) -> ProperType:
183183
return best
184184

185185

186-
def join_simple(declaration: Type | None, s: Type, t: Type) -> ProperType:
187-
"""Return a simple least upper bound given the declared type.
188-
189-
This function should be only used by binder, and should not recurse.
190-
For all other uses, use `join_types()`.
191-
"""
192-
declaration = get_proper_type(declaration)
193-
s = get_proper_type(s)
194-
t = get_proper_type(t)
195-
196-
if (s.can_be_true, s.can_be_false) != (t.can_be_true, t.can_be_false):
197-
# if types are restricted in different ways, use the more general versions
198-
s = mypy.typeops.true_or_false(s)
199-
t = mypy.typeops.true_or_false(t)
200-
201-
if isinstance(s, AnyType):
202-
return s
203-
204-
if isinstance(s, ErasedType):
205-
return t
206-
207-
if is_proper_subtype(s, t, ignore_promotions=True):
208-
return t
209-
210-
if is_proper_subtype(t, s, ignore_promotions=True):
211-
return s
212-
213-
if isinstance(declaration, UnionType):
214-
return mypy.typeops.make_simplified_union([s, t])
215-
216-
if isinstance(s, NoneType) and not isinstance(t, NoneType):
217-
s, t = t, s
218-
219-
if isinstance(s, UninhabitedType) and not isinstance(t, UninhabitedType):
220-
s, t = t, s
221-
222-
# Meets/joins require callable type normalization.
223-
s, t = normalize_callables(s, t)
224-
225-
if isinstance(s, UnionType) and not isinstance(t, UnionType):
226-
s, t = t, s
227-
228-
value = t.accept(TypeJoinVisitor(s))
229-
if declaration is None or is_subtype(value, declaration):
230-
return value
231-
232-
return declaration
233-
234-
235186
def trivial_join(s: Type, t: Type) -> Type:
236187
"""Return one of types (expanded) if it is a supertype of other, otherwise top type."""
237188
if is_subtype(s, t):

mypy/test/testtypes.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from mypy.erasetype import erase_type, remove_instance_last_known_values
99
from mypy.indirection import TypeIndirectionVisitor
10-
from mypy.join import join_simple, join_types
10+
from mypy.join import join_types
1111
from mypy.meet import meet_types, narrow_declared_type
1212
from mypy.nodes import (
1313
ARG_NAMED,
@@ -817,12 +817,12 @@ def test_any_type(self) -> None:
817817
self.assert_join(t, self.fx.anyt, self.fx.anyt)
818818

819819
def test_mixed_truth_restricted_type_simple(self) -> None:
820-
# join_simple against differently restricted truthiness types drops restrictions.
820+
# make_simplified_union against differently restricted truthiness types drops restrictions.
821821
true_a = true_only(self.fx.a)
822822
false_o = false_only(self.fx.o)
823-
j = join_simple(self.fx.o, true_a, false_o)
824-
assert j.can_be_true
825-
assert j.can_be_false
823+
u = make_simplified_union([true_a, false_o])
824+
assert u.can_be_true
825+
assert u.can_be_false
826826

827827
def test_mixed_truth_restricted_type(self) -> None:
828828
# join_types against differently restricted truthiness types drops restrictions.

test-data/unit/check-python310.test

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,11 +1487,13 @@ match m5:
14871487
case _:
14881488
reveal_type(m5) # N: Revealed type is "Tuple[Literal[2], Union[Literal['a'], Literal['b']]]"
14891489

1490-
match m5:
1490+
m6: Tuple[Literal[1, 2], Literal["a", "b"]]
1491+
1492+
match m6:
14911493
case (1, "a"):
1492-
reveal_type(m5) # N: Revealed type is "Tuple[Literal[1], Literal['a']]"
1494+
reveal_type(m6) # N: Revealed type is "Tuple[Literal[1], Literal['a']]"
14931495
case _:
1494-
reveal_type(m5) # N: Revealed type is "Tuple[Union[Literal[1], Literal[2]], Union[Literal['a'], Literal['b']]]"
1496+
reveal_type(m6) # N: Revealed type is "Tuple[Union[Literal[1], Literal[2]], Union[Literal['a'], Literal['b']]]"
14951497

14961498
[builtins fixtures/tuple.pyi]
14971499

test-data/unit/check-redefine.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ def f() -> None:
321321
x = 1
322322
if int():
323323
x = ''
324-
reveal_type(x) # N: Revealed type is "builtins.object"
324+
reveal_type(x) # N: Revealed type is "Union[builtins.str, builtins.int]"
325325
x = ''
326326
reveal_type(x) # N: Revealed type is "builtins.str"
327327
if int():

0 commit comments

Comments
 (0)