Chromium Code Reviews| 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 a2aeae15c7741c74e7444e1ef09841ccf790c371..b5de145803aaac7959c414093deef9295659130a 100644 |
| --- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart |
| +++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart |
| @@ -1967,6 +1967,49 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> { |
| argTypes.add(argumentList.arguments[i].staticType); |
| } |
| } |
| + |
| + // TODO(leafp): remove this again after code has been updated to |
| + // use FutureOr on classes that implement Future |
| + // 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 && |
| + argTypes[0].isDartAsyncFutureOr && |
|
Jennifer Messerly
2017/02/03 18:31:51
I'm not sure this check will be satisfied? it look
Leaf
2017/02/03 21:28:56
Yeesh. Totally borked. I guess the downwards inf
|
| + _resolver.isFutureThen(fnType.element)) { |
| + var firstArgType = argTypes[0]; |
| + var firstParamType = paramTypes[0] as FunctionType; |
| + if (firstArgType is FunctionType) { |
|
Jennifer Messerly
2017/02/03 18:31:52
if firstArgType was a FutureOr, then it's not a Fu
Leaf
2017/02/03 21:28:56
Done.
|
| + 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; |
|
Jennifer Messerly
2017/02/03 18:31:51
rather than this line and the following if stateme
Leaf
2017/02/03 21:28:56
Done.
|
| + if (_resolver.isSubtypeOfFuture(argReturnType)) { |
| + // 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) |
| + ..isSynthetic = 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(fnType, paramTypes, argTypes, |
| fnType.returnType, InferenceContext.getContext(node), |
| errorReporter: _resolver.errorReporter, errorNode: errorNode); |