| 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 5f089988e9c1567dae421fa306c288d335f4a163..b3484a9669f10f2a400eea6da6415c7340da9d7b 100644
|
| --- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
|
| +++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
|
| @@ -1953,6 +1953,46 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| } else {
|
| returnType = returnContext;
|
| }
|
| +
|
| + // Special case Future<T>.then upwards inference. It has signature:
|
| + //
|
| + // <S>(T -> (S | Future<S>)) -> Future<S>
|
| + //
|
| + // Based on the first argument type, we'll pick one of these signatures:
|
| + //
|
| + // <S>(T -> S) -> Future<S>
|
| + // <S>(T -> Future<S>) -> Future<S>
|
| + //
|
| + // ... and finish the inference using that.
|
| + if (argTypes.isNotEmpty && _resolver.isFutureThen(fnType.element)) {
|
| + var firstArgType = argTypes[0];
|
| + var firstParamType = paramTypes[0] as FunctionType;
|
| + if (firstArgType is FunctionType) {
|
| + var argReturnType = firstArgType.returnType;
|
| + // Skip the inference if we have the top type. It can only lead to
|
| + // worse inference. For example, this happens when the lambda returns
|
| + // S or Future<S> in a conditional.
|
| + if (!argReturnType.isObject && !argReturnType.isDynamic) {
|
| + DartType paramReturnType = fnType.typeFormals[0].type;
|
| + if (argReturnType.isDartAsyncFuture) {
|
| + // Given an argument of (T) -> Future<S>, instantiate with <S>
|
| + paramReturnType =
|
| + _typeProvider.futureType.instantiate([paramReturnType]);
|
| + }
|
| +
|
| + // Adjust the expected parameter type to have this return type.
|
| + var function = new FunctionElementImpl(firstParamType.name, -1)
|
| + ..synthetic = true
|
| + ..shareParameters(firstParamType.parameters)
|
| + ..returnType = paramReturnType;
|
| + function.type = new FunctionTypeImpl(function);
|
| +
|
| + // Use this as the expected 1st parameter type.
|
| + paramTypes[0] = function.type;
|
| + }
|
| + }
|
| + }
|
| +
|
| return ts.inferGenericFunctionCall(
|
| _typeProvider, fnType, paramTypes, argTypes, returnType);
|
| }
|
|
|