Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constraint solver regression in mypy 1.7.1 #16582

Closed
erictraut opened this issue Nov 28, 2023 · 0 comments · Fixed by #17311
Closed

Constraint solver regression in mypy 1.7.1 #16582

erictraut opened this issue Nov 28, 2023 · 0 comments · Fixed by #17311
Labels
bug mypy got something wrong

Comments

@erictraut
Copy link

Mypy 1.6.1 didn't produce any errors in this code, but 1.7.0 does.

Link to mypy playground

from typing import Callable, Generic, TypeVar

A = TypeVar("A")
B = TypeVar("B")

class Gen(Generic[A]): ...

def id_(x: A) -> A:
    raise NotImplementedError()

def bstep(
    x: Gen[A],
    y: A,
) -> Gen[Gen[A]]:
    raise NotImplementedError()

def bfn(
    x: Gen[Gen[A]],
) -> Gen[A]:
    return bfn_generic(x, id_, bstep) # False positive error here

def bfn_generic(
    x: Gen[A],
    id_: Callable[[B], B],
    step: Callable[[A, B], Gen[A]],
) -> A:
    raise NotImplementedError()

Note that pyright has a similar bug in its constraint solver, which is how I became aware of this issue. Here's the original pyright bug report.

@erictraut erictraut added the bug mypy got something wrong label Nov 28, 2023
ilevkivskyi added a commit that referenced this issue Jun 5, 2024
Fixes #16582

IMO this is long overdue. Currently, type variable IDs are 99% unique,
but when they accidentally clash, it causes hard to debug issues. The
implementation is generally straightforward, but it uncovered a whole
bunch of unrelated bugs. Few notes:
* This still doesn't fix the type variables in nested generic callable
types (those that appear in return types of another generic callable).
It is non-trivial to put namespace there, and luckily this situation is
already special-cased in `checkexpr.py` to avoid ID clashes.
* This uncovered a bug in overloaded dunder overrides handling, fix is
simple.
* This also uncovered a deeper problem in unsafe overload overlap logic
(w.r.t. partial parameters overlap). Here proper fix would be hard, so
instead I tweak current logic so it will not cause false positives, at a
cost of possible false negatives.
* This makes explicit that we use a somewhat ad-hoc logic for join/meet
of generic callables. FWIW I decided to keep it, since it seems to work
reasonably well.
* This accidentally highlighted two bugs in error message locations. One
very old one related to type aliases, I fixed newly discovered cases by
extending a previous partial fix. Second, the error locations generated
by `partial` plugin were completely off (you can see examples in
`mypy_primer` where there were errors on empty lines etc).
* This PR (naturally) causes a significant amount of new valid errors
(fixed false negatives). To improve the error messages, I extend the
name disambiguation logic to include type variables (and also type
aliases, while I am at it), previously it only applied to `Instance`s.
Note that I use a notation `TypeVar@namespace`, which is a semantic
equivalent of qualified name for type variables. For now, I shorten the
namespace to only the last component, to make errors less verbose. We
can reconsider this if it causes confusion.
* Finally, this PR will hopefully allow a more principled implementation
of #15907

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant