Version 1.23.0-dev.11.8

Cherry-pick d52a6a39d54fd2116aea7f2980500f92e4677e10 to dev
Cherry-pick 492eab84ece070ff262b958d0786fa42db9645df to dev
Cherry-pick e520fc2a455c16ef5e2bd798ab08a1842c08134d to dev
Cherry-pick 23f08ec04a1907e43469f080601822431128cd60 to dev
Cherry-pick e30b56ccbe36686612fc53e1c5da04905eaef969 to dev
Cherry-pick b277f1023c8a6e553603498710e757c5c7a2c8f1 to dev
Cherry-pick f0ae30dca5ada7fc18d7b0c42fc05ff9aa3a64d0 to dev
Cherry-pick 214308773419d67e9380dca38c7332dbd8496988 to dev
Cherry-pick 7696ec5f31e32939728641c28caf0d607fcbdbba to dev
Cherry-pick 5f28891e617cb109ba3e7a5849dfcb791b8ae3a7 to dev
Cherry-pick 54f845cfd2bcb36213e10ff5ea994d1cd86e9bee to dev
Cherry-pick fcac30e080955bea12a7d39467a91268ffad4b19 to dev
Cherry-pick 37aeef8d6e64435293415bf9aac06ba02b782149 to dev
diff --git a/DEPS b/DEPS
index 2fafc01..0a3f022 100644
--- a/DEPS
+++ b/DEPS
@@ -37,7 +37,7 @@
   "gperftools_revision": "@02eeed29df112728564a5dde6417fa4622b57a06",
 
   # Revisions of /third_party/* dependencies.
-  "angular_analyzer_plugin_tag": "@v0.0.7",
+  "angular_analyzer_plugin_tag": "@v0.0.8",
   "args_tag": "@0.13.7",
   "async_tag": "@1.13.0",
   "barback-0.13.0_rev": "@34853",
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 157d8d8..3ec8098 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -72,7 +72,7 @@
   /**
    * The version of data format, should be incremented on every format change.
    */
-  static const int DATA_VERSION = 28;
+  static const int DATA_VERSION = 29;
 
   /**
    * The number of exception contexts allowed to write. Once this field is
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
index f90698a..0079e47 100644
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -427,22 +427,6 @@
   }
 
   @override
-  Object visitGenericFunctionType(GenericFunctionType node) {
-    ElementHolder holder = new ElementHolder();
-    _visitChildren(holder, node);
-    GenericFunctionTypeElementImpl element =
-        new GenericFunctionTypeElementImpl.forOffset(node.beginToken.offset);
-    _setCodeRange(element, node);
-    element.parameters = holder.parameters;
-    element.typeParameters = holder.typeParameters;
-    FunctionType type = new FunctionTypeImpl(element);
-    element.type = type;
-    (node as GenericFunctionTypeImpl).type = type;
-    holder.validate();
-    return null;
-  }
-
-  @override
   Object visitGenericTypeAlias(GenericTypeAlias node) {
     ElementHolder holder = new ElementHolder();
     _visitChildren(holder, node);
@@ -1481,6 +1465,22 @@
   }
 
   @override
+  Object visitGenericFunctionType(GenericFunctionType node) {
+    ElementHolder holder = new ElementHolder();
+    _visitChildren(holder, node);
+    GenericFunctionTypeElementImpl element =
+        new GenericFunctionTypeElementImpl.forOffset(node.beginToken.offset);
+    _setCodeRange(element, node);
+    element.parameters = holder.parameters;
+    element.typeParameters = holder.typeParameters;
+    FunctionType type = new FunctionTypeImpl(element);
+    element.type = type;
+    (node as GenericFunctionTypeImpl).type = type;
+    holder.validate();
+    return null;
+  }
+
+  @override
   Object visitSimpleFormalParameter(SimpleFormalParameter node) {
     ParameterElementImpl parameter;
     if (node.parent is! DefaultFormalParameter) {
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 57c8d14..d3432fe 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -724,7 +724,7 @@
     if (_unlinkedClass != null && _interfaces == null) {
       ResynthesizerContext context = enclosingUnit.resynthesizerContext;
       _interfaces = _unlinkedClass.interfaces
-          .map((EntityRef t) => context.resolveTypeRef(t, this))
+          .map((EntityRef t) => context.resolveTypeRef(this, t))
           .where(_isClassInterfaceType)
           .toList(growable: false);
     }
@@ -831,7 +831,7 @@
     if (_unlinkedClass != null && _mixins == null) {
       ResynthesizerContext context = enclosingUnit.resynthesizerContext;
       _mixins = _unlinkedClass.mixins
-          .map((EntityRef t) => context.resolveTypeRef(t, this))
+          .map((EntityRef t) => context.resolveTypeRef(this, t))
           .where(_isClassInterfaceType)
           .toList(growable: false);
     }
@@ -865,7 +865,7 @@
     if (_unlinkedClass != null && _supertype == null) {
       if (_unlinkedClass.supertype != null) {
         DartType type = enclosingUnit.resynthesizerContext
-            .resolveTypeRef(_unlinkedClass.supertype, this);
+            .resolveTypeRef(this, _unlinkedClass.supertype);
         if (_isClassInterfaceType(type)) {
           _supertype = type;
         } else {
@@ -3879,10 +3879,10 @@
         _returnType == null) {
       bool isSetter =
           serializedExecutable.kind == UnlinkedExecutableKind.setter;
-      _returnType = enclosingUnit.resynthesizerContext.resolveLinkedType(
-          serializedExecutable.inferredReturnTypeSlot, typeParameterContext);
+      _returnType = enclosingUnit.resynthesizerContext
+          .resolveLinkedType(this, serializedExecutable.inferredReturnTypeSlot);
       _declaredReturnType = enclosingUnit.resynthesizerContext.resolveTypeRef(
-          serializedExecutable.returnType, typeParameterContext,
+          this, serializedExecutable.returnType,
           defaultVoid: isSetter && context.analysisOptions.strongMode,
           declaredType: true);
     }
@@ -4572,7 +4572,7 @@
   @override
   DartType get returnType {
     return _returnType ??= enclosingUnit.resynthesizerContext
-        .resolveTypeRef(_entityRef.syntheticReturnType, typeParameterContext);
+        .resolveTypeRef(this, _entityRef.syntheticReturnType);
   }
 
   @override
@@ -4736,7 +4736,7 @@
   DartType get returnType {
     if (_unlinkedTypedef != null && _returnType == null) {
       _returnType = enclosingUnit.resynthesizerContext.resolveTypeRef(
-          _unlinkedTypedef.returnType, this,
+          this, _unlinkedTypedef.returnType,
           declaredType: true);
     }
     return _returnType;
@@ -4859,11 +4859,6 @@
   EntityRef _entityRef;
 
   /**
-   * The enclosing type parameter context.
-   */
-  TypeParameterizedElementMixin _typeParameterContext;
-
-  /**
    * The declared return type of the function.
    */
   DartType _returnType;
@@ -4889,13 +4884,13 @@
    * Initialize from serialized information.
    */
   GenericFunctionTypeElementImpl.forSerialized(
-      this._entityRef, this._typeParameterContext)
-      : super.forSerialized(null);
+      ElementImpl enclosingElement, this._entityRef)
+      : super.forSerialized(enclosingElement);
 
   @override
-  TypeParameterizedElementMixin get enclosingTypeParameterContext =>
-      _typeParameterContext ??
-      (enclosingElement as ElementImpl).typeParameterContext;
+  TypeParameterizedElementMixin get enclosingTypeParameterContext {
+    return _enclosingElement.typeParameterContext;
+  }
 
   @override
   String get identifier => '-';
@@ -4928,7 +4923,7 @@
   DartType get returnType {
     if (_entityRef != null && _returnType == null) {
       _returnType = enclosingUnit.resynthesizerContext.resolveTypeRef(
-          _entityRef.syntheticReturnType, typeParameterContext,
+          this, _entityRef.syntheticReturnType,
           defaultVoid: false, declaredType: true);
     }
     return _returnType;
@@ -5102,7 +5097,7 @@
   GenericFunctionTypeElement get function {
     if (_function == null && _unlinkedTypedef != null) {
       DartType type = enclosingUnit.resynthesizerContext.resolveTypeRef(
-          _unlinkedTypedef.returnType, this,
+          this, _unlinkedTypedef.returnType,
           declaredType: true);
       if (type is FunctionType) {
         Element element = type.element;
@@ -5233,6 +5228,27 @@
     return null;
   }
 
+  /**
+   * Return the type of the function defined by this typedef after substituting
+   * the given [typeArguments] for the type parameters defined for this typedef
+   * (but not the type parameters defined by the function). If the number of
+   * [typeArguments] does not match the number of type parameters, then
+   * `dynamic` will be used in place of each of the type arguments.
+   */
+  FunctionType typeAfterSubstitution(List<DartType> typeArguments) {
+    FunctionType functionType = function.type;
+    List<TypeParameterElement> parameterElements = typeParameters;
+    List<DartType> parameterTypes =
+        TypeParameterTypeImpl.getTypes(parameterElements);
+    int parameterCount = parameterTypes.length;
+    if (typeArguments == null ||
+        parameterElements.length != typeArguments.length) {
+      DartType dynamicType = DynamicElementImpl.instance.type;
+      typeArguments = new List<DartType>.filled(parameterCount, dynamicType);
+    }
+    return functionType.substitute2(typeArguments, parameterTypes);
+  }
+
   @override
   void visitChildren(ElementVisitor visitor) {
     super.visitChildren(visitor);
@@ -7269,11 +7285,10 @@
   @override
   DartType get type {
     if (_unlinkedVariable != null && _declaredType == null && _type == null) {
-      _type = enclosingUnit.resynthesizerContext.resolveLinkedType(
-          _unlinkedVariable.inferredTypeSlot, typeParameterContext);
-      declaredType = enclosingUnit.resynthesizerContext.resolveTypeRef(
-          _unlinkedVariable.type, typeParameterContext,
-          declaredType: true);
+      _type = enclosingUnit.resynthesizerContext
+          .resolveLinkedType(this, _unlinkedVariable.inferredTypeSlot);
+      declaredType = enclosingUnit.resynthesizerContext
+          .resolveTypeRef(this, _unlinkedVariable.type, declaredType: true);
     }
     return super.type;
   }
@@ -7775,18 +7790,17 @@
           parameterTypeElement.shareParameters(subParameters);
         }
         parameterTypeElement.returnType = enclosingUnit.resynthesizerContext
-            .resolveTypeRef(_unlinkedParam.type, typeParameterContext);
+            .resolveTypeRef(this, _unlinkedParam.type);
         FunctionTypeImpl parameterType =
             new FunctionTypeImpl.elementWithNameAndArgs(parameterTypeElement,
                 null, typeParameterContext.allTypeParameterTypes, false);
         parameterTypeElement.type = parameterType;
         _type = parameterType;
       } else {
-        _type = enclosingUnit.resynthesizerContext.resolveLinkedType(
-            _unlinkedParam.inferredTypeSlot, typeParameterContext);
-        declaredType = enclosingUnit.resynthesizerContext.resolveTypeRef(
-            _unlinkedParam.type, typeParameterContext,
-            declaredType: true);
+        _type = enclosingUnit.resynthesizerContext
+            .resolveLinkedType(this, _unlinkedParam.inferredTypeSlot);
+        declaredType = enclosingUnit.resynthesizerContext
+            .resolveTypeRef(this, _unlinkedParam.type, declaredType: true);
       }
     }
   }
