python / python/mypy

`@overload` incorrectly reports error if overload param would go to different params of implementation depending on positional vs keyword calling style

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

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

bug topic-overloads
主要言語
Python
スター
20.6k
フォーク
3.3k
PR マージ指標
PR 指標を取得中

説明

Bug Report

Type-checking on the @overload decorator incorrectly reports an error in the implementation function's signature when an argument would go to different parameters of an implementation function depending on whether that argument is passed as a positional or keyword argument, even if both outcomes are still valid.

To Reproduce

Here's a minimal possible example:

from typing import overload

@overload
def func(value: int):
    ...

def func(positional_only: int | None = None, /, value: int | None = None):
    pass

func can be correctly called with either of these signatures:

func(1)  # results in call with parameters(1, None)
func(value=1)  # results in call with parameters (None, 1)

Either of these calls is valid.

Expected Behavior

The type-checker considers the code valid. (Excluding the error that there's only one overload, which is expected in this minimal example).

Actual Behavior

type_test.py:8: error: Overloaded function implementation does not accept all possible arguments of signature 1  [misc]

Your Environment

  • Mypy version used: mypy 1.7.1 (compiled: yes)
  • Mypy command-line flags: python3 -m mypy ./type_test_2.py
  • Mypy configuration options from mypy.ini (and other config files): Not changed from the default
  • Python version used: Python 3.11.6

A motivating example

I wanted to define a lookup function that can lookup an object by id (an int) or name (a str), something like this:

from typing import overload

@overload
def lookup(id: int):
    ...

@overload
def lookup(name: str):
    ...

def lookup(id_or_name: int | str | None = None, /, id: int | None = None, name: str | None = None):
    if id is None and name is None:
        if isinstance(id_or_name, int): id = id_or_name
        else: name = id_or_name  # name is str

    if id is not None:
        return _lookup_by_id(id)
    else:
        return _lookup_by_name(name)


## Possible calls:

lookup(1)  # integer positional
lookup(id=1)  # integer keyword

lookup("foo")  # string positional
lookup(name="foo")  # string keyword

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

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

はじめの一歩

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

調査の方向性

まず、最小限の overload の例で報告された python3 -m mypy ./type_test_2.py コマンドを実行し、実装シグネチャのエラーを確認します。overload の実装互換性チェックを追跡し、異なる実装パラメーターに到達する位置引数呼び出しとキーワード呼び出しのカバレッジを追加します。完了の条件は、有効な呼び出しで報告されたエラーが発生しなくなり、無効な overload 実装は引き続き拒否されることです。

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

評価

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

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

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