Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Unified Diff: pkg/analyzer/lib/src/generated/static_type_analyzer.dart

Issue 2253923002: fix #27088, future then upwards inference (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);
}
« no previous file with comments | « pkg/analyzer/lib/src/generated/resolver.dart ('k') | pkg/analyzer/test/generated/analysis_context_factory.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698