Files
ruff/crates/red_knot_python_semantic/resources/mdtest/subscript/class.md
David Peter 53fa32a389 [red-knot] Remove Type::Unbound (#13980)
<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

- Remove `Type::Unbound`
- Handle (potential) unboundness as a concept orthogonal to the type
system (see new `Symbol` type)
- Improve existing and add new diagnostics related to (potential)
unboundness

closes #13671 

## Test Plan

- Update existing markdown-based tests
- Add new tests for added/modified functionality
2024-10-31 20:05:53 +01:00

1.7 KiB

Class subscript

Class getitem unbound

class NotSubscriptable: ...

a = NotSubscriptable[0]  # error: "Cannot subscript object of type `Literal[NotSubscriptable]` with no `__class_getitem__` method"

Class getitem

class Identity:
    def __class_getitem__(cls, item: int) -> str:
        return item

reveal_type(Identity[0])  # revealed: str

Class getitem union

flag = True

class UnionClassGetItem:
    if flag:

        def __class_getitem__(cls, item: int) -> str:
            return item
    else:

        def __class_getitem__(cls, item: int) -> int:
            return item

reveal_type(UnionClassGetItem[0])  # revealed: str | int

Class getitem with class union

flag = True

class A:
    def __class_getitem__(cls, item: int) -> str:
        return item

class B:
    def __class_getitem__(cls, item: int) -> int:
        return item

x = A if flag else B

reveal_type(x)  # revealed: Literal[A, B]
reveal_type(x[0])  # revealed: str | int

Class getitem with unbound method union

flag = True

if flag:
    class Spam:
        def __class_getitem__(self, x: int) -> str:
            return "foo"

else:
    class Spam: ...

# error: [call-possibly-unbound-method] "Method `__class_getitem__` of type `Literal[Spam, Spam]` is possibly unbound"
# revealed: str
reveal_type(Spam[42])

TODO: Class getitem non-class union

flag = True

if flag:
    class Eggs:
        def __class_getitem__(self, x: int) -> str:
            return "foo"

else:
    Eggs = 1

a = Eggs[42]  # error: "Cannot subscript object of type `Literal[Eggs] | Literal[1]` with no `__getitem__` method"

# TODO: should _probably_ emit `str | Unknown`
reveal_type(a)  # revealed: Unknown