[cfe] Don't find unnamed mixin application in least upper bound

InterfaceType's referring to unnamed mixin applications continuously
cause problems for backends since these might not correspond to
types supported at runtime. The LUB specification does not mention
how to handle these so it is valid skip these in the computation of
LUB.

Change-Id: I38f46bf43d5858dec473c26326b741cf36eb57d8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/145420
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
diff --git a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
index 0046492..29e6bd3 100644
--- a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
@@ -523,6 +523,10 @@
     for (int i = 0; i < nodes2.length; i++) {
       ClassHierarchyNode node = nodes2[i];
       if (node == null) continue;
+      if (node.classBuilder.cls.isAnonymousMixin) {
+        // Never find unnamed mixin application in least upper bound.
+        continue;
+      }
       if (nodes1.contains(node)) {
         DartType candidate1 = getTypeAsInstanceOf(
             type1, node.classBuilder.cls, clientLibrary, coreTypes);
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index a825e87..f858baf 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -151,6 +151,7 @@
 decrease
 decrements
 dectcem
+deduplication
 defaulting
 defintions
 deleting
@@ -163,6 +164,7 @@
 deviation
 dfast
 di
+diagnosticable
 dictionaries
 dictionary
 differences
@@ -216,6 +218,7 @@
 execute
 exercised
 exercises
+existence
 exitcode
 exiting
 expanded
diff --git a/pkg/front_end/testcases/general/mixin_application_lub.dart b/pkg/front_end/testcases/general/mixin_application_lub.dart
new file mode 100644
index 0000000..a144b92
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_application_lub.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, 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.
+
+class Diagnosticable {}
+
+// Originally the existence of this (unused) class (which has an anonymous mixin
+// that matches that of `State<T>`) caused an error in the VM's mixin
+// deduplication code. This was due to the inferred type for `var x = a ?? b`
+// was the anonymous mixin application that got removed during deduplication.
+//
+// See https://github.com/flutter/flutter/issues/55345
+class SomeClass with Diagnosticable {}
+
+class State<T> with Diagnosticable {}
+
+class StateA extends State {}
+
+class StateB extends State<int> {}
+
+StateA a = StateA();
+StateB b = StateB();
+
+foo<T>(T x) {
+  print(T);
+}
+
+main() {
+  var x = a ?? b;
+  foo(x);
+}
diff --git a/pkg/front_end/testcases/general/mixin_application_lub.dart.outline.expect b/pkg/front_end/testcases/general/mixin_application_lub.dart.outline.expect
new file mode 100644
index 0000000..cf58674
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_application_lub.dart.outline.expect
@@ -0,0 +1,70 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Diagnosticable extends core::Object {
+  synthetic constructor •() → self::Diagnosticable*
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _SomeClass&Object&Diagnosticable = core::Object with self::Diagnosticable /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_SomeClass&Object&Diagnosticable*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class SomeClass extends self::_SomeClass&Object&Diagnosticable {
+  synthetic constructor •() → self::SomeClass*
+    ;
+}
+abstract class _State&Object&Diagnosticable = core::Object with self::Diagnosticable /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_State&Object&Diagnosticable*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class State<T extends core::Object* = dynamic> extends self::_State&Object&Diagnosticable {
+  synthetic constructor •() → self::State<self::State::T*>*
+    ;
+}
+class StateA extends self::State<dynamic> {
+  synthetic constructor •() → self::StateA*
+    ;
+}
+class StateB extends self::State<core::int*> {
+  synthetic constructor •() → self::StateB*
+    ;
+}
+static field self::StateA* a;
+static field self::StateB* b;
+static method foo<T extends core::Object* = dynamic>(self::foo::T* x) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/mixin_application_lub.dart.strong.expect b/pkg/front_end/testcases/general/mixin_application_lub.dart.strong.expect
new file mode 100644
index 0000000..e277693
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_application_lub.dart.strong.expect
@@ -0,0 +1,78 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Diagnosticable extends core::Object {
+  synthetic constructor •() → self::Diagnosticable*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _SomeClass&Object&Diagnosticable = core::Object with self::Diagnosticable /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_SomeClass&Object&Diagnosticable*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class SomeClass extends self::_SomeClass&Object&Diagnosticable {
+  synthetic constructor •() → self::SomeClass*
+    : super self::_SomeClass&Object&Diagnosticable::•()
+    ;
+}
+abstract class _State&Object&Diagnosticable = core::Object with self::Diagnosticable /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_State&Object&Diagnosticable*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class State<T extends core::Object* = dynamic> extends self::_State&Object&Diagnosticable {
+  synthetic constructor •() → self::State<self::State::T*>*
+    : super self::_State&Object&Diagnosticable::•()
+    ;
+}
+class StateA extends self::State<dynamic> {
+  synthetic constructor •() → self::StateA*
+    : super self::State::•()
+    ;
+}
+class StateB extends self::State<core::int*> {
+  synthetic constructor •() → self::StateB*
+    : super self::State::•()
+    ;
+}
+static field self::StateA* a = new self::StateA::•();
+static field self::StateB* b = new self::StateB::•();
+static method foo<T extends core::Object* = dynamic>(self::foo::T* x) → dynamic {
+  core::print(self::foo::T*);
+}
+static method main() → dynamic {
+  self::Diagnosticable* x = let final self::StateA* #t1 = self::a in #t1.{self::_State&Object&Diagnosticable::==}(null) ?{self::Diagnosticable*} self::b : #t1;
+  self::foo<self::Diagnosticable*>(x);
+}
diff --git a/pkg/front_end/testcases/general/mixin_application_lub.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin_application_lub.dart.strong.transformed.expect
new file mode 100644
index 0000000..421798b
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_application_lub.dart.strong.transformed.expect
@@ -0,0 +1,78 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Diagnosticable extends core::Object {
+  synthetic constructor •() → self::Diagnosticable*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _SomeClass&Object&Diagnosticable extends core::Object implements self::Diagnosticable /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_SomeClass&Object&Diagnosticable*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class SomeClass extends self::_SomeClass&Object&Diagnosticable {
+  synthetic constructor •() → self::SomeClass*
+    : super self::_SomeClass&Object&Diagnosticable::•()
+    ;
+}
+abstract class _State&Object&Diagnosticable extends core::Object implements self::Diagnosticable /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_State&Object&Diagnosticable*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class State<T extends core::Object* = dynamic> extends self::_State&Object&Diagnosticable {
+  synthetic constructor •() → self::State<self::State::T*>*
+    : super self::_State&Object&Diagnosticable::•()
+    ;
+}
+class StateA extends self::State<dynamic> {
+  synthetic constructor •() → self::StateA*
+    : super self::State::•()
+    ;
+}
+class StateB extends self::State<core::int*> {
+  synthetic constructor •() → self::StateB*
+    : super self::State::•()
+    ;
+}
+static field self::StateA* a = new self::StateA::•();
+static field self::StateB* b = new self::StateB::•();
+static method foo<T extends core::Object* = dynamic>(self::foo::T* x) → dynamic {
+  core::print(self::foo::T*);
+}
+static method main() → dynamic {
+  self::Diagnosticable* x = let final self::StateA* #t1 = self::a in #t1.{self::_State&Object&Diagnosticable::==}(null) ?{self::Diagnosticable*} self::b : #t1;
+  self::foo<self::Diagnosticable*>(x);
+}
diff --git a/pkg/front_end/testcases/general/mixin_application_lub.dart.textual_outline.expect b/pkg/front_end/testcases/general/mixin_application_lub.dart.textual_outline.expect
new file mode 100644
index 0000000..5603659
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_application_lub.dart.textual_outline.expect
@@ -0,0 +1,14 @@
+class Diagnosticable {}
+
+class SomeClass with Diagnosticable {}
+
+class State<T> with Diagnosticable {}
+
+class StateA extends State {}
+
+class StateB extends State<int> {}
+
+StateA a = StateA();
+StateB b = StateB();
+foo<T>(T x) {}
+main() {}
diff --git a/pkg/front_end/testcases/general/mixin_application_lub.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/mixin_application_lub.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0d56a51
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_application_lub.dart.textual_outline_modelled.expect
@@ -0,0 +1,15 @@
+StateA a = StateA();
+StateB b = StateB();
+
+class Diagnosticable {}
+
+class SomeClass with Diagnosticable {}
+
+class State<T> with Diagnosticable {}
+
+class StateA extends State {}
+
+class StateB extends State<int> {}
+
+foo<T>(T x) {}
+main() {}
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index e461ce3..446a07f 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -635,8 +635,14 @@
       }
       ++i2;
       ++i1;
+      if (next.classNode.isAnonymousMixin) {
+        // Never find unnamed mixin application in least upper bound.
+        continue;
+      }
       if (next.depth != currentDepth) {
-        if (numCandidatesAtThisDepth == 1) return candidate;
+        if (numCandidatesAtThisDepth == 1) {
+          return candidate;
+        }
         currentDepth = next.depth;
         numCandidatesAtThisDepth = 0;
         candidate = null;
diff --git a/pkg/kernel/lib/verifier.dart b/pkg/kernel/lib/verifier.dart
index a826d66..5ad6c85 100644
--- a/pkg/kernel/lib/verifier.dart
+++ b/pkg/kernel/lib/verifier.dart
@@ -796,6 +796,21 @@
           " type arguments, but the class declares"
           " ${node.classNode.typeParameters.length} parameters.");
     }
+    if (node.classNode.isAnonymousMixin) {
+      if (currentParent is FunctionNode) {
+        TreeNode functionNodeParent = currentParent.parent;
+        if (functionNodeParent is Constructor ||
+            functionNodeParent is Procedure &&
+                functionNodeParent.kind == ProcedureKind.Factory) {
+          if (functionNodeParent.parent == node.classNode) {
+            // We only allow references to anonymous mixins in types as the
+            // return type of its own constructor.
+            return;
+          }
+        }
+      }
+      problem(currentParent, "Type $node references an anonymous mixin class.");
+    }
   }
 
   @override