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

[red-knot] Literal[False] not always inferred for comparisons between tuple types with disjunct literal elements #14279

Open
AlexWaygood opened this issue Nov 11, 2024 · 3 comments
Labels
bug Something isn't working help wanted Contributions especially welcome red-knot Multi-file analysis & type inference

Comments

@AlexWaygood
Copy link
Member

AlexWaygood commented Nov 11, 2024

red-knot infers the following types for the following comparisons:

from typing import reveal_type

def int_instance() -> int:
    return 42

reveal_type("foo" == "bar")                                       # Literal[False]
reveal_type(("foo",) == ("bar",))                                 # Literal[False]
reveal_type((4, "foo") == (4, "bar"))                             # Literal[False]
reveal_type((int_instance(), "foo") == (int_instance(), "bar"))   # bool

The last one should also be inferred as Literal[False], just like the first three. This is because two objects of types Literal["foo"] and Literal["bar"] respectively will never compare equal to each other. By the same token, two 2-element tuples where the second elements are of type Literal["foo"] and Literal["bar"] respectively will never compare equal, regardless of what their first element is.

I discovered this while working on #14244. Ideally, this comparison would be inferred as Literal[False], since sys.version_info[3] should be inferred by red-knot as being of type Literal["alpha", "beta", "candidate", "final"], and objects with that type never compare equal to the string "finallllllll":

import sys
from typing import reveal_type

reveal_type(sys.version_info == (3, 8, 1, "finallllllll", 0))
@AlexWaygood AlexWaygood added bug Something isn't working help wanted Contributions especially welcome red-knot Multi-file analysis & type inference labels Nov 11, 2024
@cake-monotone
Copy link
Contributor

cake-monotone commented Nov 12, 2024

That makes sense! Additionally, we should handle tuples of different lengths.

reveal_type((int_instance(),) == (int_instance(), "bar"))   # revealed: bool

I think it might be a simple fix! If no other opinions come up, I’ll go ahead and work on it :)

@cake-monotone
Copy link
Contributor

An issue with error propagation suddenly came to mind. When tuple comparison was initially implemented, only literal comparison was supported, so there was no opportunity to properly test error propagation.

(int_instance(), "test") < (int_instance(), 3)

Since there’s a possibility of an unsupported operation error here, a diagnostic should be triggered. However, it currently isn’t, as the comparison stops immediately when Truthness::Ambiguous occurs during lexicographic comparison.

@AlexWaygood
Copy link
Member Author

Yes, I think you're correct on both counts!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Contributions especially welcome red-knot Multi-file analysis & type inference
Projects
None yet
Development

No branches or pull requests

2 participants