Index: pkg/analyzer/lib/src/generated/static_type_analyzer.dart |
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart |
index cc8e2f06e5ca9c4f409d14c684c20f332974cef1..82b3796c645d51ad12bfca232075775245660309 100644 |
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart |
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart |
@@ -461,10 +461,21 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> { |
// node. |
return null; |
} |
+ bool recordInference = false; |
ExecutableElementImpl functionElement = |
node.element as ExecutableElementImpl; |
DartType computedType = _computeStaticReturnTypeOfFunctionExpression(node); |
if (_strongMode) { |
+ // Strong mode can infer the type of a block function body. |
+ FunctionBody body = node.body; |
+ if (body is BlockFunctionBody) { |
+ DartType inferredType = InferenceContext.getType(body); |
Leaf
2016/02/23 02:17:47
It bothers me a little bit that this segment of co
Jennifer Messerly
2016/02/23 17:41:46
Yeah, makes sense. I was having the same thoughts
Jennifer Messerly
2016/02/23 22:16:21
Ah, I remembered one issue. This code isn't integr
Jennifer Messerly
2016/02/24 00:20:41
Done.
|
+ if (inferredType != null) { |
+ computedType = _computeReturnTypeOfFunction(body, inferredType); |
+ recordInference = true; |
+ } |
+ } |
+ |
// In strong mode, we don't want to allow the function's return type to |
// be bottom. If the surrounding context has a more precise type, we |
// will push it down with inference, below. If not we want to use dynamic. |
@@ -484,14 +495,17 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> { |
if (computedType.isDynamic && |
!(returnType.isDynamic || returnType.isBottom)) { |
computedType = returnType; |
- _resolver.inferenceContext.recordInference(node, functionType); |
+ recordInference = true; |
} |
} |
} |
} |
functionElement.returnType = computedType; |
_recordPropagatedTypeOfFunction(functionElement, node.body); |
- _recordStaticType(node, node.element.type); |
+ _recordStaticType(node, functionElement.type); |
+ if (recordInference) { |
+ _resolver.inferenceContext.recordInference(node, functionElement.type); |
+ } |
return null; |
} |
@@ -1473,6 +1487,27 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> { |
} |
/** |
+ * Given a function body and its return type, compute the return type of |
+ * the entire function, taking into account whether the function body |
+ * is `sync*`, `async` or `async*`. |
+ * |
+ * See also [FunctionBody.isAsynchronous], [FunctionBody.isGenerator]. |
+ */ |
+ DartType _computeReturnTypeOfFunction(FunctionBody body, DartType type) { |
+ if (body.isGenerator) { |
+ InterfaceType genericType = body.isAsynchronous |
+ ? _typeProvider.streamType |
+ : _typeProvider.iterableType; |
+ return genericType.substitute4(<DartType>[type]); |
+ } else if (body.isAsynchronous) { |
+ return _typeProvider.futureType |
+ .substitute4(<DartType>[type.flattenFutures(_typeSystem)]); |
+ } else { |
+ return type; |
+ } |
+ } |
+ |
+ /** |
* Compute the static return type of the method or function represented by the given element. |
* |
* @param element the element representing the method or function invoked by the given node |
@@ -1525,25 +1560,14 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> { |
DartType _computeStaticReturnTypeOfFunctionExpression( |
FunctionExpression node) { |
FunctionBody body = node.body; |
- if (body.isGenerator) { |
- if (body.isAsynchronous) { |
- return _typeProvider.streamDynamicType; |
- } else { |
- return _typeProvider.iterableDynamicType; |
- } |
- } |
+ |
DartType type; |
if (body is ExpressionFunctionBody) { |
type = _getStaticType(body.expression); |
} else { |
type = _dynamicType; |
} |
- if (body.isAsynchronous) { |
- return _typeProvider.futureType |
- .substitute4(<DartType>[type.flattenFutures(_typeSystem)]); |
- } else { |
- return type; |
- } |
+ return _computeReturnTypeOfFunction(body, type); |
} |
DartType _findIteratedType(DartType type, DartType targetType) { |