Skip to content

else not considered unreachable when if type binder should always match #7600

@jivid

Description

@jivid

I believe this is either a bug or I'm missing something very obvious

I am trying to add type hints to a function that takes as input either a list of strings, or a set of strings, performs a transformation on every element of the input, and returns an object of the same type as the input. A contrived example is:

def make_upper(i):
    args = [a.upper() for a in i]
    
    if isinstance(i, set):
        return set(args)
    else:
        return args

With type hints, I've arrived at:

T = TypeVar("T", List[str], Set[str])

def make_upper(i: T) -> T:
    args = [a.upper() for a in i]
    
    if isinstance(i, set):
        return set(args)
    else:
        return args

However, this results in mypy throwing an error main.py:11: error: Incompatible return value type (got "List[str]", expected "Set[str]"). The error is thrown on the return args line.

What is confusing me even more, is if I change the code to this:

T = TypeVar("T", List[str], Set[str])

def make_upper(i: T) -> T:
    args = [a.upper() for a in i]
    
    if isinstance(i, list):
        return args
    else:
        return set(args)

I get the inverse error main.py:11: error: Incompatible return value type (got "Set[str]", expected "List[str]") on the return set(args) line.

I went with a TypeVar instead of Union since the input type is preserved in the output and so a generic fit better, rather than needing to always cast() the return type in the caller code

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions