python / python/mypy

wrongly inferred type `builtins.object`

Open
#15,295 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

bug topic-join-v-union topic-paramspec
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

Bug Report

In a rather convoluted nesting, I found that a Union was turned into builtins.object.

To Reproduce

import typing as t


_T = t.TypeVar("_T")
_P = t.ParamSpec("_P")


async def works() -> None:
    async def callback(
        cb: t.Callable[_P, t.Union[t.Awaitable[_T], _T]],
        *args: _P.args, **kwargs: _P.kwargs
    ) -> _T:
        raise NotImplementedError()

    def make_t() -> t.Union[
        t.Callable[[], t.Coroutine[t.Any, t.Any, int]],
        t.Callable[[], int]
    ]:
        raise NotImplementedError()

    t = make_t()
    t_cb = await callback(t)
    reveal_type(t_cb)  # note: Revealed type is "builtins.int"


async def fails() -> None:
    async def callback(
        cb: t.Callable[_P, t.Union[t.Awaitable[_T], _T]],
        *args: _P.args, **kwargs: _P.kwargs
    ) -> _T:
        raise NotImplementedError()

    def make_t() -> t.Union[
        t.Callable[[], t.Coroutine[t.Any, t.Any, t.Union[int, str]]],
        t.Callable[[], t.Union[int, str]]
    ]:
        raise NotImplementedError()

    t = make_t()
    t_cb = await callback(t)
    reveal_type(t_cb)  # Revealed type is "builtins.object"

Gist URL: https://gist.github.com/mypy-play/f932b06f9d8638c2b0c711f8e4048348
Playground URL: https://mypy-play.net/?mypy=latest&python=3.11&gist=f932b06f9d8638c2b0c711f8e4048348

In the example you can see two example functions works and fails which are the exact same except for int in works was replaced with Union[int, str] in fails. Both end with a reveal_type.

Expected Behavior

  • works should reveal builtins.int
  • fails should reveal Union[builtins.int, builtins.str]

Actual Behavior

  • works reveals builtins.int (as expected)
  • fails reveals builtins.object (unexpected)

(here's the mypy output of the gist)

main.py:23: note: Revealed type is "builtins.int"
main.py:41: note: Revealed type is "builtins.object"
Success: no issues found in 1 source file

Your Environment

$ python -VV
Python 3.11.0 (main, Nov  2 2022, 13:45:57) [GCC 11.3.0]
$ pip freeze | grep 'mypy\|typing'
mypy==1.3.0
mypy-extensions==1.0.0
typing_extensions==4.5.0

Related
I think there's a whole bunch of related issues already, but I wanted to share this example to potentially validate a future fix.

https://github.com/python/mypy/issues/12009#issuecomment-1016081515

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

Run the supplied Python snippet with mypy 1.3.0 and compare the two reveal_type results. Trace the callable, Union, and ParamSpec inference path, add a regression test based on the fails example, and confirm it reveals Union[int, str] while works remains int.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.