python / python/mypy

narrowing to generic shouldn't introduce new `Any`

Open
#16,999 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

Bug Report

If I don't put any Any (and don't import anything with Any), there shouldn't be any Any .

But if I use isinstance to narrow to a generic, a new Any is introduced.

To Reproduce

--strict

def f(x: object) -> None:
    if isinstance(x, Iterable):
        reveal_type(x)  # `Iterable[Any]`
        # an `Any` is introduced, when I didn't put any `Any` in my code
        # should be `Iterable[object]`

        for y in x:
            reveal_type(y)  # `Any` should be `object`
            print(y + 3)  # not safe - should report type error

mypy playground

This is with --strict
It's probably ok to put this Any there in the default mode.

Also, even in --strict, if narrowing from Any, then it's ok to narrow the type variable to Any.

def g(x: Any) -> None:
    if isinstance(x, Iterable):
        reveal_type(x)
        # `Iterable[Any]` is ok here, because we narrowed from `Any`

        for y in x:
            reveal_type(y)  # `Any`
            print(y + 3)  # silenced by `Any`


# current behavior here is good - want to make sure it's not lost
def h(x: Iterable[int] | None) -> None:
    if isinstance(x, Iterable):
        reveal_type(x)  # `Iterable[int]`

        for y in x:
            reveal_type(y)  # `int`
            print(y + 3)

Your Environment

  • Mypy version used: 1.8.0
  • Mypy command-line flags: --strict
  • Python version used: 3.12

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

No source file or test is named in the issue. Start by running the supplied reproductions with mypy 1.8.0 and --strict, then trace the isinstance narrowing behavior for generic Iterable values. Done means narrowing object to Iterable yields Iterable[object] without introducing Any, while narrowing Any still preserves Any and existing Iterable[int] behavior remains unchanged.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.