@@ -8283,8 +8297,8 @@
   @override
   DartType get propagatedType {
     if (_unlinkedVariable != null && _propagatedType == null) {
-      _propagatedType = enclosingUnit.resynthesizerContext.resolveLinkedType(
-          _unlinkedVariable.propagatedTypeSlot, typeParameterContext);
+      _propagatedType = enclosingUnit.resynthesizerContext
+          .resolveLinkedType(this, _unlinkedVariable.propagatedTypeSlot);
     }
     return _propagatedType;
   }
@@ -8359,14 +8373,13 @@
    * unresolved, return `null`.
    */
   ConstructorElement resolveConstructorRef(
-      TypeParameterizedElementMixin typeParameterContext, EntityRef entry);
+      ElementImpl context, EntityRef entry);
 
   /**
    * Build the appropriate [DartType] object corresponding to a slot id in the
    * [LinkedUnit.types] table.
    */
-  DartType resolveLinkedType(
-      int slot, TypeParameterizedElementMixin typeParameterContext);
+  DartType resolveLinkedType(ElementImpl context, int slot);
 
   /**
    * Resolve an [EntityRef] into a type.  If the reference is
@@ -8375,8 +8388,7 @@
    * TODO(paulberry): or should we have a class representing an
    * unresolved type, for consistency with the full element model?
    */
-  DartType resolveTypeRef(
-      EntityRef type, TypeParameterizedElementMixin typeParameterContext,
+  DartType resolveTypeRef(ElementImpl context, EntityRef type,
       {bool defaultVoid: false,
       bool instantiateToBoundsAllowed: true,
       bool declaredType: false});
@@ -8578,7 +8590,7 @@
         return null;
       }
       return _bound ??= enclosingUnit.resynthesizerContext.resolveTypeRef(
-          _unlinkedTypeParam.bound, enclosingElement,
+          this, _unlinkedTypeParam.bound,
           instantiateToBoundsAllowed: false, declaredType: true);
     }
     return _bound;
diff --git a/pkg/analyzer/lib/src/dart/element/handle.dart b/pkg/analyzer/lib/src/dart/element/handle.dart
index e38f5fe..4b285cc 100644
--- a/pkg/analyzer/lib/src/dart/element/handle.dart
+++ b/pkg/analyzer/lib/src/dart/element/handle.dart
@@ -670,6 +670,45 @@
 }
 
 /**
+ * A handle to a [GenericTypeAliasElement].
+ */
+class GenericTypeAliasElementHandle extends ElementHandle
+    implements GenericTypeAliasElement {
+  GenericTypeAliasElementHandle(
+      ElementResynthesizer resynthesizer, ElementLocation location)
+      : super(resynthesizer, location);
+
+  @override
+  GenericTypeAliasElement get actualElement =>
+      super.actualElement as GenericTypeAliasElement;
+
+  @override
+  CompilationUnitElement get enclosingElement =>
+      super.enclosingElement as CompilationUnitElement;
+
+  @override
+  GenericFunctionTypeElement get function => actualElement.function;
+
+  @override
+  ElementKind get kind => ElementKind.FUNCTION_TYPE_ALIAS;
+
+  @override
+  List<ParameterElement> get parameters => actualElement.parameters;
+
+  @override
+  DartType get returnType => actualElement.returnType;
+
+  @override
+  FunctionType get type => actualElement.type;
+
+  @override
+  List<TypeParameterElement> get typeParameters => actualElement.typeParameters;
+
+  @override
+  FunctionTypeAlias computeNode() => actualElement.computeNode();
+}
+
+/**
  * A handle to an [ImportElement].
  */
 class ImportElementHandle extends ElementHandle implements ImportElement {
diff --git a/pkg/analyzer/lib/src/generated/declaration_resolver.dart b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
index e240504..9bbba1a 100644
--- a/pkg/analyzer/lib/src/generated/declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/builder.dart';
@@ -225,6 +226,7 @@
             elementName: functionName.name + '=');
       }
     }
+    _setGenericFunctionType(node.returnType, element.returnType);
     node.functionExpression.element = element;
     _walker._elementHolder?.addFunction(element);
     _walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
@@ -277,10 +279,20 @@
 
   @override
   Object visitGenericFunctionType(GenericFunctionType node) {
-    GenericFunctionTypeElement element = node.type.element;
-    _walk(new ElementWalker.forGenericFunctionType(element), () {
-      super.visitGenericFunctionType(node);
-    });
+    if (_walker.elementBuilder != null) {
+      _walker.elementBuilder.visitGenericFunctionType(node);
+    } else {
+      DartType type = node.type;
+      if (type != null) {
+        Element element = type.element;
+        if (element is GenericFunctionTypeElement) {
+          _setGenericFunctionType(node.returnType, element.returnType);
+          _walk(new ElementWalker.forGenericFunctionType(element), () {
+            super.visitGenericFunctionType(node);
+          });
+        }
+      }
+    }
     return null;
   }
 
@@ -288,8 +300,7 @@
   Object visitGenericTypeAlias(GenericTypeAlias node) {
     GenericTypeAliasElementImpl element =
         _match(node.name, _walker.getTypedef());
-    (node.functionType as GenericFunctionTypeImpl)?.type =
-        element.function?.type;
+    _setGenericFunctionType(node.functionType, element.function?.type);
     _walk(new ElementWalker.forGenericTypeAlias(element), () {
       super.visitGenericTypeAlias(node);
     });
@@ -357,6 +368,7 @@
             elementName: nameOfMethod + '=');
       }
     }
+    _setGenericFunctionType(node.returnType, element.returnType);
     _walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
       super.visitMethodDeclaration(node);
     });
@@ -393,10 +405,7 @@
       ParameterElement element =
           _match(node.identifier, _walker.getParameter());
       (node as SimpleFormalParameterImpl).element = element;
-      TypeAnnotation type = node.type;
-      if (type is GenericFunctionTypeImpl) {
-        type.type = element.type;
-      }
+      _setGenericFunctionType(node.type, element.type);
       _walk(new ElementWalker.forParameter(element), () {
         super.visitSimpleFormalParameter(node);
       });
@@ -463,10 +472,13 @@
     if (_walker.elementBuilder != null) {
       return _walker.elementBuilder.visitVariableDeclarationList(node);
     } else {
-      super.visitVariableDeclarationList(node);
+      node.variables.accept(this);
+      VariableElement firstVariable = node.variables[0].element;
+      _setGenericFunctionType(node.type, firstVariable.type);
+      node.type?.accept(this);
       if (node.parent is! FieldDeclaration &&
           node.parent is! TopLevelVariableDeclaration) {
-        _resolveMetadata(node, node.metadata, node.variables[0].element);
+        _resolveMetadata(node, node.metadata, firstVariable);
       }
       return null;
     }
@@ -538,6 +550,27 @@
   }
 
   /**
+   * If the given [typeNode] is a [GenericFunctionType], set its [type].
+   */
+  void _setGenericFunctionType(TypeAnnotation typeNode, DartType type) {
+    if (typeNode is GenericFunctionTypeImpl) {
+      typeNode.type = type;
+    } else if (typeNode is NamedType) {
+      typeNode.type = type;
+      if (type is ParameterizedType) {
+        List<TypeAnnotation> nodes =
+            typeNode.typeArguments?.arguments ?? const [];
+        List<DartType> types = type.typeArguments;
+        if (nodes.length == types.length) {
+          for (int i = 0; i < nodes.length; i++) {
+            _setGenericFunctionType(nodes[i], types[i]);
+          }
+        }
+      }
+    }
+  }
+
+  /**
    * Recurses through the element model and AST, verifying that all elements are
    * matched.
    *
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 6f4768b..e87b77b 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -430,6 +430,10 @@
       return true;
     }
     Token afterReturnType = skipTypeName(_currentToken);
+    if (afterReturnType != null &&
+        _tokenMatchesKeyword(afterReturnType, Keyword.FUNCTION)) {
+      afterReturnType = skipGenericFunctionTypeAfterReturnType(afterReturnType);
+    }
     if (afterReturnType == null) {
       // There was no return type, but it is optional, so go back to where we
       // started.
@@ -544,6 +548,13 @@
       // There was no type name, so this can't be a declaration.
       return false;
     }
+    while (_atGenericFunctionTypeAfterReturnType(token)) {
+      token = skipGenericFunctionTypeAfterReturnType(token);
+      if (token == null) {
+        // There was no type name, so this can't be a declaration.
+        return false;
+      }
+    }
     if (token.type != TokenType.IDENTIFIER) {
       allowAdditionalTokens = false;
     }
@@ -1239,9 +1250,19 @@
     CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
     Modifiers modifiers = parseModifiers();
     Keyword keyword = _currentToken.keyword;
-    if (keyword == Keyword.VOID) {
-      TypeName returnType = astFactory.typeName(
-          astFactory.simpleIdentifier(getAndAdvance()), null);
+    if (keyword == Keyword.VOID ||
+        _atGenericFunctionTypeAfterReturnType(_currentToken)) {
+      TypeAnnotation returnType;
+      if (keyword == Keyword.VOID) {
+        if (_atGenericFunctionTypeAfterReturnType(_peek())) {
+          returnType = parseTypeAnnotation(false);
+        } else {
+          returnType = astFactory.typeName(
+              astFactory.simpleIdentifier(getAndAdvance()), null);
+        }
+      } else {
+        returnType = parseTypeAnnotation(false);
+      }
       keyword = _currentToken.keyword;
       Token next = _peek();
       bool isFollowedByIdentifier = _tokenMatchesIdentifier(next);
@@ -1267,28 +1288,25 @@
         _validateModifiersForGetterOrSetterOrMethod(modifiers);
         return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
             modifiers.externalKeyword, modifiers.staticKeyword, returnType);
-      } else {
-        //
-        // We have found an error of some kind. Try to recover.
-        //
-        if (_matchesIdentifier()) {
-          if (_peek().matchesAny(const <TokenType>[
+      } else if (_matchesIdentifier() &&
+          _peek().matchesAny(const <TokenType>[
             TokenType.EQ,
             TokenType.COMMA,
             TokenType.SEMICOLON
           ])) {
-            //
-            // We appear to have a variable declaration with a type of "void".
-            //
-            _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType);
-            return parseInitializedIdentifierList(
-                commentAndMetadata,
-                modifiers.staticKeyword,
-                modifiers.covariantKeyword,
-                _validateModifiersForField(modifiers),
-                returnType);
-          }
+        if (returnType is! GenericFunctionType) {
+          _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType);
         }
+        return parseInitializedIdentifierList(
+            commentAndMetadata,
+            modifiers.staticKeyword,
+            modifiers.covariantKeyword,
+            _validateModifiersForField(modifiers),
+            returnType);
+      } else {
+        //
+        // We have found an error of some kind. Try to recover.
+        //
         if (_isOperator(_currentToken)) {
           //
           // We appear to have found an operator declaration without the
@@ -2036,9 +2054,19 @@
     } else if (keyword == Keyword.ENUM) {
       _validateModifiersForEnum(modifiers);
       return parseEnumDeclaration(commentAndMetadata);
-    } else if (keyword == Keyword.VOID) {
-      TypeName returnType = astFactory.typeName(
-          astFactory.simpleIdentifier(getAndAdvance()), null);
+    } else if (keyword == Keyword.VOID ||
+        _atGenericFunctionTypeAfterReturnType(_currentToken)) {
+      TypeAnnotation returnType;
+      if (keyword == Keyword.VOID) {
+        if (_atGenericFunctionTypeAfterReturnType(next)) {
+          returnType = parseTypeAnnotation(false);
+        } else {
+          returnType = astFactory.typeName(
+              astFactory.simpleIdentifier(getAndAdvance()), null);
+        }
+      } else {
+        returnType = parseTypeAnnotation(false);
+      }
       keyword = _currentToken.keyword;
       next = _peek();
       if ((keyword == Keyword.GET || keyword == Keyword.SET) &&
@@ -2063,28 +2091,25 @@
         _validateModifiersForTopLevelFunction(modifiers);
         return parseFunctionDeclaration(
             commentAndMetadata, modifiers.externalKeyword, returnType);
-      } else {
-        //
-        // We have found an error of some kind. Try to recover.
-        //
-        if (_matchesIdentifier()) {
-          if (next.matchesAny(const <TokenType>[
+      } else if (_matchesIdentifier() &&
+          next.matchesAny(const <TokenType>[
             TokenType.EQ,
             TokenType.COMMA,
             TokenType.SEMICOLON
           ])) {
-            //
-            // We appear to have a variable declaration with a type of "void".
-            //
-            _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType);
-            return astFactory.topLevelVariableDeclaration(
-                commentAndMetadata.comment,
-                commentAndMetadata.metadata,
-                parseVariableDeclarationListAfterType(null,
-                    _validateModifiersForTopLevelVariable(modifiers), null),
-                _expect(TokenType.SEMICOLON));
-          }
+        if (returnType is! GenericFunctionType) {
+          _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType);
         }
+        return astFactory.topLevelVariableDeclaration(
+            commentAndMetadata.comment,
+            commentAndMetadata.metadata,
+            parseVariableDeclarationListAfterType(null,
+                _validateModifiersForTopLevelVariable(modifiers), returnType),
+            _expect(TokenType.SEMICOLON));
+      } else {
+        //
+        // We have found an error of some kind. Try to recover.
+        //
         _reportErrorForToken(
             ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
         return null;
@@ -4024,8 +4049,13 @@
         return parseVariableDeclarationStatementAfterMetadata(
             commentAndMetadata);
       } else if (keyword == Keyword.VOID) {
-        TypeName returnType = astFactory.typeName(
-            astFactory.simpleIdentifier(getAndAdvance()), null);
+        TypeAnnotation returnType;
+        if (_atGenericFunctionTypeAfterReturnType(_peek())) {
+          returnType = parseTypeAnnotation(false);
+        } else {
+          returnType = astFactory.typeName(
+              astFactory.simpleIdentifier(getAndAdvance()), null);
+        }
         Token next = _currentToken.next;
         if (_matchesIdentifier() &&
             next.matchesAny(const <TokenType>[
@@ -4036,24 +4066,22 @@
             ])) {
           return _parseFunctionDeclarationStatementAfterReturnType(
               commentAndMetadata, returnType);
-        } else {
-          //
-          // We have found an error of some kind. Try to recover.
-          //
-          if (_matchesIdentifier()) {
-            if (next.matchesAny(const <TokenType>[
+        } else if (_matchesIdentifier() &&
+            next.matchesAny(const <TokenType>[
               TokenType.EQ,
               TokenType.COMMA,
               TokenType.SEMICOLON
             ])) {
-              //
-              // We appear to have a variable declaration with a type of "void".
-              //
-              _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType);
-              return parseVariableDeclarationStatementAfterMetadata(
-                  commentAndMetadata);
-            }
-          } else if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
+          if (returnType is! GenericFunctionType) {
+            _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType);
+          }
+          return _parseVariableDeclarationStatementAfterType(
+              commentAndMetadata, null, returnType);
+        } else {
+          //
+          // We have found an error of some kind. Try to recover.
+          //
+          if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
             //
             // We appear to have found an incomplete statement at the end of a
             // block. Parse it as a variable declaration.
@@ -4106,7 +4134,47 @@
         return astFactory
             .emptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
       }
-    } else if (_inGenerator && _matchesString(_YIELD)) {
+    } else if (_atGenericFunctionTypeAfterReturnType(_currentToken)) {
+      TypeAnnotation returnType = parseTypeAnnotation(false);
+      Token next = _currentToken.next;
+      if (_matchesIdentifier() &&
+          next.matchesAny(const <TokenType>[
+            TokenType.OPEN_PAREN,
+            TokenType.OPEN_CURLY_BRACKET,
+            TokenType.FUNCTION,
+            TokenType.LT
+          ])) {
+        return _parseFunctionDeclarationStatementAfterReturnType(
+            commentAndMetadata, returnType);
+      } else if (_matchesIdentifier() &&
+          next.matchesAny(const <TokenType>[
+            TokenType.EQ,
+            TokenType.COMMA,
+            TokenType.SEMICOLON
+          ])) {
+        if (returnType is! GenericFunctionType) {
+          _reportErrorForNode(ParserErrorCode.VOID_VARIABLE, returnType);
+        }
+        return _parseVariableDeclarationStatementAfterType(
+            commentAndMetadata, null, returnType);
+      } else {
+        //
+        // We have found an error of some kind. Try to recover.
+        //
+        if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
+          //
+          // We appear to have found an incomplete statement at the end of a
+          // block. Parse it as a variable declaration.
+          //
+          return _parseVariableDeclarationStatementAfterType(
+              commentAndMetadata, null, returnType);
+        }
+        _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT);
+        // TODO(brianwilkerson) Recover from this error.
+        return astFactory
+            .emptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
+      }
+    } else if (_inGenerator && _matchesKeyword(Keyword.YIELD)) {
       return parseYieldStatement();
     } else if (_inAsync && _matchesString(_AWAIT)) {
       if (_tokenMatchesKeyword(_peek(), Keyword.FOR)) {
@@ -4623,8 +4691,12 @@
    */
   TypeAnnotation parseReturnType(bool inExpression) {
     if (_currentToken.keyword == Keyword.VOID) {
-      return astFactory.typeName(
-          astFactory.simpleIdentifier(getAndAdvance()), null);
+      if (_atGenericFunctionTypeAfterReturnType(_peek())) {
+        return parseTypeAnnotation(false);
+      } else {
+        return astFactory.typeName(
+            astFactory.simpleIdentifier(getAndAdvance()), null);
+      }
     } else {
       return parseTypeAnnotation(inExpression);
     }
@@ -5418,7 +5490,7 @@
     if (!_tokenMatches(startToken, TokenType.OPEN_PAREN)) {
       return null;
     }
-    return (startToken as BeginToken).endToken;
+    return (startToken as BeginToken).endToken.next;
   }
 
   /**
@@ -5485,6 +5557,9 @@
    */
   Token skipReturnType(Token startToken) {
     if (_tokenMatchesKeyword(startToken, Keyword.VOID)) {
+      if (_atGenericFunctionTypeAfterReturnType(_peek())) {
+        return skipTypeAnnotation(startToken);
+      }
       return startToken.next;
     } else {
       return skipTypeAnnotation(startToken);
@@ -5652,7 +5727,7 @@
       } else if (_tokenMatches(next, TokenType.GT)) {
         depth--;
         if (depth == 0) {
-          return next;
+          return next.next;
         }
       }
       previous = next;
@@ -7160,6 +7235,9 @@
     }
     Keyword keyword = _currentToken.keyword;
     if (keyword == Keyword.VOID) {
+      if (_atGenericFunctionTypeAfterReturnType(_peek())) {
+        return parseTypeAnnotation(false);
+      }
       return astFactory.typeName(
           astFactory.simpleIdentifier(getAndAdvance()), null);
     } else if (_matchesIdentifier()) {
@@ -7532,7 +7610,9 @@
    *         variableDeclarationList ';'
    */
   VariableDeclarationStatement _parseVariableDeclarationStatementAfterType(
-      CommentAndMetadata commentAndMetadata, Token keyword, TypeName type) {
+      CommentAndMetadata commentAndMetadata,
+      Token keyword,
+      TypeAnnotation type) {
     VariableDeclarationList variableList =
         parseVariableDeclarationListAfterType(
             commentAndMetadata, keyword, type);
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index ccfa988..502fddf6 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -8466,31 +8466,18 @@
       return undefinedType;
     } else if (type is FunctionType) {
       Element element = type.element;
-      if (annotation is TypeName && element is GenericTypeAliasElement) {
-        List<TypeParameterElement> parameterElements = element.typeParameters;
-        FunctionType functionType = element.function.type;
-        if (parameterElements.isNotEmpty) {
-          List<DartType> parameterTypes =
-              TypeParameterTypeImpl.getTypes(parameterElements);
-          int parameterCount = parameterTypes.length;
-          TypeArgumentList argumentList = annotation.typeArguments;
-          List<DartType> typeArguments;
-          if (argumentList != null) {
-            List<TypeAnnotation> arguments = argumentList.arguments;
-            int argumentCount = arguments.length;
-            if (argumentCount == parameterCount) {
-              typeArguments = new List<DartType>(parameterCount);
-              for (int i = 0; i < parameterCount; i++) {
-                typeArguments[i] = _getType(arguments[i]);
-              }
-            }
+      if (annotation is TypeName && element is GenericTypeAliasElementImpl) {
+        TypeArgumentList argumentList = annotation.typeArguments;
+        List<DartType> typeArguments = null;
+        if (argumentList != null) {
+          List<TypeAnnotation> arguments = argumentList.arguments;
+          int argumentCount = arguments.length;
+          typeArguments = new List<DartType>(argumentCount);
+          for (int i = 0; i < argumentCount; i++) {
+            typeArguments[i] = _getType(arguments[i]);
           }
-          typeArguments ??=
-              new List<DartType>.filled(parameterCount, dynamicType);
-          functionType =
-              functionType.substitute2(typeArguments, parameterTypes);
         }
-        return functionType;
+        return element.typeAfterSubstitution(typeArguments);
       }
     }
     return type;
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 3119c64..d7604a3 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -1132,7 +1132,12 @@
   /**
    * The entity being referred to does not exist.
    */
-  unresolved
+  unresolved,
+
+  /**
+   * The entity is a typedef expressed using generic function type syntax.
+   */
+  genericFunctionTypedef
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index 5c70e57..673e9d8 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -683,7 +683,7 @@
    */
   InterfaceType _computeInterfaceType(EntityRef typeRef) {
     if (typeRef != null) {
-      DartType type = enclosingElement.resolveTypeRef(typeRef, this);
+      DartType type = enclosingElement.resolveTypeRef(this, typeRef);
       if (type is InterfaceType && !type.element.isEnum) {
         return type;
       }
@@ -1000,11 +1000,10 @@
 
   /**
    * Compute the type referred to by the given linked type [slot] (interpreted
-   * relative to [typeParameterContext]).  If there is no inferred type in the
+   * in [context]).  If there is no inferred type in the
    * given slot, `dynamic` is returned.
    */
-  DartType getLinkedType(
-      int slot, TypeParameterizedElementMixin typeParameterContext);
+  DartType getLinkedType(ElementImpl context, int slot);
 
   @override
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
@@ -1076,8 +1075,7 @@
   }
 
   @override
-  DartType resolveTypeRef(
-      EntityRef type, TypeParameterizedElementMixin typeParameterContext,
+  DartType resolveTypeRef(ElementImpl context, EntityRef type,
       {bool defaultVoid: false,
       bool instantiateToBoundsAllowed: true,
       bool declaredType: false}) {
@@ -1089,7 +1087,8 @@
       }
     }
     if (type.paramReference != 0) {
-      return typeParameterContext.getTypeParameterType(type.paramReference);
+      return context.typeParameterContext
+          .getTypeParameterType(type.paramReference);
     } else if (type.syntheticReturnType != null) {
       // TODO(paulberry): implement.
       throw new UnimplementedError();
@@ -1099,7 +1098,7 @@
     } else {
       DartType getTypeArgument(int i) {
         if (i < type.typeArguments.length) {
-          return resolveTypeRef(type.typeArguments[i], typeParameterContext);
+          return resolveTypeRef(context, type.typeArguments[i]);
         } else if (!instantiateToBoundsAllowed) {
           // Do not allow buildType to instantiate the bounds; force dynamic.
           return DynamicTypeImpl.instance;
@@ -1279,8 +1278,7 @@
   }
 
   @override
-  DartType getLinkedType(
-      int slot, TypeParameterizedElementMixin typeParameterContext) {
+  DartType getLinkedType(ElementImpl context, int slot) {
     // This method should only be called on compilation units that come from
     // dependencies, never on compilation units that are part of the current
     // build unit.
@@ -1406,10 +1404,9 @@
   bool get isInBuildUnit => false;
 
   @override
-  DartType getLinkedType(
-      int slot, TypeParameterizedElementMixin typeParameterContext) {
+  DartType getLinkedType(ElementImpl context, int slot) {
     if (slot < _linkedTypeRefs.length) {
-      return resolveTypeRef(_linkedTypeRefs[slot], typeParameterContext);
+      return resolveTypeRef(context, _linkedTypeRefs[slot]);
     } else {
       return DynamicTypeImpl.instance;
     }
@@ -1832,7 +1829,7 @@
       return null;
     } else {
       return _declaredReturnType ??=
-          compilationUnit.resolveTypeRef(_unlinkedExecutable.returnType, this);
+          compilationUnit.resolveTypeRef(this, _unlinkedExecutable.returnType);
     }
   }
 
@@ -1879,7 +1876,7 @@
         _inferredReturnType = _computeDefaultReturnType();
       } else {
         _inferredReturnType = compilationUnit.getLinkedType(
-            _unlinkedExecutable.inferredReturnTypeSlot, this);
+            this, _unlinkedExecutable.inferredReturnTypeSlot);
       }
     }
     return _inferredReturnType;
@@ -2327,8 +2324,7 @@
         if (ref.typeArguments.isNotEmpty) {
           return constructorElement.enclosingClass.buildType((int i) {
             if (i < ref.typeArguments.length) {
-              return unit.resolveTypeRef(
-                  ref.typeArguments[i], function.typeParameterContext);
+              return unit.resolveTypeRef(function, ref.typeArguments[i]);
             } else {
               return null;
             }
@@ -2528,7 +2524,7 @@
 
   DartType _getNextTypeRef() {
     EntityRef ref = _getNextRef();
-    return unit.resolveTypeRef(ref, function.typeParameterContext);
+    return unit.resolveTypeRef(function, ref);
   }
 
   List<DartType> _getTypeArguments() {
@@ -2885,7 +2881,7 @@
         _returnType = DynamicTypeImpl.instance;
       } else {
         _returnType = enclosingElement.compilationUnit.resolveTypeRef(
-            enclosingElement._unlinkedParam.type, typeParameterContext);
+            enclosingElement, enclosingElement._unlinkedParam.type);
       }
     }
     return _returnType;
@@ -3200,7 +3196,7 @@
 
   @override
   DartType get returnType => _returnType ??=
-      enclosingElement.resolveTypeRef(_unlinkedTypedef.returnType, this);
+      enclosingElement.resolveTypeRef(this, _unlinkedTypedef.returnType);
 
   @override
   TypeParameterizedElementMixin get typeParameterContext => this;
@@ -4191,14 +4187,14 @@
       } else if (_unlinkedParam.type == null) {
         if (!compilationUnit.isInBuildUnit) {
           _inferredType = compilationUnit.getLinkedType(
-              _unlinkedParam.inferredTypeSlot, _typeParameterContext);
+              this, _unlinkedParam.inferredTypeSlot);
           return _inferredType;
         } else {
           _declaredType = DynamicTypeImpl.instance;
         }
       } else {
-        _declaredType = compilationUnit.resolveTypeRef(
-            _unlinkedParam.type, _typeParameterContext);
+        _declaredType =
+            compilationUnit.resolveTypeRef(this, _unlinkedParam.type);
       }
     }
     return _declaredType;
@@ -4210,6 +4206,11 @@
     _inferredType = inferredType;
   }
 
+  @override
+  TypeParameterizedElementMixin get typeParameterContext {
+    return _typeParameterContext;
+  }
+
   /**
    * Store the results of type inference for this parameter in
    * [compilationUnit].
@@ -5181,8 +5182,8 @@
     if (unlinkedVariable.type == null) {
       return null;
     } else {
-      return _declaredType ??= compilationUnit.resolveTypeRef(
-          unlinkedVariable.type, _typeParameterContext);
+      return _declaredType ??=
+          compilationUnit.resolveTypeRef(this, unlinkedVariable.type);
     }
   }
 
@@ -5221,7 +5222,7 @@
         _inferredType = DynamicTypeImpl.instance;
       } else {
         _inferredType = compilationUnit.getLinkedType(
-            unlinkedVariable.inferredTypeSlot, _typeParameterContext);
+            this, unlinkedVariable.inferredTypeSlot);
       }
     }
     return _inferredType;
@@ -5280,6 +5281,11 @@
     // TODO(paulberry): store inferred type.
   }
 
+  @override
+  TypeParameterizedElementMixin get typeParameterContext {
+    return _typeParameterContext;
+  }
+
   /**
    * The context in which type parameters should be interpreted, or `null` if
    * there are no type parameters in scope.
diff --git a/pkg/analyzer/lib/src/summary/prelink.dart b/pkg/analyzer/lib/src/summary/prelink.dart
index 1e64b4a..e3c4401 100644
--- a/pkg/analyzer/lib/src/summary/prelink.dart
+++ b/pkg/analyzer/lib/src/summary/prelink.dart
@@ -383,10 +383,18 @@
               executable.typeParameters.length));
     }
     for (UnlinkedTypedef typedef in unit.typedefs) {
-      privateNamespace.add(
-          typedef.name,
-          new _Meaning(unitNum, ReferenceKind.typedef, 0,
-              typedef.typeParameters.length));
+      ReferenceKind kind;
+      switch (typedef.style) {
+        case TypedefStyle.functionType:
+          kind = ReferenceKind.typedef;
+          break;
+        case TypedefStyle.genericFunctionType:
+          kind = ReferenceKind.genericFunctionTypedef;
+          break;
+      }
+      assert(kind != null);
+      privateNamespace.add(typedef.name,
+          new _Meaning(unitNum, kind, 0, typedef.typeParameters.length));
     }
     for (UnlinkedVariable variable in unit.variables) {
       privateNamespace.add(variable.name,
diff --git a/pkg/analyzer/lib/src/summary/public_namespace_computer.dart b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
index 203043a..b11701b 100644
--- a/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
+++ b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
@@ -177,6 +177,12 @@
   }
 
   @override
+  visitGenericTypeAlias(GenericTypeAlias node) {
+    addNameIfPublic(node.name.name, ReferenceKind.genericFunctionTypedef,
+        node.typeParameters?.typeParameters?.length ?? 0);
+  }
+
+  @override
   visitPartDirective(PartDirective node) {
     parts.add(node.uri.stringValue ?? '');
   }
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index da24aba..8550ecd 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -584,8 +584,7 @@
    */
   TypeAnnotation _newTypeName() {
     EntityRef typeRef = uc.references[refPtr++];
-    DartType type =
-        resynthesizer.buildType(typeRef, context?.typeParameterContext);
+    DartType type = resynthesizer.buildType(context, typeRef);
     return _buildTypeAst(type);
   }
 
@@ -633,7 +632,7 @@
         return;
       }
       InterfaceType definingType = resynthesizer._createConstructorDefiningType(
-          context?.typeParameterContext, info, ref.typeArguments);
+          context, info, ref.typeArguments);
       constructorElement =
           resynthesizer._getConstructorForInfo(definingType, info);
       typeNode = _buildTypeAst(definingType);
@@ -938,6 +937,9 @@
       case ReferenceKind.typedef:
         return new FunctionTypeAliasElementHandle(
             summaryResynthesizer, location);
+      case ReferenceKind.genericFunctionTypedef:
+        return new GenericTypeAliasElementHandle(
+            summaryResynthesizer, location);
       case ReferenceKind.topLevelFunction:
         return new FunctionElementHandle(summaryResynthesizer, location);
       case ReferenceKind.topLevelPropertyAccessor:
@@ -1314,6 +1316,11 @@
       }
       // Done.
       return type;
