ruff/crates/red_knot_python_semantic/resources/mdtest/unary/instance.md
Shaygan Hooshyari 9dddd73c29
[red-knot] Literal special form (#13874)
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](https://github.com/python/typeshed/issues/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 <carl@astral.sh>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2024-11-05 01:45:46 +00:00

748 B

Unary Operations

from typing import Literal

class Number:
    def __init__(self, value: int):
        self.value = 1

    def __pos__(self) -> int:
        return +self.value

    def __neg__(self) -> int:
        return -self.value

    def __invert__(self) -> Literal[True]:
        return True

a = Number()

reveal_type(+a)  # revealed: int
reveal_type(-a)  # revealed: int
reveal_type(~a)  # revealed: Literal[True]

class NoDunder: ...

b = NoDunder()
+b  # error: [unsupported-operator] "Unary operator `+` is unsupported for type `NoDunder`"
-b  # error: [unsupported-operator] "Unary operator `-` is unsupported for type `NoDunder`"
~b  # error: [unsupported-operator] "Unary operator `~` is unsupported for type `NoDunder`"