Skip to content

False "Invalid index type" for min derived from return type #14664

New issue

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

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

Already on GitHub? # to your account

Open
ods opened this issue Feb 9, 2023 · 2 comments · May be fixed by #18976
Open

False "Invalid index type" for min derived from return type #14664

ods opened this issue Feb 9, 2023 · 2 comments · May be fixed by #18976
Labels
bug mypy got something wrong topic-type-context Type context / bidirectional inference

Comments

@ods
Copy link

ods commented Feb 9, 2023

Bug Report

Mypy gives [index] error for key when calling min from function that is declared to return Optional.

To Reproduce

This pretty valid

def func() -> Optional[int]:
    d = {1: 2, 3: 4}
    return min([1, 2], key=lambda k: d[k], default=None)

returns error

Invalid index type "Optional[int]" for "Dict[int, int]"; expected type "int"  [index]

Changing default to 0 doesn't fix the problem, but changing return type of func to int does. So, the following works fine:

def func() -> int:
    d = {1: 2, 3: 4}
    return min([1, 2], key=lambda k: d[k], default=0)

Expected Behavior

No error for the first example, as default is never compared to objects in collection.

Actual Behavior

Invalid index type "Optional[int]" for "Dict[int, int]"; expected type "int"  [index]

Your Environment

  • Mypy version used: 1.0.0
  • Mypy command-line flags: no
  • Mypy configuration options from mypy.ini (and other config files): no
  • Python version used: 3.10
@ods ods added the bug mypy got something wrong label Feb 9, 2023
@JelleZijlstra JelleZijlstra added the topic-type-context Type context / bidirectional inference label Feb 9, 2023
@EdwardEisenhauer
Copy link

I experienced a similar issue with the following code:

from typing import Optional


class MyObject:
    def __init__(self, attribute: int) -> None:
        self.attribute = attribute


def find_biggest_attribute(objects: list[MyObject]) -> Optional[MyObject]:
    return max(objects, default=None, key=lambda object: object.attribute)


print(find_biggest_attribute([MyObject(42), MyObject(41)]))

print(find_biggest_attribute([]))

Running mypy raises:

mypy_bug.py:10: error: Item "None" of "Optional[MyObject]" has no attribute "attribute"  [union-attr]
        return max(objects, default=None, key=lambda object: object.attribute)
                                                             ^~~~~~~~~~~~~~~~
Found 1 error in 1 file (checked 1 source file)

As per Python built-in max() documentation:

The default argument specifies an object to return if the provided iterable is empty. If the iterable is empty and default is not provided, a ValueError is raised.

@EugeneYushin
Copy link

Know what:

def func() -> Optional[int]:
    d = {1: 2, 3: 4}
    x = min([1, 2], key=lambda k: d[k], default=None)
    return x

# mypy.....................................................................Passed

This is odd

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
bug mypy got something wrong topic-type-context Type context / bidirectional inference
Projects
None yet
4 participants