Skip to content

Commit 0dfd460

Browse files
authored
Revert "For class variables, lookup type in base classes (#1338, #2022, #2211)"
1 parent 5ad40b8 commit 0dfd460

File tree

6 files changed

+25
-234
lines changed

6 files changed

+25
-234
lines changed

mypy/checker.py

+2-15
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,14 @@
3636
from mypy.sametypes import is_same_type
3737
from mypy.messages import MessageBuilder
3838
import mypy.checkexpr
39-
from mypy.checkmember import (
40-
map_type_from_supertype, bind_self, erase_to_bound, find_type_from_bases
41-
)
39+
from mypy.checkmember import map_type_from_supertype, bind_self, erase_to_bound
4240
from mypy import messages
4341
from mypy.subtypes import (
4442
is_subtype, is_equivalent, is_proper_subtype, is_more_precise, restrict_subtype_away,
4543
is_subtype_ignoring_tvars
4644
)
4745
from mypy.maptype import map_instance_to_supertype
48-
from mypy.typevars import fill_typevars
49-
from mypy.semanal import set_callable_name, refers_to_fullname
46+
from mypy.semanal import fill_typevars, set_callable_name, refers_to_fullname
5047
from mypy.erasetype import erase_typevars
5148
from mypy.expandtype import expand_type
5249
from mypy.visitor import NodeVisitor
@@ -1116,16 +1113,6 @@ def check_assignment(self, lvalue: Lvalue, rvalue: Expression, infer_lvalue_type
11161113
else:
11171114
lvalue_type, index_lvalue, inferred = self.check_lvalue(lvalue)
11181115
if lvalue_type:
1119-
if isinstance(lvalue, NameExpr):
1120-
base_type = find_type_from_bases(lvalue)
1121-
1122-
# If a type is known, validate the type is a subtype of the base type
1123-
if base_type:
1124-
self.check_subtype(lvalue_type, base_type, lvalue,
1125-
messages.INCOMPATIBLE_TYPES_IN_ASSIGNMENT,
1126-
'expression has type',
1127-
'variable has type')
1128-
11291116
if isinstance(lvalue_type, PartialType) and lvalue_type.type is None:
11301117
# Try to infer a proper type for a variable with a partial None type.
11311118
rvalue_type = self.accept(rvalue)

mypy/checkexpr.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
from mypy.checkstrformat import StringFormatterChecker
3939
from mypy.expandtype import expand_type
4040
from mypy.util import split_module_names
41-
from mypy.typevars import fill_typevars
41+
from mypy.semanal import fill_typevars
4242

4343
from mypy import experiments
4444

mypy/checkmember.py

+2-36
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,14 @@
77
Overloaded, TypeVarType, UnionType, PartialType,
88
DeletedType, NoneTyp, TypeType, function_type
99
)
10-
from mypy.nodes import (
11-
TypeInfo, FuncBase, Var, FuncDef, SymbolNode, Context, MypyFile, MDEF,
12-
NameExpr
13-
)
10+
from mypy.nodes import TypeInfo, FuncBase, Var, FuncDef, SymbolNode, Context, MypyFile
1411
from mypy.nodes import ARG_POS, ARG_STAR, ARG_STAR2
1512
from mypy.nodes import Decorator, OverloadedFuncDef
1613
from mypy.messages import MessageBuilder
1714
from mypy.maptype import map_instance_to_supertype
1815
from mypy.expandtype import expand_type_by_instance, expand_type
1916
from mypy.infer import infer_type_arguments
20-
from mypy.typevars import fill_typevars, has_no_typevars
17+
from mypy.semanal import fill_typevars
2118
from mypy import messages
2219
from mypy import subtypes
2320
MYPY = False
@@ -619,34 +616,3 @@ def erase_to_bound(t: Type):
619616
if isinstance(t.item, TypeVarType):
620617
return TypeType(t.item.upper_bound)
621618
return t
622-
623-
624-
def find_type_from_bases(e: NameExpr):
625-
"""For a NameExpr that is part of a class, walk all base classes and try
626-
to find the first class that defines a Type for the same name."""
627-
628-
expr_node = e.node
629-
if not (isinstance(expr_node, Var) and e.kind == MDEF and
630-
len(expr_node.info.bases) > 0):
631-
return None
632-
633-
expr_name = expr_node.name()
634-
expr_base = expr_node.info.bases[0]
635-
636-
for base in expr_node.info.mro[1:]:
637-
base_var = base.names.get(expr_name)
638-
if base_var and base_var.type:
639-
if has_no_typevars(base_var.type):
640-
base_type = base_var.type
641-
else:
642-
itype = map_instance_to_supertype(expr_base, base)
643-
base_type = expand_type_by_instance(base_var.type, itype)
644-
645-
if isinstance(base_type, CallableType):
646-
# If we are a property, return the Type of the return value, not the Callable
647-
if isinstance(base_var.node, Decorator) and base_var.node.func.is_property:
648-
base_type = base_type.ret_type
649-
elif isinstance(base_var.node, FuncDef) and base_var.node.is_property:
650-
base_type = base_type.ret_type
651-
652-
return base_type

mypy/semanal.py

+20-8
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@
4848
List, Dict, Set, Tuple, cast, TypeVar, Union, Optional, Callable
4949
)
5050

51-
from mypy.checkmember import find_type_from_bases
5251
from mypy.nodes import (
5352
MypyFile, TypeInfo, Node, AssignmentStmt, FuncDef, OverloadedFuncDef,
5453
ClassDef, Var, GDEF, MODULE_REF, FuncItem, Import, Expression, Lvalue,
@@ -68,7 +67,6 @@
6867
IntExpr, FloatExpr, UnicodeExpr, EllipsisExpr, TempNode,
6968
COVARIANT, CONTRAVARIANT, INVARIANT, UNBOUND_IMPORTED, LITERAL_YES,
7069
)
71-
from mypy.typevars import has_no_typevars, fill_typevars
7270
from mypy.visitor import NodeVisitor
7371
from mypy.traverser import TraverserVisitor
7472
from mypy.errors import Errors, report_internal_error
@@ -81,6 +79,7 @@
8179
from mypy.typeanal import TypeAnalyser, TypeAnalyserPass3, analyze_type_alias
8280
from mypy.exprtotype import expr_to_unanalyzed_type, TypeTranslationError
8381
from mypy.sametypes import is_same_type
82+
from mypy.erasetype import erase_typevars
8483
from mypy.options import Options
8584
from mypy import join
8685

