Skip to content

Simplify intersections with typevars whose upper bound is covered by a union of negative elements #1456

@sharkdp

Description

@sharkdp

There appear to be lots of other cases where you can have a TypeVar bound to a union (or type equivalent to a union) where we also exhibit similar issues with reachability and narrowing:

from typing import assert_never, Literal

def f[T: bool](x: T) -> T:
    match x:
        case True:
            return x
        case False:
            return x
        case _:
            reveal_type(x) # T@f & ~Literal[True] & ~Literal[False]
            assert_never(x)  # false-positive error

def g[T: Literal["foo", "bar"]](x: T) -> T:
    match x:
        case "foo":
            return x
        case "bar":
            return x
        case _:
            reveal_type(x)  # T@g & ~Literal["foo"] & ~Literal["bar"]
            assert_never(x)  # false-positive error

def h[T: int | str](x: T) -> T:
    if isinstance(x, int):
        return x
    elif isinstance(x, str):
        return x
    else:
        reveal_type(x)  # T@h & ~int & ~str
        assert_never(x)  # false-positive error

Originally posted by @AlexWaygood in astral-sh/ruff#21130 (review)

Metadata

Metadata

Assignees

No one assigned

    Labels

    control flowgenericsBugs or features relating to ty's generics implementationnarrowingrelated to flow-sensitive type narrowingset-theoretic typesunions, intersections and more

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions