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

mypy warns of redefinition of InitVar #16816

Closed
paw-lu opened this issue Jan 25, 2024 · 4 comments
Closed

mypy warns of redefinition of InitVar #16816

paw-lu opened this issue Jan 25, 2024 · 4 comments
Labels
bug mypy got something wrong

Comments

@paw-lu
Copy link

paw-lu commented Jan 25, 2024

Bug Report

When using an InitVar

To Reproduce

mypy playground link

import dataclasses
from dataclasses import InitVar

@dataclasses.dataclass
class Foo:
    x: InitVar[int] = 1

    def __post_init__(self, x: int) -> None:
        self._x = x

    @property
    def x(self) -> int:
        return self._x

    @x.setter
    def x(self, x: int) -> None:
        self._x = x
main.py:11: error: Name "x" already defined on line 6  [no-redef]

Expected Behavior

Since this is essentially

class Foo:
    def __init__(self, x: int) -> None:
        self._x = x

    @property
    def x(self) -> int:
        return self._x

    @x.setter
    def x(self, x: int) -> None:
        self._x = x

I think this should be ok in principle. The InitVar doesn't get "saved" as an attribute, so it's not a real redefinition?

Actual Behavior

mypy warns that the property is a redefinition.

main.py:11: error: Name "x" already defined on line 6  [no-redef]

Your Environment

  • Mypy version used: 1.8.0
  • Mypy command-line flags: --strict
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: 3.11

To be transparent, this is a rough semi-continuation of an old issue I wrote up:

@paw-lu paw-lu added the bug mypy got something wrong label Jan 25, 2024
@erictraut
Copy link

I think mypy is correct in generating an error here. You are redeclaring the type of the class-scoped symbol x, which isn't allowed. Pyright also generates an error for this condition.

If you would like to make the argument that this should be allowed, this would require a change to the Python typing spec. You could pitch your idea in the Python typing forum.

@paw-lu
Copy link
Author

paw-lu commented Jan 25, 2024

Thanks a lot for the help here (and honestly in other typing issues I've been involved in with mypy or pyright)! The following is more of a question than a pushback just so I can understand the spec better.

You are redeclaring the type of the class-scoped symbol x, which isn't allowed.

This is strictly technically correct, but in practice is this true? x is not saved as an attribute and is thrown away after initialization, and the code generated by dataclass is functionally this:

class Foo:
    def __init__(self, x: int) -> None:
        self._x = x

    @property
    def x(self) -> int:
        return self._x

    @x.setter
    def x(self, x: int) -> None:
        self._x = x

which is acceptable, and the stereotypical pattern for using properties. You are correct in that

@dataclasses.dataclass
class Foo:
    x: InitVar[int] = 1
    ...

is technically a symbol scoped to the class, but practically it's discarded, and I feel like its use here is acceptable?

@paw-lu
Copy link
Author

paw-lu commented Jan 25, 2024

Like as an end user, it seems like mypy is inconsistent here on InitVars.

  1. If you try to define an attribute with the same name as an InitVar, mypy warns you that the class has no such attribute, treating it as if it doesn't "exist"
  2. If you try to have a property of the same name (this issue), mypy warns you that you're refining it , treating it as if does "exist"

@erictraut
Copy link

@paw-lu, I think you have a reasonable argument to make, but it would be better to discuss this in the general typing forum rather than the mypy issue tracker. Such a change would ideally involve clarification in the typing spec and special-casing in type checker implementations. The typing spec is currently silent on the matter. Unless that's changed, I think type checkers are correct to treat InitVar like any other class-scoped symbol.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

No branches or pull requests

2 participants