Description
Feature
Is it in-scope for either mypy or stubtest to detect incorrect or missing defaults in overloads?
Incorrect default
from typing import Literal, overload, reveal_type
@overload
def foo(a: Literal[True] = ...) -> None: ...
@overload
def foo(a: Literal[False]) -> int: ...
def foo(a: bool = False) -> None | int:
return 1 if not a else None
reveal_type(foo())
Here, the default for a
is False
, yet the overload has a: Literal[True] = ...
, meaning that foo()
will be revealed to be of type None
instead of type int
Missing overload example
from typing import Literal, overload
@overload
def foo(a: Literal[True]) -> None: ...
@overload
def foo(a: Literal[False]) -> int: ...
def foo(a: bool = False) -> None | int:
return 1 if not a else None
The default for a
is False
, so the second overload should probably include a: Literal[False] = ...
?
Pitch
I tried putting together a little static analysis tool to detect simple cases of the above: https://github.com/MarcoGorelli/fix-overload-defaults
It only uses ast
parsing, and is very simple, so it can't detect much, but it was already enough to find issues in a few libraries where I tried it:
- TYP:
svd
overload incorrectly notedLiteral[False]
to be the default forcompute_uv
numpy/numpy#29331 - TYP: correct default value of
unicode
inchararray.__new__
and offull
inpolyfit
numpy/numpy#29340 - fix(python): Fix missing overload defaults in
read_ods
andtree_format
pola-rs/polars#23442 - fix(python): Overload for
eager
default inSchema.to_frame
wasFalse
instead ofTrue
pola-rs/polars#23413 - fix: type annotation default for
named: Literal[False]
was missing inDataFrame.iter_rows
narwhals-dev/narwhals#2778
So, I figured that this might be broadly useful?
I'm much more bothered about detecting incorrect defaults than potentially missing ones. Might this be in-scope for mypy or mypy.stubtest?