Chromium Code Reviews| 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 61f6a106b1835ee569844af2117f9db7b3e197b1..885552fef4fc40b92a7ed8feed4b745e7c5e1063 100644 |
| --- a/pkg/analyzer/lib/src/generated/resolver.dart |
| +++ b/pkg/analyzer/lib/src/generated/resolver.dart |
| @@ -5218,6 +5218,25 @@ class ResolverVisitor extends ScopedVisitor { |
| } |
| /** |
| + * TODO(leafp): Eliminate this when code is switched to using FutureOr |
|
Jennifer Messerly
2017/02/03 18:31:51
nit: this should go outside of the doc comment
Leaf
2017/02/03 21:28:56
Done.
|
| + * |
| + * Returns true if this method is `Future.then` or an override thereof. |
| + * |
| + * If so we will apply special typing rules in strong mode, to handle the |
| + * implicit union of `S | Future<S>` |
| + */ |
| + bool isFutureThen(Element element) { |
| + // If we are a method named then |
| + if (element is MethodElement && element.name == 'then') { |
| + DartType type = element.enclosingElement.type; |
| + // On Future or a subtype, then we're good. |
| + return (type.isDartAsyncFuture || isSubtypeOfFuture(type)); |
| + } |
| + return false; |
| + } |
| + |
| + /** |
| + * TODO(leafp): Eliminate this when code is switched to using FutureOr |
| * Returns true if this type is any subtype of the built in Future type. |
| */ |
| bool isSubtypeOfFuture(DartType type) => |
| @@ -6060,8 +6079,31 @@ class ResolverVisitor extends ScopedVisitor { |
| matchFunctionTypeParameters(node.typeParameters, functionType); |
| if (functionType is FunctionType) { |
| _inferFormalParameterList(node.parameters, functionType); |
| - InferenceContext.setType( |
| - node.body, _computeReturnOrYieldType(functionType.returnType)); |
| + DartType returnType; |
| + ParameterElement parameterElement = |
| + resolutionMap.staticParameterElementForExpression(node); |
| + if (isFutureThen(parameterElement?.enclosingElement)) { |
| + var futureThenType = |
| + InferenceContext.getContext(node.parent) as FunctionType; |
| + |
| + // TODO(leafp): Get rid of this once code has been updated to use |
| + // FutureOr |
| + // Pretend the return type of Future<T>.then<S> first parameter is |
|
Jennifer Messerly
2017/02/03 18:31:51
this comment is obsolete now, I think... should sa
Leaf
2017/02/03 21:28:56
Done.
|
| + // |
| + // T -> (S | Future<S>) |
| + // |
| + // We can't represent this in Dart so we populate it here during |
| + // inference. |
| + if (futureThenType.parameters.isNotEmpty) { |
| + if (!futureThenType.parameters[0].type.isDartAsyncFutureOr) { |
| + var typeParamS = |
| + futureThenType.returnType.flattenFutures(typeSystem); |
| + returnType = _createFutureOr(typeParamS); |
| + } |
| + } |
| + } |
| + returnType ??= _computeReturnOrYieldType(functionType.returnType); |
| + InferenceContext.setType(node.body, returnType); |
| } |
| } |
| super.visitFunctionExpression(node); |