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

Pylance didn't honor return type from __new__ in special cases #5057

Closed
Brainor opened this issue Oct 31, 2023 · 2 comments
Closed

Pylance didn't honor return type from __new__ in special cases #5057

Brainor opened this issue Oct 31, 2023 · 2 comments
Assignees
Labels
needs repro Issue has not been reproduced yet

Comments

@Brainor
Copy link

Brainor commented Oct 31, 2023

Environment data

  • Language Server version: v2023.10.50
  • OS and version:
    1. Windows 11 Pro, 22H2, 22621.2506
    2. Ubuntu 22.04.2 LTS
  • Python version & distribution:
    1. 3.11.6, Anaconda
    2. 3.10.11, Anaconda

Code Snippet

class TestClass:
    def __new__(cls, message="") -> str:
        return "stub"


a1 = TestClass(12)  # typing: (variable) a1: TestClass
a2 = TestClass()  # typing: (variable) a2: str

image

Expected behavior

a1 and a2 are both string stub, and a1 and a2 should both be typed as (variable) a2: str

Actual behavior

a1 is typed as typing: (variable) a1: TestClass
a2 is typed as (variable) a2: str

According to #1092 , pyright checks return type from __new__ since version 2021.3.4, so I guess it might be a pylance issue.

@github-actions github-actions bot added the needs repro Issue has not been reproduced yet label Oct 31, 2023
@erictraut
Copy link
Contributor

Pyright is working as intended here, so I don't consider it a bug.

The call expression TestClass(12) results in a type error because the message parameter has an inferred type of str based on the default argument value of "". Since pyright couldn't find any constructor signature that was compatible with the provided arguments, it emitted a type error and assumed that the return type of the constructor was TestClass.

If you want your constructor to support both str and int arguments for the message parameter, you can provide an explicit type annotation.

class TestClass:
    def __new__(cls, message: str | int="") -> str:
        return "stub"

@Brainor
Copy link
Author

Brainor commented Oct 31, 2023

The call expression TestClass(12) results in a type error because the message parameter has an inferred type of str based on the default argument value of "". Since pyright couldn't find any constructor signature that was compatible with the provided arguments, it emitted a type error and assumed that the return type of the constructor was TestClass.

Thank you for your detailed explanation, and you are right, default argument value causes inferred type.

class TestClass:
    def __new__(cls, message: str | int="") -> str:
        return "stub"


a1 = TestClass('12')  # typing: (variable) a1: str
a2 = TestClass()  # typing: (variable) a2: str
a3 = TestClass(12) # typing: (variable) a3: str

gets the expected typing result. Lesson learned here. Closing this.

@Brainor Brainor closed this as completed Oct 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs repro Issue has not been reproduced yet
Projects
None yet
Development

No branches or pull requests

3 participants