Skip to content

Incorrect value type inferred for min/max in some contexts #6692

Closed
@mthuurne

Description

@mthuurne

I'm using mypy 0.701 on Python 3.7.2, no flags.

When run on the following code:

from typing import Iterable, Optional

def longest(values: Iterable[str]) -> Optional[str]:
    return max(values, key=len, default=None)

print(longest(['badger', 'mushroom', 'snake']))
print(longest([]))

mypy reports:

4: error: Argument "key" to "max" has incompatible type "Callable[[Sized], int]"; expected "Callable[[Optional[str]], Any]"

While this looks similar to #6460, the root cause is not the same: mypy 0.701 contains the updated typeshed with a signature that uses a Union for the return type of max. Also the test case from that issue passes now. The difference with my test case seems to be in the expected return type.

To make absolutely certain that the built-in signature is not the problem, I created this test case that uses a custom mox function with the same signature as max:

from typing import Any, Callable, Iterable, Optional, TypeVar, Union

_T = TypeVar('_T')
_VT = TypeVar('_VT')

def mox(iterable: Iterable[_T],
        key: Callable[[_T], Any],
        default: _VT
        ) -> Union[_T, _VT]: ...

def moxest(values: Iterable[str]) -> Optional[str]:
    return mox(values, key=len, default=None)

def has_mox(values: Iterable[str]) -> bool:
    return bool(mox(values, key=len, default=None))

mypy reports:

12: error: Argument "key" to "mox" has incompatible type "Callable[[Sized], int]"; expected "Callable[[Optional[str]], Any]"
15: error: Argument "key" to "mox" has incompatible type "Callable[[Sized], int]"; expected "Callable[[object], Any]"

So the expected value type seems to be influenced by the expected return type of the expression, instead of being determined solely by the argument types.

I guess there could be situations in which picking a weaker value type is useful, but in this case the weaker type causes a false positive.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions