Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 3 additions & 18 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -3209,7 +3209,7 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> None:
# as X | Y.
if not (s.is_alias_def and self.is_stub):
with self.enter_final_context(s.is_final_def):
self.check_assignment(s.lvalues[-1], s.rvalue, s.type is None, s.new_syntax)
self.check_assignment(s.lvalues[-1], s.rvalue, s.type is None)

if s.is_alias_def:
self.check_type_alias_rvalue(s)
Expand Down Expand Up @@ -3257,11 +3257,7 @@ def check_type_alias_rvalue(self, s: AssignmentStmt) -> None:
self.store_type(s.lvalues[-1], alias_type)

def check_assignment(
self,
lvalue: Lvalue,
rvalue: Expression,
infer_lvalue_type: bool = True,
new_syntax: bool = False,
self, lvalue: Lvalue, rvalue: Expression, infer_lvalue_type: bool = True
) -> None:
"""Type check a single assignment: lvalue = rvalue."""
if isinstance(lvalue, (TupleExpr, ListExpr)):
Expand Down Expand Up @@ -3339,15 +3335,6 @@ def check_assignment(
# We are replacing partial<None> now, so the variable type
# should remain optional.
self.set_inferred_type(var, lvalue, make_optional_type(fallback))
elif (
is_literal_none(rvalue)
and isinstance(lvalue, NameExpr)
and isinstance(lvalue.node, Var)
and lvalue.node.is_initialized_in_class
and not new_syntax
):
# Allow None's to be assigned to class variables with non-Optional types.
rvalue_type = lvalue_type
elif (
isinstance(lvalue, MemberExpr) and lvalue.kind is None
): # Ignore member access to modules
Expand Down Expand Up @@ -5108,9 +5095,7 @@ def visit_operator_assignment_stmt(self, s: OperatorAssignmentStmt) -> None:
# There is no __ifoo__, treat as x = x <foo> y
expr = OpExpr(s.op, s.lvalue, s.rvalue)
expr.set_line(s)
self.check_assignment(
lvalue=s.lvalue, rvalue=expr, infer_lvalue_type=True, new_syntax=False
)
self.check_assignment(lvalue=s.lvalue, rvalue=expr, infer_lvalue_type=True)
self.check_final(s)

def visit_assert_stmt(self, s: AssertStmt) -> None:
Expand Down
2 changes: 1 addition & 1 deletion mypyc/test-data/irbuild-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -1051,7 +1051,7 @@ class B(A):
y = LOL
z: Optional[str] = None
b = True
bogus = None # type: int
bogus = None # type: int # type: ignore
[out]
def A.lol(self):
self :: __main__.A
Expand Down
2 changes: 1 addition & 1 deletion mypyc/test-data/run-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -1126,7 +1126,7 @@ class B(A):
y = LOL
z = None # type: Optional[str]
b = True
bogus = None # type: int
bogus = None # type: int # type: ignore

def g() -> None:
a = A()
Expand Down
2 changes: 1 addition & 1 deletion mypyc/test-data/run-traits.test
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ from mypy_extensions import trait

@trait
class Base:
x = None # type: int
x: int

class Plugin(Base):
def __init__(self) -> None:
Expand Down
30 changes: 15 additions & 15 deletions test-data/unit/check-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -1322,7 +1322,7 @@ main:2: error: Need type annotation for "x" (hint: "x: list[<type>] = ...")
from typing import Generic, TypeVar
T = TypeVar('T')
class A(Generic[T]):
x = None # type: T
x: T
A.x # E: Access to generic instance variables via class is ambiguous
A[int].x # E: Access to generic instance variables via class is ambiguous
[targets __main__]
Expand All @@ -1332,7 +1332,7 @@ from typing import Generic, List, TypeVar, Union
T = TypeVar('T')
U = TypeVar('U')
class A(Generic[T, U]):
x = None # type: Union[T, List[U]]
x: Union[T, List[U]]
A.x # E: Access to generic instance variables via class is ambiguous
A[int, int].x # E: Access to generic instance variables via class is ambiguous
[builtins fixtures/list.pyi]
Expand Down Expand Up @@ -4562,7 +4562,7 @@ main:4: error: Incompatible types in assignment (expression has type "str", base

[case testVariableSubclassAssignment]
class A:
a = None # type: int
a: int
class B(A):
def __init__(self) -> None:
self.a = "a"
Expand All @@ -4571,9 +4571,9 @@ main:5: error: Incompatible types in assignment (expression has type "str", vari

[case testVariableSubclassTypeOverwrite]
class A:
a = None # type: int
a: int
class B(A):
a = None # type: str
a: str
class C(B):
a = "a"
[out]
Expand All @@ -4583,7 +4583,7 @@ main:4: error: Incompatible types in assignment (expression has type "str", base
class A:
a = 1
class B(A):
a = None # type: str
a: str
[out]
main:4: error: Incompatible types in assignment (expression has type "str", base class "A" defined the type as "int")

Expand All @@ -4600,7 +4600,7 @@ class C(B):
[case testClassAllBases]
from typing import Union
class A:
a = None # type: Union[int, str]
a: Union[int, str]
class B(A):
a = 1
class C(B):
Expand All @@ -4614,15 +4614,15 @@ main:7: error: Incompatible types in assignment (expression has type "str", base
from typing import TypeVar, Generic
T = TypeVar('T')
class A(Generic[T]):
a = None # type: T
a: T
class B(A[int]):
a = 1

[case testVariableTypeVarInvalid]
from typing import TypeVar, Generic
T = TypeVar('T')
class A(Generic[T]):
a = None # type: T
a: T
class B(A[int]):
a = "abc"
[out]
Expand All @@ -4632,7 +4632,7 @@ main:6: error: Incompatible types in assignment (expression has type "str", base
from typing import TypeVar, Generic
T = TypeVar('T')
class A(Generic[T]):
a = None # type: T
a: T
class B(A[int]):
pass
class C(B):
Expand All @@ -4644,8 +4644,8 @@ main:8: error: Incompatible types in assignment (expression has type "str", base
from typing import List, TypeVar, Generic
T = TypeVar('T')
class A(Generic[T]):
a = None # type: List[T]
b = None # type: List[T]
a: List[T]
b: List[T]
class B(A[int]):
a = [1]
b = ['']
Expand All @@ -4670,7 +4670,7 @@ class A:
@property
def a(self) -> bool: pass
class B(A):
a = None # type: bool
a: bool
class C(A):
a = True
class D(A):
Expand Down Expand Up @@ -4751,7 +4751,7 @@ main:7: error: Incompatible types in assignment (expression has type "Callable[[
[case testClassSpec]
from typing import Callable
class A():
b = None # type: Callable[[int], int]
b: Callable[[int], int]
class B(A):
def c(self, a: int) -> int: pass
b = c
Expand All @@ -4761,7 +4761,7 @@ reveal_type(B().b) # N: Revealed type is "def (a: builtins.int) -> builtins.int
[case testClassSpecError]
from typing import Callable
class A():
b = None # type: Callable[[int], int]
b: Callable[[int], int]
class B(A):
def c(self, a: str) -> int: pass
b = c # E: Incompatible types in assignment (expression has type "Callable[[str], int]", base class "A" defined the type as "Callable[[int], int]")
Expand Down
38 changes: 19 additions & 19 deletions test-data/unit/check-classvar.test
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ main:6: error: Cannot assign to class variable "x" via instance
[case testOverrideOnSelf]
from typing import ClassVar
class A:
x = None # type: ClassVar[int]
x: ClassVar[int]
def __init__(self) -> None:
self.x = 0
[out]
Expand All @@ -34,7 +34,7 @@ main:5: error: Cannot assign to class variable "x" via instance
[case testOverrideOnSelfInSubclass]
from typing import ClassVar
class A:
x = None # type: ClassVar[int]
x: ClassVar[int]
class B(A):
def __init__(self) -> None:
self.x = 0
Expand Down Expand Up @@ -79,7 +79,7 @@ class A:
class B:
pass
class C:
x = None # type: ClassVar[A]
x: ClassVar[A]
C.x = B()
[out]
main:8: error: Incompatible types in assignment (expression has type "B", variable has type "A")
Expand All @@ -97,7 +97,7 @@ C.x = B()
[case testRevealType]
from typing import ClassVar
class A:
x = None # type: ClassVar[int]
x: ClassVar[int]
reveal_type(A.x)
[out]
main:4: note: Revealed type is "builtins.int"
Expand All @@ -114,9 +114,9 @@ main:5: note: Revealed type is "builtins.int"
[case testAssignmentOnUnion]
from typing import ClassVar, Union
class A:
x = None # type: int
x: int
class B:
x = None # type: ClassVar[int]
x: ClassVar[int]
c = A() # type: Union[A, B]
c.x = 1
[out]
Expand All @@ -125,7 +125,7 @@ main:7: error: Cannot assign to class variable "x" via instance
[case testAssignmentOnInstanceFromType]
from typing import ClassVar, Type
class A:
x = None # type: ClassVar[int]
x: ClassVar[int]
def f(a: Type[A]) -> None:
a().x = 0
[out]
Expand All @@ -134,7 +134,7 @@ main:5: error: Cannot assign to class variable "x" via instance
[case testAssignmentOnInstanceFromSubclassType]
from typing import ClassVar, Type
class A:
x = None # type: ClassVar[int]
x: ClassVar[int]
class B(A):
pass
def f(b: Type[B]) -> None:
Expand All @@ -145,7 +145,7 @@ main:7: error: Cannot assign to class variable "x" via instance
[case testClassVarWithList]
from typing import ClassVar, List
class A:
x = None # type: ClassVar[List[int]]
x: ClassVar[List[int]]
A.x = ['a']
A().x.append(1)
A().x.append('')
Expand All @@ -157,7 +157,7 @@ main:6: error: Argument 1 to "append" of "list" has incompatible type "str"; exp
[case testClassVarWithUnion]
from typing import ClassVar, Union
class A:
x = None # type: ClassVar[Union[int, str]]
x: ClassVar[Union[int, str]]
class B:
pass
A.x = 0
Expand All @@ -174,26 +174,26 @@ class A: pass
class B: pass
class C: pass
class D:
x = None # type: ClassVar[Union[A, B, C]]
x: ClassVar[Union[A, B, C]]
class E(D):
x = None # type: ClassVar[Union[A, B]]
x: ClassVar[Union[A, B]]

[case testOverrideWithExtendedUnion]
from typing import ClassVar, Union
class A: pass
class B: pass
class C: pass
class D:
x = None # type: ClassVar[Union[A, B]]
x: ClassVar[Union[A, B]]
class E(D):
x = None # type: ClassVar[Union[A, B, C]]
x: ClassVar[Union[A, B, C]]
[out]
main:8: error: Incompatible types in assignment (expression has type "A | B | C", base class "D" defined the type as "A | B")

[case testAssignmentToCallableRet]
from typing import ClassVar
class A:
x = None # type: ClassVar[int]
x: ClassVar[int]
def f() -> A:
return A()
f().x = 0
Expand All @@ -203,9 +203,9 @@ main:6: error: Cannot assign to class variable "x" via instance
[case testOverrideWithIncompatibleType]
from typing import ClassVar
class A:
x = None # type: ClassVar[int]
x: ClassVar[int]
class B(A):
x = None # type: ClassVar[str]
x: ClassVar[str]
[out]
main:5: error: Incompatible types in assignment (expression has type "str", base class "A" defined the type as "int")

Expand Down Expand Up @@ -265,7 +265,7 @@ class C(B):
from abc import ABCMeta
from typing import ClassVar
class A(metaclass=ABCMeta):
x = None # type: ClassVar[int]
x: ClassVar[int]
class B(A):
x = 0 # type: ClassVar[int]

Expand All @@ -276,7 +276,7 @@ m.A().x = 0
[file m.py]
from typing import ClassVar
class A:
x = None # type: ClassVar[int]
x: ClassVar[int]
[out]
main:2: note: Revealed type is "builtins.int"
main:3: error: Cannot assign to class variable "x" via instance
Expand Down
4 changes: 2 additions & 2 deletions test-data/unit/check-generics.test
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ if int():
b = a.v

class A(Generic[T]):
v = None # type: A[T]
v: A[T]

class B: pass
class C: pass
Expand Down Expand Up @@ -1094,7 +1094,7 @@ SameA = A[T, T]
SameB = B[T, T]

class C(Generic[T]):
a = None # type: SameA[T]
a: SameA[T]
b = SameB[T]([], [])

reveal_type(C[int]().a) # N: Revealed type is "__main__.A[builtins.int, builtins.int]"
Expand Down
10 changes: 5 additions & 5 deletions test-data/unit/check-incremental.test
Original file line number Diff line number Diff line change
Expand Up @@ -1746,9 +1746,9 @@ class A: pass
class B: pass

class X:
attr = None # type: A
attr: A
class Y:
attr = None # type: B
attr: B
class Z(X, Y): pass
[stale]
[out]
Expand Down Expand Up @@ -2064,10 +2064,10 @@ m.A().x = 0
[file m.py]
from typing import ClassVar
class A:
x = None # type: ClassVar[int]
x: ClassVar[int]
[file m.py.2]
class A:
x = None # type: int
x: int
[out1]
main:2: error: Cannot assign to class variable "x" via instance

Expand All @@ -2076,7 +2076,7 @@ import b
[file a.py]
from typing import ClassVar
class A:
x = None # type: ClassVar[int]
x: ClassVar[int]
[file b.py]
import a
[file b.py.2]
Expand Down
Loading