Skip to content

Returning T instead of UserDefinedClass[T] is not reported as an error #2905

Closed
@pkch

Description

@pkch

At first glance, the following code should not pass type verification because f and g return or yield T instead of Node[T]:

from typing import TypeVar, Generic, Iterator

T = TypeVar('T')
class Node(Generic[T]):
    def __init__(self, value: T) -> None:
        self.value = value

def f(v: Node) -> Node:
    return v.value

def g(v: Node) -> Iterator[Node]:
    yield v.value

However, mypy --strict --python-version 3.6 doesn't report any errors. It does produce a warning:

Returning Any from function with declared return type node.Node[Any]

but even the warning is only reported for f(), not for g().

To be fair, there are ways to call these functions that doesn't violate type expectations, for example f(Node(Node(1))) would return Node(1) which fits its promised return type. But I was hoping mypy might notice that the only way this code would be correct is if the argument to f() is a Node[Node] rather than just arbitrary Node. And so I was expecting mypy to force me to write:

def f(v: Node[Node]) -> Node:
    return v.value

def g(v: Node[Node]) -> Node:
    yield v.value

if that's what I meant of course. (Although it's much more likely that it's actually a bug, and that I meant to return v rather than return v.value; in that case, mypy would help me catch that bug.)

Furthermore, if I add the following code at the end of the original code snippet:

v = Node(1)
f(v)
for x in g(v):
    pass

mypy should be able to see that something is definitely wrong; at this point it's completely clear that f(v) won't return the promised Node, and g(v) won't yield one. But adding those lines does not add any new error or warning messages.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions