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
Copy file name to clipboardExpand all lines: crates/ty_python_semantic/resources/mdtest/snapshots/final.md_-_`typing.Final`_-_Full_diagnostics_(174fdd8134fb325b).snap
Assignments to `Final` protocol members are also invalid, both through a protocol-typed value and
725
+
through `self` inside the protocol method body.
726
+
727
+
```py
728
+
from typing import Final, Protocol
729
+
730
+
classFoo(Protocol):
731
+
value: Final[int] =42
732
+
733
+
deffoo(self, value: int):
734
+
#TODO: should emit an invalid-assignment error
735
+
self.value = value
736
+
737
+
defbar(x: Foo, value: int):
738
+
reveal_type(x.value) # revealed: int
739
+
# error: [invalid-assignment] "Cannot assign to final attribute `value` on type `Foo`: `Final` attributes can only be assigned in the class body or `__init__`"
740
+
x.value = value
741
+
```
742
+
631
743
### Explicit `Final` redeclaration
632
744
633
745
Explicit `Final` redeclaration in the same scope is accepted (shadowing).
@@ -889,7 +1001,7 @@ python-version = "3.11"
889
1001
```
890
1002
891
1003
```py
892
-
from typing import Final, Self
1004
+
from typing import Final, Generic, Self, TypeVar
893
1005
894
1006
classClassA:
895
1007
ID4: Final[int] # OK because initialized in __init__
@@ -907,8 +1019,17 @@ class ClassB:
907
1019
def__init__(self): # Without Self annotation
908
1020
self.ID5=1# Should also be OK
909
1021
1022
+
T = TypeVar("T")
1023
+
1024
+
classClassC(Generic[T]):
1025
+
value: Final[T]
1026
+
1027
+
def__init__(self: Self, value: T):
1028
+
self.value = value
1029
+
910
1030
reveal_type(ClassA().ID4) # revealed: int
911
1031
reveal_type(ClassB().ID5) # revealed: int
1032
+
reveal_type(ClassC(1).value) # revealed: int
912
1033
```
913
1034
914
1035
## Reassignment to Final in `__init__`
@@ -1003,9 +1124,18 @@ class D:
1003
1124
1004
1125
def__init__(self, other: "D"):
1005
1126
self.y =1# OK: Assigning to self
1006
-
#TODO: Should error - assigning to non-self parameter
1007
-
# Requires tracking which parameter the base expression refers to
1008
-
other.y =2
1127
+
# error: [invalid-assignment] "Cannot assign to final attribute `y`"
1128
+
other.y =2# Error: not the implicit `self` parameter
1129
+
1130
+
# When the first parameter is not named `self`, only the first parameter
1131
+
# is treated as the implicit receiver.
1132
+
classE:
1133
+
x: Final[int]
1134
+
1135
+
def__init__(sssself, self: "E"):
1136
+
sssself.x =1# OK: first parameter is the implicit receiver
1137
+
# error: [invalid-assignment] "Cannot assign to final attribute `x`"
1138
+
self.x =2# Error: `self` is the second parameter, not the implicit receiver
0 commit comments