@@ -1163,15 +1162,11 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> None:
11631162
s.type = self.anal_type(s.type, allow_tuple_literal)
11641163
else:
11651164
# For simple assignments, allow binding type aliases.
1166-
# Also use the type of the base class if available, or
1167-
# set the type if the rvalue is a simple literal.
1165+
# Also set the type if the rvalue is a simple literal.
11681166
if (s.type is None and len(s.lvalues) == 1 and
11691167
isinstance(s.lvalues[0], NameExpr)):
11701168
if s.lvalues[0].is_def:
1171-
s.type = find_type_from_bases(s.lvalues[0])
1172-
if s.type is None:
1173-
s.type = self.analyze_simple_literal_type(s.rvalue)
1174-
1169+
s.type = self.analyze_simple_literal_type(s.rvalue)
11751170
res = analyze_type_alias(s.rvalue,
11761171
self.lookup_qualified,
11771172
self.lookup_fully_qualified,
@@ -3135,6 +3130,19 @@ def builtin_type(self, name: str, args: List[Type] = None) -> Instance:
31353130
return Instance(sym.node, args or [])
31363131

31373132

3133+
def fill_typevars(typ: TypeInfo) -> Union[Instance, TupleType]:
3134+
"""For a non-generic type, return instance type representing the type.
3135+
For a generic G type with parameters T1, .., Tn, return G[T1, ..., Tn].
3136+
"""
3137+
tv = [] # type: List[Type]
3138+
for i in range(len(typ.type_vars)):
3139+
tv.append(TypeVarType(typ.defn.type_vars[i]))
3140+
inst = Instance(typ, tv)
3141+
if typ.tuple_type is None:
3142+
return inst
3143+
return typ.tuple_type.copy_modified(fallback=inst)
3144+
3145+
31383146
def replace_implicit_first_type(sig: FunctionLike, new: Type) -> FunctionLike:
31393147
if isinstance(sig, CallableType):
31403148
return sig.copy_modified(arg_types=[new] + sig.arg_types[1:])
@@ -3506,3 +3514,7 @@ def find_fixed_callable_return(expr: Expression) -> Optional[CallableType]:
35063514
if isinstance(t.ret_type, CallableType):
35073515
return t.ret_type
35083516
return None
3517+
3518+
3519+
def has_no_typevars(typ: Type) -> bool:
3520+
return is_same_type(typ, erase_typevars(typ))

mypy/typevars.py

-24
This file was deleted.

test-data/unit/check-classes.test

-150
Original file line numberDiff line numberDiff line change
@@ -2123,153 +2123,3 @@ class B(object, A): # E: Cannot determine consistent method resolution order (MR
21232123
# flags: --fast-parser
21242124
class C(metaclass=int()): # E: Dynamic metaclass not supported for 'C'
21252125
pass
2126-
2127-
[case testVariableSubclass]
2128-
class A:
2129-
a = 1 # type: int
2130-
class B(A):
2131-
a = 1
2132-
[out]
2133-
2134-
[case testVariableSubclassAssignMismatch]
2135-
class A:
2136-
a = 1 # type: int
2137-
class B(A):
2138-
a = "a"
2139-
[out]
2140-
main: note: In class "B":
2141-
main:4: error: Incompatible types in assignment (expression has type "str", variable has type "int")
2142-
2143-
[case testVariableSubclassAssignment]
2144-
class A:
2145-
a = None # type: int
2146-
class B(A):
2147-
def __init__(self) -> None:
2148-
self.a = "a"
2149-
[out]
2150-
main: note: In member "__init__" of class "B":
2151-
main:5: error: Incompatible types in assignment (expression has type "str", variable has type "int")
2152-
2153-
[case testVariableSubclassTypeOverwrite]
2154-
class A:
2155-
a = None # type: int
2156-
class B(A):
2157-
a = None # type: str
2158-
class C(B):
2159-
a = "a"
2160-
[out]
2161-
main: note: In class "B":
2162-
main:4: error: Incompatible types in assignment (expression has type "str", variable has type "int")
2163-
2164-
[case testVariableSubclassTypeOverwriteImplicit]
2165-
class A:
2166-
a = 1
2167-
class B(A):
2168-
a = None # type: str
2169-
[out]
2170-
main: note: In class "B":
2171-
main:4: error: Incompatible types in assignment (expression has type "str", variable has type "int")
2172-
2173-
[case testVariableSuperUsage]
2174-
class A:
2175-
a = [] # type: list
2176-
class B(A):
2177-
a = [1, 2]
2178-
class C(B):
2179-
a = B.a + [3]
2180-
[builtins fixtures/list.pyi]
2181-
[out]
2182-
2183-
[case testVariableRvalue]
2184-
class A:
2185-
a = None
2186-
class B(A):
2187-
a = 1
2188-
class C(B):
2189-
a = "a"
2190-
[out]
2191-
main: note: In class "A":
2192-
main:2: error: Need type annotation for variable
2193-
main: note: In class "C":
2194-
main:6: error: Incompatible types in assignment (expression has type "str", variable has type "int")
2195-
2196-
[case testVariableTypeVar]
2197-
from typing import TypeVar, Generic
2198-
T = TypeVar('T')
2199-
class A(Generic[T]):
2200-
a = None # type: T
2201-
class B(A[int]):
2202-
a = 1
2203-
2204-
[case testVariableTypeVarInvalid]
2205-
from typing import TypeVar, Generic
2206-
T = TypeVar('T')
2207-
class A(Generic[T]):
2208-
a = None # type: T
2209-
class B(A[int]):
2210-
a = "abc"
2211-
[out]
2212-
main: note: In class "B":
2213-
main:6: error: Incompatible types in assignment (expression has type "str", variable has type "int")
2214-
2215-
[case testVariableTypeVarIndirectly]
2216-
from typing import TypeVar, Generic
2217-
T = TypeVar('T')
2218-
class A(Generic[T]):
2219-
a = None # type: T
2220-
class B(A[int]):
2221-
pass
2222-
class C(B):
2223-
a = "a"
2224-
[out]
2225-
main: note: In class "C":
2226-
main:8: error: Incompatible types in assignment (expression has type "str", variable has type "int")
2227-
2228-
[case testVariableTypeVarList]
2229-
from typing import List, TypeVar, Generic
2230-
T = TypeVar('T')
2231-
class A(Generic[T]):
2232-
a = None # type: List[T]
2233-
b = None # type: List[T]
2234-
class B(A[int]):
2235-
a = [1]
2236-
b = ['']
2237-
[builtins fixtures/list.pyi]
2238-
[out]
2239-
main: note: In class "B":
2240-
main:8: error: List item 0 has incompatible type "str"
2241-
2242-
[case testVariableMethod]
2243-
class A:
2244-
def a(self) -> None: pass
2245-
b = 1
2246-
class B(A):
2247-
a = 1
2248-
def b(self) -> None: pass
2249-
[out]
2250-
main: note: In class "B":
2251-
main:5: error: Incompatible types in assignment (expression has type "int", variable has type Callable[[A], None])
2252-
main:6: error: Signature of "b" incompatible with supertype "A"
2253-
2254-
[case testVariableProperty]
2255-
class A:
2256-
@property
2257-
def a(self) -> bool: pass
2258-
class B(A):
2259-
a = None # type: bool
2260-
class C(A):
2261-
a = True
2262-
class D(A):
2263-
a = 1
2264-
[builtins fixtures/property.pyi]
2265-
[out]
2266-
main: note: In class "D":
2267-
main:9: error: Incompatible types in assignment (expression has type "int", variable has type "bool")
2268-
2269-
[case testVariableOverwriteAny]
2270-
from typing import Any
2271-
class A:
2272-
a = 1
2273-
class B(A):
2274-
a = 'x' # type: Any
2275-
[out]

0 commit comments

Comments
 (0)