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