| 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 0138526a9d239316da15ec1329bcefa1075423c6..efe8e16908058e96ff4e52722307a6c4231b19b2 100644
|
| --- a/pkg/analyzer/lib/src/generated/type_system.dart
|
| +++ b/pkg/analyzer/lib/src/generated/type_system.dart
|
| @@ -163,7 +163,7 @@ class StrongTypeSystemImpl extends TypeSystem {
|
| // subtypes (or supertypes) as necessary, and track the constraints that
|
| // are implied by this.
|
| var inferringTypeSystem =
|
| - new _StrongInferenceTypeSystem(typeProvider, fnType.typeFormals);
|
| + new _StrongInferenceTypeSystem(typeProvider, this, fnType.typeFormals);
|
|
|
| // Since we're trying to infer the instantiation, we want to ignore type
|
| // formals as we check the parameters and return type.
|
| @@ -216,7 +216,7 @@ class StrongTypeSystemImpl extends TypeSystem {
|
| // subtypes (or supertypes) as necessary, and track the constraints that
|
| // are implied by this.
|
| var inferringTypeSystem =
|
| - new _StrongInferenceTypeSystem(typeProvider, fnType.typeFormals);
|
| + new _StrongInferenceTypeSystem(typeProvider, this, fnType.typeFormals);
|
|
|
| // Special case inference for Future.then.
|
| //
|
| @@ -1271,16 +1271,16 @@ class TypeSystemImpl extends TypeSystem {
|
| /// Tracks upper and lower type bounds for a set of type parameters.
|
| class _StrongInferenceTypeSystem extends StrongTypeSystemImpl {
|
| final TypeProvider _typeProvider;
|
| +
|
| + /// The outer strong mode type system, used for GLB and LUB, so we don't
|
| + /// recurse into our constraint solving code.
|
| + final StrongTypeSystemImpl _typeSystem;
|
| final Map<TypeParameterType, _TypeParameterBound> _bounds;
|
|
|
| - _StrongInferenceTypeSystem(
|
| - this._typeProvider, Iterable<TypeParameterElement> typeFormals)
|
| - : _bounds =
|
| - new Map.fromIterable(typeFormals, key: (t) => t.type, value: (t) {
|
| - _TypeParameterBound bound = new _TypeParameterBound();
|
| - if (t.bound != null) bound.upper = t.bound;
|
| - return bound;
|
| - });
|
| + _StrongInferenceTypeSystem(this._typeProvider, this._typeSystem,
|
| + Iterable<TypeParameterElement> typeFormals)
|
| + : _bounds = new Map.fromIterable(typeFormals,
|
| + key: (t) => t.type, value: (t) => new _TypeParameterBound());
|
|
|
| /// Given the constraints that were given by calling [isSubtypeOf], find the
|
| /// instantiation of the generic function that satisfies these constraints.
|
| @@ -1288,26 +1288,19 @@ class _StrongInferenceTypeSystem extends StrongTypeSystemImpl {
|
| List<TypeParameterType> fnTypeParams =
|
| TypeParameterTypeImpl.getTypes(fnType.typeFormals);
|
|
|
| - var inferredTypes = new List<DartType>.from(fnTypeParams, growable: false);
|
| + // Initialize the inferred type array.
|
| + //
|
| + // They all start as `dynamic` to offer reasonable degradation for f-bounded
|
| + // type parameters.
|
| + var inferredTypes = new List<DartType>.filled(
|
| + fnTypeParams.length, DynamicTypeImpl.instance,
|
| + growable: false);
|
| +
|
| for (int i = 0; i < fnTypeParams.length; i++) {
|
| TypeParameterType typeParam = fnTypeParams[i];
|
| - _TypeParameterBound bound = _bounds[typeParam];
|
|
|
| - // Now we've computed lower and upper bounds for each type parameter.
|
| + // Apply the `extends` clause for the type parameter, if any.
|
| //
|
| - // To decide on which type to assign, we look at the return type and see
|
| - // if the type parameter occurs in covariant or contravariant positions.
|
| - //
|
| - // If the type is "passed in" at all, or if our lower bound was bottom,
|
| - // we choose the upper bound as being the most useful.
|
| - //
|
| - // Otherwise we choose the more precise lower bound.
|
| - _TypeParameterVariance variance =
|
| - new _TypeParameterVariance.from(typeParam, fnType.returnType);
|
| -
|
| - inferredTypes[i] =
|
| - variance.passedIn || bound.lower.isBottom ? bound.upper : bound.lower;
|
| -
|
| // Assumption: if the current type parameter has an "extends" clause
|
| // that refers to another type variable we are inferring, it will appear
|
| // before us or in this list position. For example:
|
| @@ -1323,8 +1316,28 @@ class _StrongInferenceTypeSystem extends StrongTypeSystemImpl {
|
| // Or if the type parameter's bound depends on itself such as:
|
| //
|
| // <T extends Clonable<T>>
|
| + DartType declaredUpperBound = typeParam.element.bound;
|
| + if (declaredUpperBound != null) {
|
| + // Assert that the type parameter is a subtype of its bound.
|
| + _inferTypeParameterSubtypeOf(typeParam,
|
| + declaredUpperBound.substitute2(inferredTypes, fnTypeParams), null);
|
| + }
|
| +
|
| + // Now we've computed lower and upper bounds for each type parameter.
|
| + //
|
| + // To decide on which type to assign, we look at the return type and see
|
| + // if the type parameter occurs in covariant or contravariant positions.
|
| + //
|
| + // If the type is "passed in" at all, or if our lower bound was bottom,
|
| + // we choose the upper bound as being the most useful.
|
| + //
|
| + // Otherwise we choose the more precise lower bound.
|
| + _TypeParameterVariance variance =
|
| + new _TypeParameterVariance.from(typeParam, fnType.returnType);
|
| +
|
| + _TypeParameterBound bound = _bounds[typeParam];
|
| inferredTypes[i] =
|
| - inferredTypes[i].substitute2(inferredTypes, fnTypeParams);
|
| + variance.passedIn || bound.lower.isBottom ? bound.upper : bound.lower;
|
|
|
| // See if the constraints on the type variable are satisfied.
|
| //
|
| @@ -1358,7 +1371,8 @@ class _StrongInferenceTypeSystem extends StrongTypeSystemImpl {
|
| // We already know T1 <: U, for some U.
|
| // So update U to reflect the new constraint T1 <: GLB(U, T2)
|
| //
|
| - bound.upper = getGreatestLowerBound(_typeProvider, bound.upper, t2);
|
| + bound.upper =
|
| + _typeSystem.getGreatestLowerBound(_typeProvider, bound.upper, t2);
|
| // Optimistically assume we will be able to satisfy the constraint.
|
| return true;
|
| }
|
| @@ -1372,7 +1386,8 @@ class _StrongInferenceTypeSystem extends StrongTypeSystemImpl {
|
| // We already know L <: T2, for some L.
|
| // So update L to reflect the new constraint LUB(L, T1) <: T2
|
| //
|
| - bound.lower = getLeastUpperBound(_typeProvider, bound.lower, t1);
|
| + bound.lower =
|
| + _typeSystem.getLeastUpperBound(_typeProvider, bound.lower, t1);
|
| // Optimistically assume we will be able to satisfy the constraint.
|
| return true;
|
| }
|
|
|