python / python/mypy

Mypy can't infer parameter types for nested function calls.

Open
#8,666 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

topic-inference
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

I'm trying to run mypy against this code

import itertools
itertools.starmap(
    lambda x, y: True, filter(lambda in_deg: in_deg[1],
                              [(1, 2)]))

I get the following error message:

error: Value of type "Iterable[Any]" is not indexable

It seems like mypy is starting type inference from the outside and inward, so it starts with itertools.starmap. The first callable is considered to take arguments resulting from the unpacking of an iterable: Iterable[Any], hence the second argument is considered Iterable[Iterable[Any]]. Since the second argument to itertools.starmap here is a function call to filter, it's assumed that filter must return Iterable[Iterable[Any]] to match the second argument expected by itertools.starmap. This coerces the second argument to filter to be seen as Iterable[Iterable[Any]], which in turn coerces the first argument to filter to be seen as a callable taking Iteable[Any]. This overlooks the explicitly obvious fact here that the second argument to filter is actually List[Tuple[int, int]](or at worst Iterable[Tuple[int, int]]) which will cause the first filter argument to be a callable that takes Tuple[int, int], effectively suppressing the spurious error.

One way to overcome this misinterpretation of the argument types is to explicitly cast the result of filter to be Iterable[Tuple[int, int]], which will rightfully suppress the error.

import itertools
import typing
itertools.starmap(
    lambda x, y: True, typing.cast(typing.Iterable[typing.Tuple[int, int]],
                                   filter(lambda in_deg: in_deg[1], [(1, 2)])))

mypy version: 0.761
python version: 3.7.6

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the reported error with the nested itertools.starmap and filter example using mypy 0.761. Trace how argument types are inferred through the two calls and compare the result with the explicitly cast version. Done means the original example no longer reports the spurious Iterable[Any] indexing error without requiring a cast.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.