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

False error about redeclaration of Final private(double-underscore) variables #725

Closed
Azureblade3808 opened this issue Dec 13, 2020 · 12 comments
Labels
bug Something isn't working fixed in next version (main) A fix has been implemented and will appear in an upcoming version

Comments

@Azureblade3808
Copy link

Environment data

  • Language Server version: 2020.12.2
  • OS and version: macOS Catalina 10.15.7
  • Python version (& distribution if applicable, e.g. Anaconda): Python 3.8.5(Anaconda)

Actual behavior

from typing import Final


class Parent:
    __a: Final[int]

    def __init__(self):
        self.__a = 0
        _ = self.__a


class Child(Parent):
    # Error: "__a" cannot be redeclared because parent class "Parent" declares it as Final
    __a: Final[int] 

    def __init__(self):
        self.__a = 0
        _ = self.__a

The code above is largely simplified and __init__ methods are there only to suppress "final but not assigned" errors and "unused" warnings.

Expected behavior

No error.

Reason

A class member named with a prefix of double-underscore and without a suffix of double-underscore is meant to be purely private. There should be no collisions between such members even if they share a same name.

@Azureblade3808
Copy link
Author

@final private methods are OK, though there should be no needs to add @final to private methods.

@erictraut
Copy link
Contributor

The behavior is correct as per PEP 591.

As confirmation, the same error is emitted by other type checkers like mypy.

@erictraut
Copy link
Contributor

I think one could make the argument that PEP 591 should make an exception for class members with double-underscore names since they are obfuscated and therefore cannot conflict with same-named members in parent classes.

@gvanrossum, I'm interest in any advice you can offer here.

@Azureblade3808
Copy link
Author

The behavior is correct as per PEP 591.

As confirmation, the same error is emitted by other type checkers like mypy.

Your are right that mypy has the same behavior.

But I'm quite confused that Final variables and @final methods are treated in different ways. As I just checked, overriding a @final method prefixed with either single-underscore or double-underscore does NOT get an error, while I believe that at least the single-underscore case deserves one.

@judej judej added the waiting for user response Requires more information from user label Dec 14, 2020
@github-actions github-actions bot removed the triage label Dec 14, 2020
@jakebailey
Copy link
Member

Revisiting this, I do think there's a bug here:

image

In the derived class, only the double underscore prefixed things should be error-less (as they get hidden to children and are not a part of the API). I.e., __bar has an error but should not, and _foo does not have an error but should.

@jakebailey jakebailey added bug Something isn't working needs investigation Could be an issue - needs investigation and removed waiting for user response Requires more information from user labels Jan 13, 2021
@jakebailey
Copy link
Member

I know there's sort of a question as to whether or not __ should be exempt from Final (I'd argue it should), but the single underscore bit appears to be a bug.

@gvanrossum
Copy link

The __ prefix translates to name mangling (C.__foo really is a variable named _C__foo) so it really should be exempt. Agree that the single _ appears to be a bug.

@erictraut
Copy link
Contributor

I've updated the logic in pyright to exempt private (double underscored) symbols from this check. @gvanrossum, you can decide whether to update PEP 591 to reflect this exemption. Also, it appears that mypy may need to also apply this fix.

I've also fixed the logic for single-underscore methods.

@erictraut erictraut added fixed in next version (main) A fix has been implemented and will appear in an upcoming version and removed needs investigation Could be an issue - needs investigation labels Jan 14, 2021
@gvanrossum
Copy link

I don't see why PEP 591 should be updated -- the two __foo symbols are unrelated, by virtue of the language definition for private variable name mangling.

@erictraut
Copy link
Contributor

That logic makes sense, yet both pyright and mypy maintainers missed this point (or came to different conclusions) because PEP 591 didn't say anything on the topic.

@gvanrossum
Copy link

gvanrossum commented Jan 14, 2021 via email

@jakebailey
Copy link
Member

This issue has been fixed in version 2021.1.2, which we've just released. You can find the changelog here: https://github.com/microsoft/pylance-release/blob/main/CHANGELOG.md#202112-20-january-2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working fixed in next version (main) A fix has been implemented and will appear in an upcoming version
Projects
None yet
Development

No branches or pull requests

5 participants