+    } else if (element is GenericTypeAliasElementHandle) {
+      GenericTypeAliasElementImpl actualElement = element.actualElement;
+      List<DartType> argumentTypes =
+          new List.generate(numTypeArguments, getTypeArgument);
+      return actualElement.typeAfterSubstitution(argumentTypes);
     } else if (element is FunctionTypedElement) {
       if (element is FunctionTypeAliasElementHandle) {
         List<DartType> typeArguments;
@@ -1421,24 +1428,21 @@
 
   @override
   ConstructorElement resolveConstructorRef(
-      TypeParameterizedElementMixin typeParameterContext, EntityRef entry) {
-    return _unitResynthesizer._getConstructorForEntry(
-        typeParameterContext, entry);
+      ElementImpl context, EntityRef entry) {
+    return _unitResynthesizer._getConstructorForEntry(context, entry);
   }
 
   @override
-  DartType resolveLinkedType(
-      int slot, TypeParameterizedElementMixin typeParameterContext) {
-    return _unitResynthesizer.buildLinkedType(slot, typeParameterContext);
+  DartType resolveLinkedType(ElementImpl context, int slot) {
+    return _unitResynthesizer.buildLinkedType(context, slot);
   }
 
   @override
-  DartType resolveTypeRef(
-      EntityRef type, TypeParameterizedElementMixin typeParameterContext,
+  DartType resolveTypeRef(ElementImpl context, EntityRef type,
       {bool defaultVoid: false,
       bool instantiateToBoundsAllowed: true,
       bool declaredType: false}) {
-    return _unitResynthesizer.buildType(type, typeParameterContext,
+    return _unitResynthesizer.buildType(context, type,
         defaultVoid: defaultVoid,
         instantiateToBoundsAllowed: instantiateToBoundsAllowed,
         declaredType: declaredType);
@@ -1607,8 +1611,7 @@
    * Build the appropriate [DartType] object corresponding to a slot id in the
    * [LinkedUnit.types] table.
    */
-  DartType buildLinkedType(
-      int slot, TypeParameterizedElementMixin typeParameterContext) {
+  DartType buildLinkedType(ElementImpl context, int slot) {
     if (slot == 0) {
       // A slot id of 0 means there is no [DartType] object to build.
       return null;
@@ -1619,7 +1622,7 @@
       // stored in this slot.
       return null;
     }
-    return buildType(type, typeParameterContext);
+    return buildType(context, type);
   }
 
   /**
@@ -1628,8 +1631,7 @@
    * deserialized, so handles are used to avoid having to deserialize other
    * libraries in the process.
    */
-  DartType buildType(
-      EntityRef type, TypeParameterizedElementMixin typeParameterContext,
+  DartType buildType(ElementImpl context, EntityRef type,
       {bool defaultVoid: false,
       bool instantiateToBoundsAllowed: true,
       bool declaredType: false}) {
@@ -1641,20 +1643,20 @@
       }
     }
     if (type.paramReference != 0) {
-      return typeParameterContext.getTypeParameterType(type.paramReference);
+      return context.typeParameterContext
+          .getTypeParameterType(type.paramReference);
     } else if (type.entityKind == EntityRefKind.genericFunctionType) {
       GenericFunctionTypeElement element =
-          new GenericFunctionTypeElementImpl.forSerialized(
-              type, typeParameterContext);
+          new GenericFunctionTypeElementImpl.forSerialized(context, type);
       return element.type;
     } else if (type.syntheticReturnType != null) {
-      FunctionElementImpl element =
-          new FunctionElementImpl_forLUB(unit, typeParameterContext, type);
+      FunctionElementImpl element = new FunctionElementImpl_forLUB(
+          unit, context.typeParameterContext, type);
       return element.type;
     } else {
       DartType getTypeArgument(int i) {
         if (i < type.typeArguments.length) {
-          return buildType(type.typeArguments[i], typeParameterContext,
+          return buildType(context, type.typeArguments[i],
               declaredType: declaredType);
         } else {
           return DynamicTypeImpl.instance;
@@ -1839,6 +1841,11 @@
                 summaryResynthesizer, location);
             isDeclarableType = true;
             break;
+          case ReferenceKind.genericFunctionTypedef:
+            element = new GenericTypeAliasElementHandle(
+                summaryResynthesizer, location);
+            isDeclarableType = true;
+            break;
           case ReferenceKind.variable:
             Element enclosingElement = enclosingInfo.element;
             if (enclosingElement is ExecutableElement) {
@@ -1898,18 +1905,15 @@
    * [typeArgumentRefs] to the given linked [info].  Return [DynamicTypeImpl]
    * if the [info] is unresolved.
    */
-  DartType _createConstructorDefiningType(
-      TypeParameterizedElementMixin typeParameterContext,
-      _ReferenceInfo info,
-      List<EntityRef> typeArgumentRefs) {
+  DartType _createConstructorDefiningType(ElementImpl context,
+      _ReferenceInfo info, List<EntityRef> typeArgumentRefs) {
     bool isClass = info.element is ClassElement;
     _ReferenceInfo classInfo = isClass ? info : info.enclosing;
     if (classInfo == null) {
       return DynamicTypeImpl.instance;
     }
-    List<DartType> typeArguments = typeArgumentRefs
-        .map((t) => buildType(t, typeParameterContext))
-        .toList();
+    List<DartType> typeArguments =
+        typeArgumentRefs.map((t) => buildType(context, t)).toList();
     return classInfo.buildType(true, typeArguments.length, (i) {
       if (i < typeArguments.length) {
         return typeArguments[i];
@@ -1923,10 +1927,10 @@
    * Return the [ConstructorElement] corresponding to the given [entry].
    */
   ConstructorElement _getConstructorForEntry(
-      TypeParameterizedElementMixin typeParameterContext, EntityRef entry) {
+      ElementImpl context, EntityRef entry) {
     _ReferenceInfo info = getReferenceInfo(entry.reference);
-    DartType type = _createConstructorDefiningType(
-        typeParameterContext, info, entry.typeArguments);
+    DartType type =
+        _createConstructorDefiningType(context, info, entry.typeArguments);
     if (type is InterfaceType) {
       return _getConstructorForInfo(type, info);
     }
diff --git a/pkg/analyzer/lib/src/summary/summarize_ast.dart b/pkg/analyzer/lib/src/summary/summarize_ast.dart
index 36fda8b..1c2ed1d 100644
--- a/pkg/analyzer/lib/src/summary/summarize_ast.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_ast.dart
@@ -799,11 +799,11 @@
     scopes.add(typeParameterScope);
     EntityRefBuilder b = new EntityRefBuilder();
     b.entityKind = EntityRefKind.genericFunctionType;
+    b.typeParameters =
+        serializeTypeParameters(node.typeParameters, typeParameterScope);
     b.syntheticReturnType = node.returnType == null
         ? serializeDynamic()
         : serializeTypeName(node.returnType);
-    b.typeParameters =
-        serializeTypeParameters(node.typeParameters, typeParameterScope);
     b.syntheticParams = node.parameters.parameters
         .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
         .toList();
diff --git a/pkg/analyzer/test/dart/element/builder_test.dart b/pkg/analyzer/test/dart/element/builder_test.dart
index ecbb202..033e66e 100644
--- a/pkg/analyzer/test/dart/element/builder_test.dart
+++ b/pkg/analyzer/test/dart/element/builder_test.dart
@@ -1113,6 +1113,19 @@
     expect(variableElement.initializer, isNotNull);
   }
 
+  void test_genericFunction_isExpression() {
+    buildElementsForText('main(p) { p is Function(int a, String); }');
+    var main = compilationUnit.declarations[0] as FunctionDeclaration;
+    var body = main.functionExpression.body as BlockFunctionBody;
+    var statement = body.block.statements[0] as ExpressionStatement;
+    var expression = statement.expression as IsExpression;
+    var typeNode = expression.type as GenericFunctionType;
+    var typeElement = typeNode.type.element as GenericFunctionTypeElementImpl;
+    expect(typeElement.parameters, hasLength(2));
+    expect(typeElement.parameters[0].name, 'a');
+    expect(typeElement.parameters[1].name, '');
+  }
+
   void test_visitDefaultFormalParameter_local() {
     CompilationUnit unit = parseCompilationUnit('''
 main() {
@@ -1183,6 +1196,16 @@
    */
   void checkMetadata(Element element);
 
+  void test_genericFunction_asTopLevelVariableType() {
+    buildElementsForText('int Function(int a, String) v;');
+    var v = compilationUnit.declarations[0] as TopLevelVariableDeclaration;
+    var typeNode = v.variables.type as GenericFunctionType;
+    var typeElement = typeNode.type.element as GenericFunctionTypeElementImpl;
+    expect(typeElement.parameters, hasLength(2));
+    expect(typeElement.parameters[0].name, 'a');
+    expect(typeElement.parameters[1].name, '');
+  }
+
   void test_metadata_fieldDeclaration() {
     List<FieldElement> fields =
         buildElementsForText('class C { @a int x, y; }').types[0].fields;
diff --git a/pkg/analyzer/test/generated/declaration_resolver_test.dart b/pkg/analyzer/test/generated/declaration_resolver_test.dart
index 2a034bc..8b0a4e3 100644
--- a/pkg/analyzer/test/generated/declaration_resolver_test.dart
+++ b/pkg/analyzer/test/generated/declaration_resolver_test.dart
@@ -468,6 +468,109 @@
     expect(getterName.staticElement, same(setterElement));
   }
 
+  test_genericFunction_asFunctionReturnType() async {
+    String code = r'''
+Function(int, String) f() => null;
+''';
+    CompilationUnit unit = await resolveSource(code);
+    // re-resolve
+    _cloneResolveUnit(unit);
+    // no other validations than built into DeclarationResolver
+  }
+
+  test_genericFunction_asGenericFunctionReturnType() async {
+    String code = r'''
+typedef F<T> = int Function(T t, S s) Function<S>(int);
+''';
+    CompilationUnit unit = await resolveSource(code);
+    // re-resolve
+    _cloneResolveUnit(unit);
+    // no other validations than built into DeclarationResolver
+  }
+
+  test_genericFunction_asMethodReturnType() async {
+    String code = r'''
+class C {
+  Function(int, String) m() => null;
+}
+''';
+    CompilationUnit unit = await resolveSource(code);
+    // re-resolve
+    _cloneResolveUnit(unit);
+    // no other validations than built into DeclarationResolver
+  }
+
+  test_genericFunction_asParameterReturnType() async {
+    String code = r'''
+f(Function(int, String) p) => null;
+''';
+    CompilationUnit unit = await resolveSource(code);
+    // re-resolve
+    _cloneResolveUnit(unit);
+    // no other validations than built into DeclarationResolver
+  }
+
+  test_genericFunction_asTopLevelVariableType() async {
+    String code = r'''
+int Function(int, String) v;
+''';
+    CompilationUnit unit = await resolveSource(code);
+    // re-resolve
+    _cloneResolveUnit(unit);
+    // no other validations than built into DeclarationResolver
+  }
+
+  test_genericFunction_asTypeArgument() async {
+    String code = r'''
+List<Function(int)> v;
+''';
+    CompilationUnit unit = await resolveSource(code);
+    // re-resolve
+    _cloneResolveUnit(unit);
+    // no other validations than built into DeclarationResolver
+  }
+
+  test_genericFunction_asTypeArgument_lessNodes() async {
+    String code = r'''
+Map<Function<int>> v;
+''';
+    CompilationUnit unit = await resolveSource(code);
+    // re-resolve
+    _cloneResolveUnit(unit);
+    // no other validations than built into DeclarationResolver
+  }
+
+  test_genericFunction_asTypeArgument_moreNodes() async {
+    String code = r'''
+List<Function<int>, Function<String>> v;
+''';
+    CompilationUnit unit = await resolveSource(code);
+    // re-resolve
+    _cloneResolveUnit(unit);
+    // no other validations than built into DeclarationResolver
+  }
+
+  test_genericFunction_asTypeArgument_noNodes() async {
+    String code = r'''
+List v;
+''';
+    CompilationUnit unit = await resolveSource(code);
+    // re-resolve
+    _cloneResolveUnit(unit);
+    // no other validations than built into DeclarationResolver
+  }
+
+  test_genericFunction_asTypeArgument_ofInitializer() async {
+    String code = r'''
+var v = <Function(int)>[];
+''';
+    CompilationUnit unit = await resolveSource(code);
+    CompilationUnit newUnit = _cloneResolveUnit(unit);
+    var v = newUnit.declarations[0] as TopLevelVariableDeclaration;
+    var initializer = v.variables.variables[0].initializer as ListLiteral;
+    expect(initializer.typeArguments.arguments[0].type, isNotNull);
+  }
+
   test_invalid_functionDeclaration_getter_inFunction() async {
     String code = r'''
 var v = (() {
diff --git a/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart
index be0f9b5..b18fe32 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart
@@ -16,9 +16,4 @@
 class NonErrorResolverTest_Driver extends NonErrorResolverTest {
   @override
   bool get enableNewAnalysisDriver => true;
-
-  @failingTest
-  test_genericTypeAlias_fieldAndReturnType() async {
-    return super.test_genericTypeAlias_fieldAndReturnType();
-  }
 }
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index e89057b..e516d5d 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -2158,7 +2158,7 @@
     verify([source]);
   }
 
-  test_genericTypeAlias_fieldAndReturnType() async {
+  test_genericTypeAlias_fieldAndReturnType_noTypeParameters() async {
     Source source = addSource(r'''
 typedef Foo = int Function<T>(T x);
 int foo<T>(T x) => 3;
@@ -2179,6 +2179,48 @@
     verify([source]);
   }
 
+  test_genericTypeAlias_fieldAndReturnType_typeParameters_arguments() async {
+    Source source = addSource(r'''
+typedef Foo<S> = S Function<T>(T x);
+int foo<T>(T x) => 3;
+Foo<int> bar() => foo;
+void test1() {
+  bar()<String>("hello");
+}
+
+class A {
+  Foo<int> f;
+  void test() {
+    f<String>("hello");
+  }
+}
+''');
+    await computeAnalysisResult(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  test_genericTypeAlias_fieldAndReturnType_typeParameters_noArguments() async {
+    Source source = addSource(r'''
+typedef Foo<S> = S Function<T>(T x);
+int foo<T>(T x) => 3;
+Foo bar() => foo;
+void test1() {
+  bar()<String>("hello");
+}
+
+class A {
+  Foo f;
+  void test() {
+    f<String>("hello");
+  }
+}
+''');
+    await computeAnalysisResult(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   test_genericTypeAlias_noTypeParameters() async {
     Source source = addSource(r'''
 typedef Foo = int Function<T>(T x);
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 20c2daa..e577850 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -4106,18 +4106,12 @@
 
   void test_voidVariable_statement_initializer() {
     parseStatement("void x = 0;");
-    assertErrorsWithCodes([
-      ParserErrorCode.VOID_VARIABLE,
-      ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE
-    ]);
+    assertErrorsWithCodes([ParserErrorCode.VOID_VARIABLE]);
   }
 
   void test_voidVariable_statement_noInitializer() {
     parseStatement("void x;");
-    assertErrorsWithCodes([
-      ParserErrorCode.VOID_VARIABLE,
-      ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE
-    ]);
+    assertErrorsWithCodes([ParserErrorCode.VOID_VARIABLE]);
   }
 
   void test_withBeforeExtends() {
@@ -10027,6 +10021,50 @@
     expect(arguments, hasLength(3));
   }
 
+  void test_parseClassMember_field_gftType_gftReturnType() {
+    createParser('''
+Function(int) Function(String) v;
+''');
+    ClassMember member = parser.parseClassMember('C');
+    listener.assertNoErrors();
+    expect(member, new isInstanceOf<FieldDeclaration>());
+    VariableDeclarationList fields = (member as FieldDeclaration).fields;
+    expect(fields.type, new isInstanceOf<GenericFunctionType>());
+  }
+
+  void test_parseClassMember_field_gftType_noReturnType() {
+    createParser('''
+Function(int, String) v;
+''');
+    ClassMember member = parser.parseClassMember('C');
+    listener.assertNoErrors();
+    expect(member, new isInstanceOf<FieldDeclaration>());
+    VariableDeclarationList fields = (member as FieldDeclaration).fields;
+    expect(fields.type, new isInstanceOf<GenericFunctionType>());
+  }
+
+  void test_parseClassMember_method_gftReturnType() {
+    createParser('''
+void Function<A>(core.List<core.int> x) m() => null;
+''');
+    ClassMember member = parser.parseClassMember('C');
+    listener.assertNoErrors();
+    expect(member, new isInstanceOf<MethodDeclaration>());
+    expect((member as MethodDeclaration).body,
+        new isInstanceOf<ExpressionFunctionBody>());
+  }
+
+  void test_parseClassMember_method_noReturnType() {
+    createParser('''
+Function<A>(core.List<core.int> x) m() => null;
+''');
+    ClassMember member = parser.parseClassMember('C');
+    listener.assertNoErrors();
+    expect(member, new isInstanceOf<MethodDeclaration>());
+    expect((member as MethodDeclaration).body,
+        new isInstanceOf<ExpressionFunctionBody>());
+  }
+
   void test_parseCombinator_hide() {
     createParser('hide a;');
     Combinator combinator = parser.parseCombinator();
@@ -10627,6 +10665,49 @@
     expect(reference.offset, 15);
   }
 
+  void test_parseCompilationUnitMember_function_gftReturnType() {
+    createParser('''
+void Function<A>(core.List<core.int> x) f() => null;
+''');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    listener.assertNoErrors();
+    expect(unit, isNotNull);
+    expect(unit.declarations, hasLength(1));
+  }
+
+  void test_parseCompilationUnitMember_function_noReturnType() {
+    createParser('''
+Function<A>(core.List<core.int> x) f() => null;
+''');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    listener.assertNoErrors();
+    expect(unit, isNotNull);
+    expect(unit.declarations, hasLength(1));
+  }
+
+  void test_parseCompilationUnitMember_variable_gftType_gftReturnType() {
+    createParser('''
+Function(int) Function(String) v;
+''');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    listener.assertNoErrors();
+    expect(unit, isNotNull);
+    expect(unit.declarations, hasLength(1));
+    TopLevelVariableDeclaration declaration =
+        unit.declarations[0] as TopLevelVariableDeclaration;
+    expect(declaration.variables.type, new isInstanceOf<GenericFunctionType>());
+  }
+
+  void test_parseCompilationUnitMember_variable_gftType_noReturnType() {
+    createParser('''
+Function(int, String) v;
+''');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    listener.assertNoErrors();
+    expect(unit, isNotNull);
+    expect(unit.declarations, hasLength(1));
+  }
+
   void test_parseConfiguration_noOperator_dottedIdentifier() {
     createParser("if (a.b) 'c.dart'");
     Configuration configuration = parser.parseConfiguration();
@@ -11239,6 +11320,13 @@
     expect(modifiers.varKeyword, isNotNull);
   }
 
+  void test_parseNonLabeledStatement_localFunction_gftReturnType() {
+    createParser('int Function(int) f(String s) => null;');
+    Statement statement = parser.parseNonLabeledStatement();
+    expectNotNullIfNoErrors(statement);
+    listener.assertNoErrors();
+  }
+
   void test_parseNonLabeledStatement_variableDeclaration_final_namedFunction() {
     createParser('final int Function = 0;');
     Statement statement = parser.parseNonLabeledStatement();
@@ -11246,6 +11334,61 @@
     listener.assertNoErrors();
   }
 
+  void test_parseNonLabeledStatement_variableDeclaration_gftType() {
+    createParser('int Function(int) v;');
+    Statement statement = parser.parseNonLabeledStatement();
+    expectNotNullIfNoErrors(statement);
+    listener.assertNoErrors();
+  }
+
+  void
+      test_parseNonLabeledStatement_variableDeclaration_gftType_functionReturnType() {
+    createParser(
+        'Function Function(int x1, {Function x}) Function<B extends core.int>(int x) l771;');
+    Statement statement = parser.parseNonLabeledStatement();
+    expectNotNullIfNoErrors(statement);
+    listener.assertNoErrors();
+  }
+
+  void
+      test_parseNonLabeledStatement_variableDeclaration_gftType_gftReturnType() {
+    createParser('Function(int) Function(int) v;');
+    Statement statement = parser.parseNonLabeledStatement();
+    expectNotNullIfNoErrors(statement);
+    listener.assertNoErrors();
+  }
+
+  void
+      test_parseNonLabeledStatement_variableDeclaration_gftType_gftReturnType2() {
+    createParser('int Function(int) Function(int) v;');
+    Statement statement = parser.parseNonLabeledStatement();
+    expectNotNullIfNoErrors(statement);
+    listener.assertNoErrors();
+  }
+
+  void
+      test_parseNonLabeledStatement_variableDeclaration_gftType_noReturnType() {
+    createParser('Function(int) v;');
+    Statement statement = parser.parseNonLabeledStatement();
+    expectNotNullIfNoErrors(statement);
+    listener.assertNoErrors();
+  }
+
+  void test_parseNonLabeledStatement_variableDeclaration_gftType_returnType() {
+    createParser('int Function<T>() v;');
+    Statement statement = parser.parseNonLabeledStatement();
+    expectNotNullIfNoErrors(statement);
+    listener.assertNoErrors();
+  }
+
+  void
+      test_parseNonLabeledStatement_variableDeclaration_gftType_voidReturnType() {
+    createParser('void Function() v;');
+    Statement statement = parser.parseNonLabeledStatement();
+    expectNotNullIfNoErrors(statement);
+    listener.assertNoErrors();
+  }
+
   void test_parseOptionalReturnType() {
     // TODO(brianwilkerson) Implement tests for this method.
   }
@@ -11302,6 +11445,34 @@
     expect(typeName.typeArguments, isNull);
   }
 
+  void test_parseStatement_function_gftReturnType() {
+    createParser('''
+void Function<A>(core.List<core.int> x) m() => null;
+''');
+    Statement statement = parser.parseStatement2();
+    expect(statement, new isInstanceOf<FunctionDeclarationStatement>());
+    expect(
+        (statement as FunctionDeclarationStatement)
+            .functionDeclaration
+            .functionExpression
+            .body,
+        new isInstanceOf<ExpressionFunctionBody>());
+  }
+
+  void test_parseStatement_function_noReturnType() {
+    createParser('''
+Function<A>(core.List<core.int> x) m() => null;
+''');
+    Statement statement = parser.parseStatement2();
+    expect(statement, new isInstanceOf<FunctionDeclarationStatement>());
+    expect(
+        (statement as FunctionDeclarationStatement)
+            .functionDeclaration
+            .functionExpression
+            .body,
+        new isInstanceOf<ExpressionFunctionBody>());
+  }
+
   void test_parseStatements_multiple() {
     List<Statement> statements = parseStatements("return; return;", 2);
     expect(statements, hasLength(2));
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 5f6ee00..7aefb1f 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -442,13 +442,26 @@
     writeDocumentation(e);
     writeMetadata(e, '', '\n');
 
-    buffer.write('typedef ');
-    writeType2(e.returnType);
+    if (e is GenericTypeAliasElement) {
+      buffer.write('typedef ');
+      writeName(e);
+      writeTypeParameterElements(e.typeParameters);
 
-    writeName(e);
+      buffer.write(' = ');
 
-    writeTypeParameterElements(e.typeParameters);
-    writeParameterElements(e.parameters);
+      writeType(e.function.returnType);
+      buffer.write(' Function');
+      writeTypeParameterElements(e.function.typeParameters);
+      writeParameterElements(e.function.parameters);
+    } else {
+      buffer.write('typedef ');
+      writeType2(e.returnType);
+
+      writeName(e);
+
+      writeTypeParameterElements(e.typeParameters);
+      writeParameterElements(e.parameters);
+    }
 
     buffer.writeln(';');
   }
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 38455bc..aec154d 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -8542,6 +8542,82 @@
     }
   }
 
+  test_genericFunction_asFunctionReturnType() {
+    shouldCompareLibraryElements = false;
+    var library = checkLibrary(r'''
+int Function(int a, String b) f() => null;
+''');
+    checkElementText(
+        library,
+        r'''
+(int, String) → int f() {}
+''');
+  }
+
+  test_genericFunction_asFunctionTypedParameterReturnType() {
+    shouldCompareLibraryElements = false;
+    var library = checkLibrary(r'''
+void f(int Function(int a, String b) p(num c)) => null;
+''');
+    checkElementText(
+        library,
+        r'''
+void f((num) → (int, String) → int p) {}
+''');
+  }
+
+  test_genericFunction_asGenericFunctionReturnType() {
+    shouldCompareLibraryElements = false;
+    var library = checkLibrary(r'''
+typedef F = void Function(String a) Function(int b);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F = (String) → void Function(int b);
+''');
+  }
+
+  test_genericFunction_asMethodReturnType() {
+    shouldCompareLibraryElements = false;
+    var library = checkLibrary(r'''
+class C {
+  int Function(int a, String b) m() => null;
+}
+''');
+    checkElementText(
+        library,
+        r'''
+class C {
+  (int, String) → int m() {}
+}
+''');
+  }
+
+  test_genericFunction_asParameterType() {
+    shouldCompareLibraryElements = false;
+    var library = checkLibrary(r'''
+void f(int Function(int a, String b) p) => null;
+''');
+    checkElementText(
+        library,
+        r'''
+void f((int, String) → int p) {}
+''');
+  }
+
+  test_genericFunction_asTopLevelVariableType() {
+    shouldCompareLibraryElements = false;
+    var library = checkLibrary(r'''
+int Function(int a, String b) v;
+''');
+    checkElementText(
+        library,
+        r'''
+(int, String) → int v;
+''');
+  }
+
   test_getElement_constructor_named() {
     String text = 'class C { C.named(); }';
     Source source = addLibrarySource('/test.dart', text);
@@ -13860,8 +13936,50 @@
   }
 
   test_typedef_generic() {
-    checkLibrary(
-        'typedef F<T> = Function<S>(List<S> list, Function<A>(A), T);');
+    var library = checkLibrary(
+        'typedef F<T> = int Function<S>(List<S> list, num Function<A>(A), T);');
+    if (isStrongMode) {
+      checkElementText(
+          library,
+          r'''
+typedef F<T> = int Function<S>(List<S> list, <A>(A) → num , T );
+''');
+    } else {
+      checkElementText(
+          library,
+          r'''
+typedef F<T> = int Function<S>(List<S> list, <A>(A) → num , T );
+''');
+    }
+  }
+
+  test_typedef_generic_asFieldType() {
+    shouldCompareLibraryElements = false;
+    var library = checkLibrary(r'''
+typedef Foo<S> = S Function<T>(T x);
+class A {
+  Foo<int> f;
+}
+''');
+    if (isStrongMode) {
+      checkElementText(
+          library,
+          r'''
+typedef Foo<S> = S Function<T>(T x);
+class A {
+  <T>(T) → int f;
+}
+''');
+    } else {
+      checkElementText(
+          library,
+          r'''
+typedef Foo<S> = S Function<T>(T x);
+class A {
+  <T>(T) → int f;
+}
+''');
+    }
   }
 
   test_typedef_parameter_parameters() {
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index a765d6c..b76f860 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -6455,6 +6455,14 @@
         linked.exportNames[0], absUri('/a.dart'), 'F', ReferenceKind.typedef);
   }
 
+  test_export_typedef_genericFunction() {
+    addNamedSource('/a.dart', 'typedef F<S> = S Function<T>(T x);');
+    serializeLibraryText('export "a.dart";');
+    expect(linked.exportNames, hasLength(1));
+    checkExportName(linked.exportNames[0], absUri('/a.dart'), 'F',
+        ReferenceKind.genericFunctionTypedef);
+  }
+
   test_export_uri() {
     addNamedSource('/a.dart', 'library my.lib;');
     String uriString = '"a.dart"';
@@ -10135,6 +10143,60 @@
     checkDocumentationComment(typedef.documentationComment, text);
   }
 
+  test_typedef_genericFunction_reference() {
+    EntityRef typeRef = serializeTypeText('F',
+        otherDeclarations: 'typedef F<S> = S Function<T>(T x);');
+    checkTypeRef(typeRef, null, 'F',
+        numTypeParameters: 1,
+        expectedKind: ReferenceKind.genericFunctionTypedef);
+  }
+
+  test_typedef_genericFunction_typeNames() {
+    UnlinkedTypedef typedef =
+        serializeTypedefText('typedef F<S> = S Function(int x, String y);');
+    expect(typedef.style, TypedefStyle.genericFunctionType);
+    expect(typedef.typeParameters, hasLength(1));
+    expect(typedef.typeParameters[0].name, 'S');
+    expect(typedef.parameters, isEmpty);
+
+    EntityRef genericFunction = typedef.returnType;
+    expect(genericFunction.entityKind, EntityRefKind.genericFunctionType);
+    expect(genericFunction.typeParameters, isEmpty);
+
+    List<UnlinkedParam> functionParameters = genericFunction.syntheticParams;
+    expect(functionParameters, hasLength(2));
+    expect(functionParameters[0].name, 'x');
+    expect(functionParameters[1].name, 'y');
+    checkLinkedTypeRef(functionParameters[0].type, 'dart:core', 'int');
+    checkLinkedTypeRef(functionParameters[1].type, 'dart:core', 'String');
+
+    checkParamTypeRef(genericFunction.syntheticReturnType, 1);
+  }
+
+  test_typedef_genericFunction_typeParameters() {
+    UnlinkedTypedef typedef =
+        serializeTypedefText('typedef F<S> = S Function<T1, T2>(T1 x, T2 y);');
+    expect(typedef.style, TypedefStyle.genericFunctionType);
+    expect(typedef.typeParameters, hasLength(1));
+    expect(typedef.typeParameters[0].name, 'S');
+    expect(typedef.parameters, isEmpty);
+
+    EntityRef genericFunction = typedef.returnType;
+    expect(genericFunction.entityKind, EntityRefKind.genericFunctionType);
+
+    expect(genericFunction.typeParameters, hasLength(2));
+    expect(genericFunction.typeParameters[0].name, 'T1');
+    expect(genericFunction.typeParameters[1].name, 'T2');
+
+    expect(genericFunction.syntheticParams, hasLength(2));
+    expect(genericFunction.syntheticParams[0].name, 'x');
+    expect(genericFunction.syntheticParams[1].name, 'y');
+    checkParamTypeRef(genericFunction.syntheticParams[0].type, 2);
+    checkParamTypeRef(genericFunction.syntheticParams[1].type, 1);
+
+    checkParamTypeRef(genericFunction.syntheticReturnType, 3);
+  }
+
   test_typedef_name() {
     String text = 'typedef F();';
     UnlinkedTypedef type = serializeTypedefText(text);
diff --git a/runtime/bin/secure_socket_boringssl.cc b/runtime/bin/secure_socket_boringssl.cc
index f2df95d..a3740a8 100644
--- a/runtime/bin/secure_socket_boringssl.cc
+++ b/runtime/bin/secure_socket_boringssl.cc
@@ -83,24 +83,26 @@
 // Get the error messages from BoringSSL, and put them in buffer as a
 // null-terminated string.
 static void FetchErrorString(const SSL* ssl, TextBuffer* text_buffer) {
-  uint32_t error = 0;
-  const char* path = NULL;
-  int line = -1;
   const char* sep = File::PathSeparator();
-  do {
-    error = ERR_get_error_line(&path, &line);
-    const char* file = strrchr(path, sep[0]);
-    path = file ? file + 1 : path;
+  while (true) {
+    const char* path = NULL;
+    int line = -1;
+    uint32_t error = ERR_get_error_line(&path, &line);
+    if (error == 0) {
+      break;
+    }
+    text_buffer->Printf("\n\t%s", ERR_reason_error_string(error));
     if ((ssl != NULL) && (ERR_GET_LIB(error) == ERR_LIB_SSL) &&
         (ERR_GET_REASON(error) == SSL_R_CERTIFICATE_VERIFY_FAILED)) {
       intptr_t result = SSL_get_verify_result(ssl);
-      text_buffer->Printf("\n\t%s: %s (%s:%d)", ERR_reason_error_string(error),
-                          X509_verify_cert_error_string(result), path, line);
-    } else if (error != 0) {
-      text_buffer->Printf("\n\t%s (%s:%d)", ERR_reason_error_string(error),
-                          path, line);
+      text_buffer->Printf(": %s", X509_verify_cert_error_string(result));
     }
-  } while (error != 0);
+    if ((path != NULL) && (line >= 0)) {
+      const char* file = strrchr(path, sep[0]);
+      path = file ? file + 1 : path;
+      text_buffer->Printf("(%s:%d)", path, line);
+    }
+  }
 }
 
 
diff --git a/tools/VERSION b/tools/VERSION
index e09399d..f52e40f 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
 MINOR 23
 PATCH 0
 PRERELEASE 11
-PRERELEASE_PATCH 7
+PRERELEASE_PATCH 8