Consider the example below, which errors with all tested type checkers (mypy/pyright/ty/pyrefly):
fromtypingimportProtocolclassInterval: ...
classMake(Protocol):
def__call__(self, /, lower: float, upper: float) ->Interval: ...
defmake_impl(
string_or_lower: str|float|None=None,
/,
lower: float|None=None,
upper: float|None=None,
) ->Interval: ...
deftest() ->None:
_f: Make=make_impl# ❌️ type checkers error here.
I believe from a pure type theory POV, this assignment should be legal, because all legal arguments to Make are also legal arguments to make_impl. The spec phrases it in the same spirit:
A callable type B is assignable to a callable type A if the return type of B is assignable to the return type of A and the input signature of B accepts all possible combinations of arguments that the input signature of A accepts. All of the specific assignability rules described below derive from this general rule.
And I couldn't find anything else in https://typing.python.org/en/latest/spec/callables.html#assignability-rules-for-callables that would disallow this assignment.
It seems the type-checkers try to match the KEYWORD_OR_POSITIONAL parameters by name, which is incorrect. Make has 3 legal call signatures:
Make(float, float)Make(float, upper=float)Make(lower=float, upper=float)
and all these 3 call signatures are supported by make_impl, but the parameter mapping is not constant:
make_impl(float, float) -> {lower:string_or_lower, upper:lower}make_impl(float, upper=float) -> {lower:string_or_lower, upper:upper}make_impl(lower=float, upper=float) -> {lower:lower, upper:upper}
So either the spec should demand a constant parameter mapping, or this example should be added to the conformance tests.
Consider the example below, which errors with all tested type checkers (mypy/pyright/ty/pyrefly):
I believe from a pure type theory POV, this assignment should be legal, because all legal arguments to
Makeare also legal arguments tomake_impl. The spec phrases it in the same spirit:And I couldn't find anything else in https://typing.python.org/en/latest/spec/callables.html#assignability-rules-for-callables that would disallow this assignment.
It seems the type-checkers try to match the
KEYWORD_OR_POSITIONALparameters by name, which is incorrect.Makehas 3 legal call signatures:Make(float, float)Make(float, upper=float)Make(lower=float, upper=float)and all these 3 call signatures are supported by
make_impl, but the parameter mapping is not constant:make_impl(float, float)->{lower:string_or_lower, upper:lower}make_impl(float, upper=float)->{lower:string_or_lower, upper:upper}make_impl(lower=float, upper=float)->{lower:lower, upper:upper}So either the spec should demand a constant parameter mapping, or this example should be added to the conformance tests.