Skip to content

Expected Iterable[Buffer] when using map(str, ...) #2087

@karlicoss

Description

@karlicoss

Summary

playground link: https://play.ty.dev/eab57770-64e1-44c8-940a-561b4340e9af

Consider the following program

from typing import Sequence, reveal_type

def test(command: Sequence[str]) -> None:
    if isinstance(command, list):
        reveal_type(command)
        print(list(map(str, command)))

test(['echo', 'hello'])

This works in runtime, however since 0.0.3, ty is reporting a type error

$ uv run --with ty==0.0.3 -m ty check test.py 
info[revealed-type]: Revealed type
 --> test.py:5:21
  |
3 | def test(command: Sequence[str]) -> None:
4 |     if isinstance(command, list):
5 |         reveal_type(command)
  |                     ^^^^^^^ `Sequence[str] & Top[list[Unknown]]`
6 |         print(list(map(str, command)))
  |

error[invalid-argument-type]: Argument to function `__new__` is incorrect
 --> test.py:6:29
  |
4 |     if isinstance(command, list):
5 |         reveal_type(command)
6 |         print(list(map(str, command)))
  |                             ^^^^^^^ Expected `Iterable[Buffer]`, found `Sequence[str] & Top[list[Unknown]]`
7 |
8 | test(['echo', 'hello'])
  |
info: Matching overload defined here
    --> stdlib/builtins.pyi:3839:13
     |
3837 |     else:
3838 |         @overload
3839 |         def __new__(cls, func: Callable[[_T1], _S], iterable: Iterable[_T1], /) -> Self: ...
     |             ^^^^^^^                                 ----------------------- Parameter declared here
3840 |         @overload
3841 |         def __new__(cls, func: Callable[[_T1, _T2], _S], iterable: Iterable[_T1], iter2: Iterable[_T2], /) -> Self: ...
     |
info: Non-matching overloads for function `__new__`:
info:   (cls, func: (_T1@__new__, _T2@__new__, /) -> _S@map, iterable: Iterable[_T1@__new__], iter2: Iterable[_T2@__new__], /) -> Self@__new__
info:   (cls, func: (_T1@__new__, _T2@__new__, _T3@__new__, /) -> _S@map, iterable: Iterable[_T1@__new__], iter2: Iterable[_T2@__new__], iter3: Iterable[_T3@__new__], /) -> Self@__new__
info:   (cls, func: (_T1@__new__, _T2@__new__, _T3@__new__, _T4@__new__, /) -> _S@map, iterable: Iterable[_T1@__new__], iter2: Iterable[_T2@__new__], iter3: Iterable[_T3@__new__], iter4: Iterable[_T4@__new__], /) -> Self@__new__
info:   (cls, func: (_T1@__new__, _T2@__new__, _T3@__new__, _T4@__new__, _T5@__new__, /) -> _S@map, iterable: Iterable[_T1@__new__], iter2: Iterable[_T2@__new__], iter3: Iterable[_T3@__new__], iter4: Iterable[_T4@__new__], iter5: Iterable[_T5@__new__], /) -> Self@__new__
info:   (cls, func: (...) -> _S@map, iterable: Iterable[Any], iter2: Iterable[Any], iter3: Iterable[Any], iter4: Iterable[Any], iter5: Iterable[Any], iter6: Iterable[Any], /, *iterables: Iterable[Any]) -> Self@__new__
info: rule `invalid-argument-type` is enabled by default

Found 2 diagnostics

This only started happening in 0.0.3; 0.0.2 works without type error. Interesting enough, on 0.0.2 reveal_type still shows Sequence[str] & Top[list[Unknown]], so felt like possible typeshed change? But doesn't look like there've been any recent typeshed syncs, so not sure what to make of it! https://github.com/astral-sh/ruff/commits/main/

Funny enough, if we change to isinstance(command, list[str]), this type checks in 0.0.3

4 |     if isinstance(command, list[str]):
5 |         reveal_type(command)
  |                     ^^^^^^^ `Sequence[str]`

However

  • it's not allowed in runtime: TypeError: isinstance() argument 2 cannot be a parameterized generic
  • the inferred type isn't correct, should be list[str]? (I guess this is irrelevant since ideally ty would flag this as invalid in runtime anyway)

Apologies if it's an existing issue, didn't really manage to find anything similar, and encountered independently in two separate projects, so figured worth reporting so people can find it in search.

Version

ty 0.0.3/latest master

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions