`@overload` breaks with named tuple and some overloaded functions
オープン
まだ誰も着手していません。
bug
topic-overloads
- 主要言語
- Python
- スター
- 20.6k
- フォーク
- 3.3k
- PR マージ指標
- PR 指標を取得中
説明
Bug Report
Mypy incorrectly reports Any as the resolved type (quite possibly due this https://github.com/python/typing/issues/253#issuecomment-235358878 )
To Reproduce
from collections import namedtuple
from typing import Any, Callable, cast, Dict, List, NamedTuple, overload, TypeVar, Union
F = TypeVar("F", bound=Callable[..., Any])
Arg: NamedTuple = namedtuple("Arg", ["arg"])
class Test:
@overload
def __call__(self, fn: F) -> F:
...
@overload
def __call__(self, *args: Any, **kwargs: Any) -> "Test":
...
def __call__(self, *args: Any, **kwargs: Any) -> Union[F, "Test"]:
if len(args) == 1:
return cast(F, args[0])
return self
reveal_type(Test()(Test))
def broken(arg: Arg) -> Arg:
return arg
reveal_type(broken)
reveal_type(Test()(broken))
def working(arg: int) -> int:
return arg
reveal_type(Test()(working))
@overload
def overloaded_broken(arg: F) -> F:
...
@overload
def overloaded_broken(*args: Any, **kwargs: Any) -> Dict[str, int]:
...
def overloaded_broken(*args: Any, **kwargs: Any) -> Union[F, Dict[str, int]]:
if len(args) == 1:
return cast(F, args[0])
return dict(args=len(args), kwargs=len(kwargs))
reveal_type(overloaded_broken)
reveal_type(Test()(overloaded_broken))
@overload
def overloaded_working(arg: str) -> str:
...
@overload
def overloaded_working(arg: bytes) -> bytes:
...
def overloaded_working(arg: Union[bytes, str]) -> Union[bytes, str]:
return arg
reveal_type(Test()(overloaded_working))
Expected Behavior
All revealed types are printed as non Any
Actual Behavior
# a class is OK
test.py:23:13: note: Revealed type is 'def () -> test.Test'
# this is what is expected when using a named tuple, but it resolves as any
test.py:30:13: note: Revealed type is 'def (arg: Tuple[Any, fallback=test.Arg]) -> Tuple[Any, fallback=test.Arg]'
test.py:31:13: note: Revealed type is 'Any'
# this is not using a named tuple and it works as expected
test.py:38:13: note: Revealed type is 'def (arg: builtins.int) -> builtins.int'
# this is what is expected for a complex overloaded function, but it resolves as any
test.py:57:13: note: Revealed type is 'Overload(def [F <: def (*Any, **Any) -> Any] (arg: F`-1) -> F`-1, def (*args: Any, **kwargs: Any) -> builtins.dict[builtins.str, builtins.int])'
test.py:58:13: note: Revealed type is 'Any'
# passing a simpler overloaded function
test.py:73:13: note: Revealed type is 'Overload(def (arg: builtins.str) -> builtins.str, def (arg: builtins.bytes) -> builtins.bytes)'
Your Environment
mypy --version: mypy 0.812 (default config)
python --version: Python 3.8.9
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
まず、mypy 0.812 を使って test.py の再現を実行し、named-tuple と overloaded-function のケースで revealed types を比較します。オーバーロード解決と named-tuple 型の扱いを追跡し、その後、影響を受ける reveals が Any ではなく、期待される callable 型に解決されることを確認します。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- python
- 領域
- compilers
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 停滞
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 35/100