`d or {}` where `d` is something other than builtin `dict` gets errors about `Never` for indexing and splatting
Nessuno ha ancora preso questa issue.
- Lingua principale
- Python
- Stelle
- 20.6k
- Fork
- 3.3k
- Metriche di merge delle PR
- Metriche PR in attesa
Descrizione
Bug Report
When using d or {} where d is a subclass of dict or something that implements the SupportsKeysAndGetItem protocol can lead to errors/different behaviour in downstream code than when it is a dict directly. There errors are things indicating the Never key type of {} is causing problem:
Invalid index type "str" for "DictSubclass | dict[Never, Never]"; expected type "Never" [index]
Unpacked dict entry 0 has incompatible type "SKAGI | dict[Never, Never]"; expected "SupportsKeysAndGetItem[str, int]" [dict-item]
This is potentially the same as #17684, but felt different.
(As always, thanks for Mypy!)
To Reproduce
https://mypy-play.net/?mypy=latest&python=3.12&gist=a7075c4918e6e95f4f9429bd261aa4c0
from typing import Iterable
class DictSubclass(dict[str, int]): pass
class SKAGI: # SupportsKeysAndGetItem
def keys(self) -> Iterable[str]:
return ['foo']
def __getitem__(self, __key: str) -> int:
return 1
def dict_subclass(d: None | DictSubclass):
if d is not None: # proving the basic operations work:
d["x"] # no error
{**d} # no error
index = (d or {})["x"] # error: Invalid index type "str" for "DictSubclass | dict[Never, Never]"; expected type "Never" [index]
get = (d or {}).get("x") # error: No overload variant of "get" of "dict" matches argument type "str" [call-overload]
splat = {**(d or {})} # error: Unpacked dict entry 0 has incompatible type "DictSubclass | dict[Never, Never]"; expected "SupportsKeysAndGetItem[str, int]" [dict-item]
def skagi(d: None | SKAGI):
if d is not None: # proving the basic operations work:
d["x"] # no error
{**d} # no error
index = (d or {})["x"] # error: Invalid index type "str" for "SKAGI | dict[Never, Never]"; expected type "Never" [index]
splat = {**(d or {})} # error: Unpacked dict entry 0 has incompatible type "SKAGI | dict[Never, Never]"; expected "SupportsKeysAndGetItem[str, int]" [dict-item]
# using the normal dict for comparison:
def dict_builtin(d: None | dict[str, int]):
index = (d or {})["x"] # no error
get = (d or {}).get("x") # no error
splat = {**(d or {})} # no error
Expected Behavior
I'd expect the subclass and SupportsKeysAndGetItem-implementing type to behave the same as the normal dict instance, where the Never key arg is unified and/or ignored appropriately.
Actual Behavior
main.py:17: error: Invalid index type "str" for "DictSubclass | dict[Never, Never]"; expected type "Never" [index]
main.py:18: error: No overload variant of "get" of "dict" matches argument type "str" [call-overload]
main.py:18: note: Possible overload variants:
main.py:18: note: def get(self, Never, /) -> None
main.py:18: note: def get(self, Never, Never, /) -> Never
main.py:18: note: def [_T] get(self, Never, _T, /) -> _T
main.py:19: error: Unpacked dict entry 0 has incompatible type "DictSubclass | dict[Never, Never]"; expected "SupportsKeysAndGetItem[str, int]" [dict-item]
main.py:26: error: Invalid index type "str" for "SKAGI | dict[Never, Never]"; expected type "Never" [index]
main.py:27: error: Unpacked dict entry 0 has incompatible type "SKAGI | dict[Never, Never]"; expected "SupportsKeysAndGetItem[str, int]" [dict-item]
Found 5 errors in 1 file (checked 1 source file)
Your Environment
- Mypy version used: 1.11.2
- Mypy command-line flags: N/A
- Mypy configuration options from
mypy.ini(and other config files): N/A - Python version used: 3.12
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Inizia con la riproduzione collegata in mypy-play e confronta il comportamento di d or {} per i dict integrati, le sottoclassi di dict e le implementazioni di SupportsKeysAndGetItem. Traccia l’inferenza dei tipi e la gestione delle union rilevanti; il lavoro è completato quando gli esempi riprodotti di indicizzazione, get e dictionary-splat non segnalano più gli errori relativi a Never, mentre il comportamento dei dict integrati rimane corretto.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- python
- Ambito
- compilers, devtools
- Tipo di issue
- Bug
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Stato di attività
- Ferma
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 35/100