You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit adds support for very basic and simple union math when
calling overloaded functions, resolving python#4576.
One thing led to another, and this ended up accidentally fixing or
touching on several different overload-related issues. In particular,
I believe this pull request:
1. Fixes the bug (?) where calling overloaded functions can sometimes
silently infer a return type of 'Any'
2. Changes the semantics of how mypy handles overlapping functions,
which I believe is currently under discussion in python/typing#253
Although this change is functional and mergable, I was planning on
polishing it more -- adding more tests, fleshing out the union math
behavior, etc.
However, I think these are sort of big changes and wanted to check in
and make sure this pull request is actually welcome/is a good idea.
If not, let me know, and I'd be happy to abandon it.
---
Details on specific changes made:
1. The new algorithm works by modifying checkexpr.overload_call_targets
to return all possible matches, rather then just one.
We start by trying the first matching signature. If there was some
error, we (conservatively) attempt to union all of the matching
signatures together and repeat the typechecking process.
If it doesn't seem like it's possible to combine the matching
signatures in a sound way, we end and just output the errors we
obtained from typechecking the first match.
The "signature-unioning" code is currently deliberately very
conservative. I figured it was better to start small and attempt to
handle only basic cases like python#1943 and relax the restrictions later
as needed. For more details on this algorithm, see the comments in
checkexpr.union_overload_matches.
2. This change incidentally resolves any bugs related to how calling
an overloaded function can sometimes silently infer a return type
of Any. Previously, if a function call caused an overload to be
less precise then a previous one, we gave up and returned a silent
Any.
This change removes this case altogether and only infers Any if
either (a) the caller arguments explicitly contains Any or (b) if
there was some error.
For example, see python#3295 and python#1322 -- I believe this pull request touches
on and maybe resolves (??) those two issues.
3. As a result, I needed to fix a few parts of mypy that were
relying on this "silently infer Any" behavior -- see the changes in
checker.py and semanal.py. Both files were using expressions of the
form `zip(*iterable)`, which ended up having a type of `Any` under
the old algorithm. The new algorithm will instead infer
`Iterable[Tuple[Any, ...]]` which actually matches the stubs in
typeshed.
4. These changes cause the attr stubs in `test-data/unit/lib-stub` to
no longer work. It seems that the stubs both here and in typeshed
were both also falling prey to the 'silently infer Any' bug: code
like `a = attr.ib()` typechecked not because they matched the
signature of any of the overloads, but because that particular call
caused one or more overloads to overlap, which made mypy give up and
infer Any.
I couldn't find a clean way of fixing the stubs to infer the correct
thing under this new behavior, so just gave up and removed the
overloads altogether. I think this is fine though -- it seems like
the attrs plugin infers the correct type for us anyways, regardless
of what the stubs say.
If this pull request is accepted, I plan on submitting a similar
pull request to the stubs in typeshed.
4. This pull request also probably touches on
python/typing#253. We still require the
overloads to be written from the most narrow to general and disallow
overlapping signatures.
However, if a *call* now causes overlaps, we try the "union"
algorithm described above and default to selecting the first
matching overload instead of giving up.
0 commit comments