@@ -163,7 +163,7 @@ class StrongTypeSystemImpl extends TypeSystem {
163
163
// subtypes (or supertypes) as necessary, and track the constraints that
164
164
// are implied by this.
165
165
var inferringTypeSystem =
166
- new _StrongInferenceTypeSystem (typeProvider, fnType.typeFormals);
166
+ new _StrongInferenceTypeSystem (typeProvider, this , fnType.typeFormals);
167
167
168
168
// Since we're trying to infer the instantiation, we want to ignore type
169
169
// formals as we check the parameters and return type.
@@ -216,7 +216,7 @@ class StrongTypeSystemImpl extends TypeSystem {
216
216
// subtypes (or supertypes) as necessary, and track the constraints that
217
217
// are implied by this.
218
218
var inferringTypeSystem =
219
- new _StrongInferenceTypeSystem (typeProvider, fnType.typeFormals);
219
+ new _StrongInferenceTypeSystem (typeProvider, this , fnType.typeFormals);
220
220
221
221
// Special case inference for Future.then.
222
222
//
@@ -1271,43 +1271,36 @@ class TypeSystemImpl extends TypeSystem {
1271
1271
/// Tracks upper and lower type bounds for a set of type parameters.
1272
1272
class _StrongInferenceTypeSystem extends StrongTypeSystemImpl {
1273
1273
final TypeProvider _typeProvider;
1274
+
1275
+ /// The outer strong mode type system, used for GLB and LUB, so we don't
1276
+ /// recurse into our constraint solving code.
1277
+ final StrongTypeSystemImpl _typeSystem;
1274
1278
final Map <TypeParameterType , _TypeParameterBound > _bounds;
1275
1279
1276
- _StrongInferenceTypeSystem (
1277
- this ._typeProvider, Iterable <TypeParameterElement > typeFormals)
1278
- : _bounds =
1279
- new Map .fromIterable (typeFormals, key: (t) => t.type, value: (t) {
1280
- _TypeParameterBound bound = new _TypeParameterBound ();
1281
- if (t.bound != null ) bound.upper = t.bound;
1282
- return bound;
1283
- });
1280
+ _StrongInferenceTypeSystem (this ._typeProvider, this ._typeSystem,
1281
+ Iterable <TypeParameterElement > typeFormals)
1282
+ : _bounds = new Map .fromIterable (typeFormals,
1283
+ key: (t) => t.type, value: (t) => new _TypeParameterBound ());
1284
1284
1285
1285
/// Given the constraints that were given by calling [isSubtypeOf] , find the
1286
1286
/// instantiation of the generic function that satisfies these constraints.
1287
1287
FunctionType _infer (FunctionType fnType) {
1288
1288
List <TypeParameterType > fnTypeParams =
1289
1289
TypeParameterTypeImpl .getTypes (fnType.typeFormals);
1290
1290
1291
- var inferredTypes = new List <DartType >.from (fnTypeParams, growable: false );
1291
+ // Initialize the inferred type array.
1292
+ //
1293
+ // They all start as `dynamic` to offer reasonable degradation for f-bounded
1294
+ // type parameters.
1295
+ var inferredTypes = new List <DartType >.filled (
1296
+ fnTypeParams.length, DynamicTypeImpl .instance,
1297
+ growable: false );
1298
+
1292
1299
for (int i = 0 ; i < fnTypeParams.length; i++ ) {
1293
1300
TypeParameterType typeParam = fnTypeParams[i];
1294
- _TypeParameterBound bound = _bounds[typeParam];
1295
1301
1296
- // Now we've computed lower and upper bounds for each type parameter.
1302
+ // Apply the `extends` clause for the type parameter, if any .
1297
1303
//
1298
- // To decide on which type to assign, we look at the return type and see
1299
- // if the type parameter occurs in covariant or contravariant positions.
1300
- //
1301
- // If the type is "passed in" at all, or if our lower bound was bottom,
1302
- // we choose the upper bound as being the most useful.
1303
- //
1304
- // Otherwise we choose the more precise lower bound.
1305
- _TypeParameterVariance variance =
1306
- new _TypeParameterVariance .from (typeParam, fnType.returnType);
1307
-
1308
- inferredTypes[i] =
1309
- variance.passedIn || bound.lower.isBottom ? bound.upper : bound.lower;
1310
-
1311
1304
// Assumption: if the current type parameter has an "extends" clause
1312
1305
// that refers to another type variable we are inferring, it will appear
1313
1306
// before us or in this list position. For example:
@@ -1323,8 +1316,28 @@ class _StrongInferenceTypeSystem extends StrongTypeSystemImpl {
1323
1316
// Or if the type parameter's bound depends on itself such as:
1324
1317
//
1325
1318
// <T extends Clonable<T>>
1319
+ DartType declaredUpperBound = typeParam.element.bound;
1320
+ if (declaredUpperBound != null ) {
1321
+ // Assert that the type parameter is a subtype of its bound.
1322
+ _inferTypeParameterSubtypeOf (typeParam,
1323
+ declaredUpperBound.substitute2 (inferredTypes, fnTypeParams), null );
1324
+ }
1325
+
1326
+ // Now we've computed lower and upper bounds for each type parameter.
1327
+ //
1328
+ // To decide on which type to assign, we look at the return type and see
1329
+ // if the type parameter occurs in covariant or contravariant positions.
1330
+ //
1331
+ // If the type is "passed in" at all, or if our lower bound was bottom,
1332
+ // we choose the upper bound as being the most useful.
1333
+ //
1334
+ // Otherwise we choose the more precise lower bound.
1335
+ _TypeParameterVariance variance =
1336
+ new _TypeParameterVariance .from (typeParam, fnType.returnType);
1337
+
1338
+ _TypeParameterBound bound = _bounds[typeParam];
1326
1339
inferredTypes[i] =
1327
- inferredTypes[i]. substitute2 (inferredTypes, fnTypeParams) ;
1340
+ variance.passedIn || bound.lower.isBottom ? bound.upper : bound.lower ;
1328
1341
1329
1342
// See if the constraints on the type variable are satisfied.
1330
1343
//
@@ -1358,7 +1371,8 @@ class _StrongInferenceTypeSystem extends StrongTypeSystemImpl {
1358
1371
// We already know T1 <: U, for some U.
1359
1372
// So update U to reflect the new constraint T1 <: GLB(U, T2)
1360
1373
//
1361
- bound.upper = getGreatestLowerBound (_typeProvider, bound.upper, t2);
1374
+ bound.upper =
1375
+ _typeSystem.getGreatestLowerBound (_typeProvider, bound.upper, t2);
1362
1376
// Optimistically assume we will be able to satisfy the constraint.
1363
1377
return true ;
1364
1378
}
@@ -1372,7 +1386,8 @@ class _StrongInferenceTypeSystem extends StrongTypeSystemImpl {
1372
1386
// We already know L <: T2, for some L.
1373
1387
// So update L to reflect the new constraint LUB(L, T1) <: T2
1374
1388
//
1375
- bound.lower = getLeastUpperBound (_typeProvider, bound.lower, t1);
1389
+ bound.lower =
1390
+ _typeSystem.getLeastUpperBound (_typeProvider, bound.lower, t1);
1376
1391
// Optimistically assume we will be able to satisfy the constraint.
1377
1392
return true ;
1378
1393
}
0 commit comments