Skip to content

Union of multiple sets idiom broken because member type is not inferred #8087

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

Closed
cjolowicz opened this issue Dec 5, 2019 · 2 comments
Closed
Labels
false-positive mypy gave an error on correct code feature priority-1-normal

Comments

@cjolowicz
Copy link
Contributor

cjolowicz commented Dec 5, 2019

The idiom set().union(*sets) is used to produce the union of multiple sets:

>>> sets = [{1, 2}, {2, 3}]
>>> set().union(*sets)
{1, 2, 3}

This does not type check with mypy:

from typing import Set


sets = [{1, 2}, {2, 3}]
union: Set[int] = set().union(*sets)


# main.py:5: error: 
#  Incompatible types in assignment (expression has type "Set[<nothing>]", 
#  variable has type "Set[int]")
# main.py:5: error: 
#  Argument 1 to "union" of "set" has incompatible type "*List[Set[int]]"; 
#  expected "Iterable[<nothing>]"

Apparently, mypy infers the type of set() to be Set[<nothing>]. Ideally, it would work out from the context that set() should have type Set[int]. I would think that an empty set (with no other reference to it) can have any member type, including the one that works in the specific context.

The following code type-checks:

from typing import Set
sets = [{1, 2}, {2, 3}]
zero: Set[int] = set()
union = zero.union(*sets)
@JukkaL JukkaL added false-positive mypy gave an error on correct code feature priority-1-normal labels Dec 6, 2019
@goodmami
Copy link
Contributor

goodmami commented Jun 30, 2020

This appears to be a duplicate of #2013. Also I don't think the problem is with the idiom of the union of multiple sets, but just the union on the same line as set instantiation. Here is what I came across:

# error: Incompatible types in assignment (expression has type "Set[str]", variable has type "Set[Optional[str]]")
maybe_strs: Set[Optional[str]] = set('abc').union((None,))
# the following type checks
maybe_strs2: Set[Optional[str]] = set('abc')
maybe_strs2.add(None)

edit
I just noticed that using the | operator instead of union type checks fine:

maybe_strs3: Set[Optional[str]] = set('abc') | {None}

@JukkaL
Copy link
Collaborator

JukkaL commented Jul 3, 2020

Closing as duplicate of #2013, as pointed out by @goodmami.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
false-positive mypy gave an error on correct code feature priority-1-normal
Projects
None yet
Development

No branches or pull requests

3 participants