[fasta] Handle function types in arguments of mixin applications

Fixes #34511

Bug: http://dartbug.com/34511
Change-Id: I88da959b329199fc879f4db6e282829d21f6670a
Reviewed-on: https://dart-review.googlesource.com/c/82987
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Peter von der Ahé <ahe@google.com>
Auto-Submit: Dmitry Stefantsov <dmitryas@google.com>
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index ffd5b41..7660133 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -420,16 +420,29 @@
 
       /// Helper function that returns `true` if a type variable with a name
       /// from [typeVariableNames] is referenced in [type].
-      bool usesTypeVariables(KernelNamedTypeBuilder type) {
-        List<KernelTypeBuilder> typeArguments = type.arguments;
-        if (typeArguments != null && typeVariables != null) {
-          for (KernelTypeBuilder argument in typeArguments) {
-            if (typeVariableNames.contains(argument.name)) {
-              return true;
-            } else if (argument is KernelNamedTypeBuilder) {
-              if (usesTypeVariables(argument)) return true;
+      bool usesTypeVariables(KernelTypeBuilder type) {
+        if (type is KernelNamedTypeBuilder) {
+          if (type.declaration is KernelTypeVariableBuilder) {
+            return typeVariableNames.contains(type.declaration.name);
+          }
+
+          List<KernelTypeBuilder> typeArguments = type.arguments;
+          if (typeArguments != null && typeVariables != null) {
+            for (KernelTypeBuilder argument in typeArguments) {
+              if (usesTypeVariables(argument)) {
+                return true;
+              }
             }
           }
+        } else if (type is KernelFunctionTypeBuilder) {
+          if (type.formals != null) {
+            for (FormalParameterBuilder formal in type.formals) {
+              if (usesTypeVariables(formal.type)) {
+                return true;
+              }
+            }
+          }
+          return usesTypeVariables(type.returnType);
         }
         return false;
       }
diff --git a/pkg/front_end/testcases/bug34511.dart b/pkg/front_end/testcases/bug34511.dart
new file mode 100644
index 0000000..d8ad848
--- /dev/null
+++ b/pkg/front_end/testcases/bug34511.dart
@@ -0,0 +1,11 @@
+// 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.
+
+// See http://dartbug.com/34511 for details.
+
+class A<X> {}
+
+class B<Z> extends Object with A<Z Function()> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/bug34511.dart.legacy.expect b/pkg/front_end/testcases/bug34511.dart.legacy.expect
new file mode 100644
index 0000000..ebad4e6
--- /dev/null
+++ b/pkg/front_end/testcases/bug34511.dart.legacy.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+abstract class _B&Object&A<Z extends core::Object = dynamic> = core::Object with self::A<() → self::_B&Object&A::Z> {
+  synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z>
+    : super core::Object::•()
+    ;
+}
+class B<Z extends core::Object = dynamic> extends self::_B&Object&A<self::B::Z> {
+  synthetic constructor •() → self::B<self::B::Z>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/bug34511.dart.legacy.transformed.expect b/pkg/front_end/testcases/bug34511.dart.legacy.transformed.expect
new file mode 100644
index 0000000..739a1e4
--- /dev/null
+++ b/pkg/front_end/testcases/bug34511.dart.legacy.transformed.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+abstract class _B&Object&A<Z extends core::Object = dynamic> extends core::Object implements self::A<() → self::_B&Object&A::Z> {
+  synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z>
+    : super core::Object::•()
+    ;
+}
+class B<Z extends core::Object = dynamic> extends self::_B&Object&A<self::B::Z> {
+  synthetic constructor •() → self::B<self::B::Z>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/bug34511.dart.outline.expect b/pkg/front_end/testcases/bug34511.dart.outline.expect
new file mode 100644
index 0000000..0291dc5
--- /dev/null
+++ b/pkg/front_end/testcases/bug34511.dart.outline.expect
@@ -0,0 +1,19 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    ;
+}
+abstract class _B&Object&A<Z extends core::Object = dynamic> = core::Object with self::A<() → self::_B&Object&A::Z> {
+  synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z>
+    : super core::Object::•()
+    ;
+}
+class B<Z extends core::Object = dynamic> extends self::_B&Object&A<self::B::Z> {
+  synthetic constructor •() → self::B<self::B::Z>
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/bug34511.dart.strong.expect b/pkg/front_end/testcases/bug34511.dart.strong.expect
new file mode 100644
index 0000000..ebad4e6
--- /dev/null
+++ b/pkg/front_end/testcases/bug34511.dart.strong.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+abstract class _B&Object&A<Z extends core::Object = dynamic> = core::Object with self::A<() → self::_B&Object&A::Z> {
+  synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z>
+    : super core::Object::•()
+    ;
+}
+class B<Z extends core::Object = dynamic> extends self::_B&Object&A<self::B::Z> {
+  synthetic constructor •() → self::B<self::B::Z>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/bug34511.dart.strong.transformed.expect b/pkg/front_end/testcases/bug34511.dart.strong.transformed.expect
new file mode 100644
index 0000000..739a1e4
--- /dev/null
+++ b/pkg/front_end/testcases/bug34511.dart.strong.transformed.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+abstract class _B&Object&A<Z extends core::Object = dynamic> extends core::Object implements self::A<() → self::_B&Object&A::Z> {
+  synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z>
+    : super core::Object::•()
+    ;
+}
+class B<Z extends core::Object = dynamic> extends self::_B&Object&A<self::B::Z> {
+  synthetic constructor •() → self::B<self::B::Z>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}