Repository: python/mypy

Issue:
Crash on double inheritance
The following code:

``` python
from typing import Dict

class DifferentDict(dict, Dict[str, str]):

    def _len(self) -> int: ...
    __len__ = _len
```

crashes mypy with an internal error. (instead of just reporting the duplicate ancestor class).



Discussion:

Resolving patch:
diff --git a/mypy/semanal.py b/mypy/semanal.py
--- a/mypy/semanal.py
+++ b/mypy/semanal.py
@@ -778,7 +778,8 @@ def analyze_base_classes(self, defn: ClassDef) -> None:
         # the bases of defn include classes imported from other
         # modules in an import loop. We'll recompute it in ThirdPass.
         if not self.verify_base_classes(defn):
-            defn.info.mro = []
+            # Give it an MRO consisting of just the class itself and object.
+            defn.info.mro = [defn.info, self.object_type().type]
             return
         calculate_class_mro(defn, self.fail)
         # If there are cyclic imports, we may be missing 'object' in
@@ -804,16 +805,16 @@ def verify_base_classes(self, defn: ClassDef) -> bool:
         for base in info.bases:
             baseinfo = base.type
             if self.is_base_class(info, baseinfo):
-                self.fail('Cycle in inheritance hierarchy', defn)
+                self.fail('Cycle in inheritance hierarchy', defn, blocker=True)
                 # Clear bases to forcefully get rid of the cycle.
                 info.bases = []
             if baseinfo.fullname() == 'builtins.bool':
                 self.fail("'%s' is not a valid base class" %
-                          baseinfo.name(), defn)
+                          baseinfo.name(), defn, blocker=True)
                 return False
         dup = find_duplicate(info.direct_base_classes())
         if dup:
-            self.fail('Duplicate base class "%s"' % dup.name(), defn)
+            self.fail('Duplicate base class "%s"' % dup.name(), defn, blocker=True)
             return False
         return True
 


Test patch:
diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test
--- a/test-data/unit/check-classes.test
+++ b/test-data/unit/check-classes.test
@@ -1751,8 +1751,8 @@ UserType = User  # type: Type[User]
 def f(a: type) -> int:
     return 1
 @overload
-def f(a: int) -> str: 
-    return "a" 
+def f(a: int) -> str:
+    return "a"
 
 reveal_type(f(User))  # E: Revealed type is 'builtins.int'
 reveal_type(f(UserType))  # E: Revealed type is 'builtins.int'
@@ -1768,13 +1768,13 @@ UserType = User  # type: Type[User]
 
 @overload
 def f(a: User) -> User:
-    return User() 
+    return User()
 @overload
 def f(a: Type[User]) -> int:
     return 1
 @overload
-def f(a: int) -> str: 
-    return "a" 
+def f(a: int) -> str:
+    return "a"
 
 reveal_type(f(User))  # E: Revealed type is 'builtins.int'
 reveal_type(f(UserType))  # E: Revealed type is 'builtins.int'
@@ -1795,7 +1795,7 @@ def f(a: User) -> Type[User]:
 def f(a: Type[User]) -> User:
     return a()
 @overload
-def f(a: int) -> Type[User]: 
+def f(a: int) -> Type[User]:
     return User
 @overload
 def f(a: str) -> User:
@@ -1901,7 +1901,7 @@ class B: pass
 class BChild(B): pass
 
 @overload
-def f(a: Type[A]) -> int: pass 
+def f(a: Type[A]) -> int: pass
 @overload
 def f(a: Type[B]) -> str: pass
 @overload
@@ -2046,4 +2046,9 @@ int.__eq__(3, 4)
 main:33: error: Too few arguments for "__eq__" of "int"
 main:33: error: Unsupported operand types for == ("int" and "int")
 
-
+[case testMroSetAfterError]
+class C(str, str):
+    foo = 0
+    bar = foo
+[out]
+main:1: error: Duplicate base class "str"