Description
In my PR for updating the mypy docs, @gvanrossum pointed out that one of my examples didn't typecheck -- the simplified repro was this:
class A: pass
class B: pass
@overload
def foo(a: int) -> A: pass
@overload
def foo(a: int, b: int) -> B: pass
def foo(*args: int) -> Union[A, B]:
raise NotImplementedError()
After debugging, I realized that the checks are actually technically correct: the overloads suggest that running foo(a=1, b=2)
is type-safe; that call will crash at runtime.
This feels a bit annoying though, so I'm thinking it'd be nice if we could relax these checks -- basically, allow the existence of "de-facto positional-only arguments".
I'm thinking one way we can do this is to:
- Relax the overload definition checks so they ignore the argument names
- Perform an extra check every time we call an overload: if the overload has an implementation, we check and see names match and report a (custom) error if they don't.
So under this proposal, foo
would continue to type-check, but we'd report an error if somebody tried doing foo(a=1, a=2)
.
The main disadvantage is that this would cause feature disparity with overloads in stubs since stubs don't allow you to include an implementation. We could either live with this or maybe allow users to add an implementations with empty bodies in stubs if we really want to maintain parity.
Thoughts? (I wanted to file an issue to get consensus/see if anybody is able to come up with a better solution before I start implementation.)