Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

d or {} where d is something other than builtin dict gets errors about Never for indexing and splatting #17790

Open
huonw opened this issue Sep 19, 2024 · 0 comments
Labels
bug mypy got something wrong

Comments

@huonw
Copy link

huonw commented Sep 19, 2024

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
@huonw huonw added the bug mypy got something wrong label Sep 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

No branches or pull requests

1 participant