Skip to content

Using map causes known type to become Unkown #5324

@ImplyingICheck

Description

@ImplyingICheck

Describe the bug
Using the map builtin function causes the type reported by pyright to become Unknown even if the type was previously well defined.

To Reproduce
map() itertools.compress to any data with a well defined type. In my example, each parameter is well defined in type (Iterable[Iterable[tuple[str, int]]] and Iterable[Iterable[int]], respectively) but this information is lost during the call to map(itertools.compress, keyword_argument_pairs, falsy_filter).

Expected behavior
pyright should maintain the inferred type of data prior to being used in map(itertools.compress, data, selection). That is, it should have the inferred type map[compress[<type of data>]]. As comparison, a call to itertools.compress(data, selection) currently returns compress[<type of data>].

As an example, for data: list[list[int]], we should have map[compress[list[int]]] for map(itertools.compress, ...) and pyright currently returns compress[list[int]] for itertools.compress(...).

Code or Screenshots

# pyright: strict
import itertools
from _collections_abc import Iterable, Iterator


def remove_falsy(keyword_argument_pairs: Iterable[Iterable[tuple[str, int]]],
                 falsy_filter: Iterable[Iterable[int]],
                 ) -> Iterator[dict[str, int]]:
  # This line propagates a "reportUnknownVariableType" error
  filtered_pairs = map(itertools.compress, keyword_argument_pairs, falsy_filter)
  for flat_kwargs in filtered_pairs:
    yield dict(flat_kwargs)

if __name__ == '__main__':
  aa = [[('a', 1), ('b', 10), ('c', 0)],
        [('a', 0), ('b', 10), ('c', 1)]]
  bb = [[pair[1] for pair in a] for a in aa]
  print(*remove_falsy(aa, bb))

VS Code extension or command-line
I am running pyright from the command-line.

pyright --version

pyright 1.1.314

Additional context
My minimal reproducible example originally had the following form (as implemented in my project):

import itertools
from _collections_abc import Iterable, Iterator
from typing import TypeVar


_T = TypeVar('_T')

def generate_flattened_kwargs_remove_falsy(
    **kwargs: Iterable[_T],
) -> Iterator[dict[str, _T]]:
  arguments = itertools.zip_longest(*kwargs.values())
  arguments, falsy_filter = itertools.tee(arguments)
  keyword_argument_pairs = map(zip, itertools.repeat(kwargs), arguments)
  filtered_pairs = map(itertools.compress, keyword_argument_pairs, falsy_filter)
  for flat_kwargs in filtered_pairs:
    yield dict(flat_kwargs)

I originally believed this to be an issue specific to map and compress but it also affects other functions. For example, this snippet exhibits the same behaviour:

def small_example(data: list[list[int]]):
  filtered_pairs = map(list, data)
  return filtered_pairs

Metadata

Metadata

Assignees

No one assigned

    Labels

    addressed in next versionIssue is fixed and will appear in next published versionbugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions