Collapsed Optionals in TypeVar cause weird error messages
まだ誰も着手していません。
- 主要言語
- Python
- スター
- 20.6k
- フォーク
- 3.3k
- PR マージ指標
- PR 指標を取得中
説明
At a minimum, I'm reporting a bug in an error message.
I have a function, run_tasks, which takes a list of tasks and a worker function, and executes the worker function on almost all the tasks. For some of them, run_tasks will decide to not execute the task.
run_tasks returns List[Optional[Result]] where Result is a TypeVar.
This works until the worker function's returns Optional[x] where Result is now Optional[x] and run_tasks is asked to return List[Optional[Optional[x]]].
Example code:
from typing import (
TypeVar,
List,
Callable,
Optional,
)
Task = TypeVar("Task")
Result = TypeVar("Result")
def run_tasks(
tasks: List[Task], worker_fun: Callable[[Task], Result]
) -> List[Optional[Result]]:
results: List[Optional[Result]] = []
toggle: bool = True
todo: Task
for todo in tasks:
toggle = not toggle
if toggle:
work_result: Result
work_result = worker_fun(todo)
results.append(work_result)
else:
results.append(None)
return results
def test() -> None:
def worker(d: int) -> Optional[int]:
if d % 2 == 0:
return None
else:
return d + 1
output: List[Optional[Optional[int]]] = run_tasks(
[1, 2, 2, 1], worker,
)
from pprint import pprint
pprint(output)
assert output == [None, None, None, 2]
test()
I get the error message: error: Argument 2 to "run_tasks" has incompatible type "Callable[[int], Optional[int]]"; expected "Callable[[int], int]"
I understand Python can't really represent Optional[Optional[int]]. The problem is in the error message, I think. This code does work correctly, and validates:
def test2() -> None:
def worker(d: int) -> int:
return d + 1
output: List[Optional[int]] = run_tasks(
[1, 2, 2, 1], worker,
)
from pprint import pprint
pprint(output)
assert output == [None, 3, None, 2]
test2()
and so someone unfamiliar with the intricacies and details may be confused by the type signature being correctly updated in 2 places, but not validating.
Instead, I sort of expected it to either (a) work, or (b) have an error specific to the case of nested Optional.
$ mypy --version
mypy 0.761
$ python --version
Python 3.7.6
flags: none.
My apologies, but I did not test with mypy from Git master.
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
まず、提供されている run_tasks の再現手順を mypy で実行し、nested-Optional の診断を動作する test2 のケースと比較します。完了条件は、互換性のない Callable エラーが修正されるか、この nested Optional のケースを正確に説明する診断に置き換えられ、例に対するリグレッションカバレッジが追加されていることです。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- python
- 領域
- devtools
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 停滞
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 35/100