Version 2.17.0-79.0.dev

Merge commit '58a42b5cfca08b2f0c546835f28375212296806d' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 0592060..97b16e1 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -1004,6 +1004,10 @@
   E? accept<E>(AstVisitor<E> visitor) => visitor.visitBlockFunctionBody(this);
 
   @override
+  DartType resolve(ResolverVisitor resolver, DartType? imposedType) =>
+      resolver.visitBlockFunctionBody(this, imposedType: imposedType);
+
+  @override
   void visitChildren(AstVisitor visitor) {
     _block.accept(visitor);
   }
@@ -3245,6 +3249,10 @@
   E? accept<E>(AstVisitor<E> visitor) => visitor.visitEmptyFunctionBody(this);
 
   @override
+  DartType resolve(ResolverVisitor resolver, DartType? imposedType) =>
+      resolver.visitEmptyFunctionBody(this, imposedType: imposedType);
+
+  @override
   void visitChildren(AstVisitor visitor) {
     // Empty function bodies have no children.
   }
@@ -3657,6 +3665,10 @@
       visitor.visitExpressionFunctionBody(this);
 
   @override
+  DartType resolve(ResolverVisitor resolver, DartType? imposedType) =>
+      resolver.visitExpressionFunctionBody(this, imposedType: imposedType);
+
+  @override
   void visitChildren(AstVisitor visitor) {
     _expression.accept(visitor);
   }
@@ -4930,6 +4942,12 @@
     }
     return localVariableInfo!.potentiallyMutatedInScope.contains(variable);
   }
+
+  /// Dispatch this function body to the resolver, imposing [imposedType] as the
+  /// return type context for `return` statements.
+  ///
+  /// Return value is the actual return type of the method.
+  DartType resolve(ResolverVisitor resolver, DartType? imposedType);
 }
 
 /// A top-level declaration.
@@ -7866,6 +7884,10 @@
   E? accept<E>(AstVisitor<E> visitor) => visitor.visitNativeFunctionBody(this);
 
   @override
+  DartType resolve(ResolverVisitor resolver, DartType? imposedType) =>
+      resolver.visitNativeFunctionBody(this, imposedType: imposedType);
+
+  @override
   void visitChildren(AstVisitor visitor) {
     _stringLiteral?.accept(visitor);
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart
index 2558708..7204620 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart
@@ -43,6 +43,7 @@
     }
 
     var contextType = InferenceContext.getContext(node);
+    DartType? imposedType;
     if (contextType is FunctionType) {
       contextType = _matchTypeParameters(
         node.typeParameters,
@@ -50,17 +51,22 @@
       );
       if (contextType is FunctionType) {
         _inferFormalParameters(node.parameters, contextType);
-        InferenceContext.setType(body, contextType.returnType);
+        var returnType = contextType.returnType;
+        if (!returnType.isDynamic) {
+          imposedType = returnType;
+        }
       }
     }
 
-    node.visitChildren(_resolver);
+    node.typeParameters?.accept(_resolver);
+    node.parameters?.accept(_resolver);
+    imposedType = node.body.resolve(_resolver, imposedType);
     if (isFunctionDeclaration) {
       // A side effect of visiting the children is that the parameters are now
       // in scope, so we can visit the documentation comment now.
       parent.documentationComment?.accept(_resolver);
     }
-    _resolve2(node);
+    _resolve2(node, imposedType);
 
     if (_resolver.flowAnalysis.flow != null && !isFunctionDeclaration) {
       _resolver.checkForBodyMayCompleteNormally(
@@ -135,13 +141,6 @@
     }
   }
 
-  /// Infers the return type of a local function, either a lambda or
-  /// (in strong mode) a local function declaration.
-  DartType _inferLocalFunctionReturnType(FunctionExpression node) {
-    var body = node.body;
-    return InferenceContext.getContext(body) ?? DynamicTypeImpl.instance;
-  }
-
   /// Given the downward inference [type], return the function type expressed
   /// in terms of the type parameters from [typeParameterList].
   ///
@@ -168,12 +167,11 @@
     }).toList());
   }
 
-  void _resolve2(FunctionExpressionImpl node) {
+  void _resolve2(FunctionExpressionImpl node, DartType? imposedType) {
     var functionElement = node.declaredElement as ExecutableElementImpl;
 
     if (_shouldUpdateReturnType(node)) {
-      var returnType = _inferLocalFunctionReturnType(node);
-      functionElement.returnType = returnType;
+      functionElement.returnType = imposedType ?? DynamicTypeImpl.instance;
     }
 
     _inferenceHelper.recordStaticType(node, functionElement.type);
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 ca56632..5cbf8db 100644
--- a/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
@@ -43,13 +43,13 @@
     var isTopLevel =
         element is FieldElement || element is TopLevelVariableElement;
 
-    InferenceContext.setTypeFromNode(initializer, node);
     if (isTopLevel) {
       _resolver.flowAnalysis.topLevelDeclaration_enter(node, null);
     } else if (element.isLate) {
       _resolver.flowAnalysis.flow?.lateInitializer_begin(node);
     }
 
+    InferenceContext.setType(initializer, element.type);
     initializer.accept(_resolver);
     initializer = node.initializer!;
     var whyNotPromoted =
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 3b38316..8506477 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -106,20 +106,17 @@
     }
   }
 
-  void popFunctionBodyContext(FunctionBody node) {
+  DartType popFunctionBodyContext(FunctionBody node) {
     var context = _bodyContexts.removeLast();
 
     var flow = _resolver.flowAnalysis.flow;
 
-    var resultType = context.computeInferredReturnType(
+    return context.computeInferredReturnType(
       endOfBlockIsReachable: flow == null || flow.isReachable,
     );
-
-    setType(node, resultType);
   }
 
-  void pushFunctionBodyContext(FunctionBody node) {
-    var imposedType = getContext(node);
+  void pushFunctionBodyContext(FunctionBody node, DartType? imposedType) {
     _bodyContexts.add(
       BodyInferenceContext(
         typeSystem: _typeSystem,
@@ -143,7 +140,9 @@
   /// [TypeSystemImpl.lowerBoundForType] if you would prefer a known type
   /// that represents the bound of the context type.
   static DartType? getContext(AstNode? node) {
-    if (node is ArgumentList) {
+    if (node is ArgumentList ||
+        node is VariableDeclaration ||
+        node is FunctionBody) {
       assert(false, 'Nodes of type ${node.runtimeType} should use context');
     }
     return node?.getProperty(_typeProperty);
@@ -152,7 +151,9 @@
   /// Attach contextual type information [type] to [node] for use during
   /// inference.
   static void setType(AstNode? node, DartType? type) {
-    if (node is ArgumentList) {
+    if (node is ArgumentList ||
+        node is VariableDeclaration ||
+        node is FunctionBody) {
       assert(false, 'Nodes of type ${node.runtimeType} should use context');
     }
     if (type == null || type.isDynamic) {
@@ -1238,16 +1239,18 @@
   }
 
   @override
-  void visitBlockFunctionBody(BlockFunctionBody node) {
+  DartType visitBlockFunctionBody(BlockFunctionBody node,
+      {DartType? imposedType}) {
     try {
-      inferenceContext.pushFunctionBodyContext(node);
+      inferenceContext.pushFunctionBodyContext(node, imposedType);
       _thisAccessTracker.enterFunctionBody(node);
       checkUnreachableNode(node);
       node.visitChildren(this);
     } finally {
       _thisAccessTracker.exitFunctionBody(node);
-      inferenceContext.popFunctionBodyContext(node);
+      imposedType = inferenceContext.popFunctionBodyContext(node);
     }
+    return imposedType;
   }
 
   @override
@@ -1391,12 +1394,11 @@
   }
 
   @override
-  void visitConstructorDeclaration(ConstructorDeclaration node) {
+  void visitConstructorDeclaration(covariant ConstructorDeclarationImpl node) {
     flowAnalysis.topLevelDeclaration_enter(node, node.parameters);
     flowAnalysis.executableDeclaration_enter(node, node.parameters, false);
 
     var returnType = node.declaredElement!.type.returnType;
-    InferenceContext.setType(node.body, returnType);
 
     var outerFunction = _enclosingFunction;
     try {
@@ -1404,7 +1406,14 @@
       assert(_thisType == null);
       _setupThisType();
       checkUnreachableNode(node);
-      node.visitChildren(this);
+      node.documentationComment?.accept(this);
+      node.metadata.accept(this);
+      node.returnType.accept(this);
+      node.name?.accept(this);
+      node.parameters.accept(this);
+      node.initializers.accept(this);
+      node.redirectedConstructor?.accept(this);
+      node.body.resolve(this, returnType);
       elementResolver.visitConstructorDeclaration(node);
     } finally {
       _enclosingFunction = outerFunction;
@@ -1526,12 +1535,13 @@
   }
 
   @override
-  void visitEmptyFunctionBody(EmptyFunctionBody node) {
-    if (resolveOnlyCommentInFunctionBody) {
-      return;
+  DartType visitEmptyFunctionBody(EmptyFunctionBody node,
+      {DartType? imposedType}) {
+    if (!resolveOnlyCommentInFunctionBody) {
+      checkUnreachableNode(node);
+      node.visitChildren(this);
     }
-    checkUnreachableNode(node);
-    node.visitChildren(this);
+    return imposedType ?? typeProvider.dynamicType;
   }
 
   @override
@@ -1607,13 +1617,14 @@
   }
 
   @override
-  void visitExpressionFunctionBody(ExpressionFunctionBody node) {
+  DartType visitExpressionFunctionBody(ExpressionFunctionBody node,
+      {DartType? imposedType}) {
     if (resolveOnlyCommentInFunctionBody) {
-      return;
+      return imposedType ?? typeProvider.dynamicType;
     }
 
     try {
-      inferenceContext.pushFunctionBodyContext(node);
+      inferenceContext.pushFunctionBodyContext(node, imposedType);
       InferenceContext.setType(
         node.expression,
         inferenceContext.bodyContext!.contextType,
@@ -1629,8 +1640,9 @@
       inferenceContext.bodyContext!.addReturnExpression(node.expression);
     } finally {
       _thisAccessTracker.exitFunctionBody(node);
-      inferenceContext.popFunctionBodyContext(node);
+      imposedType = inferenceContext.popFunctionBodyContext(node);
     }
+    return imposedType;
   }
 
   @override
@@ -2010,12 +2022,11 @@
   }
 
   @override
-  void visitMethodDeclaration(MethodDeclaration node) {
+  void visitMethodDeclaration(covariant MethodDeclarationImpl node) {
     flowAnalysis.topLevelDeclaration_enter(node, node.parameters);
     flowAnalysis.executableDeclaration_enter(node, node.parameters, false);
 
     DartType returnType = node.declaredElement!.returnType;
-    InferenceContext.setType(node.body, returnType);
 
     var outerFunction = _enclosingFunction;
     try {
@@ -2023,7 +2034,13 @@
       assert(_thisType == null);
       _setupThisType();
       checkUnreachableNode(node);
-      node.visitChildren(this);
+      node.documentationComment?.accept(this);
+      node.metadata.accept(this);
+      node.returnType?.accept(this);
+      node.name.accept(this);
+      node.typeParameters?.accept(this);
+      node.parameters?.accept(this);
+      node.body.resolve(this, returnType);
       elementResolver.visitMethodDeclaration(node);
     } finally {
       _enclosingFunction = outerFunction;
@@ -2123,9 +2140,11 @@
   }
 
   @override
-  void visitNativeFunctionBody(NativeFunctionBody node) {
+  DartType visitNativeFunctionBody(NativeFunctionBody node,
+      {DartType? imposedType}) {
     checkUnreachableNode(node);
     node.visitChildren(this);
+    return imposedType ?? typeProvider.dynamicType;
   }
 
   @override
@@ -2543,10 +2562,6 @@
   @override
   void visitVariableDeclarationList(VariableDeclarationList node) {
     flowAnalysis.variableDeclarationList(node);
-    for (VariableDeclaration decl in node.variables) {
-      VariableElement variableElement = decl.declaredElement!;
-      InferenceContext.setType(decl, variableElement.type);
-    }
     checkUnreachableNode(node);
     node.visitChildren(this);
     elementResolver.visitVariableDeclarationList(node);
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 8891e87..940d786 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -21,6 +21,17 @@
 @reflectiveTest
 class NonErrorResolverTest extends PubPackageResolutionTest
     with NonErrorResolverTestCases {
+  test_async_callback_in_with_unknown_return_type_context() async {
+    await assertNoErrorsInCode('''
+abstract class C {
+  R run<R>(R Function() action);
+}
+f(C c) {
+  c.run(() async {});
+}
+''');
+  }
+
   test_await_flattened() async {
     await assertNoErrorsInCode('''
 Future<Future<int>>? ffi() => null;
diff --git a/tools/VERSION b/tools/VERSION
index 9a2d9f1..afae815 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 78
+PRERELEASE 79
 PRERELEASE_PATCH 0
\ No newline at end of file