-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Covariance is not inferred for NamedTuple and frozen Dataclasses #17623
Comments
It makes sense that variables in a NamedTuple and a frozen dataclass should be considered read-only and should therefore not cause a TypeVar to be inferred as invariant. Interestingly, Python 3.13's addition of a @dataclass(frozen=True)
class FrozenDataclassBox[T]:
value: T
def __replace__(self, *, value: T) -> Self: ... This You can see this here in the pyright playground. If you hover over However, if the python version is then changed to Python 3.13, its variance changes to invariant, and a type error is reported in the @max-muoto, I'm interested in your thoughts here since you added the support for Here are some options for us to consider:
|
I thought about synthesizing a signature like this:
(Note the addition of a default for Now, if (given However, this is invalid because TypeVar defaults may not use TypeVars from an outer scope (https://typing.readthedocs.io/en/latest/spec/generics.html#scoping-rules) and because the meaning of TypeVar defaults with function-scoped type parameters is unspecified (https://typing.readthedocs.io/en/latest/spec/generics.html#function-defaults). I tried to get around that by using a different type variable, but pyright still doesn't allow it (https://pyright-play.net/?pythonVersion=3.13&strict=true&code=GYJw9gtgBAJghgFzgYwDZwM4YKYagSwgAcwQFZEV0sBYAKFEigQE8j8A7AcwONPMw4yAfVZFs9egAF4SNIIAUjAF7YOAXgAqIAK7YAlPXlYoAMXCqOAEUrGMAITAAPANqaAugC56UX1ABucKh6nlCaknR%2BsNjAUMLCINhE6MjY8W4ATAA0YQDMUOphGe4KOKjAoeZgljZy1A7Ome45AFQ5gcHYoZr5hQB0A-pQALQAfGYWarVUgo6uPV5QA30RMDHMuAhKyABGlZPWtvVzLjtgYKju%2Bt6RfoLYImLY2zt98YnJKGnCCvo5VTUjrNGmcLlcfHcsA8EKI2M9gLs3gkkilvgoOnp1ABGP4TapTIFYE6cBDguhAA), and I don't think its behavior is incorrect. Still, perhaps a type checker could synthesize an internal signature following this approach. |
This is definitely something I didn't think of when adding this to dataclasses, but it makes sense that we'd start to hit this. I think special-casing is probably the best path forward here, I obviously don't maintain any type-checkers, but the main concern here that comes to mind is the lack of documentation around this + all of the current special casing for At least, in my experience, the more I can rely on auto-variance from 3.12 type parameters, the faster I can work with the typing system, so I think making it work correctly by default, even with special casing, is probably the best option for most users. I think it would be good to define this implicit behavior around synthesizing I do like @JelleZijlstra's idea though, I could play around with it in MyPy to see if it might work. |
from dataclasses import dataclass
@dataclass(frozen=True)
class A:
x: int | str
def get_str(self) -> str:
return ""
class B(A):
x: str
def get_str(self) -> str:
return self.x
a: A = B(x="")
five: str = a.__replace__(x=5).get_str() # 5
five.upper() # AttributeError at runtime (Of course, |
I'm running into this error trying to support Python 3.13 -- how can you suppress these errors? Since it's autogenerated so you can't add a type ignore comment and I checked the PR adding this (#17469) and it seems to add it unconditionally. Defining your own |
I see that issue #18115 was opened addressing this... cross-referencing in case that's helpful... |
The new experimental feature
NewGenericSyntax
(#15238) should infer the variance of type variables. For attributes inNamedTuple
and frozendataclass
the variance is inferred as "invariant" when it should be "covariant"(A clear and concise description of what the bug is.)
To Reproduce
I defined a generic NamedTuple and frozen dataclass with one member of type
T
. The classes should be covariant inT
. So converting fromContainer[int]
toContainer[int |None]
should be no problem.playground link
Expected Behavior
mypy
should accept all four variants of the type defActual Behavior
For
Sequence
andtuple[T, ...]
it correctly accepts the function definition.But for NamedTuple and dataclass it says
It looks like
mypy
does not think that the NamedTuple and dataclass are not covariant inT
.Your Environment
--strict
--enable-incomplete-feature=NewGenericSyntax
1.11.1
andmaster
The text was updated successfully, but these errors were encountered: