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

Skip to content

New style unions and special forms #6219

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
sobolevn opened this issue Nov 1, 2021 · 4 comments
Closed

New style unions and special forms #6219

sobolevn opened this issue Nov 1, 2021 · 4 comments

Comments

@sobolevn
Copy link
Member

sobolevn commented Nov 1, 2021

Today we got a bug report in mypy, that Literal[1] | Literal[2] is not supported: python/mypy#11426

Currently this happens on 3.10:

from typing import Literal

Literal[1, 2] | Literal[3]
# error: Unsupported left operand type for | ("object")

This happens because mypy treats | as a regular __or__ operator. And _SpecialForm does not have this method. We have two ways to solve this:

  1. Special case it in mypy. This is quite easy, but I don't think that this is a good way
  2. Add __or__ method to _SpecialForm type, just like it is done in cpython: https://github.com/python/cpython/blob/14a4fce457033412278ca9a056787db424310dc3/Lib/typing.py#L396-L397 This way we can be sure mypy will just work! πŸŽ‰

There are several notes:

  • There are _SpecialForms that raise TypeError when used with |. Example: Final | int. But, this happens because Final is not allowed for Union. But, operator is supported. So, I guess this should be handled by a typechecker itself
  • TypedDict is not special in typeshed:
    # TypedDict is a (non-subscriptable) special form.
    TypedDict: object
    But, | is supported by it:
>>> from typing import TypedDict
>>> class My(TypedDict): ...
... 
>>> My | int
__main__.My | int
  • TypeVar is a separate class, not a special form. But, we can use T | S in runtime as well.

I will send a PR with my proposal. We can work from there! πŸ‘‹

@srittau
Copy link
Collaborator

srittau commented Nov 1, 2021

typeshed should match the implementation. We should add __or__ (and the other missing methods) to _SpecialForm in the stubs.

@JelleZijlstra
Copy link
Member

Agree with @srittau, but would changing typeshed really be enough to fix the mypy issue? Even if we return something from __or__, would mypy recognize the result as a type?

@sobolevn
Copy link
Member Author

sobolevn commented Nov 2, 2021

Even if we return something from or, would mypy recognize the result as a type?

After trying this out locally, I can say for sure that it won't work. Because L = Literal[1]; reveal_type(L) would reveal object type, not _SpecialForm. 😞

But, anyways adding new _SpecialForm methods is a good thing. I am working on it πŸ™‚

@AlexWaygood
Copy link
Member

__or__/__ror__ were added to _SpecialForm in #6498, so I think this can now be closed

carljm added a commit to astral-sh/ruff that referenced this issue Nov 5, 2024
Handling `Literal` type in annotations.

Resolves: #13672 

## Implementation

Since Literals are not a fully defined type in typeshed. I used a trick
to figure out when a special form is a literal.
When we are inferring assignment types I am checking if the type of that
assignment was resolved to typing.SpecialForm and the name of the target
is `Literal` if that is the case then I am re creating a new instance
type and set the known instance field to `KnownInstance:Literal`.

**Why not defining a new type?**

From this [issue](python/typeshed#6219) I
learned that we want to resolve members to SpecialMethod class. So if we
create a new instance here we can rely on the member resolving in that
already exists.


## Tests


https://typing.readthedocs.io/en/latest/spec/literal.html#equivalence-of-two-literals
Since the type of the value inside Literal is evaluated as a
Literal(LiteralString, LiteralInt, ...) then the equality is only true
when types and value are equal.


https://typing.readthedocs.io/en/latest/spec/literal.html#legal-and-illegal-parameterizations

The illegal parameterizations are mostly implemented I'm currently
checking the slice expression and the slice type to make sure it's
valid.

https://typing.readthedocs.io/en/latest/spec/literal.html#shortening-unions-of-literals

---------

Co-authored-by: Carl Meyer <[email protected]>
Co-authored-by: Alex Waygood <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants