@@ -2009,13 +2009,11 @@ class GenericInferrer {
2009
2009
// degradation for f-bounded type parameters.
2010
2010
var inferredTypes = new List <DartType >.filled (
2011
2011
typeFormals.length, UnknownInferredType .instance);
2012
- var _inferTypeParameter = downwardsInferPhase
2013
- ? _inferTypeParameterFromContext
2014
- : _inferTypeParameterFromAll;
2015
2012
2016
2013
for (int i = 0 ; i < typeFormals.length; i++ ) {
2017
- TypeParameterElement typeParam = typeFormals[i];
2018
-
2014
+ // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
2015
+ // variance is added to the interface.
2016
+ TypeParameterElementImpl typeParam = typeFormals[i];
2019
2017
_TypeConstraint extendsClause;
2020
2018
if (considerExtendsClause && typeParam.bound != null ) {
2021
2019
extendsClause = new _TypeConstraint .fromExtends (
@@ -2024,8 +2022,12 @@ class GenericInferrer {
2024
2022
.substituteType (typeParam.bound));
2025
2023
}
2026
2024
2027
- inferredTypes[i] =
2028
- _inferTypeParameter (constraints[typeParam], extendsClause);
2025
+ inferredTypes[i] = downwardsInferPhase || ! typeParam.isLegacyCovariant
2026
+ ? _inferTypeParameterFromContext (
2027
+ constraints[typeParam], extendsClause,
2028
+ isContravariant: typeParam.variance.isContravariant)
2029
+ : _inferTypeParameterFromAll (constraints[typeParam], extendsClause,
2030
+ isContravariant: typeParam.variance.isContravariant);
2029
2031
}
2030
2032
2031
2033
// If the downwards infer phase has failed, we'll catch this in the upwards
@@ -2166,8 +2168,12 @@ class GenericInferrer {
2166
2168
/// * `int <: T`
2167
2169
///
2168
2170
/// ... and no upper bound. Therefore the lower bound is the best choice.
2171
+ ///
2172
+ /// If [isContravariant] is `true` , then we are solving for a contravariant
2173
+ /// type parameter which means we choose the upper bound rather than the
2174
+ /// lower bound for normally covariant type parameters.
2169
2175
DartType _chooseTypeFromConstraints (Iterable <_TypeConstraint > constraints,
2170
- {bool toKnownType: false }) {
2176
+ {bool toKnownType: false , @required bool isContravariant }) {
2171
2177
DartType lower = UnknownInferredType .instance;
2172
2178
DartType upper = UnknownInferredType .instance;
2173
2179
for (var constraint in constraints) {
@@ -2193,20 +2199,37 @@ class GenericInferrer {
2193
2199
// Prefer the known bound, if any.
2194
2200
// Otherwise take whatever bound has partial information, e.g. `Iterable<?>`
2195
2201
//
2196
- // For both of those, prefer the lower bound (arbitrary heuristic).
2197
- if (UnknownInferredType .isKnown (lower)) {
2198
- return lower;
2199
- }
2200
- if (UnknownInferredType .isKnown (upper)) {
2202
+ // For both of those, prefer the lower bound (arbitrary heuristic) or upper
2203
+ // bound if [isContravariant] is `true`
2204
+ if (isContravariant) {
2205
+ if (UnknownInferredType .isKnown (upper)) {
2206
+ return upper;
2207
+ }
2208
+ if (UnknownInferredType .isKnown (lower)) {
2209
+ return lower;
2210
+ }
2211
+ if (! identical (UnknownInferredType .instance, upper)) {
2212
+ return toKnownType ? _typeSystem.upperBoundForType (upper) : upper;
2213
+ }
2214
+ if (! identical (UnknownInferredType .instance, lower)) {
2215
+ return toKnownType ? _typeSystem.lowerBoundForType (lower) : lower;
2216
+ }
2201
2217
return upper;
2218
+ } else {
2219
+ if (UnknownInferredType .isKnown (lower)) {
2220
+ return lower;
2221
+ }
2222
+ if (UnknownInferredType .isKnown (upper)) {
2223
+ return upper;
2224
+ }
2225
+ if (! identical (UnknownInferredType .instance, lower)) {
2226
+ return toKnownType ? _typeSystem.lowerBoundForType (lower) : lower;
2227
+ }
2228
+ if (! identical (UnknownInferredType .instance, upper)) {
2229
+ return toKnownType ? _typeSystem.upperBoundForType (upper) : upper;
2230
+ }
2231
+ return lower;
2202
2232
}
2203
- if (! identical (UnknownInferredType .instance, lower)) {
2204
- return toKnownType ? _typeSystem.lowerBoundForType (lower) : lower;
2205
- }
2206
- if (! identical (UnknownInferredType .instance, upper)) {
2207
- return toKnownType ? _typeSystem.upperBoundForType (upper) : upper;
2208
- }
2209
- return lower;
2210
2233
}
2211
2234
2212
2235
String _formatError (TypeParameterElement typeParam, DartType inferred,
@@ -2280,11 +2303,13 @@ class GenericInferrer {
2280
2303
}
2281
2304
2282
2305
DartType _inferTypeParameterFromAll (
2283
- List <_TypeConstraint > constraints, _TypeConstraint extendsClause) {
2306
+ List <_TypeConstraint > constraints, _TypeConstraint extendsClause,
2307
+ {@required bool isContravariant}) {
2284
2308
// See if we already fixed this type from downwards inference.
2285
2309
// If so, then we aren't allowed to change it based on argument types.
2286
2310
DartType t = _inferTypeParameterFromContext (
2287
- constraints.where ((c) => c.isDownwards), extendsClause);
2311
+ constraints.where ((c) => c.isDownwards), extendsClause,
2312
+ isContravariant: isContravariant);
2288
2313
if (UnknownInferredType .isKnown (t)) {
2289
2314
// Remove constraints that aren't downward ones; we'll ignore these for
2290
2315
// error reporting, because inference already succeeded.
@@ -2296,13 +2321,16 @@ class GenericInferrer {
2296
2321
constraints = constraints.toList ()..add (extendsClause);
2297
2322
}
2298
2323
2299
- var choice = _chooseTypeFromConstraints (constraints, toKnownType: true );
2324
+ var choice = _chooseTypeFromConstraints (constraints,
2325
+ toKnownType: true , isContravariant: isContravariant);
2300
2326
return choice;
2301
2327
}
2302
2328
2303
2329
DartType _inferTypeParameterFromContext (
2304
- Iterable <_TypeConstraint > constraints, _TypeConstraint extendsClause) {
2305
- DartType t = _chooseTypeFromConstraints (constraints);
2330
+ Iterable <_TypeConstraint > constraints, _TypeConstraint extendsClause,
2331
+ {@required bool isContravariant}) {
2332
+ DartType t = _chooseTypeFromConstraints (constraints,
2333
+ isContravariant: isContravariant);
2306
2334
if (UnknownInferredType .isUnknown (t)) {
2307
2335
return t;
2308
2336
}
@@ -2316,7 +2344,8 @@ class GenericInferrer {
2316
2344
// If we consider the `T extends num` we conclude `<num>`, which works.
2317
2345
if (extendsClause != null ) {
2318
2346
constraints = constraints.toList ()..add (extendsClause);
2319
- return _chooseTypeFromConstraints (constraints);
2347
+ return _chooseTypeFromConstraints (constraints,
2348
+ isContravariant: isContravariant);
2320
2349
}
2321
2350
return t;
2322
2351
}
0 commit comments