New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow assignments to multiple targets from union types #4067

Merged
merged 11 commits into from Oct 11, 2017

Conversation

Projects
None yet
2 participants
@ilevkivskyi
Collaborator

ilevkivskyi commented Oct 6, 2017

Fixes #3859
Fixes #3240
Fixes #1855
Fixes #1575

This is a simple fix of various bugs and a crash based on the idea originally proposed in #2219. The idea is to check assignment for every item in a union. However, in contrast to #2219, I think it will be more expected/consistent to construct a union of the resulting types instead of a join, for example:

x: Union[int, str]
x1 = x
reveal_type(x1) # Revealed type is 'Union[int, str]'

y: Union[Tuple[int], Tuple[str]]
(y1,) = y
reveal_type(y1) # Revealed type is 'Union[int, str]'

Thanks to @elazarg for initial work on this!

@ilevkivskyi ilevkivskyi referenced this pull request Oct 9, 2017

Closed

Release 0.540 planning #4084

@JukkaL JukkaL self-assigned this Oct 9, 2017

@JukkaL

It's great to finally have this fixed. Left a bunch of minor comments, mostly about documenting what's going on.

b: B
a: Union[Tuple[int, int], Tuple[int, object]]
(x[0], b.x) = a

This comment has been minimized.

@JukkaL

JukkaL Oct 10, 2017

Collaborator

Add test similar to this but where there is a type error.

@JukkaL

JukkaL Oct 10, 2017

Collaborator

Add test similar to this but where there is a type error.

@@ -1417,3 +1417,33 @@ async def main() -> None:
[out]
_testAsyncioGatherPreciseType.py:9: error: Revealed type is 'builtins.str'
_testAsyncioGatherPreciseType.py:10: error: Revealed type is 'builtins.str'
[case testNoCrashOnGenericUnionUnpacking]

This comment has been minimized.

@JukkaL

JukkaL Oct 10, 2017

Collaborator

Pythoneval test cases have a big fixed overhead, so I'd suggest combining all of these three test cases into a single test case.

@JukkaL

JukkaL Oct 10, 2017

Collaborator

Pythoneval test cases have a big fixed overhead, so I'd suggest combining all of these three test cases into a single test case.

