|
30 | 30 | it will reject Dict[int]. We don't do this in the second pass, |
31 | 31 | since we infer the type argument counts of classes during this |
32 | 32 | pass, and it is possible to refer to classes defined later in a |
33 | | - file, which would not have the type argument count set yet. |
| 33 | + file, which would not have the type argument count set yet. This |
| 34 | + pass also recomputes the method resolution order of each class, in |
| 35 | + case one of its bases belongs to a module involved in an import |
| 36 | + loop. |
34 | 37 |
|
35 | 38 | Semantic analysis of types is implemented in module mypy.typeanal. |
36 | 39 |
|
|
41 | 44 | """ |
42 | 45 |
|
43 | 46 | from typing import ( |
44 | | - List, Dict, Set, Tuple, cast, Any, overload, TypeVar, Union, Optional |
| 47 | + List, Dict, Set, Tuple, cast, Any, overload, TypeVar, Union, Optional, Callable |
45 | 48 | ) |
46 | 49 |
|
47 | 50 | from mypy.nodes import ( |
@@ -753,22 +756,17 @@ def analyze_base_classes(self, defn: ClassDef) -> None: |
753 | 756 | obj = self.object_type() |
754 | 757 | defn.base_types.insert(0, obj) |
755 | 758 | defn.info.bases = defn.base_types |
| 759 | + # Calculate the MRO. It might be incomplete at this point if |
| 760 | + # the bases of defn include classes imported from other |
| 761 | + # modules in an import loop. We'll recompute it in ThirdPass. |
756 | 762 | if not self.verify_base_classes(defn): |
757 | 763 | defn.info.mro = [] |
758 | 764 | return |
759 | | - try: |
760 | | - defn.info.calculate_mro() |
761 | | - except MroError: |
762 | | - self.fail("Cannot determine consistent method resolution order " |
763 | | - '(MRO) for "%s"' % defn.name, defn) |
764 | | - defn.info.mro = [] |
765 | | - else: |
766 | | - # If there are cyclic imports, we may be missing 'object' in |
767 | | - # the MRO. Fix MRO if needed. |
768 | | - if defn.info.mro[-1].fullname() != 'builtins.object': |
769 | | - defn.info.mro.append(self.object_type().type) |
770 | | - # The property of falling back to Any is inherited. |
771 | | - defn.info.fallback_to_any = any(baseinfo.fallback_to_any for baseinfo in defn.info.mro) |
| 765 | + calculate_class_mro(defn, self.fail) |
| 766 | + # If there are cyclic imports, we may be missing 'object' in |
| 767 | + # the MRO. Fix MRO if needed. |
| 768 | + if defn.info.mro and defn.info.mro[-1].fullname() != 'builtins.object': |
| 769 | + defn.info.mro.append(self.object_type().type) |
772 | 770 |
|
773 | 771 | def expr_to_analyzed_type(self, expr: Node) -> Type: |
774 | 772 | if isinstance(expr, CallExpr): |
@@ -2437,6 +2435,12 @@ def visit_func_def(self, fdef: FuncDef) -> None: |
2437 | 2435 | def visit_class_def(self, tdef: ClassDef) -> None: |
2438 | 2436 | for type in tdef.info.bases: |
2439 | 2437 | self.analyze(type) |
| 2438 | + # Recompute MRO now that we have analyzed all modules, to pick |
| 2439 | + # up superclasses of bases imported from other modules in an |
| 2440 | + # import loop. (Only do so if we succeeded the first time.) |
| 2441 | + if tdef.info.mro: |
| 2442 | + tdef.info.mro = [] # Force recomputation |
| 2443 | + calculate_class_mro(tdef, self.fail) |
2440 | 2444 | super().visit_class_def(tdef) |
2441 | 2445 |
|
2442 | 2446 | def visit_decorator(self, dec: Decorator) -> None: |
@@ -2569,6 +2573,17 @@ def refers_to_class_or_function(node: Node) -> bool: |
2569 | 2573 | OverloadedFuncDef))) |
2570 | 2574 |
|
2571 | 2575 |
|
| 2576 | +def calculate_class_mro(defn: ClassDef, fail: Callable[[str, Context], None]) -> None: |
| 2577 | + try: |
| 2578 | + defn.info.calculate_mro() |
| 2579 | + except MroError: |
| 2580 | + fail("Cannot determine consistent method resolution order " |
| 2581 | + '(MRO) for "%s"' % defn.name, defn) |
| 2582 | + defn.info.mro = [] |
| 2583 | + # The property of falling back to Any is inherited. |
| 2584 | + defn.info.fallback_to_any = any(baseinfo.fallback_to_any for baseinfo in defn.info.mro) |
| 2585 | + |
| 2586 | + |
2572 | 2587 | def find_duplicate(list: List[T]) -> T: |
2573 | 2588 | """If the list has duplicates, return one of the duplicates. |
2574 | 2589 |
|
|
0 commit comments