Chromium Code Reviews| Index: pkg/analyzer/lib/src/generated/type_system.dart |
| diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart |
| index 2b6012a4eb8e61022de5e507ac72e31364719341..b951f4f4dff2f4099045d17b8f5858af7ee0475e 100644 |
| --- a/pkg/analyzer/lib/src/generated/type_system.dart |
| +++ b/pkg/analyzer/lib/src/generated/type_system.dart |
| @@ -696,13 +696,6 @@ class StrongTypeSystemImpl extends TypeSystem { |
| }; |
| } |
| - /// If [t1] or [t2] is a type parameter we are inferring, update its bound. |
| - /// Returns `true` if we could possibly find a compatible type, |
| - /// otherwise `false`. |
| - bool _inferTypeParameterSubtypeOf(DartType t1, DartType t2) { |
| - return false; |
| - } |
| - |
| /** |
| * This currently does not implement a very complete least upper bound |
| * algorithm, but handles a couple of the very common cases that are |
| @@ -840,28 +833,7 @@ class StrongTypeSystemImpl extends TypeSystem { |
| // Trivially false. |
| if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) || |
| _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) { |
| - return _inferTypeParameterSubtypeOf(t1, t2); |
| - } |
| - |
| - // S <: T where S is a type variable |
| - // T is not dynamic or object (handled above) |
| - // True if T == S |
| - // Or true if bound of S is S' and S' <: T |
| - if (t1 is TypeParameterType) { |
| - if (t2 is TypeParameterType && |
| - t1.definition == t2.definition && |
| - guardedSubtype(t1.bound, t2.bound, visited)) { |
| - return true; |
| - } |
| - if (_inferTypeParameterSubtypeOf(t1, t2)) { |
| - return true; |
| - } |
| - DartType bound = t1.element.bound; |
| - return bound == null ? false : guardedSubtype(bound, t2, visited); |
| - } |
| - |
| - if (t2 is TypeParameterType) { |
| - return _inferTypeParameterSubtypeOf(t1, t2); |
| + return false; |
| } |
| // Handle FutureOr<T> union type. |
| @@ -887,6 +859,23 @@ class StrongTypeSystemImpl extends TypeSystem { |
| return isSubtypeOf(t1, t2Future) || isSubtypeOf(t1, t2TypeArg); |
| } |
| + // S <: T where S is a type variable |
| + // T is not dynamic or object (handled above) |
| + // True if T == S |
| + // Or true if bound of S is S' and S' <: T |
| + if (t1 is TypeParameterType) { |
| + if (t2 is TypeParameterType && |
| + t1.definition == t2.definition && |
| + guardedSubtype(t1.bound, t2.bound, visited)) { |
| + return true; |
| + } |
| + DartType bound = t1.element.bound; |
| + return bound == null ? false : guardedSubtype(bound, t2, visited); |
| + } |
| + if (t2 is TypeParameterType) { |
| + return false; |
| + } |
| + |
| // Void only appears as the return type of a function, and we handle it |
| // directly in the function subtype rules. We should not get to a point |
| // where we're doing a subtype test on a "bare" void, but just in case we |
| @@ -1482,6 +1471,7 @@ class _StrongInferenceTypeSystem extends StrongTypeSystemImpl { |
| for (int i = 0; i < fnTypeParams.length; i++) { |
| TypeParameterType typeParam = fnTypeParams[i]; |
| + _TypeParameterBound bound = _bounds[typeParam]; |
| // Apply the `extends` clause for the type parameter, if any. |
| // |
| @@ -1503,7 +1493,9 @@ class _StrongInferenceTypeSystem extends StrongTypeSystemImpl { |
| DartType declaredUpperBound = typeParam.element.bound; |
| if (declaredUpperBound != null) { |
| // Assert that the type parameter is a subtype of its bound. |
| - _inferTypeParameterSubtypeOf(typeParam, |
| + // TODO(jmesserly): the order of calling GLB here matters, because of |
| + // https://github.com/dart-lang/sdk/issues/28513 |
| + bound.upper = _typeSystem.getGreatestLowerBound(bound.upper, |
|
Jennifer Messerly
2017/01/27 23:04:49
this fix is new.
|
| declaredUpperBound.substitute2(inferredTypes, fnTypeParams)); |
| } |
| @@ -1519,7 +1511,6 @@ class _StrongInferenceTypeSystem extends StrongTypeSystemImpl { |
| _TypeParameterVariance variance = |
| new _TypeParameterVariance.from(typeParam, declaredReturnType); |
| - _TypeParameterBound bound = _bounds[typeParam]; |
| DartType lowerBound = bound.lower; |
| DartType upperBound = bound.upper; |
| @@ -1562,8 +1553,19 @@ class _StrongInferenceTypeSystem extends StrongTypeSystemImpl { |
| } |
| @override |
| - bool _inferTypeParameterSubtypeOf(DartType t1, DartType t2) { |
| + bool _isSubtypeOf(DartType t1, DartType t2, Set<Element> visited, |
| + {bool dynamicIsBottom: false}) { |
| + // TODO(jmesserly): the trivial constraints are not treated as part of |
| + // the constraint set here. This seems incorrect once we are able to pin the |
| + // inferred type of a type parameter based on the downwards information. |
| + if (identical(t1, t2) || |
| + _isTop(t2, dynamicIsBottom: dynamicIsBottom) || |
| + _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) { |
| + return true; |
| + } |
| + |
| if (t1 is TypeParameterType) { |
| + // TODO(jmesserly): we ignore `dynamicIsBottom` here, is that correct? |
| _TypeParameterBound bound = _bounds[t1]; |
| if (bound != null) { |
| // Ensure T1 <: T2, where T1 is a type parameter we are inferring. |
| @@ -1591,7 +1593,8 @@ class _StrongInferenceTypeSystem extends StrongTypeSystemImpl { |
| return true; |
| } |
| } |
| - return false; |
| + return super |
| + ._isSubtypeOf(t1, t2, visited, dynamicIsBottom: dynamicIsBottom); |
| } |
| } |