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

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

Issue 1609093003: fixes #25482, flatten Futures in strong mode so Future.then works (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 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 7aaa2fa07dc9fdd28878277b7a2177ad5d536c8e..e67d09669df01d823329161503dbc508d9074782 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -282,11 +282,11 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
// TODO(brianwilkerson) Determine whether this can still happen.
staticExpressionType = _dynamicType;
}
- DartType staticType = flattenFutures(_typeProvider, staticExpressionType);
+ DartType staticType = staticExpressionType.flattenFutures(_typeSystem);
_recordStaticType(node, staticType);
DartType propagatedExpressionType = node.expression.propagatedType;
DartType propagatedType =
- flattenFutures(_typeProvider, propagatedExpressionType);
+ propagatedExpressionType?.flattenFutures(_typeSystem);
_resolver.recordPropagatedTypeIfBetter(node, propagatedType);
return null;
}
@@ -735,7 +735,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
// Check for special cases.
bool needPropagatedType = true;
String methodName = methodNameNode.name;
- if (methodName == "then") {
+ if (!_strongMode && methodName == "then") {
Expression target = node.realTarget;
if (target != null) {
DartType targetType = target.bestType;
@@ -754,16 +754,10 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
_computePropagatedReturnType(closureExpr.element);
if (returnType != null) {
// prepare the type of the returned Future
- InterfaceTypeImpl newFutureType;
- if (_isAsyncFutureType(returnType)) {
- newFutureType = returnType as InterfaceTypeImpl;
- } else {
- InterfaceType futureType = targetType as InterfaceType;
- newFutureType = new InterfaceTypeImpl(futureType.element);
- newFutureType.typeArguments = <DartType>[returnType];
- }
+ InterfaceType newFutureType = _typeProvider.futureType
+ .substitute4([returnType.flattenFutures(_typeSystem)]);
// set the 'then' invocation type
- _recordPropagatedType(node, newFutureType);
+ _resolver.recordPropagatedTypeIfBetter(node, newFutureType);
needPropagatedType = false;
return null;
}
@@ -1503,7 +1497,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
}
if (body.isAsynchronous) {
return _typeProvider.futureType
- .substitute4(<DartType>[flattenFutures(_typeProvider, type)]);
+ .substitute4(<DartType>[type.flattenFutures(_typeSystem)]);
} else {
return type;
}
@@ -2120,47 +2114,6 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
}
/**
- * Implements the function "flatten" defined in the spec:
- *
- * If T = Future<S> then flatten(T) = flatten(S).
- *
- * Otherwise if T <: Future then let S be a type such that T << Future<S>
- * and for all R, if T << Future<R> then S << R. Then flatten(T) = S.
- *
- * In any other circumstance, flatten(T) = T.
- */
- static DartType flattenFutures(TypeProvider typeProvider, DartType type) {
- if (type is InterfaceType) {
- // Implement the case: "If T = Future<S> then flatten(T) = flatten(S)."
- if (type.element == typeProvider.futureType.element &&
- type.typeArguments.length > 0) {
- return flattenFutures(typeProvider, type.typeArguments[0]);
- }
-
- // Implement the case: "Otherwise if T <: Future then let S be a type
- // such that T << Future<S> and for all R, if T << Future<R> then S << R.
- // Then flatten(T) = S."
- //
- // In other words, given the set of all types R such that T << Future<R>,
- // let S be the most specific of those types, if any such S exists.
- //
- // Since we only care about the most specific type, it is sufficent to
- // look at the types appearing as a parameter to Future in the type
- // hierarchy of T. We don't need to consider the supertypes of those
- // types, since they are by definition less specific.
- List<DartType> candidateTypes =
- _searchTypeHierarchyForFutureParameters(typeProvider, type);
- DartType flattenResult = _findMostSpecificType(candidateTypes);
- if (flattenResult != null) {
- return flattenResult;
- }
- }
-
- // Implement the case: "In any other circumstance, flatten(T) = T."
- return type;
- }
-
- /**
* Create a table mapping HTML tag names to the names of the classes (in 'dart:html') that
* implement those tags.
*
@@ -2228,88 +2181,6 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
map["video"] = "VideoElement";
return map;
}
-
- /**
- * If there is a single type which is at least as specific as all of the
- * types in [types], return it. Otherwise return `null`.
- */
- static DartType _findMostSpecificType(List<DartType> types) {
- // The << relation ("more specific than") is a partial ordering on types,
- // so to find the most specific type of a set, we keep a bucket of the most
- // specific types seen so far such that no type in the bucket is more
- // specific than any other type in the bucket.
- List<DartType> bucket = <DartType>[];
-
- // Then we consider each type in turn.
- for (DartType type in types) {
- // If any existing type in the bucket is more specific than this type,
- // then we can ignore this type.
- if (bucket.any((DartType t) => t.isMoreSpecificThan(type))) {
- continue;
- }
- // Otherwise, we need to add this type to the bucket and remove any types
- // that are less specific than it.
- bool added = false;
- int i = 0;
- while (i < bucket.length) {
- if (type.isMoreSpecificThan(bucket[i])) {
- if (added) {
- if (i < bucket.length - 1) {
- bucket[i] = bucket.removeLast();
- } else {
- bucket.removeLast();
- }
- } else {
- bucket[i] = type;
- i++;
- added = true;
- }
- } else {
- i++;
- }
- }
- if (!added) {
- bucket.add(type);
- }
- }
-
- // Now that we are finished, if there is exactly one type left in the
- // bucket, it is the most specific type.
- if (bucket.length == 1) {
- return bucket[0];
- }
-
- // Otherwise, there is no single type that is more specific than the
- // others.
- return null;
- }
-
- /**
- * Given a seed type [type], search its class hierarchy for types of the form
- * Future<R>, and return a list of the resulting R's.
- */
- static List<DartType> _searchTypeHierarchyForFutureParameters(
- TypeProvider typeProvider, InterfaceType type) {
- List<DartType> result = <DartType>[];
- HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
- void recurse(InterfaceType type) {
- if (type.element == typeProvider.futureType.element &&
- type.typeArguments.length > 0) {
- result.add(type.typeArguments[0]);
- }
- if (visitedClasses.add(type.element)) {
- if (type.superclass != null) {
- recurse(type.superclass);
- }
- for (InterfaceType interface in type.interfaces) {
- recurse(interface);
- }
- visitedClasses.remove(type.element);
- }
- }
- recurse(type);
- return result;
- }
}
class _StaticTypeAnalyzer_computePropagatedReturnTypeOfFunction

Powered by Google App Engine
This is Rietveld 408576698