Version 2.15.0-238.0.dev

Merge commit '4e822a354058bc0ed8a441e6d59c4355170c2e8d' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d770091..7ae5db7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -494,7 +494,9 @@
 
 #### Linter
 
-Updated the Linter to `1.13.0`, which includes changes that
+Updated the Linter to `1.14.0`, which includes changes that
+- fix `omit_local_variable_types` to not flag a local type that is 
+  required for inference.
 - allow `while (true) { ... }` in `literal_only_boolean_expressions`.
 - fix `file_names` to report at the start of the file (not the entire
   compilation unit).
diff --git a/DEPS b/DEPS
index 3f5007c..72dd637 100644
--- a/DEPS
+++ b/DEPS
@@ -122,7 +122,7 @@
   "intl_tag": "0.17.0-nullsafety",
   "jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_rev": "7e00f893440a72de0637970325e4ea44bd1e8c8e",
-  "linter_tag": "1.13.0",
+  "linter_tag": "1.14.0",
   "lints_tag": "f9670df2a66e0ec12eb51554e70c1cbf56c8f5d0",
   "logging_rev": "575781ef196e4fed4fb737e38fb4b73d62727187",
   "markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 362575d..b9efa0a 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -3221,7 +3221,7 @@
 /// An expression that implicitly makes reference to a method.
 ///
 /// Clients may not extend, implement or mix-in this class.
