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: Overloaded functions using Discriminated Unions with Boolean Literals now reports incompatible type #6420

Closed
winstxnhdw opened this issue Sep 21, 2024 · 3 comments
Assignees

Comments

@winstxnhdw
Copy link

This issue only starts appearing from Pylance 2024.9.1 and onwards. Works fine on 2024.8.2.

Environment data

  • Pylance version: 2024.9.1
  • OS and version: Arch Linux (WSL)
  • Python version (& distribution if applicable, e.g. Anaconda): Python 3.12.6

Code Snippet

from typing import BinaryIO, Literal, overload

from numpy import float32
from numpy.typing import NDArray

@overload
def decode_audio(  # Overload 1 for "decode_audio" overlaps overload 2 and returns an incompatible type Pylance[reportOverlappingOverload]
    input_file: str | BinaryIO,
    sampling_rate: int = 16000,
    split_stereo: Literal[False] = False,
) -> NDArray[float32]: ...
@overload
def decode_audio(
    input_file: str | BinaryIO,
    sampling_rate: int = 16000,
    split_stereo: Literal[True] = True,
) -> tuple[NDArray[float32], NDArray[float32]]: ...
def decode_audio(
    input_file: str | BinaryIO,
    sampling_rate: int = 16000,
    split_stereo: bool = False,
) -> NDArray[float32] | tuple[NDArray[float32], NDArray[float32]]: ...

Expected behavior

No reports. This is a valid discriminated union.

Actual behavior

Overload 1 for "decode_audio" overlaps overload 2 and returns an incompatible type 
@github-actions github-actions bot added the needs repro Issue has not been reproduced yet label Sep 21, 2024
@erictraut
Copy link
Contributor

This error is correct. The behavior you're seeing is due to a recent bug fix. Pyright (the type checker that underlies pylance) previously contained a bug that resulted in a false negative. It failed to report an overlapping overload in this case. With this bug now fixed, it correctly reports the issue.

Until recently, there was no formal definition for an "overlapping overload" provided in the Python typing spec, but we've worked to address this omission. I wrote this new update to to the Python typing spec. Its contents have already gone through extensive review, and it's in its near-final form. Search for the "Overlapping Overloads" subsection if you're interested in the details.

The problem with your code sample is that both overloads specify a default value for the third parameter (split_stereo), so it's possible to call the function with just two arguments (those corresponding to parameters input_file and sampling_rate). In that case, the argument list would apply to both overloads, which makes it ambiguous. It might be easier to understand with a simplified example:

Code sample in pyright playground

from typing import Literal, overload

@overload
def foo(x: Literal[False] = False) -> int: ...
@overload
def foo(x: Literal[True] = True) -> str: ...
def foo(x: bool = False) -> int | str: ...

reveal_type(foo())

@debonte debonte added by design and removed needs repro Issue has not been reproduced yet labels Sep 21, 2024
@debonte debonte closed this as completed Sep 21, 2024
@winstxnhdw
Copy link
Author

winstxnhdw commented Sep 22, 2024

The problem with your code sample is that both overloads specify a default value for the third parameter (split_stereo), so it's possible to call the function with just two arguments (those corresponding to parameters input_file and sampling_rate). In that case, the argument list would apply to both overloads, which makes it ambiguous.

That's strange. Since the default value is False, shouldn't it be able to infer that it should take on the first overload if split_stereo is not specified?

@erictraut
Copy link
Contributor

If you would like to comment on the proposed spec update, here is the thread.

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

No branches or pull requests

4 participants