You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Describe the bug
In both pyright and mypy, it is possible to specify the default value for a generic self using __init__ parameter type hint or __new__ return type hint. However, when a @dataclass decorator is applied to the class, the old __init__/__new__ definition gets erased. Note that if both __new__ and __init__ are present, then pyright works correctly.
To Reproduce
fromdataclassesimportdataclassfromtypingimportGeneric, Literal, TypeVar, castT=TypeVar("T", bound=Literal["LoggedIn", "NotLoggedIn"])
@dataclass(init=False)classUser(Generic[T]):
name: str# Adding this definition will fix the problem but mypy does not require `__new__` to be added# def __new__(cls: "type[User]", name: str) -> "User[Literal['NotLoggedIn']]":# return object.__new__(cls)def__init__(self: "User[Literal['NotLoggedIn']]", name: str) ->None:
self.name=namedeflog_in(self) ->"User[Literal['LoggedIn']]":
returncast(User[Literal["LoggedIn"]], self)
defscream(self: "User[Literal['LoggedIn']]") ->None:
print(f"{self.name} screams!")
f=User("admin")
reveal_type(f)
Actual behavior reveal_type(f) outputs Type of "f" is "User[Unknown]"
Expected behavior reveal_type(f) must output Type of "f" is "User[Literal['NotLoggedIn']]"
VS Code extension or command-line
VS Code extension: v2022.12.20
The technique of using a self annotation in an __init__ method to influence the type of the constructed class instance is not standard and is fraught with problems. It has never been specified anywhere, so these issues have never been explored or discussed, and it's difficult to say what its specific behavior should be and what circumstances it should or should not handle. It's something that mypy implemented and typeshed stubs adopted in a limited form to handle a specific situation where the type of a constructed object varies depending on its input parameters.
Because this mechanism is not documented or specified anywhere, I needed to make certain assumptions when implementing it in pyright. One of the assumptions I made was that it would be used only with overloads. This is a reasonable assumption given the use case that motivated the original implementation in mypy.
In your sample above, you are attempting to use this mechanism without an overload. That means the type of the constructed object does not vary depending on the input parameter types, and the only type that you can construct is User[Literal['LoggedIn']]. In such a case, it doesn't make sense to use generics because there is only one type argument that is legal here. You cannot construct an instance with any other type, so the class isn't really generic.
I'm going to close this issue because I don't think it's a bug in pyright.
Describe the bug
In both pyright and mypy, it is possible to specify the default value for a generic self using
__init__
parameter type hint or__new__
return type hint. However, when a@dataclass
decorator is applied to the class, the old__init__
/__new__
definition gets erased. Note that if both__new__
and__init__
are present, then pyright works correctly.To Reproduce
Actual behavior
reveal_type(f)
outputsType of "f" is "User[Unknown]"
Expected behavior
reveal_type(f)
must outputType of "f" is "User[Literal['NotLoggedIn']]"
VS Code extension or command-line
VS Code extension:
v2022.12.20
Additional context
The text was updated successfully, but these errors were encountered: