@@ -5415,6 +5415,8 @@ class InferenceContext {
5415
5415
* A stack of return types for all of the enclosing
5416
5416
* functions and methods.
5417
5417
*/
5418
+ // TODO(leafp) Handle the implicit union type for Futures
5419
+ // https://github.com/dart-lang/sdk/issues/25322
5418
5420
List <DartType > _returnStack = < DartType > [];
5419
5421
5420
5422
InferenceContext ._(this ._errorListener, TypeProvider typeProvider,
@@ -5423,9 +5425,15 @@ class InferenceContext {
5423
5425
5424
5426
/**
5425
5427
* Get the return type of the current enclosing function, if any.
5428
+ *
5429
+ * The type returned for a function is the type that is expected
5430
+ * to be used in a return or yield context. For ordinary functions
5431
+ * this is the same as the return type of the function. For async
5432
+ * functions returning Future<T> and for generator functions
5433
+ * returning Stream<T> or Iterable<T>, this is T.
5426
5434
*/
5427
5435
DartType get returnContext =>
5428
- ( _returnStack.isNotEmpty) ? _returnStack.last : null ;
5436
+ _returnStack.isNotEmpty ? _returnStack.last : null ;
5429
5437
5430
5438
/**
5431
5439
* Match type [t1] against type [t2] as follows.
@@ -8359,8 +8367,10 @@ class ResolverVisitor extends ScopedVisitor {
8359
8367
8360
8368
@override
8361
8369
Object visitAwaitExpression (AwaitExpression node) {
8362
- //TODO(leafp): Handle the implicit union type here
8363
- DartType contextType = InferenceContext .getType (node);
8370
+ // TODO(leafp): Handle the implicit union type here
8371
+ // https://github.com/dart-lang/sdk/issues/25322
8372
+ DartType contextType = StaticTypeAnalyzer .flattenFutures (
8373
+ typeProvider, InferenceContext .getType (node));
8364
8374
if (contextType != null ) {
8365
8375
InterfaceType futureT =
8366
8376
typeProvider.futureType.substitute4 ([contextType]);
@@ -8894,7 +8904,11 @@ class ResolverVisitor extends ScopedVisitor {
8894
8904
DartType functionType = InferenceContext .getType (node);
8895
8905
if (functionType is FunctionType ) {
8896
8906
_inferFormalParameterList (node.parameters, functionType);
8897
- InferenceContext .setType (node.body, functionType.returnType);
8907
+ DartType returnType = _computeReturnOrYieldType (
8908
+ functionType.returnType,
8909
+ _enclosingFunction.isGenerator,
8910
+ _enclosingFunction.isAsynchronous);
8911
+ InferenceContext .setType (node.body, returnType);
8898
8912
}
8899
8913
super .visitFunctionExpression (node);
8900
8914
} finally {
@@ -9099,7 +9113,11 @@ class ResolverVisitor extends ScopedVisitor {
9099
9113
ExecutableElement outerFunction = _enclosingFunction;
9100
9114
try {
9101
9115
_enclosingFunction = node.element;
9102
- InferenceContext .setType (node.body, node.element.type? .returnType);
9116
+ DartType returnType = _computeReturnOrYieldType (
9117
+ _enclosingFunction.type? .returnType,
9118
+ _enclosingFunction.isGenerator,
9119
+ _enclosingFunction.isAsynchronous);
9120
+ InferenceContext .setType (node.body, returnType);
9103
9121
super .visitMethodDeclaration (node);
9104
9122
} finally {
9105
9123
_enclosingFunction = outerFunction;
@@ -9328,18 +9346,15 @@ class ResolverVisitor extends ScopedVisitor {
9328
9346
// If we're not in a generator ([a]sync*, then we shouldn't have a yield.
9329
9347
// so don't infer
9330
9348
if (_enclosingFunction.isGenerator) {
9331
- // If this is a yield* , then we just propagate the return type downwards
9349
+ // If this just a yield, then we just pass on the element type
9332
9350
DartType type = returnType;
9333
- // If this just a yield, then we need to get the element type
9334
- if (node.star == null ) {
9351
+ if (node.star != null ) {
9352
+ // If this is a yield*, then we wrap the element return type
9335
9353
// If it's synchronous, we expect Iterable<T>, otherwise Stream<T>
9336
- InterfaceType wrapperD = _enclosingFunction.isSynchronous
9337
- ? typeProvider.iterableDynamicType
9338
- : typeProvider.streamDynamicType;
9339
- // Match the types to instantiate the type arguments if possible
9340
- List <DartType > targs =
9341
- inferenceContext.matchTypes (wrapperD, returnType);
9342
- type = (targs? .length == 1 ) ? targs[0 ] : null ;
9354
+ InterfaceType wrapperType = _enclosingFunction.isSynchronous
9355
+ ? typeProvider.iterableType
9356
+ : typeProvider.streamType;
9357
+ type = wrapperType.substitute4 (< DartType > [type]);
9343
9358
}
9344
9359
InferenceContext .setType (node.expression, type);
9345
9360
}
@@ -9379,6 +9394,34 @@ class ResolverVisitor extends ScopedVisitor {
9379
9394
}
9380
9395
}
9381
9396
9397
+ /**
9398
+ * Given the declared return type of a function, compute the type of the
9399
+ * values which should be returned or yielded as appropriate. If a type
9400
+ * cannot be computed from the declared return type, return null.
9401
+ */
9402
+ DartType _computeReturnOrYieldType (
9403
+ DartType declaredType, bool isGenerator, bool isAsynchronous) {
9404
+ // Ordinary functions just return their declared types.
9405
+ if (! isGenerator && ! isAsynchronous) {
9406
+ return declaredType;
9407
+ }
9408
+ if (isGenerator) {
9409
+ if (declaredType is ! InterfaceType ) {
9410
+ return null ;
9411
+ }
9412
+ // If it's synchronous, we expect Iterable<T>, otherwise Stream<T>
9413
+ InterfaceType rawType = isAsynchronous
9414
+ ? typeProvider.streamDynamicType
9415
+ : typeProvider.iterableDynamicType;
9416
+ // Match the types to instantiate the type arguments if possible
9417
+ List <DartType > typeArgs =
9418
+ inferenceContext.matchTypes (rawType, declaredType);
9419
+ return (typeArgs? .length == 1 ) ? typeArgs[0 ] : null ;
9420
+ }
9421
+ // Must be asynchronous to reach here, so strip off any layers of Future
9422
+ return StaticTypeAnalyzer .flattenFutures (typeProvider, declaredType);
9423
+ }
9424
+
9382
9425
/**
9383
9426
* The given expression is the expression used to compute the iterator for a
9384
9427
* for-each statement. Attempt to compute the type of objects that will be
0 commit comments