Files
ruff/crates/red_knot_python_semantic/resources/mdtest/call/union.md
2025-02-18 13:34:39 +01:00

2.3 KiB

Unions in calls

Union of return types

def _(flag: bool):
    if flag:
        def f() -> int:
            return 1
    else:
        def f() -> str:
            return "foo"
    reveal_type(f())  # revealed: int | str

Calling with an unknown union

from nonexistent import f  # error: [unresolved-import] "Cannot resolve import `nonexistent`"

def coinflip() -> bool:
    return True

if coinflip():
    def f() -> int:
        return 1

reveal_type(f())  # revealed: Unknown | int

Non-callable elements in a union

Calling a union with a non-callable element should emit a diagnostic.

def _(flag: bool):
    if flag:
        f = 1
    else:
        def f() -> int:
            return 1
    x = f()  # error: [call-non-callable] "Object of type `Literal[1]` is not callable"
    reveal_type(x)  # revealed: int | Unknown

Multiple non-callable elements in a union

Calling a union with multiple non-callable elements should mention all of them in the diagnostic.

def _(flag: bool, flag2: bool):
    if flag:
        f = 1
    elif flag2:
        f = "foo"
    else:
        def f() -> int:
            return 1
    # error: [call-non-callable] "Object of type `Literal[1]` is not callable"
    # revealed: int | Unknown
    reveal_type(f())

All non-callable union elements

Calling a union with no callable elements can emit a simpler diagnostic.

def _(flag: bool):
    if flag:
        f = 1
    else:
        f = "foo"

    x = f()  # error: [call-non-callable] "Object of type `Literal[1, "foo"]` is not callable"
    reveal_type(x)  # revealed: Unknown

Mismatching signatures

Calling a union where the arguments don't match the signature of all variants.

def f1(a: int) -> int: ...
def f2(a: str) -> str: ...
def _(flag: bool):
    if flag:
        f = f1
    else:
        f = f2

    # error: [invalid-argument-type] "Object of type `Literal[3]` cannot be assigned to parameter 1 (`a`) of function `f2`; expected type `str`"
    x = f(3)
    reveal_type(x)  # revealed: int | str

Any non-callable variant

def f1(a: int): ...
def _(flag: bool):
    if flag:
        f = f1
    else:
        f = "This is a string literal"

    # error: [call-non-callable] "Object of type `Literal["This is a string literal"]` is not callable"
    x = f(3)
    reveal_type(x)  # revealed: Unknown