[vm/aot] Make mixin deduplication transformation more robust wrt new mixins

Previously, mixin deduplication transformation expected that isAnonymousMixin
classes could occur only in a superclass position. After this change,
deduplication also handles (canonicalizes) isAnonymousMixin classes in
implementedTypes, as CFE uses isAnonymousMixin classes in implementedTypes
to represent superclass constraints for mixin declarations.
No other uses of isAnonymousMixin classes supported.

Fixes https://github.com/dart-lang/sdk/issues/34704

Change-Id: I8558ce53c4fb1e5a06f839fa5ec8022958d9dafd
Reviewed-on: https://dart-review.googlesource.com/c/78383
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
Auto-Submit: Alexander Markov <alexmarkov@google.com>
diff --git a/pkg/vm/lib/transformations/mixin_deduplication.dart b/pkg/vm/lib/transformations/mixin_deduplication.dart
index 68ade75..19375aa 100644
--- a/pkg/vm/lib/transformations/mixin_deduplication.dart
+++ b/pkg/vm/lib/transformations/mixin_deduplication.dart
@@ -76,8 +76,12 @@
     }
 
     if (c.supertype != null) {
-      _transformSupertype(c);
+      c.supertype = _transformSupertype(c.supertype, c, true);
     }
+    if (c.mixedInType != null) {
+      throw 'All mixins should be transformed already.';
+    }
+    transformSupertypeList(c.implementedTypes, this);
 
     if (!c.isAnonymousMixin) {
       return c;
@@ -97,18 +101,24 @@
     return c;
   }
 
-  void _transformSupertype(Class c) {
-    Class oldSuper = c.superclass;
-    if (oldSuper == null) {
-      return;
-    }
+  @override
+  Supertype visitSupertype(Supertype node) {
+    return _transformSupertype(node, null, false);
+  }
+
+  Supertype _transformSupertype(
+      Supertype supertype, Class cls, bool isSuperclass) {
+    Class oldSuper = supertype.classNode;
     Class newSuper = visitClass(oldSuper);
     if (newSuper == null) {
       Class canonicalSuper = _duplicatedMixins[oldSuper];
       assert(canonicalSuper != null);
-      c.supertype = new Supertype(canonicalSuper, c.supertype.typeArguments);
-      _correctForwardingConstructors(c, oldSuper, canonicalSuper);
+      supertype = new Supertype(canonicalSuper, supertype.typeArguments);
+      if (isSuperclass) {
+        _correctForwardingConstructors(cls, oldSuper, canonicalSuper);
+      }
     }
+    return supertype;
   }
 
   @override
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index 6c38373..5d8f770 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -159,7 +159,6 @@
 covariant_subtyping_test: RuntimeError
 generic_methods_generic_function_result_test/01: MissingCompileTimeError
 generic_no_such_method_dispatcher_test: RuntimeError # Issue 31424
-mixin_declaration/mixin_declaration_inference_valid_mixin_applications_test: DartkCrash
 web_int_literals_test/*: SkipByDesign # Test applies only to JavaScript targets
 
 [ $compiler == fasta ]
diff --git a/tests/language_2/mixin_deduplication_test.dart b/tests/language_2/mixin_deduplication_test.dart
new file mode 100644
index 0000000..f401bf1
--- /dev/null
+++ b/tests/language_2/mixin_deduplication_test.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test mixin de-duplication with new mixin syntax.
+
+import 'package:expect/expect.dart';
+
+class A {
+  int foo() => 1;
+}
+
+class B {
+  int bar() => 2;
+}
+
+abstract class C implements A, B {
+}
+
+mixin M1 on A, B {
+  int sum() => foo() + bar();
+}
+
+mixin M2 on A, B, M1 {
+  int sumX2() => sum()*2;
+}
+
+class X extends C with M1, M2 {
+  int foo() => 4;
+  int bar() => 5;
+}
+
+class Y extends C with M1, M2 {
+  int foo() => 7;
+  int bar() => 10;
+}
+
+X x = new X();
+Y y = new Y();
+
+void main() {
+  Expect.equals(9, x.sum());
+  Expect.equals(18, x.sumX2());
+  Expect.equals(17, y.sum());
+  Expect.equals(34, y.sumX2());
+}