Show outdated Hide outdated mypy/binder.py
Show outdated Hide outdated mypy/checker.py
@@ -1716,7 +1749,7 @@ def split_around_star(self, items: List[T], star_index: int,
returns in: ([1,2], [3,4,5], [6,7])
"""
nr_right_of_star = length - star_index - 1
right_index = nr_right_of_star if -nr_right_of_star != 0 else len(items)
right_index = -nr_right_of_star if nr_right_of_star != 0 else len(items)

This comment has been minimized.

@JukkaL

JukkaL Oct 10, 2017

Collaborator

What's this change?

@JukkaL

JukkaL Oct 10, 2017

Collaborator

What's this change?

This comment has been minimized.

@ilevkivskyi

ilevkivskyi Oct 10, 2017

Collaborator

This bug was exposed by one of the tests. It's quite surprising that it never appeared before, since the old logic took first types after nr_right_of_star, instead of the same number counting from the end of items.

EDIT: fixed wording.

@ilevkivskyi

ilevkivskyi Oct 10, 2017

Collaborator

This bug was exposed by one of the tests. It's quite surprising that it never appeared before, since the old logic took first types after nr_right_of_star, instead of the same number counting from the end of items.

EDIT: fixed wording.

Show outdated Hide outdated mypy/checker.py
Show outdated Hide outdated mypy/checker.py
Show outdated Hide outdated mypy/checker.py
Show outdated Hide outdated mypy/checker.py
c, *d = x
reveal_type(c) # E: Revealed type is 'builtins.int'
reveal_type(d) # E: Revealed type is 'builtins.list[builtins.int*]'
[builtins fixtures/tuple.pyi]

This comment has been minimized.

@JukkaL

JukkaL Oct 10, 2017

Collaborator

Ideas for additional test cases:

  • Multiple lvalues such as <first> = <second> = <rvalue>.
  • Multiple assignment in a for loop (for x, y in ...).
  • None of the union items are iterable.
  • None of the union items have the correct number of items (try with too few and too many).
@JukkaL

JukkaL Oct 10, 2017

Collaborator

Ideas for additional test cases:

  • Multiple lvalues such as <first> = <second> = <rvalue>.
  • Multiple assignment in a for loop (for x, y in ...).
  • None of the union items are iterable.
  • None of the union items have the correct number of items (try with too few and too many).
@ilevkivskyi

This comment has been minimized.

Show comment
Hide comment
@ilevkivskyi

ilevkivskyi Oct 10, 2017

Collaborator

@JukkaL Thanks for review! I think I addressed all comments in new commits.

Collaborator

ilevkivskyi commented Oct 10, 2017

@JukkaL Thanks for review! I think I addressed all comments in new commits.

@JukkaL

Thanks for the updates! Looks mostly good now, just a few remaining minor things.

Show outdated Hide outdated mypy/checker.py
Show outdated Hide outdated mypy/binder.py
@JukkaL

This comment has been minimized.

Show comment
Hide comment
@JukkaL

JukkaL Oct 11, 2017

Collaborator

This causes a crash on internal Dropbox code. It happens on a line like this:

            for error_label, error_type in error_set:

I haven't isolated a small repro yet, but here's the traceback:

Traceback (most recent call last):
  File "/Users/jukka/src/review-mypy/scripts/mypy", line 6, in <module>
    main(__file__)
  File "/Users/jukka/src/review-mypy/mypy/main.py", line 50, in main
    res = type_check_only(sources, bin_dir, options)
  File "/Users/jukka/src/review-mypy/mypy/main.py", line 103, in type_check_only
    options=options)
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 199, in build
    graph = dispatch(sources, manager)
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 1865, in dispatch
    process_graph(graph, manager)
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 2115, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 2218, in process_stale_scc
    graph[id].type_check_first_pass()
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 1775, in type_check_first_pass
    self.type_checker.check_first_pass()
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 194, in check_first_pass
    self.accept(d)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 282, in accept
    stmt.accept(self)
  File "/Users/jukka/src/review-mypy/mypy/nodes.py", line 690, in accept
    return visitor.visit_class_def(self)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 1184, in visit_class_def
    self.accept(defn.defs)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 282, in accept
    stmt.accept(self)
  File "/Users/jukka/src/review-mypy/mypy/nodes.py", line 750, in accept
    return visitor.visit_block(self)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 1304, in visit_block
    self.accept(s)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 282, in accept
    stmt.accept(self)
  File "/Users/jukka/src/review-mypy/mypy/nodes.py", line 496, in accept
    return visitor.visit_func_def(self)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 530, in visit_func_def
    self.check_func_item(defn, name=defn.name())
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 590, in check_func_item
    self.check_func_def(defn, typ, name)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 750, in check_func_def
    self.accept(item.body)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 282, in accept
    stmt.accept(self)
  File "/Users/jukka/src/review-mypy/mypy/nodes.py", line 750, in accept
    return visitor.visit_block(self)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 1304, in visit_block
    self.accept(s)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 282, in accept
    stmt.accept(self)
  File "/Users/jukka/src/review-mypy/mypy/nodes.py", line 851, in accept
    return visitor.visit_for_stmt(self)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 2390, in visit_for_stmt
    self.accept_loop(s.body, s.else_body)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 298, in accept_loop
    self.accept(body)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 282, in accept
    stmt.accept(self)
  File "/Users/jukka/src/review-mypy/mypy/nodes.py", line 750, in accept
    return visitor.visit_block(self)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 1304, in visit_block
    self.accept(s)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 282, in accept
    stmt.accept(self)
  File "/Users/jukka/src/review-mypy/mypy/nodes.py", line 851, in accept
    return visitor.visit_for_stmt(self)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 2388, in visit_for_stmt
    item_type = self.analyze_iterable_item_type(s.expr)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 2424, in analyze_iterable_item_type
    expr, messages.ITERABLE_EXPECTED)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 2584, in check_subtype
    if is_subtype(subtype, supertype):
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 83, in is_subtype
    ignore_declared_variance=ignore_declared_variance))
  File "/Users/jukka/src/review-mypy/mypy/types.py", line 1227, in accept
    return visitor.visit_union_type(self)
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 312, in visit_union_type
    for item in left.items)
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 312, in <genexpr>
    for item in left.items)
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 83, in is_subtype
    ignore_declared_variance=ignore_declared_variance))
  File "/Users/jukka/src/review-mypy/mypy/types.py", line 1286, in accept
    return visitor.visit_partial_type(self)
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 316, in visit_partial_type
    raise RuntimeError
RuntimeError:
Collaborator

JukkaL commented Oct 11, 2017

This causes a crash on internal Dropbox code. It happens on a line like this:

            for error_label, error_type in error_set:

I haven't isolated a small repro yet, but here's the traceback:

Traceback (most recent call last):
  File "/Users/jukka/src/review-mypy/scripts/mypy", line 6, in <module>
    main(__file__)
  File "/Users/jukka/src/review-mypy/mypy/main.py", line 50, in main
    res = type_check_only(sources, bin_dir, options)
  File "/Users/jukka/src/review-mypy/mypy/main.py", line 103, in type_check_only
    options=options)
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 199, in build
    graph = dispatch(sources, manager)
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 1865, in dispatch
    process_graph(graph, manager)
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 2115, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 2218, in process_stale_scc
    graph[id].type_check_first_pass()
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 1775, in type_check_first_pass
    self.type_checker.check_first_pass()
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 194, in check_first_pass
    self.accept(d)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 282, in accept
    stmt.accept(self)
  File "/Users/jukka/src/review-mypy/mypy/nodes.py", line 690, in accept
    return visitor.visit_class_def(self)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 1184, in visit_class_def
    self.accept(defn.defs)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 282, in accept
    stmt.accept(self)
  File "/Users/jukka/src/review-mypy/mypy/nodes.py", line 750, in accept
    return visitor.visit_block(self)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 1304, in visit_block
    self.accept(s)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 282, in accept
    stmt.accept(self)
  File "/Users/jukka/src/review-mypy/mypy/nodes.py", line 496, in accept
    return visitor.visit_func_def(self)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 530, in visit_func_def
    self.check_func_item(defn, name=defn.name())
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 590, in check_func_item
    self.check_func_def(defn, typ, name)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 750, in check_func_def
    self.accept(item.body)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 282, in accept
    stmt.accept(self)
  File "/Users/jukka/src/review-mypy/mypy/nodes.py", line 750, in accept
    return visitor.visit_block(self)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 1304, in visit_block
    self.accept(s)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 282, in accept
    stmt.accept(self)
  File "/Users/jukka/src/review-mypy/mypy/nodes.py", line 851, in accept
    return visitor.visit_for_stmt(self)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 2390, in visit_for_stmt
    self.accept_loop(s.body, s.else_body)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 298, in accept_loop
    self.accept(body)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 282, in accept
    stmt.accept(self)
  File "/Users/jukka/src/review-mypy/mypy/nodes.py", line 750, in accept
    return visitor.visit_block(self)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 1304, in visit_block
    self.accept(s)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 282, in accept
    stmt.accept(self)
  File "/Users/jukka/src/review-mypy/mypy/nodes.py", line 851, in accept
    return visitor.visit_for_stmt(self)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 2388, in visit_for_stmt
    item_type = self.analyze_iterable_item_type(s.expr)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 2424, in analyze_iterable_item_type
    expr, messages.ITERABLE_EXPECTED)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 2584, in check_subtype
    if is_subtype(subtype, supertype):
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 83, in is_subtype
    ignore_declared_variance=ignore_declared_variance))
  File "/Users/jukka/src/review-mypy/mypy/types.py", line 1227, in accept
    return visitor.visit_union_type(self)
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 312, in visit_union_type
    for item in left.items)
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 312, in <genexpr>
    for item in left.items)
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 83, in is_subtype
    ignore_declared_variance=ignore_declared_variance))
  File "/Users/jukka/src/review-mypy/mypy/types.py", line 1286, in accept
    return visitor.visit_partial_type(self)
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 316, in visit_partial_type
    raise RuntimeError
RuntimeError:
@JukkaL

This comment has been minimized.

Show comment
Hide comment
@JukkaL

JukkaL Oct 11, 2017

Collaborator

The type of error_set is Union[builtins.set[Tuple[builtins.str, builtins.str]], <partial None>]. It looks like a partial None type is leaking to a union, which shouldn't happen. So apparently this PR triggers the crash, but the underlying problem is elsewhere. I'll try to understand and fix the partial None issue.

Collaborator

JukkaL commented Oct 11, 2017

The type of error_set is Union[builtins.set[Tuple[builtins.str, builtins.str]], <partial None>]. It looks like a partial None type is leaking to a union, which shouldn't happen. So apparently this PR triggers the crash, but the underlying problem is elsewhere. I'll try to understand and fix the partial None issue.

@JukkaL

This comment has been minimized.

Show comment
Hide comment
@JukkaL

JukkaL Oct 11, 2017

Collaborator

The inferred partial None seems to be caused by this PR. Here's a short repro (use --strict-optional):

from typing import Dict, Tuple, Set, Any

a: Any
d: Dict[str, Tuple[Set[Tuple[str, str]], str]]
x, _ = d.get(a, (None, None))
reveal_type(x)

for y in x: pass

Output from mypy:

$ mypy --show-traceback --strict-optional rt2.py
rt2.py:6: error: Revealed type is 'Union[builtins.set[Tuple[builtins.str, builtins.str]], <partial None>]'
rt2.py:8: error: INTERNAL ERROR -- please report a bug at https://github.com/python/mypy/issues version: 0.540-dev-ee93a9b96abdb1a4a61ca1b97fa29eed2ec1d73f
Traceback (most recent call last):
  File "/Users/jukka/src/mypy/scripts/mypy", line 6, in <module>
    main(__file__)
  File "/Users/jukka/src/review-mypy/mypy/main.py", line 50, in main
    res = type_check_only(sources, bin_dir, options)
  File "/Users/jukka/src/review-mypy/mypy/main.py", line 103, in type_check_only
    options=options)
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 199, in build
    graph = dispatch(sources, manager)
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 1865, in dispatch
    process_graph(graph, manager)
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 2115, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 2218, in process_stale_scc
    graph[id].type_check_first_pass()
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 1775, in type_check_first_pass
    self.type_checker.check_first_pass()
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 194, in check_first_pass
    self.accept(d)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 282, in accept
    stmt.accept(self)
  File "/Users/jukka/src/review-mypy/mypy/nodes.py", line 851, in accept
    return visitor.visit_for_stmt(self)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 2388, in visit_for_stmt
    item_type = self.analyze_iterable_item_type(s.expr)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 2424, in analyze_iterable_item_type
    expr, messages.ITERABLE_EXPECTED)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 2584, in check_subtype
    if is_subtype(subtype, supertype):
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 83, in is_subtype
    ignore_declared_variance=ignore_declared_variance))
  File "/Users/jukka/src/review-mypy/mypy/types.py", line 1227, in accept
    return visitor.visit_union_type(self)
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 312, in visit_union_type
    for item in left.items)
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 312, in <genexpr>
    for item in left.items)
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 83, in is_subtype
    ignore_declared_variance=ignore_declared_variance))
  File "/Users/jukka/src/review-mypy/mypy/types.py", line 1286, in accept
    return visitor.visit_partial_type(self)
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 316, in visit_partial_type
    raise RuntimeError
RuntimeError:
Collaborator

JukkaL commented Oct 11, 2017

The inferred partial None seems to be caused by this PR. Here's a short repro (use --strict-optional):

from typing import Dict, Tuple, Set, Any

a: Any
d: Dict[str, Tuple[Set[Tuple[str, str]], str]]
x, _ = d.get(a, (None, None))
reveal_type(x)

for y in x: pass

Output from mypy:

$ mypy --show-traceback --strict-optional rt2.py
rt2.py:6: error: Revealed type is 'Union[builtins.set[Tuple[builtins.str, builtins.str]], <partial None>]'
rt2.py:8: error: INTERNAL ERROR -- please report a bug at https://github.com/python/mypy/issues version: 0.540-dev-ee93a9b96abdb1a4a61ca1b97fa29eed2ec1d73f
Traceback (most recent call last):
  File "/Users/jukka/src/mypy/scripts/mypy", line 6, in <module>
    main(__file__)
  File "/Users/jukka/src/review-mypy/mypy/main.py", line 50, in main
    res = type_check_only(sources, bin_dir, options)
  File "/Users/jukka/src/review-mypy/mypy/main.py", line 103, in type_check_only
    options=options)
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 199, in build
    graph = dispatch(sources, manager)
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 1865, in dispatch
    process_graph(graph, manager)
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 2115, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 2218, in process_stale_scc
    graph[id].type_check_first_pass()
  File "/Users/jukka/src/review-mypy/mypy/build.py", line 1775, in type_check_first_pass
    self.type_checker.check_first_pass()
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 194, in check_first_pass
    self.accept(d)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 282, in accept
    stmt.accept(self)
  File "/Users/jukka/src/review-mypy/mypy/nodes.py", line 851, in accept
    return visitor.visit_for_stmt(self)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 2388, in visit_for_stmt
    item_type = self.analyze_iterable_item_type(s.expr)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 2424, in analyze_iterable_item_type
    expr, messages.ITERABLE_EXPECTED)
  File "/Users/jukka/src/review-mypy/mypy/checker.py", line 2584, in check_subtype
    if is_subtype(subtype, supertype):
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 83, in is_subtype
    ignore_declared_variance=ignore_declared_variance))
  File "/Users/jukka/src/review-mypy/mypy/types.py", line 1227, in accept
    return visitor.visit_union_type(self)
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 312, in visit_union_type
    for item in left.items)
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 312, in <genexpr>
    for item in left.items)
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 83, in is_subtype
    ignore_declared_variance=ignore_declared_variance))
  File "/Users/jukka/src/review-mypy/mypy/types.py", line 1286, in accept
    return visitor.visit_partial_type(self)
  File "/Users/jukka/src/review-mypy/mypy/subtypes.py", line 316, in visit_partial_type
    raise RuntimeError
RuntimeError:
@ilevkivskyi

This comment has been minimized.

Show comment
Hide comment
@ilevkivskyi

ilevkivskyi Oct 11, 2017

Collaborator

OK, I will take a look now.

Collaborator

ilevkivskyi commented Oct 11, 2017

OK, I will take a look now.

@ilevkivskyi

This comment has been minimized.

Show comment
Hide comment
@ilevkivskyi

ilevkivskyi Oct 11, 2017

Collaborator

It looks like the simplest solution is to not infer partial types while unpacking unions, anyway the resulting type will be Union[None, <other types...>].

Collaborator

ilevkivskyi commented Oct 11, 2017

It looks like the simplest solution is to not infer partial types while unpacking unions, anyway the resulting type will be Union[None, <other types...>].

@JukkaL

JukkaL approved these changes Oct 11, 2017

@JukkaL JukkaL merged commit 77ce5e2 into python:master Oct 11, 2017

2 checks passed

continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details

@ilevkivskyi ilevkivskyi deleted the ilevkivskyi:multi-assign-from-union branch Oct 11, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment