Skip to content
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

Union of unions doesn't work using Python 3.10 Type Union Operator #12005

Closed
Garrett-R opened this issue Jan 17, 2022 · 4 comments · Fixed by #14008
Closed

Union of unions doesn't work using Python 3.10 Type Union Operator #12005

Garrett-R opened this issue Jan 17, 2022 · 4 comments · Fixed by #14008
Labels
bug mypy got something wrong topic-pep-604 PEP 604 (union | operator)

Comments

@Garrett-R
Copy link

Garrett-R commented Jan 17, 2022

Bug Report

It seems you can't take a union of unions using the new Type Union Operator.

To Reproduce

  1. Run Mypy on this file:
from typing import TypeAlias, Union


class Dog:
    pass

class Cat:
    pass

class Salmon:
    pass

class Trout:
    pass


Mammal: TypeAlias = Dog | Cat

Fish: TypeAlias = Salmon | Trout

Animal: TypeAlias = Mammal | Fish  # type error!!

Animal2: TypeAlias = Union[Mammal, Fish]  # no type error, as expected

Expected Behavior

In PEP-0604, it says "The existing typing.Union and | syntax should be equivalent.". Therefore, I assumed the last 2 lines above would both behave similarly.

Actual Behavior

Mypy throws type error:

error: Unsupported left operand type for | ("object")

Your Environment

  • Mypy version used: 0.931
  • Mypy command-line flags: <no flags>
  • Mypy configuration options from mypy.ini (and other config files): <no config>
  • Python version used: 3.10.2
  • Operating system and version: Ubuntu 20.04
@Garrett-R Garrett-R added the bug mypy got something wrong label Jan 17, 2022
@KotlinIsland
Copy link
Contributor

Workaround

Put the union on the right if possible

a = int | float
b = str | a  # works
c = a | str  # error: Unsupported left operand type for | ("object")

@DetachHead
Copy link
Contributor

related: #11426

@svenpanne
Copy link

Is there some progress on this issue or a better workaround? The trick above doesn't work if both sides of the union are, well, unions themselves, which is exactly what we have in our code. 😭

JukkaL added a commit that referenced this issue Nov 4, 2022
Fix Python 3.10 `|` union syntax in type aliases, when one of
the operands is a type alias or a type with an overloaded `__init__`.

Fixes #12368. Fixes #12005. Fixes #11426.
JukkaL added a commit that referenced this issue Nov 7, 2022
Fix Python 3.10 `|` union syntax in type aliases, when one of
the operands is a type alias or a type with an overloaded `__init__`.

We can now infer `typing._SpecialForm` for type aliases in a runtime 
context.

Also create a bunch of minimal test-only stubs for stdlib modules 
to fix some test failures caused by the missing `typing._SpecialForm`
in the default test stubs. This is generally what we want in any case, 
since using typeshed stubs with minimal builtins/typing stubs can
result in unpredictable behavior and slow tests.

Fixes #12368. Fixes #12005. Fixes #11426.
@Garrett-R
Copy link
Author

Woohoo! Thanks for fixing this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-pep-604 PEP 604 (union | operator)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants