Overloads with Generics "does not accept all possible arguments"

オープン
#19,053 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
45/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
停滞
技術スタック
python
領域
devtools

調査の方向性

まず、issue にある最小限の Python 例を mypy で実行し、その結果をリンク先の Pyright の動作と比較します。シグネチャ 1 と 2 を報告する overload 実装の互換性チェックを追跡します。例が互換性エラーを生成せず、示されている assert_type の結果を維持できれば完了です。

索引モデルが issue の本文から書いたものです。

説明

bug topic-overloads

I have a function whose return type is determined by the type of an input parameter (with a default value). I have attempted to type-hint it with generics. I get "error: Overloaded function implementation does not accept all possible arguments of signature".

To Reproduce

In the toy example below, the function has two return types (original-type or list) depending on two possible types of the force_list input (Force or NoForce). For completeness I have overloaded all 4 permutations of the input and output types.

Playground: https://mypy-play.net/?mypy=latest&python=3.12&gist=283290e33e2618dfcdf447513d0f4543

  from typing import TypeVar, assert_type, overload
  
  class Force: ...
  ForceInstance = Force()
  
  class NoForce: ...
  NoForceInstance = NoForce()
  
  T = TypeVar("T")
  
  @overload
  def list_or_orig(x: list[T], force_list: Force = ...) -> list[T]: ...
  
  @overload
  def list_or_orig(x: list[T], force_list: NoForce = ...) -> list[T]: ...
  
  @overload
  def list_or_orig(x: T, force_list: Force = ...) -> list[T]: ...
  
  @overload
  def list_or_orig(x: T, force_list: NoForce = ...) -> T: ...
  
  def list_or_orig(x: list[T] | T, force_list: Force | NoForce = ForceInstance) -> list[T] | T:
      """Return a list or scalar depending on force_list flag."""
      if isinstance(x, list):
          return x
      elif isinstance(force_list, Force):
          return [x]
      else:
          return x
  
  
  a_list = list_or_orig(1)  # Since default is Force, this will return list[int]
  assert_type(a_list, list[int])
  
  b_list = list_or_orig(1, ForceInstance)
  assert_type(b_list, list[int])
  
  a_int = list_or_orig(1, NoForceInstance)  # This will return int
  assert_type(a_int, int)

Expected Behavior

No errors when running through mypy.

Actual Behavior

main.py:29: error: Overloaded function implementation does not accept all possible arguments of signature 1  [misc]
main.py:29: error: Overloaded function implementation does not accept all possible arguments of signature 2  [misc]
Found 2 errors in 1 file (checked 1 source file)

Notes

If I replace the generic type T with a specific type, say, int then it's fine.

I appreciate there is an ambiguity between list[T] and T but have included the less-general list[T] first in the overloads.

The same code passes in the pyright playground.

主要言語
Python
スター
20.6k
フォーク
3.3k
平均マージ
1日 18時間
マージ済み PR(30日)
54

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

python/mypy のほかの issue

python/mypy の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。