Skip to content

Commit 7416549

Browse files
authored
Always initialize mro in TypeInfo (#5472)
Currently the mro is left `None` to cause accesses to it before it is properly initialized to blow up more quickly. This sort of behavior doesn't play well with mypyc, and leaving it actually uninitialized causes a lot of blowups. Just always initialize mro to an empty list.
1 parent e43eb89 commit 7416549

File tree

3 files changed

+13
-25
lines changed

3 files changed

+13
-25
lines changed

mypy/nodes.py

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2174,8 +2174,7 @@ def __init__(self, names: 'SymbolTable', defn: ClassDef, module_name: str) -> No
21742174
self.module_name = module_name
21752175
self.type_vars = []
21762176
self.bases = []
2177-
# Leave self.mro uninitialized until we compute it for real,
2178-
# so we don't accidentally try to use it prematurely.
2177+
self.mro = []
21792178
self._fullname = defn.fullname
21802179
self.is_abstract = False
21812180
self.abstract_attributes = []
@@ -2202,9 +2201,6 @@ def is_generic(self) -> bool:
22022201
return len(self.type_vars) > 0
22032202

22042203
def get(self, name: str) -> 'Optional[SymbolTableNode]':
2205-
if self.mro is None: # Might be because of a previous error.
2206-
return None
2207-
22082204
for cls in self.mro:
22092205
n = cls.names.get(name)
22102206
if n:
@@ -2243,8 +2239,6 @@ def has_readable_member(self, name: str) -> bool:
22432239
return self.get(name) is not None
22442240

22452241
def get_method(self, name: str) -> Optional[FuncBase]:
2246-
if self.mro is None: # Might be because of a previous error.
2247-
return None
22482242
for cls in self.mro:
22492243
if name in cls.names:
22502244
node = cls.names[name].node
@@ -2265,8 +2259,6 @@ def calculate_metaclass_type(self) -> 'Optional[mypy.types.Instance]':
22652259
if s.declared_metaclass is not None
22662260
and s.declared_metaclass.type is not None]
22672261
for c in candidates:
2268-
if c.type.mro is None:
2269-
continue
22702262
if all(other.type in c.type.mro for other in candidates):
22712263
return c
22722264
return None
@@ -2280,10 +2272,9 @@ def has_base(self, fullname: str) -> bool:
22802272
22812273
This can be either via extension or via implementation.
22822274
"""
2283-
if self.mro:
2284-
for cls in self.mro:
2285-
if cls.fullname() == fullname:
2286-
return True
2275+
for cls in self.mro:
2276+
if cls.fullname() == fullname:
2277+
return True
22872278
return False
22882279

22892280
def direct_base_classes(self) -> 'List[TypeInfo]':

mypy/semanal.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2154,7 +2154,7 @@ def basic_new_typeinfo(self, name: str, basetype_or_fallback: Instance) -> TypeI
21542154
info = TypeInfo(SymbolTable(), class_def, self.cur_mod_id)
21552155
class_def.info = info
21562156
mro = basetype_or_fallback.type.mro
2157-
if mro is None:
2157+
if not mro:
21582158
# Forward reference, MRO should be recalculated in third pass.
21592159
mro = [basetype_or_fallback.type, self.object_type().type]
21602160
info.mro = [info] + mro
@@ -3073,7 +3073,7 @@ def lookup_qualified(self, name: str, ctx: Context,
30733073
if n:
30743074
for i in range(1, len(parts)):
30753075
if isinstance(n.node, TypeInfo):
3076-
if n.node.mro is None:
3076+
if not n.node.mro:
30773077
# We haven't yet analyzed the class `n.node`. Fall back to direct
30783078
# lookup in the names declared directly under it, without its base
30793079
# classes. This can happen when we have a forward reference to a

mypy/subtypes.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -154,16 +154,13 @@ def visit_instance(self, left: Instance) -> bool:
154154
if isinstance(right, Instance):
155155
if TypeState.is_cached_subtype_check(left, right):
156156
return True
157-
# NOTE: left.type.mro may be None in quick mode if there
158-
# was an error somewhere.
159-
if left.type.mro is not None:
160-
for base in left.type.mro:
161-
# TODO: Also pass recursively ignore_declared_variance
162-
if base._promote and is_subtype(
163-
base._promote, self.right, self.check_type_parameter,
164-
ignore_pos_arg_names=self.ignore_pos_arg_names):
165-
TypeState.record_subtype_cache_entry(left, right)
166-
return True
157+
for base in left.type.mro:
158+
# TODO: Also pass recursively ignore_declared_variance
159+
if base._promote and is_subtype(
160+
base._promote, self.right, self.check_type_parameter,
161+
ignore_pos_arg_names=self.ignore_pos_arg_names):
162+
TypeState.record_subtype_cache_entry(left, right)
163+
return True
167164
rname = right.type.fullname()
168165
# Always try a nominal check if possible,
169166
# there might be errors that a user wants to silence *once*.

0 commit comments

Comments
 (0)