Mixins have no static members

Change-Id: I93b43ad2d58ab2804ed7deafeadb6346eade9eab
Reviewed-on: https://dart-review.googlesource.com/c/91481
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Peter von der Ahé <ahe@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 c0575b3..d69df1a 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
@@ -280,7 +280,7 @@
         mixin = named.mixedInType.declaration;
       }
       if (mixin is KernelClassBuilder) {
-        scope = mixin.scope;
+        scope = mixin.scope.computeMixinScope();
       }
     }
 
diff --git a/pkg/front_end/lib/src/fasta/scope.dart b/pkg/front_end/lib/src/fasta/scope.dart
index b7c8584..c74cc99 100644
--- a/pkg/front_end/lib/src/fasta/scope.dart
+++ b/pkg/front_end/lib/src/fasta/scope.dart
@@ -284,6 +284,36 @@
     });
     return nestingLevel;
   }
+
+  Scope computeMixinScope() {
+    List<String> names = this.local.keys.toList();
+    Map<String, Declaration> local = <String, Declaration>{};
+    bool needsCopy = false;
+    for (int i = 0; i < names.length; i++) {
+      String name = names[i];
+      Declaration declaration = this.local[name];
+      if (declaration.isStatic) {
+        needsCopy = true;
+      } else {
+        local[name] = declaration;
+      }
+    }
+    names = this.setters.keys.toList();
+    Map<String, Declaration> setters = <String, Declaration>{};
+    for (int i = 0; i < names.length; i++) {
+      String name = names[i];
+      Declaration declaration = this.setters[name];
+      if (declaration.isStatic) {
+        needsCopy = true;
+      } else {
+        setters[name] = declaration;
+      }
+    }
+    return needsCopy
+        ? new Scope(local, setters, parent, classNameOrDebugName,
+            isModifiable: isModifiable)
+        : this;
+  }
 }
 
 class ScopeBuilder {
diff --git a/pkg/front_end/testcases/mixin_with_static_member.dart b/pkg/front_end/testcases/mixin_with_static_member.dart
new file mode 100644
index 0000000..27ce9da
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_with_static_member.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2019, 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 A extends B with M {}
+
+class B {
+  final Object m = null;
+}
+
+class M {
+  static Object m() => null;
+}
+
+main() {
+  new A();
+}
diff --git a/pkg/front_end/testcases/mixin_with_static_member.dart.hierarchy.expect b/pkg/front_end/testcases/mixin_with_static_member.dart.hierarchy.expect
new file mode 100644
index 0000000..6eaae17
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_with_static_member.dart.hierarchy.expect
@@ -0,0 +1,120 @@
+Object:
+  superclasses:
+  interfaces:
+  classMembers:
+    Object._haveSameRuntimeType
+    Object.toString
+    Object.runtimeType
+    Object._toString
+    Object._simpleInstanceOf
+    Object._hashCodeRnd
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._objectHashCode
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+B:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    B.m
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+M:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    M.m
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+B with M:
+  superclasses:
+    Object
+      -> B
+  interfaces: M
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    B.m
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    B.m
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
+
+A:
+  superclasses:
+    Object
+      -> B
+        -> _A&B&M
+  interfaces: M
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    B.m
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    B.m
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
diff --git a/pkg/front_end/testcases/mixin_with_static_member.dart.legacy.expect b/pkg/front_end/testcases/mixin_with_static_member.dart.legacy.expect
new file mode 100644
index 0000000..8c1ae5e
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_with_static_member.dart.legacy.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class _A&B&M = self::B with self::M {
+  synthetic constructor •() → self::_A&B&M
+    : super self::B::•()
+    ;
+}
+class A extends self::_A&B&M {
+  synthetic constructor •() → self::A
+    : super self::_A&B&M::•()
+    ;
+}
+class B extends core::Object {
+  final field core::Object m = null;
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class M extends core::Object {
+  synthetic constructor •() → self::M
+    : super core::Object::•()
+    ;
+  static method m() → core::Object
+    return null;
+}
+static method main() → dynamic {
+  new self::A::•();
+}
diff --git a/pkg/front_end/testcases/mixin_with_static_member.dart.legacy.transformed.expect b/pkg/front_end/testcases/mixin_with_static_member.dart.legacy.transformed.expect
new file mode 100644
index 0000000..e243b45
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_with_static_member.dart.legacy.transformed.expect
@@ -0,0 +1,32 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class _A&B&M extends self::B implements self::M {
+  synthetic constructor •() → self::_A&B&M
+    : super self::B::•()
+    ;
+  static method m() → core::Object
+    return null;
+}
+class A extends self::_A&B&M {
+  synthetic constructor •() → self::A
+    : super self::_A&B&M::•()
+    ;
+}
+class B extends core::Object {
+  final field core::Object m = null;
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class M extends core::Object {
+  synthetic constructor •() → self::M
+    : super core::Object::•()
+    ;
+  static method m() → core::Object
+    return null;
+}
+static method main() → dynamic {
+  new self::A::•();
+}
diff --git a/pkg/front_end/testcases/mixin_with_static_member.dart.outline.expect b/pkg/front_end/testcases/mixin_with_static_member.dart.outline.expect
new file mode 100644
index 0000000..2de8dc52
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_with_static_member.dart.outline.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class _A&B&M = self::B with self::M {
+  synthetic constructor •() → self::_A&B&M
+    : super self::B::•()
+    ;
+}
+class A extends self::_A&B&M {
+  synthetic constructor •() → self::A
+    ;
+}
+class B extends core::Object {
+  final field core::Object m;
+  synthetic constructor •() → self::B
+    ;
+}
+class M extends core::Object {
+  synthetic constructor •() → self::M
+    ;
+  static method m() → core::Object
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/mixin_with_static_member.dart.strong.expect b/pkg/front_end/testcases/mixin_with_static_member.dart.strong.expect
new file mode 100644
index 0000000..8c1ae5e
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_with_static_member.dart.strong.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class _A&B&M = self::B with self::M {
+  synthetic constructor •() → self::_A&B&M
+    : super self::B::•()
+    ;
+}
+class A extends self::_A&B&M {
+  synthetic constructor •() → self::A
+    : super self::_A&B&M::•()
+    ;
+}
+class B extends core::Object {
+  final field core::Object m = null;
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class M extends core::Object {
+  synthetic constructor •() → self::M
+    : super core::Object::•()
+    ;
+  static method m() → core::Object
+    return null;
+}
+static method main() → dynamic {
+  new self::A::•();
+}
diff --git a/pkg/front_end/testcases/mixin_with_static_member.dart.strong.transformed.expect b/pkg/front_end/testcases/mixin_with_static_member.dart.strong.transformed.expect
new file mode 100644
index 0000000..e243b45
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_with_static_member.dart.strong.transformed.expect
@@ -0,0 +1,32 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class _A&B&M extends self::B implements self::M {
+  synthetic constructor •() → self::_A&B&M
+    : super self::B::•()
+    ;
+  static method m() → core::Object
+    return null;
+}
+class A extends self::_A&B&M {
+  synthetic constructor •() → self::A
+    : super self::_A&B&M::•()
+    ;
+}
+class B extends core::Object {
+  final field core::Object m = null;
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class M extends core::Object {
+  synthetic constructor •() → self::M
+    : super core::Object::•()
+    ;
+  static method m() → core::Object
+    return null;
+}
+static method main() → dynamic {
+  new self::A::•();
+}
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 424fbf9..8ac7058 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -681,6 +681,7 @@
 mixin_constructors_with_default_values: TextSerializationFailure # Was: Pass
 mixin_inherited_setter_for_mixed_in_field: TextSerializationFailure # Was: Pass
 mixin_super_repeated: TextSerializationFailure # Was: Pass
+mixin_with_static_member: TextSerializationFailure
 mixin: TextSerializationFailure # Was: Pass
 named_function_scope: TextSerializationFailure # Was: Pass
 named_parameters: TextSerializationFailure # Was: Pass