Skip to content

Wrong overload resolution with Any union item in argument #5249

Closed

Description

@JukkaL

This fragment derived from production code causes a false positive:

def f(): pass  # No annotation
t = False
t &= f() and True  # Incompatible types in assignment 
                   # (expression has type "int", variable has type "bool")

Here's a self-contained repro:

from typing import overload, Union, Any

class C:
    def f(self, other: C) -> C: ...

class D(C):
    @overload  # type: ignore
    def f(self, other: D) -> D: ...
    @overload
    def f(self, other: C) -> C: ...
    def f(self, other): ...

x: D
y: Union[D, Any]
reveal_type(x.f(y))  # C

I'd expect the inferred type for x.f(y) to be Union[D, Any] (or maybe D, though it's slightly less correct arguably).

Activity

  1. ilevkivskyi commented on Jun 20, 2018

    @ilevkivskyi
    Member

    I think we should switch to a new union math algorithm, I have some ideas how to make it fast enough to replace the current one (that is apparently to dangerous). I will give it a try now.

  2. JukkaL commented on Jun 20, 2018

    @JukkaL
    CollaboratorAuthor

    Another real-world example where things go wrong:

    from typing import Union, Any, List
    i: Union[int, Any]
    a: List[int]
    reveal_type(a[i])  # Union[int, List[int]]
  3. JelleZijlstra commented on Jun 20, 2018

    @JelleZijlstra
    Member

    I think that one is actually correct: if i is a slice object, it will return List[int].

  4. self-assigned this
    on Jun 20, 2018
  5. JukkaL commented on Jun 20, 2018

    @JukkaL
    CollaboratorAuthor

    List[int] is inconsistent with how Any works with overloads generally -- if there is ambiguity due to Any types in overload resolution, we tend to fall back to Any to avoid false positives. False negatives are preferred over false positives when Any types are involved. Here is a simple analogy:

    from typing import Union, Any
    class A:
        x: str
    class B:
        x: int
    a: Union[A, Any]
    reveal_type(a.x)  # Union[str, Any]

    We don't infer Union[str, int] as the type of a.x even though int is a plausible type for a.x -- since it could well be something else. Similarly, the precise type of i could actually be just int (though we can't tell for certain), and assuming that it can be a slice would be wrong.

  6. ilevkivskyi commented on Jun 21, 2018

    @ilevkivskyi
    Member

    The PR I am working on will produce (after some tweaks that I didn't push yet) Union[int, Any] for this example:

    from typing import Union, Any, List
    i: Union[int, Any]
    a: List[int]
    reveal_type(a[i]) # Union[int, Any]

    @JukkaL does this make sense to you?

  7. ilevkivskyi commented on Jun 21, 2018

    @ilevkivskyi
    Member

    (Also I think Union[D, Any] in the original example is best.)

  8. JukkaL commented on Jun 21, 2018

    @JukkaL
    CollaboratorAuthor

    Yes, I think thatUnion[int, Any] is the most correct type for a[i], and similarly Union[D, Any] for the other example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions