| 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..5d90f3c03d3c59932fa4978a73d9d30a7cf213f9 100644
|
| --- a/pkg/analyzer/lib/src/generated/resolver.dart
|
| +++ b/pkg/analyzer/lib/src/generated/resolver.dart
|
| @@ -5218,8 +5218,26 @@ class ResolverVisitor extends ScopedVisitor {
|
| }
|
|
|
| /**
|
| + * 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>`
|
| + */
|
| + // TODO(leafp): Eliminate this when code is switched to using FutureOr
|
| + 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;
|
| + }
|
| +
|
| + /**
|
| * Returns true if this type is any subtype of the built in Future type.
|
| */
|
| + // TODO(leafp): Eliminate this when code is switched to using FutureOr
|
| bool isSubtypeOfFuture(DartType type) =>
|
| typeSystem.isSubtypeOf(type, typeProvider.futureDynamicType);
|
|
|
| @@ -6060,8 +6078,27 @@ 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
|
| + // Introduce FutureOr<T> for backwards compatibility if it was
|
| + // missing in old code.
|
| + 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);
|
|
|