Cannot infer type of generic subclass within a function call

Open
#2,044 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
39/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Stale
Tech stack
python
Domain
devtools

Research direction

Reproduce the diagnostic from the test.py snippet, comparing the inline output.update(node.accept(self)) call with the temporary-variable version. Trace how generic Node.accept, Visitor[T], and the Iterable argument to set.update are inferred, and use the fake_update variants to isolate the behavior. Done means the inline form is handled correctly with regression coverage.

Written by the indexing model from the issue text.

Description

bug false-positive priority-1-normal topic-type-context topic-type-variables

Sorry about the bland title -- I think I lack the vocabulary to concisely describe what exactly is going on and to determine if this is a duplicate issue or not. Feel free to change it to something more descriptive.

Here's a somewhat boiled down snippit of code:

from typing import Generic, TypeVar, Set, List, Iterable

T = TypeVar('T')

class Node:
    def __init__(self, children: List['Node']) -> None:
        self.children = children

    def accept(self, visitor: 'Visitor[T]') -> T:
        pass

class NodeChild(Node):
    def accept(self, visitor: 'Visitor[T]') -> T:
        return visitor.visit_node_child(self)

class Visitor(Generic[T]):
    def visit_node_child(self, node: NodeChild) -> T:
        pass

class ExampleVisitor(Visitor[Set[str]]):
    def _visit(self, nodes: List[Node]) -> Set[str]:
        output = set()  # type: Set[str]
        for node in nodes:
            output.update(node.accept(self))  # Error here
        return output

    def visit_node_child(self, node: NodeChild) -> Set[str]:
        return {'a'} | self._visit(node.children)

When I try running this snippit of code, I get the following unexpected error:

test.py: note: In member "_visit" of class "ExampleVisitor":
test.py:24: error: Argument 1 to "accept" of "Node" has incompatible type "ExampleVisitor"; expected Visitor[Iterable[str]]

However, when I try modifying the definition of _visit to look like the following:

    def _visit(self, nodes: List[Node]) -> Set[str]:
        output = set()  # type: Set[str]
        for node in nodes:
            data = node.accept(self)   # Extract this into a separate variable
            output.update(data)
        return output

...mypy behaves as expected and does not report any errors.

I think this bug is also related to the type signature of set.update -- the type signature is update(self, *x: Iterable[_T]) -> None. The same bug still exists if I try swapping out the call to output.update(...) with a dummy function with a signature of fake_update(x: Iterable[T]) -> None, but goes away if I try changing the dummy signature to look like fake_update(x: Set[T]) -> None.

Dominant language
Python
Stars
20.6k
Forks
3.3k
Avg merge
1d 18h
Merged PRs (30d)
54

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from python/mypy

All issues in python/mypy

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.