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

Regression: Literal[False] and Literal[True] are no longer merged into type bool #5421

Closed
marcelgerber opened this issue Jul 1, 2023 · 2 comments
Labels
as designed Not a bug, working as intended bug Something isn't working

Comments

@marcelgerber
Copy link

marcelgerber commented Jul 1, 2023

Describe the bug

Up until pyright 1.1.314, the following code was valid without error, but now in 1.1.316 it is erroring.

To Reproduce
Run pyright on the below code, and you will get the following error:

Expression of type "list[tuple[Literal['b'], Literal[False]] | tuple[Literal['a'], Literal[True]]]" cannot be assigned to return type "list[tuple[str, bool]]"
  "list[tuple[Literal['b'], Literal[False]] | tuple[Literal['a'], Literal[True]]]" is incompatible with "list[tuple[str, bool]]"
    TypeVar "_T@list" is invariant
      Type "tuple[Literal['b'], Literal[False]] | tuple[Literal['a'], Literal[True]]" cannot be assigned to type "tuple[str, bool]"
        "tuple[Literal['b'], Literal[False]]" is incompatible with "tuple[str, bool]"
          Tuple entry 1 is incorrect typePylance[reportGeneralTypeIssues](https://github.com/microsoft/pyright/blob/main/docs/configuration.md#reportGeneralTypeIssues)

Expected behavior
No type errors should be thrown.

Code or Screenshots

def a() -> list[tuple[str, bool]]:
    return [("a", True)] + [("b", False)]

VS Code extension or command-line
This is happening in both the VS Code extension and the pyright cli; both are 1.1.316.

As I said above, this is a recent regression since the same code was working fine back in 1.1.314.

@erictraut
Copy link
Collaborator

This isn't a case of failing to "merge" two literal types into bool.

This should produce a type error. There was a bug in previous versions of pyright that resulted in a false negative.

The inferred type of expression [("a", True)] is list[tuple[Literal['a'], Literal[True]]]. This cannot be added to a list of type list[tuple[Literal['b'], Literal[False]]].

You can work around this by creating a temporary variable with an annotated type:

def a() -> list[tuple[str, bool]]:
    x: list[tuple[str, bool]] = [("a", True)]
    return x + [("b", False)]

This happens to work in mypy because its type inference rules for tuples differ from pyright's. It doesn't retain literal values within tuples. See pyright's documentation about inference for details.

@erictraut erictraut added the as designed Not a bug, working as intended label Jul 12, 2023
@Pwuts
Copy link

Pwuts commented May 26, 2024

I wonder why this was marked as "as designed". I'm sure there is solid reasoning behind it, but it seems like an impractical approach to type checking.

If a function generates output that is type-wise within its signature, why shouldn't that be acceptable to the type checker?

I am currently experiencing a related issue:

class PartiAlphabet(str, enum.Enum):
    A = "a"
    B = "b"
    C = "c"

@overload
def fun(letter: Literal[PartiAlphabet.A]) -> Literal["a"]:
    ...

@overload
def fun(letter: Literal[PartiAlphabet.B]) -> Literal["b"]:
    ...

@overload
def fun(letter: Literal[PartiAlphabet.C]) -> Literal["c"]:
    ...

def fun(letter: PartiAlphabet) -> str:
    return letter.value

# error: No overloads for "fun" match the provided arguments
# error: Argument of type "PartiAlphabet" cannot be assigned to parameter "letter" of type "Literal[PartiAlphabet.A]"
# error: Argument of type "PartiAlphabet" cannot be assigned to parameter "letter" of type "Literal[PartiAlphabet.B]"
# error: Argument of type "PartiAlphabet" cannot be assigned to parameter "letter" of type "Literal[PartiAlphabet.C]"

The overloads exhaust the PartiAlphabet enum, so this shouldn't raise any errors imo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
as designed Not a bug, working as intended bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants