Chromium Code Reviews

Unified Diff: pkg/analyzer/lib/src/generated/resolver.dart

Issue 1724543002: fix #25487, infer block lambdas from return statements (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Index: pkg/analyzer/lib/src/generated/resolver.dart
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 496b821de8f7b985808eea72ca1e4ce9c9071f30..d66d60eff9e8d6fa3d27db4562ecc93d908509b1 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -4602,12 +4602,20 @@ class InferenceContext {
final TypeSystem _typeSystem;
/**
+ * When no context type is available, this will track the least upper bound
+ * of all return statements in a lambda.
+ *
+ * This will always be kept in sync with [_returnStack].
+ */
+ final List<DartType> _inferredReturn = <DartType>[];
+
+ /**
* A stack of return types for all of the enclosing
* functions and methods.
*/
// TODO(leafp) Handle the implicit union type for Futures
// https://github.com/dart-lang/sdk/issues/25322
- List<DartType> _returnStack = <DartType>[];
+ final List<DartType> _returnStack = <DartType>[];
InferenceContext._(this._errorListener, TypeProvider typeProvider,
this._typeSystem, this._inferenceHints)
@@ -4638,19 +4646,49 @@ class InferenceContext {
/**
* Pop a return type off of the return stack.
+ *
+ * Also record any inferred return type using [setType], unless this node
+ * already has a context type. This recorded type will be the least upper
+ * bound of all types added with [addReturnType].
*/
- void popReturnContext() {
- assert(_returnStack.isNotEmpty);
+ void popReturnContext(BlockFunctionBody node) {
+ assert(_returnStack.isNotEmpty && _inferredReturn.isNotEmpty);
if (_returnStack.isNotEmpty) {
_returnStack.removeLast();
}
+ if (_inferredReturn.isNotEmpty) {
+ DartType inferred = _inferredReturn.removeLast();
+ if (!inferred.isBottom) {
+ setType(node, inferred);
+ }
+ }
}
/**
- * Push a [returnType] onto the return stack.
+ * Push a block function body's return type onto the return stack.
*/
- void pushReturnContext(DartType returnType) {
+ void pushReturnContext(BlockFunctionBody node) {
+ DartType returnType = getType(node);
_returnStack.add(returnType);
+ _inferredReturn.add(BottomTypeImpl.instance);
+ }
+
+ /**
+ * Records the type of the expression of a return statement.
+ *
+ * This will be used for inferring a block bodied lambda, if no context
+ * type was available.
+ */
+ void addReturnType(DartType type) {
+ if (type == null || _returnStack.isEmpty) {
+ return;
+ }
+ DartType context = _returnStack.last;
+ if (context == null || context.isDynamic) {
+ DartType inferred = _inferredReturn.last;
+ inferred = _typeSystem.getLeastUpperBound(_typeProvider, type, inferred);
+ _inferredReturn[_inferredReturn.length - 1] = inferred;
+ }
}
/**
@@ -7657,11 +7695,11 @@ class ResolverVisitor extends ScopedVisitor {
Object visitBlockFunctionBody(BlockFunctionBody node) {
_overrideManager.enterScope();
try {
- inferenceContext.pushReturnContext(InferenceContext.getType(node));
+ inferenceContext.pushReturnContext(node);
super.visitBlockFunctionBody(node);
} finally {
_overrideManager.exitScope();
- inferenceContext.popReturnContext();
+ inferenceContext.popReturnContext(node);
}
return null;
}
@@ -8451,8 +8489,13 @@ class ResolverVisitor extends ScopedVisitor {
@override
Object visitReturnStatement(ReturnStatement node) {
- InferenceContext.setType(node.expression, inferenceContext.returnContext);
- return super.visitReturnStatement(node);
+ Expression e = node.expression;
+ InferenceContext.setType(e, inferenceContext.returnContext);
+ super.visitReturnStatement(node);
+ if (e != null) {
+ inferenceContext.addReturnType(e.staticType);
Leaf 2016/02/23 02:17:47 As it stands, I think that this will do the right
Jennifer Messerly 2016/02/23 17:41:46 Nice catch. Yeah, it seems like we should interpre
Jennifer Messerly 2016/02/24 00:20:40 Done.
+ }
+ return null;
}
@override

Powered by Google App Engine