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

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

Issue 2647833002: fix #28008, fix #28009 implement FutureOr<T> (Closed)
Patch Set: add test Created 3 years, 11 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 b3ec3eb61a30dffadb3b6a2dc1be868cfc9ee549..9ff7ec1b41f6c9ecea3f361e8b9c99038f35a0dc 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -811,7 +811,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
Expression target = node.realTarget;
if (target != null) {
DartType targetType = target.bestType;
- if (_isAsyncFutureType(targetType)) {
+ if (targetType.isDartAsyncFuture) {
// Future.then(closure) return type is:
// 1) the returned Future type, if the closure returns a Future;
// 2) Future<valueType>, if the closure returns a value.
@@ -1419,11 +1419,23 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
// TODO(brianwilkerson) Determine whether this can still happen.
staticType2 = _dynamicType;
}
+
DartType staticType =
- _typeSystem.getLeastUpperBound(staticType1, staticType2);
- if (staticType == null) {
- staticType = _dynamicType;
+ _typeSystem.getLeastUpperBound(staticType1, staticType2) ??
+ _dynamicType;
+
+ // TODO(jmesserly): this behavior needs to be specified.
+ // The goal here is to avoid LUB concluding Object when we already had a
+ // valid FutureOr<T> as the downward context type for a conditional.
Leaf 2017/01/24 21:56:26 I'm not keen on putting this in just as a hack for
Jennifer Messerly 2017/01/25 00:33:35 Done.
+ if (_strongMode && staticType.isObject) {
Paul Berry 2017/01/24 17:45:13 Why put this logic here and not in _typeSystem.get
Jennifer Messerly 2017/01/24 18:58:20 yeah ... the problem tho is we have two implementa
Paul Berry 2017/01/24 19:19:09 Agreed. It's really unfortunate that we have two
Paul Berry 2017/01/24 20:14:50 Ack! I just re-read this and realized that it onl
Jennifer Messerly 2017/01/25 00:33:35 ahhh gotcha :) yeah that explains why a lot of th
+ DartType context = InferenceContext.getContext(node);
+ if (context != null && context.isDartAsyncFutureOr &&
+ _typeSystem.isSubtypeOf(staticType1, context) &&
+ _typeSystem.isSubtypeOf(staticType2, context)) {
+ staticType = context;
+ }
}
+
_recordStaticType(node, staticType);
DartType propagatedType1 = expr1.propagatedType;
DartType propagatedType2 = expr2.propagatedType;
@@ -1520,6 +1532,9 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
: _typeProvider.iterableType;
return genericType.instantiate(<DartType>[type]);
} else if (body.isAsynchronous) {
+ if (type.isDartAsyncFutureOr) {
Paul Berry 2017/01/24 17:45:13 I'm worried that this behavior hasn't been impleme
Jennifer Messerly 2017/01/24 18:58:20 this is the same logic that was below, on line 208
Paul Berry 2017/01/24 19:19:09 Ok, I didn't realize this was preexisting behavior
+ type = (type as InterfaceType).typeArguments[0];
+ }
return _typeProvider.futureType
.instantiate(<DartType>[type.flattenFutures(_typeSystem)]);
} else {
@@ -1962,44 +1977,6 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
argTypes.add(argumentList.arguments[i].staticType);
}
}
-
- // 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 (_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);
@@ -2081,12 +2058,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
// * we also normalize bottom to dynamic here.
if (_strongMode && (computedType.isBottom || computedType.isDynamic)) {
DartType contextType = InferenceContext.getContext(body);
- if (contextType is FutureUnionType) {
- // TODO(jmesserly): can we do something better here?
- computedType = body.isAsynchronous ? contextType.type : _dynamicType;
- } else {
- computedType = contextType ?? _dynamicType;
- }
+ computedType = contextType ?? _dynamicType;
recordInference = !computedType.isDynamic;
}
@@ -2221,23 +2193,6 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
}
/**
- * Return `true` if the given [Type] is the `Future` form the 'dart:async'
- * library.
- */
- bool _isAsyncFutureType(DartType type) =>
- type is InterfaceType &&
- type.name == "Future" &&
- _isAsyncLibrary(type.element.library);
-
- /**
- * Return `true` if the given library is the 'dart:async' library.
- *
- * @param library the library being tested
- * @return `true` if the library is 'dart:async'
- */
- bool _isAsyncLibrary(LibraryElement library) => library.name == "dart.async";
-
- /**
* Return `true` if the given library is the 'dart:html' library.
*
* @param library the library being tested

Powered by Google App Engine
This is Rietveld 408576698