-abstract class MethodReferenceExpression implements AstNode {
+abstract class MethodReferenceExpression implements Expression {
   /// Return the element associated with the expression based on the static
   /// types, or `null` if the AST structure has not been resolved, or there is
   /// no meaningful static element to return (e.g. because this is a
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 6e2918a..ec080e8 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -3004,11 +3004,15 @@
   ///
   /// Throws an [ArgumentError] if either node is `null`, if the old node does
   /// not have a parent node, or if the AST structure has been corrupted.
-  static bool replace(AstNode oldNode, AstNode newNode) {
+  ///
+  /// If [newNode] is the parent of [oldNode] already (because [newNode] became
+  /// the parent of [oldNode] in its constructor), this action will loop
+  /// infinitely; pass [oldNode]'s previous parent as [parent] to avoid this.
+  static bool replace(AstNode oldNode, AstNode newNode, {AstNode? parent}) {
     if (identical(oldNode, newNode)) {
       return true;
     }
-    var parent = oldNode.parent;
+    parent ??= oldNode.parent;
     if (parent == null) {
       throw ArgumentError("The old node is not a child of another node");
     }
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index ce90a43..ef329f4 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -312,8 +312,12 @@
         .toList();
   }
 
-  /// Given a type t, if t is an interface type with a call method defined,
-  /// return the function type for the call method, otherwise return null.
+  /// Given a type [t], if [t] is an interface type with a `call` method
+  /// defined, return the function type for the `call` method, otherwise return
+  /// `null`.
+  ///
+  /// This does not find extension methods (which are not defined on an
+  /// interface type); it is meant to find implicit call references.
   FunctionType? getCallMethodType(DartType t) {
     if (t is InterfaceType) {
       return t
@@ -685,7 +689,7 @@
       return true;
     }
 
-    // A call method tearoff
+    // A 'call' method tearoff.
     if (fromType is InterfaceType &&
         !isNullable(fromType) &&
         acceptsFunctionType(toType)) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
index 53c06aa..718c99b 100644
--- a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
@@ -204,9 +204,10 @@
     DartType assignedType;
     DartType nodeType;
 
+    var rightHandSide = node.rightHandSide;
     var operator = node.operator.type;
     if (operator == TokenType.EQ) {
-      assignedType = node.rightHandSide.typeOrThrow;
+      assignedType = rightHandSide.typeOrThrow;
       nodeType = assignedType;
     } else if (operator == TokenType.QUESTION_QUESTION_EQ) {
       var leftType = node.readType!;
@@ -216,7 +217,7 @@
         leftType = _typeSystem.promoteToNonNull(leftType);
       }
 
-      assignedType = node.rightHandSide.typeOrThrow;
+      assignedType = rightHandSide.typeOrThrow;
       nodeType = _typeSystem.getLeastUpperBound(leftType, assignedType);
     } else if (operator == TokenType.AMPERSAND_AMPERSAND_EQ ||
         operator == TokenType.BAR_BAR_EQ) {
@@ -226,7 +227,7 @@
       var operatorElement = node.staticElement;
       if (operatorElement != null) {
         var leftType = node.readType!;
-        var rightType = node.rightHandSide.typeOrThrow;
+        var rightType = rightHandSide.typeOrThrow;
         assignedType = _typeSystem.refineBinaryExpressionType(
           leftType,
           operator,
@@ -241,6 +242,10 @@
     }
 
     _inferenceHelper.recordStaticType(node, nodeType);
+    var callReference = _resolver.insertImplicitCallReference(rightHandSide);
+    if (callReference != rightHandSide) {
+      assignedType = callReference.typeOrThrow;
+    }
 
     // TODO(scheglov) Remove from ErrorVerifier?
     _checkForInvalidAssignment(
diff --git a/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart b/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart
index 7a39ba8..077946d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart
@@ -369,6 +369,11 @@
   }
 
   @override
+  bool visitImplicitCallReference(ImplicitCallReference node) {
+    return _nodeExits(node.expression);
+  }
+
+  @override
   bool visitIndexExpression(IndexExpression node) {
     Expression target = node.realTarget;
     if (_nodeExits(target)) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
index 515cc1e..192c7e5 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
@@ -78,10 +78,10 @@
       } else if (functionType is FunctionType) {
         _resolve(node: node, rawType: functionType);
       } else {
-        var callMethodType =
-            _resolver.typeSystem.getCallMethodType(functionType);
-        if (callMethodType != null) {
-          _resolve(node: node, rawType: callMethodType);
+        var callMethod = _getCallMethod(node, function.staticType);
+        if (callMethod is MethodElement) {
+          _resolveAsImplicitCallReference(node, callMethod);
+          return;
         } else {
           _resolveDisallowedExpression(node, functionType);
         }
@@ -98,7 +98,7 @@
     if (prefixElement is VariableElement) {
       prefixType = prefixElement.type;
     } else if (prefixElement is PropertyAccessorElement) {
-      prefixType = prefixElement.returnType;
+      prefixType = prefixElement.variable.type;
     }
 
     if (prefixType != null && prefixType.isDynamic) {
@@ -146,6 +146,27 @@
     }
   }
 
+  ExecutableElement? _getCallMethod(
+      FunctionReferenceImpl node, DartType? type) {
+    if (type is! InterfaceType) {
+      return null;
+    }
+    if (type.nullabilitySuffix == NullabilitySuffix.question) {
+      // If the interface type is nullable, only an applicable extension method
+      // applies.
+      return _extensionResolver
+          .findExtension(type, node, FunctionElement.CALL_METHOD_NAME)
+          .getter;
+    }
+    // Otherwise, a 'call' method on the interface, or on an applicable
+    // extension method applies.
+    return type.lookUpMethod2(
+            FunctionElement.CALL_METHOD_NAME, type.element.library) ??
+        _extensionResolver
+            .findExtension(type, node, FunctionElement.CALL_METHOD_NAME)
+            .getter;
+  }
+
   void _reportInvalidAccessToStaticMember(
     SimpleIdentifier nameNode,
     ExecutableElement element, {
@@ -245,6 +266,27 @@
     }
   }
 
+  void _resolveAsImplicitCallReference(
+      FunctionReferenceImpl node, MethodElement callMethod) {
+    // `node<...>` is to be treated as `node.call<...>`.
+    var callMethodType = callMethod.type;
+    var typeArgumentTypes = _checkTypeArguments(
+      // `node.typeArguments`, coming from the parser, is never null.
+      node.typeArguments!, FunctionElement.CALL_METHOD_NAME,
+      callMethodType.typeFormals,
+      CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION,
+    );
+    var callReference = astFactory.implicitCallReference(
+      expression: node.function,
+      staticElement: callMethod,
+      typeArguments: node.typeArguments,
+      typeArgumentTypes: typeArgumentTypes,
+    );
+    NodeReplacer.replace(node, callReference);
+    var instantiatedType = callMethodType.instantiate(typeArgumentTypes);
+    callReference.staticType = instantiatedType;
+  }
+
   void _resolveConstructorReference(FunctionReferenceImpl node) {
     // TODO(srawlins): Rewrite and resolve [node] as a constructor reference.
     node.function.accept(_resolver);
@@ -427,6 +469,11 @@
   void _resolvePropertyAccessFunction(
       FunctionReferenceImpl node, PropertyAccessImpl function) {
     function.accept(_resolver);
+    var callMethod = _getCallMethod(node, function.staticType);
+    if (callMethod is MethodElement) {
+      _resolveAsImplicitCallReference(node, callMethod);
+      return;
+    }
     var target = function.realTarget;
 
     DartType targetType;
@@ -439,7 +486,7 @@
       if (targetElement is VariableElement) {
         targetType = targetElement.type;
       } else if (targetElement is PropertyAccessorElement) {
-        targetType = targetElement.returnType;
+        targetType = targetElement.variable.type;
       } else {
         // TODO(srawlins): Can we get here?
         node.staticType = DynamicTypeImpl.instance;
@@ -540,6 +587,11 @@
       }
     } else if (element is ExecutableElement) {
       node.function.accept(_resolver);
+      var callMethod = _getCallMethod(node, node.function.staticType);
+      if (callMethod is MethodElement) {
+        _resolveAsImplicitCallReference(node, callMethod);
+        return;
+      }
       _resolve(
         node: node,
         rawType: node.function.typeOrThrow as FunctionType,
@@ -604,7 +656,7 @@
         }
 
         if (method is PropertyAccessorElement) {
-          _resolve(node: node, rawType: method.returnType);
+          _resolve(node: node, rawType: method.variable.type);
           return;
         }
 
@@ -661,7 +713,12 @@
       return;
     } else if (element is PropertyAccessorElement) {
       function.staticElement = element;
-      function.staticType = element.returnType;
+      function.staticType = element.variable.type;
+      var callMethod = _getCallMethod(node, element.variable.type);
+      if (callMethod is MethodElement) {
+        _resolveAsImplicitCallReference(node, callMethod);
+        return;
+      }
       _resolve(node: node, rawType: element.returnType);
       return;
     } else if (element is ExecutableElement) {
@@ -672,6 +729,11 @@
     } else if (element is VariableElement) {
       function.staticElement = element;
       function.staticType = element.type;
+      var callMethod = _getCallMethod(node, element.type);
+      if (callMethod is MethodElement) {
+        _resolveAsImplicitCallReference(node, callMethod);
+        return;
+      }
       _resolve(node: node, rawType: element.type);
       return;
     } else if (element is ExtensionElement) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
index e781de9..a9fce6a 100644
--- a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
@@ -98,6 +98,7 @@
     }
 
     node.visitChildren(_resolver);
+    _insertImplicitCallReferences(node);
     _resolveListLiteral2(node);
   }
 
@@ -154,6 +155,7 @@
     }
 
     node.visitChildren(_resolver);
+    _insertImplicitCallReferences(node);
     _resolveSetOrMapLiteral2(node);
   }
 
@@ -597,6 +599,34 @@
     );
   }
 
+  void _insertImplicitCallReference(CollectionElement? node) {
+    if (node is Expression) {
+      _resolver.insertImplicitCallReference(node);
+    } else if (node is MapLiteralEntry) {
+      _insertImplicitCallReference(node.key);
+      _insertImplicitCallReference(node.value);
+    } else if (node is IfElement) {
+      _insertImplicitCallReference(node.thenElement);
+      _insertImplicitCallReference(node.elseElement);
+    } else if (node is ForElement) {
+      _insertImplicitCallReference(node.body);
+    }
+    // Nothing to do for [SpreadElement] as analyzer does not desugar this
+    // element.
+  }
+
+  void _insertImplicitCallReferences(TypedLiteral node) {
+    if (node is ListLiteral) {
+      for (var element in node.elements) {
+        _insertImplicitCallReference(element);
+      }
+    } else if (node is SetOrMapLiteral) {
+      for (var element in node.elements) {
+        _insertImplicitCallReference(element);
+      }
+    }
+  }
+
   void _pushCollectionTypesDown(CollectionElement? element,
       {DartType? elementType,
       required DartType iterableType,
diff --git a/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
index 1e41759..8542adc 100644
--- a/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
@@ -71,6 +71,11 @@
       element.constantInitializer = initializer;
     }
 
+    var callReference = _resolver.insertImplicitCallReference(initializer);
+    if (callReference != initializer) {
+      initializer = callReference;
+    }
+
     _resolver.checkForInvalidAssignment(node.name, initializer,
         whyNotPromoted: whyNotPromoted);
   }
diff --git a/pkg/analyzer/lib/src/error/literal_element_verifier.dart b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
index b233a83..a6962f4 100644
--- a/pkg/analyzer/lib/src/error/literal_element_verifier.dart
+++ b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/error_verifier.dart';
 
 /// Verifier for [CollectionElement]s in list, set, or map literals.
 class LiteralElementVerifier {
@@ -18,7 +19,7 @@
   final TypeSystemImpl typeSystem;
   final ErrorReporter errorReporter;
   final FeatureSet featureSet;
-  final bool Function(Expression) checkForUseOfVoidResult;
+  final ErrorVerifier _errorVerifier;
 
   final bool forList;
   final bool forSet;
@@ -32,7 +33,7 @@
     this.typeProvider,
     this.typeSystem,
     this.errorReporter,
-    this.checkForUseOfVoidResult, {
+    this._errorVerifier, {
     this.forList = false,
     this.forSet = false,
     this.elementType,
@@ -67,7 +68,8 @@
   void _verifyElement(CollectionElement? element) {
     if (element is Expression) {
       if (forList || forSet) {
-        if (!elementType!.isVoid && checkForUseOfVoidResult(element)) {
+        if (!elementType!.isVoid &&
+            _errorVerifier.checkForUseOfVoidResult(element)) {
           return;
         }
         _checkAssignableToElementType(element.typeOrThrow, element);
@@ -102,12 +104,14 @@
   /// and [mapValueType].
   void _verifyMapLiteralEntry(MapLiteralEntry entry) {
     var mapKeyType = this.mapKeyType;
-    if (!mapKeyType!.isVoid && checkForUseOfVoidResult(entry.key)) {
+    if (!mapKeyType!.isVoid &&
+        _errorVerifier.checkForUseOfVoidResult(entry.key)) {
       return;
     }
 
     var mapValueType = this.mapValueType;
-    if (!mapValueType!.isVoid && checkForUseOfVoidResult(entry.value)) {
+    if (!mapValueType!.isVoid &&
+        _errorVerifier.checkForUseOfVoidResult(entry.value)) {
       return;
     }
 
@@ -180,11 +184,39 @@
       var errorCode = forList
           ? CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
           : CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE;
-      errorReporter.reportErrorForNode(
-        errorCode,
-        expression,
-        [iterableElementType, elementType],
-      );
+      // Also check for an "implicit tear-off conversion" which would be applied
+      // after desugaring a spread element.
+      var implicitCallMethod = _errorVerifier.getImplicitCallMethod(
+          iterableElementType, elementType, expression);
+      if (implicitCallMethod == null) {
+        errorReporter.reportErrorForNode(
+          errorCode,
+          expression,
+          [iterableElementType, elementType],
+        );
+      } else {
+        var tearoffType = implicitCallMethod.type;
+        if (featureSet.isEnabled(Feature.constructor_tearoffs)) {
+          var typeArguments = typeSystem.inferFunctionTypeInstantiation(
+            elementType as FunctionType,
+            tearoffType,
+            errorReporter: errorReporter,
+            errorNode: expression,
+            genericMetadataIsEnabled: true,
+          )!;
+          if (typeArguments.isNotEmpty) {
+            tearoffType = tearoffType.instantiate(typeArguments);
+          }
+        }
+
+        if (!typeSystem.isAssignableTo(tearoffType, elementType)) {
+          errorReporter.reportErrorForNode(
+            errorCode,
+            expression,
+            [iterableElementType, elementType],
+          );
+        }
+      }
     }
   }
 
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index daa682e..af56535 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -499,7 +499,7 @@
   }
 
   @override
-  void visitVariableDeclaration(VariableDeclaration node) {
+  void visitVariableDeclarationList(VariableDeclarationList node) {
     _resolveAnnotations(node.metadata);
   }
 
diff --git a/pkg/analyzer/lib/src/generated/error_detection_helpers.dart b/pkg/analyzer/lib/src/generated/error_detection_helpers.dart
index 7903c73..41ecb65 100644
--- a/pkg/analyzer/lib/src/generated/error_detection_helpers.dart
+++ b/pkg/analyzer/lib/src/generated/error_detection_helpers.dart
@@ -6,6 +6,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/syntactic_entity.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/diagnostic/diagnostic.dart';
 import 'package:analyzer/error/error.dart';
@@ -29,20 +30,17 @@
   /// argument.
   void checkForArgumentTypeNotAssignable(
       Expression expression,
-      DartType? expectedStaticType,
+      DartType expectedStaticType,
       DartType actualStaticType,
       ErrorCode errorCode,
       {Map<DartType, NonPromotionReason> Function()? whyNotPromoted}) {
-    // Warning case: test static type information
-    if (expectedStaticType != null) {
-      if (!expectedStaticType.isVoid && checkForUseOfVoidResult(expression)) {
-        return;
-      }
-
-      _checkForAssignableExpressionAtType(
-          expression, actualStaticType, expectedStaticType, errorCode,
-          whyNotPromoted: whyNotPromoted);
+    if (!expectedStaticType.isVoid && checkForUseOfVoidResult(expression)) {
+      return;
     }
+
+    _checkForAssignableExpressionAtType(
+        expression, actualStaticType, expectedStaticType, errorCode,
+        whyNotPromoted: whyNotPromoted);
   }
 
   /// Verify that the given [argument] can be assigned to its corresponding
@@ -55,7 +53,7 @@
   void checkForArgumentTypeNotAssignableForArgument(Expression argument,
       {bool promoteParameterToNullable = false,
       Map<DartType, NonPromotionReason> Function()? whyNotPromoted}) {
-    _checkForArgumentTypeNotAssignableForArgument2(
+    _checkForArgumentTypeNotAssignableForArgument(
       argument: argument is NamedExpression ? argument.expression : argument,
       parameter: argument.staticParameterElement,
       promoteParameterToNullable: promoteParameterToNullable,
@@ -160,8 +158,8 @@
       return;
     }
 
-    _checkForAssignableExpression(
-        rhs, leftType, CompileTimeErrorCode.INVALID_ASSIGNMENT,
+    _checkForAssignableExpressionAtType(
+        rhs, rhs.typeOrThrow, leftType, CompileTimeErrorCode.INVALID_ASSIGNMENT,
         whyNotPromoted: whyNotPromoted);
   }
 
@@ -196,7 +194,7 @@
     if (readElement is MethodElement) {
       var parameters = readElement.parameters;
       if (parameters.isNotEmpty) {
-        _checkForArgumentTypeNotAssignableForArgument2(
+        _checkForArgumentTypeNotAssignableForArgument(
           argument: index,
           parameter: parameters[0],
           promoteParameterToNullable: false,
@@ -208,7 +206,7 @@
     if (writeElement is MethodElement) {
       var parameters = writeElement.parameters;
       if (parameters.isNotEmpty) {
-        _checkForArgumentTypeNotAssignableForArgument2(
+        _checkForArgumentTypeNotAssignableForArgument(
           argument: index,
           parameter: parameters[0],
           promoteParameterToNullable: false,
@@ -232,6 +230,27 @@
       SyntacticEntity errorEntity,
       Map<DartType, NonPromotionReason>? whyNotPromoted);
 
+  /// If an assignment from [type] to [context] is a case of an implicit 'call'
+  /// method, returns the element of the 'call' method.
+  ///
+  /// From the spec:
+  ///
+  /// > Let `e` be an expression whose static type is an interface type that has
+  /// > a method named `call`. In the case where the context type for `e`
+  /// > is a function type or the type `Function`, `e` is treated as `e.call`.
+  MethodElement? getImplicitCallMethod(
+      DartType type, DartType? context, SyntacticEntity errorNode) {
+    if (context != null &&
+        typeSystem.acceptsFunctionType(context) &&
+        type is InterfaceType &&
+        type.nullabilitySuffix != NullabilitySuffix.question) {
+      return type.lookUpMethod2(
+          FunctionElement.CALL_METHOD_NAME, type.element.library);
+    } else {
+      return null;
+    }
+  }
+
   /// Return the variable element represented by the given [expression], or
   /// `null` if there is no such element.
   VariableElement? getVariableElement(Expression? expression) {
@@ -244,48 +263,25 @@
     return null;
   }
 
-  void _checkForArgumentTypeNotAssignableForArgument2({
+  void _checkForArgumentTypeNotAssignableForArgument({
     required Expression argument,
     required ParameterElement? parameter,
     required bool promoteParameterToNullable,
     Map<DartType, NonPromotionReason> Function()? whyNotPromoted,
   }) {
     var staticParameterType = parameter?.type;
-    if (promoteParameterToNullable && staticParameterType != null) {
-      staticParameterType =
-          typeSystem.makeNullable(staticParameterType as TypeImpl);
+    if (staticParameterType != null) {
+      if (promoteParameterToNullable) {
+        staticParameterType =
+            typeSystem.makeNullable(staticParameterType as TypeImpl);
+      }
+      checkForArgumentTypeNotAssignable(
+          argument,
+          staticParameterType,
+          argument.typeOrThrow,
+          CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
+          whyNotPromoted: whyNotPromoted);
     }
-    _checkForArgumentTypeNotAssignableWithExpectedTypes(
-        argument,
-        staticParameterType,
-        CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
-        whyNotPromoted);
-  }
-
-  /// Verify that the given [expression] can be assigned to its corresponding
-  /// parameters.
-  ///
-  /// See [CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE],
-  /// [CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE],
-  /// [CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and
-  /// [CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE].
-  void _checkForArgumentTypeNotAssignableWithExpectedTypes(
-      Expression expression,
-      DartType? expectedStaticType,
-      ErrorCode errorCode,
-      Map<DartType, NonPromotionReason> Function()? whyNotPromoted) {
-    checkForArgumentTypeNotAssignable(
-        expression, expectedStaticType, expression.typeOrThrow, errorCode,
-        whyNotPromoted: whyNotPromoted);
-  }
-
-  bool _checkForAssignableExpression(
-      Expression expression, DartType expectedStaticType, ErrorCode errorCode,
-      {required Map<DartType, NonPromotionReason> Function()? whyNotPromoted}) {
-    DartType actualStaticType = expression.typeOrThrow;
-    return _checkForAssignableExpressionAtType(
-        expression, actualStaticType, expectedStaticType, errorCode,
-        whyNotPromoted: whyNotPromoted);
   }
 
   bool _checkForAssignableExpressionAtType(
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index af0cfcf..b53caa5 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -2190,9 +2190,6 @@
       awaitKeyword = parent.awaitKeyword;
     }
 
-    // Use an explicit string instead of [loopType] to remove the "<E>".
-    String loopNamedType = awaitKeyword != null ? "Stream" : "Iterable";
-
     // The object being iterated has to implement Iterable<T> for some T that
     // is assignable to the variable's type.
     // TODO(rnystrom): Move this into mostSpecificTypeArgument()?
@@ -2207,6 +2204,8 @@
     }
 
     if (!typeSystem.isAssignableTo(iterableType, requiredSequenceType)) {
+      // Use an explicit string instead of [loopType] to remove the "<E>".
+      String loopNamedType = awaitKeyword != null ? 'Stream' : 'Iterable';
       errorReporter.reportErrorForNode(
         CompileTimeErrorCode.FOR_IN_OF_INVALID_TYPE,
         node.iterable,
@@ -2231,11 +2230,48 @@
     }
 
     if (!typeSystem.isAssignableTo(sequenceElementType, variableType)) {
-      errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE,
-        node.iterable,
-        [iterableType, loopNamedType, variableType],
-      );
+      // Use an explicit string instead of [loopType] to remove the "<E>".
+      String loopNamedType = awaitKeyword != null ? 'Stream' : 'Iterable';
+
+      // A for-in loop is specified to desugar to a different set of statements
+      // which include an assignment of the sequence element's `iterator`'s
+      // `current` value, at which point "implicit tear-off conversion" may be
+      // performed. We do not perform this desugaring; instead we allow a
+      // special assignability here.
+      var implicitCallMethod = getImplicitCallMethod(
+          sequenceElementType, variableType, node.iterable);
+      if (implicitCallMethod == null) {
+        errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE,
+          node.iterable,
+          [iterableType, loopNamedType, variableType],
+        );
+      } else {
+        var tearoffType = implicitCallMethod.type;
+        // An implicit tear-off conversion does occur on the values of the
+        // iterator, but this does not guarantee their assignability.
+
+        if (_featureSet?.isEnabled(Feature.constructor_tearoffs) ?? true) {
+          var typeArguments = typeSystem.inferFunctionTypeInstantiation(
+            variableType as FunctionType,
+            tearoffType,
+            errorReporter: errorReporter,
+            errorNode: node.iterable,
+            genericMetadataIsEnabled: true,
+          )!;
+          if (typeArguments.isNotEmpty) {
+            tearoffType = tearoffType.instantiate(typeArguments);
+          }
+        }
+
+        if (!typeSystem.isAssignableTo(tearoffType, variableType)) {
+          errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE,
+            node.iterable,
+            [iterableType, loopNamedType, variableType],
+          );
+        }
+      }
     }
 
     return true;
@@ -2674,8 +2710,10 @@
   void _checkForIntNotAssignable(Expression argument) {
     var staticParameterElement = argument.staticParameterElement;
     var staticParameterType = staticParameterElement?.type;
-    checkForArgumentTypeNotAssignable(argument, staticParameterType, _intType,
-        CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE);
+    if (staticParameterType != null) {
+      checkForArgumentTypeNotAssignable(argument, staticParameterType, _intType,
+          CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE);
+    }
   }
 
   /// Verify that the given [annotation] isn't defined in a deferred library.
@@ -2863,7 +2901,7 @@
       _typeProvider,
       typeSystem,
       errorReporter,
-      checkForUseOfVoidResult,
+      this,
       forList: true,
       elementType: listElementType,
       featureSet: _featureSet!,
@@ -2951,7 +2989,7 @@
         _typeProvider,
         typeSystem,
         errorReporter,
-        checkForUseOfVoidResult,
+        this,
         forMap: true,
         mapKeyType: keyType,
         mapValueType: valueType,
@@ -3911,7 +3949,7 @@
         _typeProvider,
         typeSystem,
         errorReporter,
-        checkForUseOfVoidResult,
+        this,
         forSet: true,
         elementType: setElementType,
         featureSet: _featureSet!,
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 2c44a64..202769a 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -7,6 +7,7 @@
 import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/syntactic_entity.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -19,6 +20,7 @@
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/extensions.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
 import 'package:analyzer/src/dart/element/member.dart' show Member;
@@ -454,6 +456,13 @@
   /// See [CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE].
   void checkForArgumentTypesNotAssignableInList(ArgumentList argumentList,
       List<WhyNotPromotedGetter> whyNotPromotedList) {
+    for (var argument in argumentList.arguments) {
+      if (argument is NamedExpression) {
+        insertImplicitCallReference(argument.expression);
+      } else {
+        insertImplicitCallReference(argument);
+      }
+    }
     var arguments = argumentList.arguments;
     for (int i = 0; i < arguments.length; i++) {
       checkForArgumentTypeNotAssignableForArgument(arguments[i],
@@ -619,6 +628,69 @@
     return null;
   }
 
+  /// If `expression` should be treated as `expression.call`, inserts an
+  /// [ImplicitCallReferece] node which wraps [expression].
+  ///
+  /// If an [ImplicitCallReferece] is inserted, returns it; otherwise, returns
+  /// [expression].
+  ExpressionImpl insertImplicitCallReference(Expression expression) {
+    expression as ExpressionImpl;
+    if (!isConstructorTearoffsEnabled) {
+      // Temporarily, only create [ImplicitCallReference] nodes under the
+      // 'constructor-tearoffs' feature.
+      // TODO(srawlins): When we are ready to make a breaking change release to
+      // the analyzer package, remove this exception.
+      return expression;
+    }
+
+    var parent = expression.parent;
+    if (parent is CascadeExpression && parent.target == expression) {
+      // Do not perform an "implicit tear-off conversion" here. It should only
+      // be performed on [parent]. See
+      // https://github.com/dart-lang/language/issues/1873.
+      return expression;
+    }
+    var context = InferenceContext.getContext(expression);
+    var callMethod =
+        getImplicitCallMethod(expression.typeOrThrow, context, expression);
+    if (callMethod == null || context == null) {
+      return expression;
+    }
+
+    // `expression` is to be treated as `expression.call`.
+    context = typeSystem.flatten(context);
+    var callMethodType = callMethod.type;
+    List<DartType> typeArgumentTypes;
+    if (isConstructorTearoffsEnabled &&
+        callMethodType.typeFormals.isNotEmpty &&
+        context is FunctionType) {
+      typeArgumentTypes = typeSystem.inferFunctionTypeInstantiation(
+        context,
+        callMethodType,
+        errorNode: expression,
+        // If the constructor-tearoffs feature is enabled, then so is
+        // generic-metadata.
+        genericMetadataIsEnabled: true,
+      )!;
+      if (typeArgumentTypes.isNotEmpty) {
+        callMethodType = callMethodType.instantiate(typeArgumentTypes);
+      }
+    } else {
+      typeArgumentTypes = [];
+    }
+    var callReference = astFactory.implicitCallReference(
+      expression: expression,
+      staticElement: callMethod,
+      typeArguments: null,
+      typeArgumentTypes: typeArgumentTypes,
+    ) as ImplicitCallReferenceImpl;
+    NodeReplacer.replace(expression, callReference, parent: parent);
+
+    callReference.staticType = callMethodType;
+
+    return callReference;
+  }
+
   /// If we reached a null-shorting termination, and the [node] has null
   /// shorting, make the type of the [node] nullable.
   void nullShortingTermination(ExpressionImpl node,
@@ -1224,13 +1296,22 @@
     // to be visited in the context of the constructor field initializer node.
     //
     var fieldElement = enclosingClass!.getField(node.fieldName.name);
-    InferenceContext.setType(node.expression, fieldElement?.type);
-    node.expression.accept(this);
-    var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(node.expression);
+    var fieldType = fieldElement?.type;
+    var expression = node.expression;
+    InferenceContext.setType(expression, fieldType);
+    expression.accept(this);
+    var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(expression);
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
-    var enclosingConstructor = enclosingFunction as ConstructorElement;
     if (fieldElement != null) {
+      if (fieldType != null && expression.staticType != null) {
+        var callReference = insertImplicitCallReference(expression);
+        if (expression != callReference) {
+          checkForInvalidAssignment(node.fieldName, callReference,
+              whyNotPromoted: whyNotPromoted);
+        }
+      }
+      var enclosingConstructor = enclosingFunction as ConstructorElement;
       checkForFieldInitializerNotAssignable(node, fieldElement,
           isConstConstructor: enclosingConstructor.isConst,
           whyNotPromoted: whyNotPromoted);
@@ -1337,6 +1418,7 @@
       _thisAccessTracker.enterFunctionBody(node);
 
       super.visitExpressionFunctionBody(node);
+      insertImplicitCallReference(node.expression);
 
       flowAnalysis.flow?.handleExit();
 
@@ -1850,6 +1932,11 @@
 
     inferenceContext.bodyContext?.addReturnExpression(node.expression);
     flowAnalysis.flow?.handleExit();
+
+    var expression = node.expression;
+    if (expression != null) {
+      insertImplicitCallReference(expression);
+    }
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/test_utilities/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index f07b84c..21b51e7 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -203,6 +203,10 @@
     return _node(search, (n) => n is IfStatement);
   }
 
+  ImplicitCallReference implicitCallReference(String search) {
+    return _node(search, (n) => n is ImplicitCallReference);
+  }
+
   ImportDirective import(String search) {
     return _node(search, (n) => n is ImportDirective);
   }
diff --git a/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart b/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
index 800bc3e..e300c65 100644
--- a/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
@@ -13,6 +13,7 @@
 
 main() {
   defineReflectiveSuite(() {
+    defineReflectiveTests(AstRewriteImplicitCallReferenceTest);
     defineReflectiveTests(AstRewriteMethodInvocationTest);
     defineReflectiveTests(AstRewritePrefixedIdentifierTest);
 
@@ -26,6 +27,254 @@
 }
 
 @reflectiveTest
+class AstRewriteImplicitCallReferenceTest extends PubPackageResolutionTest {
+  test_assignment_indexExpression() async {
+    await assertNoErrorsInCode('''
+abstract class C {
+  void call(int t) => t;
+}
+
+void Function(int) foo(C c) {
+  var map = <int, C>{};
+  return map[1] = c;
+}
+''');
+
+    assertImplicitCallReference(
+      findNode.implicitCallReference('map[1] = c'),
+      findElement.method('call'),
+      'void Function(int)',
+    );
+  }
+
+  test_explicitTypeArguments() async {
+    await assertNoErrorsInCode('''
+class C {
+  T call<T>(T t) => t;
+}
+
+void foo() {
+  var c = C();
+  c<int>;
+}
+''');
+
+    assertImplicitCallReference(
+      findNode.implicitCallReference('c<int>'),
+      findElement.method('call'),
+      'int Function(int)',
+    );
+  }
+
+  test_ifNull() async {
+    await assertNoErrorsInCode('''
+abstract class C {
+  void call(int t) => t;
+}
+
+void Function(int) foo(C? c1, C c2) {
+  return c1 ?? c2;
+}
+''');
+
+    assertImplicitCallReference(
+      findNode.implicitCallReference('c1 ?? c2'),
+      findElement.method('call'),
+      'void Function(int)',
+    );
+  }
+
+  test_listLiteral_element() async {
+    await assertNoErrorsInCode('''
+abstract class C {
+  void call(int t) => t;
+}
+
+List<void Function(int)> foo(C c) {
+  return [c];
+}
+''');
+
+    assertImplicitCallReference(
+      findNode.implicitCallReference('c]'),
+      findElement.method('call'),
+      'void Function(int)',
+    );
+  }
+
+  test_listLiteral_forElement() async {
+    await assertNoErrorsInCode('''
+abstract class C {
+  void call(int t) => t;
+}
+
+List<void Function(int)> foo(C c) {
+  return [
+    for (var _ in [1, 2, 3]) c,
+  ];
+}
+''');
+
+    assertImplicitCallReference(
+      findNode.implicitCallReference('c,'),
+      findElement.method('call'),
+      'void Function(int)',
+    );
+  }
+
+  test_listLiteral_ifElement() async {
+    await assertNoErrorsInCode('''
+abstract class C {
+  void call(int t) => t;
+}
+
+List<void Function(int)> foo(C c) {
+  return [
+    if (1==2) c,
+  ];
+}
+''');
+
+    assertImplicitCallReference(
+      findNode.implicitCallReference('c,'),
+      findElement.method('call'),
+      'void Function(int)',
+    );
+  }
+
+  test_listLiteral_ifElement_else() async {
+    await assertNoErrorsInCode('''
+abstract class C {
+  void call(int t) => t;
+}
+
+List<void Function(int)> foo(C c1, C c2) {
+  return [
+    if (1==2) c1
+    else c2,
+  ];
+}
+''');
+
+    assertImplicitCallReference(
+      findNode.implicitCallReference('c2,'),
+      findElement.method('call'),
+      'void Function(int)',
+    );
+  }
+
+  test_prefixedIdentifier() async {
+    await assertNoErrorsInCode('''
+abstract class C {
+  C get c;
+  void call(int t) => t;
+}
+
+void Function(int) foo(C c) {
+  return c.c;
+}
+''');
+
+    assertImplicitCallReference(
+      findNode.implicitCallReference('c.c;'),
+      findElement.method('call'),
+      'void Function(int)',
+    );
+  }
+
+  test_propertyAccess() async {
+    await assertNoErrorsInCode('''
+abstract class C {
+  C get c;
+  void call(int t) => t;
+}
+
+void Function(int) foo(C c) {
+  return c.c.c;
+}
+''');
+
+    assertImplicitCallReference(
+      findNode.implicitCallReference('c.c.c;'),
+      findElement.method('call'),
+      'void Function(int)',
+    );
+  }
+
+  test_setOrMapLiteral_element() async {
+    await assertNoErrorsInCode('''
+abstract class C {
+  void call(int t) => t;
+}
+
+Set<void Function(int)> foo(C c) {
+  return {c};
+}
+''');
+
+    assertImplicitCallReference(
+      findNode.implicitCallReference('c}'),
+      findElement.method('call'),
+      'void Function(int)',
+    );
+  }
+
+  test_setOrMapLiteral_mapLiteralEntry_key() async {
+    await assertNoErrorsInCode('''
+abstract class C {
+  void call(int t) => t;
+}
+
+Map<void Function(int), int> foo(C c) {
+  return {c: 1};
+}
+''');
+
+    assertImplicitCallReference(
+      findNode.implicitCallReference('c:'),
+      findElement.method('call'),
+      'void Function(int)',
+    );
+  }
+
+  test_setOrMapLiteral_mapLiteralEntry_value() async {
+    await assertNoErrorsInCode('''
+abstract class C {
+  void call(int t) => t;
+}
+
+Map<int, void Function(int)> foo(C c) {
+  return {1: c};
+}
+''');
+
+    assertImplicitCallReference(
+      findNode.implicitCallReference('c}'),
+      findElement.method('call'),
+      'void Function(int)',
+    );
+  }
+
+  test_simpleIdentifier() async {
+    await assertNoErrorsInCode('''
+abstract class C {
+  void call(int t) => t;
+}
+
+void Function(int) foo(C c) {
+  return c;
+}
+''');
+
+    assertImplicitCallReference(
+      findNode.implicitCallReference('c;'),
+      findElement.method('call'),
+      'void Function(int)',
+    );
+  }
+}
+
+@reflectiveTest
 class AstRewriteMethodInvocationTest extends PubPackageResolutionTest
     with AstRewriteMethodInvocationTestCases {}
 
diff --git a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
index 1a2adbb..9a56b92 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
@@ -466,12 +466,49 @@
 }
 ''');
 
-    // TODO(srawlins): An arbitrary expression with a static type which is
-    // callable does not necessarily have an element. However, if we implement
-    // some "implicit call tearoff" node, it would have an element referring to
-    // the `call` method.
-    var functionReference = findNode.functionReference('C()<int>;');
-    assertType(functionReference, 'int Function(int)');
+    assertImplicitCallReference(findNode.implicitCallReference('C()<int>;'),
+        findElement.method('call'), 'int Function(int)');
+  }
+
+  test_implicitCallTearoff_extensionOnNullable() async {
+    await assertNoErrorsInCode('''
+Object? v = null;
+extension E on Object? {
+  void call<R, S>(R r, S s) {}
+}
+void foo() {
+  v<int, String>;
+}
+
+''');
+
+    assertImplicitCallReference(
+        findNode.implicitCallReference('v<int, String>;'),
+        findElement.method('call'),
+        'void Function(int, String)');
+  }
+
+  test_implicitCallTearoff_prefixed() async {
+    newFile('$testPackageLibPath/a.dart', content: '''
+class C {
+  T call<T>(T t) => t;
+}
+C c = C();
+''');
+    await assertNoErrorsInCode('''
+import 'a.dart' as prefix;
+
+bar() {
+  prefix.c<int>;
+}
+''');
+
+    assertImportPrefix(
+        findNode.simple('prefix.'), findElement.prefix('prefix'));
+    assertImplicitCallReference(
+        findNode.implicitCallReference('c<int>;'),
+        findElement.importFind('package:test/a.dart').method('call'),
+        'int Function(int)');
   }
 
   test_implicitCallTearoff_tooFewTypeArguments() async {
@@ -485,18 +522,11 @@
 }
 ''', [
       error(
-          CompileTimeErrorCode
-              .WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION,
-          57,
-          5),
+          CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 57, 5),
     ]);
 
-    // TODO(srawlins): An arbitrary expression with a static type which is
-    // callable does not necessarily have an element. However, if we implement
-    // some "implicit call tearoff" node, it would have an element referring to
-    // the `call` method.
-    var functionReference = findNode.functionReference('C()<int>;');
-    assertType(functionReference, 'void Function(dynamic, dynamic)');
+    assertImplicitCallReference(findNode.implicitCallReference('C()<int>;'),
+        findElement.method('call'), 'void Function(dynamic, dynamic)');
   }
 
   test_implicitCallTearoff_tooManyTypeArguments() async {
@@ -510,18 +540,11 @@
 }
 ''', [
       error(
-          CompileTimeErrorCode
-              .WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION,
-          50,
-          5),
+          CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 50, 5),
     ]);
 
-    // TODO(srawlins): An arbitrary expression with a static type which is
-    // callable does not necessarily have an element. However, if we implement
-    // some "implicit call tearoff" node, it would have an element referring to
-    // the `call` method.
-    var functionReference = findNode.functionReference('C()<int>;');
-    assertType(functionReference, 'int Function(int)');
+    assertImplicitCallReference(findNode.implicitCallReference('C()<int>;'),
+        findElement.method('call'), 'int Function(int)');
   }
 
   test_instanceGetter_explicitReceiver() async {
@@ -1348,6 +1371,26 @@
         findElement.topFunction('foo'), 'void Function(int)');
   }
 
+  test_topLevelVariable_prefix() async {
+    newFile('$testPackageLibPath/a.dart', content: '''
+void Function<T>(T) foo = <T>(T arg) {}
+''');
+    await assertNoErrorsInCode('''
+import 'a.dart' as prefix;
+
+bar() {
+  prefix.foo<int>;
+}
+''');
+
+    assertImportPrefix(
+        findNode.simple('prefix.'), findElement.prefix('prefix'));
+    assertFunctionReference(
+        findNode.functionReference('foo<int>;'),
+        findElement.importFind('package:test/a.dart').topGet('foo'),
+        'void Function(int)');
+  }
+
   test_topLevelVariable_prefix_unknownIdentifier() async {
     newFile('$testPackageLibPath/a.dart', content: '');
     await assertErrorsInCode('''
diff --git a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
index 4dca4cb..7c96192 100644
--- a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
@@ -151,6 +151,46 @@
 ''');
   }
 
+  test_onLocalVariable() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  final int a;
+  const A(this.a);
+}
+
+void f() {
+  @A(3)
+  int? x;
+  print(x);
+}
+''');
+
+    var annotation = findNode.annotation('@A');
+    _assertResolvedNodeText(annotation, '''
+Annotation
+  arguments: ArgumentList
+    arguments
+      IntegerLiteral
+        literal: 3
+        staticType: int
+    leftParenthesis: (
+    rightParenthesis: )
+  atSign: @
+  element: self::@class::A::@constructor::•
+  name: SimpleIdentifier
+    staticElement: self::@class::A
+    staticType: null
+    token: A
+''');
+
+    final localVariable = findElement.localVar('x');
+    final annotationOnElement = localVariable.metadata.single;
+    _assertElementAnnotationValueText(annotationOnElement, '''
+A
+  a: int 3
+''');
+  }
+
   test_optIn_fromOptOut_class() async {
     newFile('$testPackageLibPath/a.dart', content: r'''
 class A {
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 5290a73..6d89730 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -384,6 +384,12 @@
     assertType(ref, type);
   }
 
+  void assertImplicitCallReference(ImplicitCallReference node,
+      Element? expectedElement, String expectedType) {
+    assertElement(node, expectedElement);
+    assertType(node, expectedType);
+  }
+
   /// In valid code [element] must be a [PrefixElement], but for invalid code
   /// like `int.double v;` we want to resolve `int` somehow. Still not type.
   void assertImportPrefix(Expression? identifier, Element? element) {
@@ -902,6 +908,8 @@
       }
     } else if (node is Identifier) {
       return node.staticElement;
+    } else if (node is ImplicitCallReference) {
+      return node.staticElement;
     } else if (node is IndexExpression) {
       return node.staticElement;
     } else if (node is InstanceCreationExpression) {
diff --git a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
index f238eba..60ca6a0 100644
--- a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
@@ -147,6 +147,18 @@
     ]);
   }
 
+  test_implicitCallReference_namedAndRequired() async {
+    await assertNoErrorsInCode('''
+class A {
+  void call(int p) {}
+}
+void f({required void Function(int) a}) {}
+void g(A a) {
+  f(a: a);
+}
+''');
+  }
+
   test_invocation_functionTypes_optional() async {
     await assertErrorsInCode('''
 void acceptFunOptBool(void funNumOptBool([bool b])) {}
@@ -199,8 +211,8 @@
   const A.fromInt(int p);
 }
 @A.fromInt('0')
-main() {
-}''', [
+main() {}
+''', [
       error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 49, 3),
     ]);
   }
@@ -330,6 +342,44 @@
     ]);
   }
 
+  test_implicitCallReference() async {
+    await assertNoErrorsInCode('''
+class A {
+  void call(int p) {}
+}
+void f(void Function(int) a) {}
+void g(A a) {
+  f(a);
+}
+''');
+  }
+
+  test_implicitCallReference_named() async {
+    await assertNoErrorsInCode('''
+class A {
+  void call(int p) {}
+}
+void defaultFunc(int p) {}
+void f({void Function(int) a = defaultFunc}) {}
+void g(A a) {
+  f(a: a);
+}
+''');
+  }
+
+  test_implicitCallReference_this() async {
+    await assertNoErrorsInCode('''
+class A {
+  void call(int p) {}
+
+  void f(void Function(int) a) {}
+  void g() {
+    f(this);
+  }
+}
+''');
+  }
+
   test_index_invalidRead() async {
     await assertErrorsInCode('''
 class A {
diff --git a/pkg/analyzer/test/src/diagnostics/field_initializer_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/field_initializer_not_assignable_test.dart
index a86aaa2..07abbcd 100644
--- a/pkg/analyzer/test/src/diagnostics/field_initializer_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/field_initializer_not_assignable_test.dart
@@ -16,6 +16,30 @@
 
 @reflectiveTest
 class FieldInitializerNotAssignableTest extends PubPackageResolutionTest {
+  test_implicitCallReference() async {
+    await assertNoErrorsInCode('''
+class C {
+  void call(int p) {}
+}
+class A {
+  void Function(int) x;
+  A() : x = C();
+}
+''');
+  }
+
+  test_implicitCallReference_genericFunctionInstantiation() async {
+    await assertNoErrorsInCode('''
+class C {
+  void call<T>(T p) {}
+}
+class A {
+  void Function(int) x;
+  A() : x = C();
+}
+''');
+  }
+
   test_unrelated() async {
     await assertErrorsInCode('''
 class A {
diff --git a/pkg/analyzer/test/src/diagnostics/for_in_of_invalid_element_type_test.dart b/pkg/analyzer/test/src/diagnostics/for_in_of_invalid_element_type_test.dart
index 07478d0..25599a7 100644
--- a/pkg/analyzer/test/src/diagnostics/for_in_of_invalid_element_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/for_in_of_invalid_element_type_test.dart
@@ -74,6 +74,32 @@
 ''');
   }
 
+  test_declaredVariable_implicitCallReference() async {
+    await assertNoErrorsInCode('''
+class C {
+  void call() {}
+}
+void foo(C c) {
+  for (void Function() f in [c]) {
+    f;
+  }
+}
+''');
+  }
+
+  test_declaredVariable_implicitCallReference_genericFunctionInstantiation() async {
+    await assertNoErrorsInCode('''
+class C {
+  void call<T>(T p) {}
+}
+void foo(C c) {
+  for (void Function(int) f in [c]) {
+    f;
+  }
+}
+''');
+  }
+
   test_declaredVariable_interfaceTypeTypedef_ok() async {
     await assertNoErrorsInCode('''
 typedef S = String;
@@ -119,4 +145,48 @@
       error(CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 27, 10),
     ]);
   }
+
+  test_implicitCallReference() async {
+    await assertNoErrorsInCode('''
+class C {
+  void call(int a) {}
+}
+void foo(Iterable<C> iterable) {
+  void Function(int) f;
+  for (f in iterable) {
+    f;
+  }
+}
+''');
+  }
+
+  test_implicitCallReference_genericFunctionInstantiation() async {
+    await assertNoErrorsInCode('''
+class C {
+  void call<T>(T p) {}
+}
+void foo(Iterable<C> iterable) {
+  void Function(int) f;
+  for (f in iterable) {
+    f;
+  }
+}
+''');
+  }
+
+  test_implicitCallReference_unassignableFunctionType() async {
+    await assertErrorsInCode('''
+class C {
+  void call(int a) {}
+}
+void foo(Iterable<C> iterable) {
+  void Function(String) f;
+  for (f in iterable) {
+    f;
+  }
+}
+''', [
+      error(CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 106, 8),
+    ]);
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
index 63aacca..2de6c7e 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
@@ -9,6 +9,7 @@
 
 main() {
   defineReflectiveSuite(() {
+    defineReflectiveTests(InvalidAssignment_ImplicitCallReferenceTest);
     defineReflectiveTests(InvalidAssignmentTest);
     defineReflectiveTests(InvalidAssignmentWithNoImplicitCastsTest);
     defineReflectiveTests(InvalidAssignmentWithoutNullSafetyTest);
@@ -16,6 +17,304 @@
 }
 
 @reflectiveTest
+class InvalidAssignment_ImplicitCallReferenceTest
+    extends PubPackageResolutionTest {
+  test_invalid_genericBoundedCall_nonGenericContext() async {
+    await assertNoErrorsInCode('''
+class C {
+  T call<T extends num>(T t) => t;
+}
+
+String Function(String) f = C();
+''');
+  }
+
+  test_invalid_genericCall() async {
+    await assertErrorsInCode('''
+class C {
+  T call<T>(T t) => t;
+}
+
+void Function() f = C();
+''', [
+      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 56, 3),
+    ]);
+  }
+
+  test_invalid_genericCall_genericEnclosingClass_nonGenericContext() async {
+    await assertErrorsInCode('''
+class C<T> {
+  C(T a);
+  void call<U>(T t, U u) {}
+}
+
+void Function(bool, String) f = C(7);
+''', [
+      // The type arguments of the instance of `C` should be accurate and be
+      // taken into account when evaluating the assignment of the implicit call
+      // reference.
+      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 86, 4),
+    ]);
+  }
+
+  test_invalid_genericCall_nonGenericContext_withoutConstructorTearoffs() async {
+    await assertErrorsInCode('''
+// @dart=2.12
+class C {
+  T call<T>(T t) => t;
+}
+
+int Function(int) f = C();
+''', [
+      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 72, 3),
+    ]);
+  }
+
+  test_invalid_noCall_functionContext() async {
+    await assertErrorsInCode('''
+class C {}
+
+Function f = C();
+''', [
+      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 25, 3),
+    ]);
+  }
+
+  test_invalid_noCall_functionTypeContext() async {
+    await assertErrorsInCode('''
+class C {}
+
+String Function(String) f = C();
+''', [
+      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 40, 3),
+    ]);
+  }
+
+  test_invalid_nonGenericCall() async {
+    await assertErrorsInCode('''
+class C {
+  void call(int a) {}
+}
+
+void Function(String) f = C();
+''', [
+      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 61, 3),
+    ]);
+  }
+
+  test_invalid_nonGenericCall_typeVariableExtendsFunctionContext() async {
+    await assertErrorsInCode('''
+class C {
+  void call(int a) {}
+}
+class D<U extends Function> {
+  U f = C();
+}
+''', [
+      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 72, 3),
+    ]);
+  }
+
+  test_invalid_nonGenericCall_typeVariableExtendsFunctionTypeContext() async {
+    await assertErrorsInCode('''
+class C {
+  void call(int a) {}
+}
+class D<U extends void Function(int)> {
+  U f = C();
+}
+''', [
+      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 82, 3),
+    ]);
+  }
+
+  test_valid_genericBoundedCall_nonGenericContext() async {
+    await assertNoErrorsInCode('''
+class C {
+  T call<T extends num>(T t) => t;
+}
+
+int Function(int) f = C();
+''');
+  }
+
+  test_valid_genericCall_functionContext() async {
+    await assertNoErrorsInCode('''
+class C {
+  T call<T>(T t) => t;
+}
+
+Function f = C();
+''');
+  }
+
+  test_valid_genericCall_futureOrFunctionContext() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+class C {
+  T call<T>(T t) => t;
+}
+
+FutureOr<Function> f = C();
+''');
+  }
+
+  test_valid_genericCall_futureOrFunctionTypeContext_generic() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+class C {
+  T call<T>(T t) => t;
+}
+
+FutureOr<T Function<T>(T)> f = C();
+''');
+  }
+
+  test_valid_genericCall_futureOrFunctionTypeContext_nonGeneric() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+class C {
+  T call<T>(T t) => t;
+}
+
+FutureOr<int Function(int)> f = C();
+''');
+  }
+
+  test_valid_genericCall_genericContext() async {
+    await assertNoErrorsInCode('''
+class C {
+  T call<T>(T t) => t;
+}
+
+T Function<T>(T) f = C();
+''');
+  }
+
+  test_valid_genericCall_genericEnclosingClass_nonGenericContext() async {
+    await assertNoErrorsInCode('''
+class C<T> {
+  C(T a);
+  void call<U>(T t, U u) {}
+}
+
+void Function(int, String) f = C(7);
+''');
+  }
+
+  test_valid_genericCall_genericTypedefContext() async {
+    await assertNoErrorsInCode('''
+class C {
+  T call<T>(T t) => t;
+}
+typedef Fn<T> = T Function(T);
+class D<U> {
+  Fn<U> f = C();
+}
+
+''');
+  }
+
+  test_valid_genericCall_nonGenericContext() async {
+    await assertNoErrorsInCode('''
+class C {
+  T call<T>(T t) => t;
+}
+
+int Function(int) f = C();
+''');
+  }
+
+  test_valid_genericCall_nullableFunctionContext() async {
+    await assertNoErrorsInCode('''
+class C {
+  T call<T>(T t) => t;
+}
+
+Function? f = C();
+''');
+  }
+
+  test_valid_genericCall_nullableNonGenericContext() async {
+    await assertNoErrorsInCode('''
+class C {
+  T call<T>(T t) => t;
+}
+
+int Function(int)? f = C();
+''');
+  }
+
+  test_valid_genericCall_typedefOfGenericContext() async {
+    await assertNoErrorsInCode('''
+class C {
+  T call<T>(T t) => t;
+}
+
+typedef Fn = T Function<T>(T);
+
+Fn f = C();
+''');
+  }
+
+  test_valid_nonGenericCall() async {
+    await assertNoErrorsInCode('''
+class C {
+  void call(int a) {}
+}
+
+void Function(int) f = C();
+''');
+  }
+
+  test_valid_nonGenericCall_declaredOnMixin() async {
+    await assertNoErrorsInCode('''
+mixin M {
+  void call(int a) {}
+}
+class C with M {}
+
+Function f = C();
+''');
+  }
+
+  test_valid_nonGenericCall_inCascade() async {
+    await assertNoErrorsInCode('''
+class C {
+  void call(int a) {}
+}
+class D {
+  late void Function(int) f;
+}
+
+void foo() {
+  D()..f = C();
+}
+''');
+  }
+
+  test_valid_nonGenericCall_subTypeViaParameter() async {
+    await assertNoErrorsInCode('''
+class C {
+  void call(num a) {}
+}
+
+void Function(int) f = C();
+''');
+  }
+
+  test_valid_nonGenericCall_subTypeViaReturnType() async {
+    await assertNoErrorsInCode('''
+class C {
+  int call() => 7;
+}
+
+num Function() f = C();
+''');
+  }
+}
+
+@reflectiveTest
 class InvalidAssignmentTest extends PubPackageResolutionTest
     with InvalidAssignmentTestCases {
   test_constructorTearoff_inferredTypeArgs() async {
diff --git a/pkg/vm/lib/transformations/ffi/native.dart b/pkg/vm/lib/transformations/ffi/native.dart
index dd28967..2919bf1 100644
--- a/pkg/vm/lib/transformations/ffi/native.dart
+++ b/pkg/vm/lib/transformations/ffi/native.dart
@@ -128,7 +128,7 @@
   FunctionType _wrapFunctionType(
       FunctionType dartFunctionType, FunctionType ffiFunctionType) {
     return FunctionType(
-      [
+      <DartType>[
         for (var i = 0; i < dartFunctionType.positionalParameters.length; i++)
           _wrapArgumentType(dartFunctionType.positionalParameters[i],
               ffiFunctionType.positionalParameters[i]),
@@ -164,7 +164,7 @@
     final resolverInvocation = FunctionInvocation(
         FunctionAccessKind.FunctionType,
         StaticGet(resolverField),
-        Arguments([
+        Arguments(<Expression>[
           ConstantExpression(
               StringConstant(currentLibrary.importUri.toString())),
           ConstantExpression(nativeFunctionName),
@@ -176,11 +176,11 @@
     // _fromAddress<NativeFunction<Double Function(Double)>>(...)
     final fromAddressInvocation = StaticInvocation(
         fromAddressInternal,
-        Arguments([
+        Arguments(<Expression>[
           resolverInvocation
         ], types: [
-          InterfaceType(
-              nativeFunctionClass, Nullability.legacy, [ffiFunctionType])
+          InterfaceType(nativeFunctionClass, Nullability.legacy,
+              <DartType>[ffiFunctionType])
         ]))
       ..fileOffset = fileOffset;
 
@@ -188,9 +188,14 @@
     //     <Double Function(Double), double Function(double)>(..., isLeaf:true)
     final asFunctionInvocation = StaticInvocation(
         asFunctionMethod,
-        Arguments([fromAddressInvocation],
-            types: [ffiFunctionType, dartFunctionType],
-            named: [NamedExpression('isLeaf', BoolLiteral(isLeaf))]))
+        Arguments(<Expression>[
+          fromAddressInvocation
+        ], types: <DartType>[
+          ffiFunctionType,
+          dartFunctionType
+        ], named: <NamedExpression>[
+          NamedExpression('isLeaf', BoolLiteral(isLeaf))
+        ]))
       ..fileOffset = fileOffset;
 
     // static final _doXyz$FfiNative$Ptr = ...
@@ -234,10 +239,10 @@
       // Pointer.fromAddress(_getNativeField(#t0))
       return StaticInvocation(
           fromAddressInternal,
-          Arguments([
-            StaticInvocation(
-                getNativeFieldFunction, Arguments([VariableGet(temporary)]))
-          ], types: [
+          Arguments(<Expression>[
+            StaticInvocation(getNativeFieldFunction,
+                Arguments(<Expression>[VariableGet(temporary)]))
+          ], types: <DartType>[
             voidType
           ]));
     }
@@ -305,12 +310,12 @@
     //   reachabilityFence(#t0);
     // } => #t1
     final resultBlock = BlockExpression(
-      Block([
+      Block(<Statement>[
         ...temporariesForArguments,
         result,
         for (final argument in fencedArguments)
-          ExpressionStatement(StaticInvocation(
-              reachabilityFenceFunction, Arguments([VariableGet(argument)])))
+          ExpressionStatement(StaticInvocation(reachabilityFenceFunction,
+              Arguments(<Expression>[VariableGet(argument)])))
       ]),
       VariableGet(result),
     );
@@ -467,7 +472,7 @@
       for (final parameter in node.function.positionalParameters) parameter.type
     ], node.function.returnType, Nullability.nonNullable);
 
-    final argumentList = [
+    final argumentList = <Expression>[
       ThisExpression(),
       for (final parameter in node.function.positionalParameters)
         VariableGet(parameter)
@@ -495,7 +500,7 @@
     final dartFunctionType =
         node.function.computeThisFunctionType(Nullability.nonNullable);
 
-    final argumentList = [
+    final argumentList = <Expression>[
       for (final parameter in node.function.positionalParameters)
         VariableGet(parameter)
     ];
diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc
index 2333b43..62cc613 100644
--- a/runtime/bin/socket.cc
+++ b/runtime/bin/socket.cc
@@ -383,6 +383,11 @@
   }
 }
 
+// This function will abort if sourceAddr is a Unix domain socket.
+// The family ("sa_family") of the socket address is infered from the length
+// of the address. Unix domain sockets addresses are the bytes of their file
+// system path so they have variable length. They cannot, therefore, be
+// differentiated from other address types in this function.
 void FUNCTION_NAME(Socket_CreateBindConnect)(Dart_NativeArguments args) {
   RawAddr addr;
   SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 1), &addr);
diff --git a/sdk/lib/_internal/vm/bin/socket_patch.dart b/sdk/lib/_internal/vm/bin/socket_patch.dart
index 5f0379e..8ce0776 100644
--- a/sdk/lib/_internal/vm/bin/socket_patch.dart
+++ b/sdk/lib/_internal/vm/bin/socket_patch.dart
@@ -740,7 +740,16 @@
           connectionResult = socket.nativeCreateUnixDomainConnect(
               address.address, _Namespace._namespace);
         } else {
-          assert(source.type == InternetAddressType.unix);
+          if (source.type != InternetAddressType.unix) {
+            return SocketException(
+                // Use the same error message as used on Linux for better
+                // searchability...
+                "Address family not supported by protocol family, "
+                // ...and then add some details.
+                "sourceAddress.type must be ${InternetAddressType.unix} but was "
+                "${source.type}",
+                address: address);
+          }
           connectionResult = socket.nativeCreateUnixDomainBindConnect(
               address.address, source.address, _Namespace._namespace);
         }
@@ -753,6 +762,17 @@
           connectionResult = socket.nativeCreateConnect(
               address_._in_addr, port, address_._scope_id);
         } else {
+          if (source.type != InternetAddressType.IPv4 &&
+              source.type != InternetAddressType.IPv6) {
+            return SocketException(
+                // Use the same error message as used on Linux for better
+                // searchability...
+                "Address family not supported by protocol family, "
+                // ...and then add some details.
+                "sourceAddress.type must be ${InternetAddressType.IPv4} or "
+                "${InternetAddressType.IPv6} but was ${source.type}",
+                address: address);
+          }
           connectionResult = socket.nativeCreateBindConnect(
               address_._in_addr, port, source._in_addr, address_._scope_id);
         }
@@ -773,6 +793,8 @@
           return createError(
               connectionResult, "Connection failed", address, port);
         }
+      } else if (connectionResult is SocketException) {
+        return connectionResult;
       } else if (connectionResult is Error) {
         return connectionResult;
       }
diff --git a/tests/standalone/io/issue_30687_test.dart b/tests/standalone/io/issue_30687_test.dart
index e994f09..1b140e1 100644
--- a/tests/standalone/io/issue_30687_test.dart
+++ b/tests/standalone/io/issue_30687_test.dart
@@ -7,7 +7,7 @@
 import 'package:expect/expect.dart';
 import 'package:path/path.dart' as path;
 
-import 'unix_socket_test.dart' show withTempDir;
+import 'test_utils.dart' show withTempDir;
 
 main() async {
   await withTempDir('issue_30687', (Directory tempDir) async {
diff --git a/tests/standalone/io/socket_source_address_test.dart b/tests/standalone/io/socket_source_address_test.dart
index 4fe8b39..1e7eb34 100644
--- a/tests/standalone/io/socket_source_address_test.dart
+++ b/tests/standalone/io/socket_source_address_test.dart
@@ -6,39 +6,83 @@
 import "dart:async";
 import "dart:io";
 
-import 'test_utils.dart' show retry, throws;
+import 'test_utils.dart' show retry, throws, withTempDir;
 
-Future testArguments(connectFunction) async {
+Future testArguments(connectFunction, String socketDir) async {
   var sourceAddress;
-  final server = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0);
-  server.listen((_) {
+  final serverIPv4 = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0);
+  serverIPv4.listen((_) {
+    throw 'Unexpected connection from address $sourceAddress';
+  });
+
+  final serverIPv6 = await ServerSocket.bind(InternetAddress.loopbackIPv6, 0);
+  serverIPv6.listen((_) {
+    throw 'Unexpected connection from address $sourceAddress';
+  });
+
+  ServerSocket serverUnix = await ServerSocket.bind(
+      InternetAddress('$socketDir/sock', type: InternetAddressType.unix), 0);
+  serverUnix.listen((_) {
     throw 'Unexpected connection from address $sourceAddress';
   });
 
   // Illegal type for sourceAddress.
   for (sourceAddress in ['www.google.com', 'abc']) {
     await throws(
-        () => connectFunction('127.0.0.1', server.port,
+        () => connectFunction('127.0.0.1', serverIPv4.port,
             sourceAddress: sourceAddress),
         (e) => e is ArgumentError);
   }
   // Unsupported local address.
   for (sourceAddress in ['8.8.8.8', new InternetAddress('8.8.8.8')]) {
     await throws(
-        () => connectFunction('127.0.0.1', server.port,
+        () => connectFunction('127.0.0.1', serverIPv4.port,
             sourceAddress: sourceAddress),
         (e) =>
             e is SocketException &&
             e.address == new InternetAddress('8.8.8.8'));
   }
-  // Address family mismatch.
-  for (sourceAddress in ['::1', InternetAddress.loopbackIPv6]) {
+  // Address family mismatch for IPv4.
+  for (sourceAddress in [
+    '::1',
+    InternetAddress.loopbackIPv6,
+    InternetAddress('$socketDir/sock', type: InternetAddressType.unix)
+  ]) {
     await throws(
-        () => connectFunction('127.0.0.1', server.port,
+        () => connectFunction('127.0.0.1', serverIPv4.port,
             sourceAddress: sourceAddress),
         (e) => e is SocketException);
   }
-  await server.close();
+  // Address family mismatch for IPv6.
+  for (sourceAddress in [
+    '127.0.0.1',
+    InternetAddress.loopbackIPv4,
+    InternetAddress('$socketDir/sock', type: InternetAddressType.unix)
+  ]) {
+    await throws(
+        () => connectFunction('::1', serverIPv6.port,
+            sourceAddress: sourceAddress),
+        (e) => e is SocketException);
+  }
+  // Address family mismatch for Unix domain sockets.
+  for (sourceAddress in [
+    '127.0.0.1',
+    InternetAddress.loopbackIPv4,
+    '::1',
+    InternetAddress.loopbackIPv6,
+  ]) {
+    await throws(
+        () => connectFunction(
+            InternetAddress("$socketDir/sock", type: InternetAddressType.unix),
+            serverUnix.port,
+            sourceAddress: sourceAddress),
+        (e) =>
+            e is SocketException &&
+            e.toString().contains('Address family not supported'));
+  }
+  await serverIPv4.close();
+  await serverIPv6.close();
+  await serverUnix.close();
 }
 
 // IPv4 addresses to use as source address when connecting locally.
@@ -112,10 +156,14 @@
 
 main() async {
   await retry(() async {
-    await testArguments(RawSocket.connect);
+    await withTempDir('unix_socket_test', (Directory dir) async {
+      await testArguments(RawSocket.connect, "${dir.path}");
+    });
   });
   await retry(() async {
-    await testArguments(Socket.connect);
+    await withTempDir('unix_socket_test', (Directory dir) async {
+      await testArguments(Socket.connect, "${dir.path}");
+    });
   });
 
   await retry(() async {
diff --git a/tests/standalone/io/test_utils.dart b/tests/standalone/io/test_utils.dart
index fb3b3ef..9160c18 100644
--- a/tests/standalone/io/test_utils.dart
+++ b/tests/standalone/io/test_utils.dart
@@ -37,3 +37,24 @@
   }
   Expect.fail('Did not throw');
 }
+
+// Create a temporary directory and delete it when the test function exits.
+Future withTempDir(String prefix, Future<void> test(Directory dir)) async {
+  final tempDir = Directory.systemTemp.createTempSync(prefix);
+  try {
+    await runZonedGuarded(() => test(tempDir), (e, st) {
+      try {
+        tempDir.deleteSync(recursive: true);
+      } catch (_) {
+        // ignore errors
+      }
+      throw e;
+    });
+  } finally {
+    try {
+      tempDir.deleteSync(recursive: true);
+    } catch (_) {
+      // ignore errors
+    }
+  }
+}
diff --git a/tests/standalone/io/unix_socket_regress_46634_test.dart b/tests/standalone/io/unix_socket_regress_46634_test.dart
index 31bce79..fca1b2a 100644
--- a/tests/standalone/io/unix_socket_regress_46634_test.dart
+++ b/tests/standalone/io/unix_socket_regress_46634_test.dart
@@ -4,7 +4,8 @@
 
 import 'dart:io';
 
-import 'unix_socket_test.dart' show withTempDir, testListenCloseListenClose;
+import 'test_utils.dart' show withTempDir;
+import 'unix_socket_test.dart' show testListenCloseListenClose;
 
 void main() async {
   if (!Platform.isMacOS && !Platform.isLinux && !Platform.isAndroid) {
diff --git a/tests/standalone/io/unix_socket_test.dart b/tests/standalone/io/unix_socket_test.dart
index a8bf0cb..2a096b9 100644
--- a/tests/standalone/io/unix_socket_test.dart
+++ b/tests/standalone/io/unix_socket_test.dart
@@ -8,6 +8,8 @@
 
 import 'package:expect/expect.dart';
 
+import 'test_utils.dart' show withTempDir;
+
 Future testAddress(String name) async {
   var address = InternetAddress('$name/sock', type: InternetAddressType.unix);
   var server = await ServerSocket.bind(address, 0);
@@ -821,27 +823,6 @@
   });
 }
 
-// Create socket in temp directory
-Future withTempDir(String prefix, Future<void> test(Directory dir)) async {
-  final tempDir = Directory.systemTemp.createTempSync(prefix);
-  try {
-    await runZonedGuarded(() => test(tempDir), (e, st) {
-      try {
-        tempDir.deleteSync(recursive: true);
-      } catch (_) {
-        // ignore errors
-      }
-      throw e;
-    });
-  } finally {
-    try {
-      tempDir.deleteSync(recursive: true);
-    } catch (_) {
-      // ignore errors
-    }
-  }
-}
-
 void main(List<String> args) async {
   runZonedGuarded(() async {
     if (args.length > 0 && args[0] == '--start-stdio-message-test') {
diff --git a/tests/standalone_2/io/issue_30687_test.dart b/tests/standalone_2/io/issue_30687_test.dart
index 71ee6fd..b814cc7 100644
--- a/tests/standalone_2/io/issue_30687_test.dart
+++ b/tests/standalone_2/io/issue_30687_test.dart
@@ -9,7 +9,7 @@
 import 'package:expect/expect.dart';
 import 'package:path/path.dart' as path;
 
-import 'unix_socket_test.dart' show withTempDir;
+import 'test_utils.dart' show withTempDir;
 
 main() async {
   await withTempDir('issue_30687', (Directory tempDir) async {
diff --git a/tests/standalone_2/io/socket_source_address_test.dart b/tests/standalone_2/io/socket_source_address_test.dart
index 57efc5af..7e77209 100644
--- a/tests/standalone_2/io/socket_source_address_test.dart
+++ b/tests/standalone_2/io/socket_source_address_test.dart
@@ -8,39 +8,83 @@
 import "dart:async";
 import "dart:io";
 
-import 'test_utils.dart' show retry, throws;
+import 'test_utils.dart' show retry, throws, withTempDir;
 
-Future testArguments(connectFunction) async {
+Future testArguments(connectFunction, String socketDir) async {
   var sourceAddress;
-  final server = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0);
-  server.listen((_) {
+  final serverIPv4 = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0);
+  serverIPv4.listen((_) {
+    throw 'Unexpected connection from address $sourceAddress';
+  });
+
+  final serverIPv6 = await ServerSocket.bind(InternetAddress.loopbackIPv6, 0);
+  serverIPv6.listen((_) {
+    throw 'Unexpected connection from address $sourceAddress';
+  });
+
+  ServerSocket serverUnix = await ServerSocket.bind(
+      InternetAddress('$socketDir/sock', type: InternetAddressType.unix), 0);
+  serverUnix.listen((_) {
     throw 'Unexpected connection from address $sourceAddress';
   });
 
   // Illegal type for sourceAddress.
   for (sourceAddress in ['www.google.com', 'abc']) {
     await throws(
-        () => connectFunction('127.0.0.1', server.port,
+        () => connectFunction('127.0.0.1', serverIPv4.port,
             sourceAddress: sourceAddress),
         (e) => e is ArgumentError);
   }
   // Unsupported local address.
   for (sourceAddress in ['8.8.8.8', new InternetAddress('8.8.8.8')]) {
     await throws(
-        () => connectFunction('127.0.0.1', server.port,
+        () => connectFunction('127.0.0.1', serverIPv4.port,
             sourceAddress: sourceAddress),
         (e) =>
             e is SocketException &&
             e.address == new InternetAddress('8.8.8.8'));
   }
-  // Address family mismatch.
-  for (sourceAddress in ['::1', InternetAddress.loopbackIPv6]) {
+  // Address family mismatch for IPv4.
+  for (sourceAddress in [
+    '::1',
+    InternetAddress.loopbackIPv6,
+    InternetAddress('$socketDir/sock', type: InternetAddressType.unix)
+  ]) {
     await throws(
-        () => connectFunction('127.0.0.1', server.port,
+        () => connectFunction('127.0.0.1', serverIPv4.port,
             sourceAddress: sourceAddress),
         (e) => e is SocketException);
   }
-  await server.close();
+  // Address family mismatch for IPv6.
+  for (sourceAddress in [
+    '127.0.0.1',
+    InternetAddress.loopbackIPv4,
+    InternetAddress('$socketDir/sock', type: InternetAddressType.unix)
+  ]) {
+    await throws(
+        () => connectFunction('::1', serverIPv6.port,
+            sourceAddress: sourceAddress),
+        (e) => e is SocketException);
+  }
+  // Address family mismatch for Unix domain sockets.
+  for (sourceAddress in [
+    '127.0.0.1',
+    InternetAddress.loopbackIPv4,
+    '::1',
+    InternetAddress.loopbackIPv6,
+  ]) {
+    await throws(
+        () => connectFunction(
+            InternetAddress("$socketDir/sock", type: InternetAddressType.unix),
+            serverUnix.port,
+            sourceAddress: sourceAddress),
+        (e) =>
+            e is SocketException &&
+            e.toString().contains('Address family not supported'));
+  }
+  await serverIPv4.close();
+  await serverIPv6.close();
+  await serverUnix.close();
 }
 
 // IPv4 addresses to use as source address when connecting locally.
@@ -114,10 +158,14 @@
 
 main() async {
   await retry(() async {
-    await testArguments(RawSocket.connect);
+    await withTempDir('unix_socket_test', (Directory dir) async {
+      await testArguments(RawSocket.connect, "${dir.path}");
+    });
   });
   await retry(() async {
-    await testArguments(Socket.connect);
+    await withTempDir('unix_socket_test', (Directory dir) async {
+      await testArguments(Socket.connect, "${dir.path}");
+    });
   });
 
   await retry(() async {
diff --git a/tests/standalone_2/io/test_utils.dart b/tests/standalone_2/io/test_utils.dart
index 0a36318..256740d 100644
--- a/tests/standalone_2/io/test_utils.dart
+++ b/tests/standalone_2/io/test_utils.dart
@@ -39,3 +39,24 @@
   }
   Expect.fail('Did not throw');
 }
+
+// Create a temporary directory and delete it when the test function exits.
+Future withTempDir(String prefix, Future<void> test(Directory dir)) async {
+  final tempDir = Directory.systemTemp.createTempSync(prefix);
+  try {
+    await runZonedGuarded(() => test(tempDir), (e, st) {
+      try {
+        tempDir.deleteSync(recursive: true);
+      } catch (_) {
+        // ignore errors
+      }
+      throw e;
+    });
+  } finally {
+    try {
+      tempDir.deleteSync(recursive: true);
+    } catch (_) {
+      // ignore errors
+    }
+  }
+}
diff --git a/tests/standalone_2/io/unix_socket_regress_46634_test.dart b/tests/standalone_2/io/unix_socket_regress_46634_test.dart
index 8920965..2ac0168b 100644
--- a/tests/standalone_2/io/unix_socket_regress_46634_test.dart
+++ b/tests/standalone_2/io/unix_socket_regress_46634_test.dart
@@ -5,7 +5,8 @@
 // @dart = 2.9
 import 'dart:io';
 
-import 'unix_socket_test.dart' show withTempDir, testListenCloseListenClose;
+import 'test_utils.dart' show withTempDir;
+import 'unix_socket_test.dart' show testListenCloseListenClose;
 
 void main() async {
   if (!Platform.isMacOS && !Platform.isLinux && !Platform.isAndroid) {
diff --git a/tests/standalone_2/io/unix_socket_test.dart b/tests/standalone_2/io/unix_socket_test.dart
index 04e8cb2..ecc6b3d 100644
--- a/tests/standalone_2/io/unix_socket_test.dart
+++ b/tests/standalone_2/io/unix_socket_test.dart
@@ -10,6 +10,8 @@
 
 import 'package:expect/expect.dart';
 
+import 'test_utils.dart' show withTempDir;
+
 Future testAddress(String name) async {
   var address = InternetAddress('$name/sock', type: InternetAddressType.unix);
   var server = await ServerSocket.bind(address, 0);
@@ -823,27 +825,6 @@
   return completer.future;
 }
 
-// Create socket in temp directory
-Future withTempDir(String prefix, Future<void> test(Directory dir)) async {
-  final tempDir = Directory.systemTemp.createTempSync(prefix);
-  try {
-    await runZonedGuarded(() => test(tempDir), (e, st) {
-      try {
-        tempDir.deleteSync(recursive: true);
-      } catch (_) {
-        // ignore errors
-      }
-      throw e;
-    });
-  } finally {
-    try {
-      tempDir.deleteSync(recursive: true);
-    } catch (_) {
-      // ignore errors
-    }
-  }
-}
-
 void main(List<String> args) async {
   runZonedGuarded(() async {
     if (args.length > 0 && args[0] == '--start-stdio-message-test') {
diff --git a/tools/VERSION b/tools/VERSION
index 05b635f..542d300 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 237
+PRERELEASE 238
 PRERELEASE_PATCH 0
\ No newline at end of file