microsoft / pyright

Static Type Checker for Python
Other
13.12k stars 1.4k forks source link

False positive for `defaultdict(defaultdict)` #8840

Closed erictraut closed 3 days ago

erictraut commented 2 weeks ago

Discussed in https://github.com/microsoft/pyright/discussions/8839

Originally posted by **matt-the-midnight-hacker** August 26, 2024 Hi I just updated pyright to 1.1.377 and I get now type errors for `defaultdict(defaultdict)` assignments. I'm not sure if it is a bug or a typeshed issue or just me. The code to reproduce what I mean would be: ``` from typing import DefaultDict from collections import defaultdict class MyClass: pass d: DefaultDict[int, DefaultDict[int, MyClass]] = defaultdict(defaultdict) d[1][2] = MyClass() ``` I get error: `error: Expression of type "defaultdict[Unknown, defaultdict[Unknown, defaultdict[Unknown, Unknown]]]" is incompatible with declared type "DefaultDict[int, DefaultDict[int, MyClass]]` How to do the `defaultdict` instantiation here to fulfill the type I've declared? fyi. I've also asked this on [stackoverflow](https://stackoverflow.com/questions/78917316/how-to-instantiate-defaultdict-to-fulfill-defaultdictint-defaultdictint-mycl)
tofetpuzo commented 1 week ago

A work around would be something like this

from typing import DefaultDict
from collections import defaultdict

class MyClass:
    pass

d: DefaultDict[int, DefaultDict[int, MyClass]] = defaultdict(lambda: defaultdict(MyClass))

d[1][2] = MyClass()

Test for it could be

d: DefaultDict[int, DefaultDict[int, MyClass]] = defaultdict(lambda: defaultdict(MyClass))

def func(a: DefaultDict[int, DefaultDict[int, MyClass]]):
    reveal_type(a)  # pyright should now reveal Runtime type is 'defaultdict'

func(d)
erictraut commented 3 days ago

This is addressed in pyright 1.1.380.