Cannot infer type of generic subclass within a function call
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 39/100
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
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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from python/mypy
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
documentation
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
bug topic-configuration topic-error-reporting
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
-
🐛 Bug 🔔 Pending processing
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
jumpserver/jumpserver#17584 ·