@@ -1315,11 +1315,13 @@ class _Universe {
13151315 '#: new Map(),'
13161316 '#: {},'
13171317 '#: {},'
1318+ '#: {},'
13181319 '#: [],' // shared empty array.
13191320 '}' ,
13201321 RtiUniverseFieldNames .evalCache,
13211322 RtiUniverseFieldNames .typeRules,
13221323 RtiUniverseFieldNames .erasedTypes,
1324+ RtiUniverseFieldNames .typeParameterVariances,
13231325 RtiUniverseFieldNames .sharedEmptyArray);
13241326 }
13251327
@@ -1334,6 +1336,9 @@ class _Universe {
13341336 static Object erasedTypes (universe) =>
13351337 JS ('' , '#.#' , universe, RtiUniverseFieldNames .erasedTypes);
13361338
1339+ static Object typeParameterVariances (universe) =>
1340+ JS ('' , '#.#' , universe, RtiUniverseFieldNames .typeParameterVariances);
1341+
13371342 static Object _findRule (universe, String targetType) =>
13381343 JS ('' , '#.#' , typeRules (universe), targetType);
13391344
@@ -1365,12 +1370,18 @@ class _Universe {
13651370 }
13661371 }
13671372
1373+ static Object findTypeParameterVariances (universe, String cls) =>
1374+ JS ('' , '#.#' , typeParameterVariances (universe), cls);
1375+
13681376 static void addRules (universe, rules) =>
13691377 _Utils .objectAssign (typeRules (universe), rules);
13701378
13711379 static void addErasedTypes (universe, types) =>
13721380 _Utils .objectAssign (erasedTypes (universe), types);
13731381
1382+ static void addTypeParameterVariances (universe, variances) =>
1383+ _Utils .objectAssign (typeParameterVariances (universe), variances);
1384+
13741385 static Object sharedEmptyArray (universe) =>
13751386 JS ('JSArray' , '#.#' , universe, RtiUniverseFieldNames .sharedEmptyArray);
13761387
@@ -2247,6 +2258,14 @@ class TypeRule {
22472258 JS ('' , '#.#' , rule, supertype);
22482259}
22492260
2261+ class Variance {
2262+ // TODO(fishythefish): Try bitmask representation.
2263+ static const legacyCovariant = 0 ;
2264+ static const covariant = 1 ;
2265+ static const contravariant = 2 ;
2266+ static const invariant = 3 ;
2267+ }
2268+
22502269// -------- Subtype tests ------------------------------------------------------
22512270
22522271// Future entry point from compiled code.
@@ -2431,10 +2450,41 @@ bool _isSubtypeOfInterface(
24312450 var sArgs = Rti ._getInterfaceTypeArguments (s);
24322451 int length = _Utils .arrayLength (sArgs);
24332452 assert (length == _Utils .arrayLength (tArgs));
2453+
2454+ var sVariances;
2455+ bool hasVariances;
2456+ if (JS_GET_FLAG ("VARIANCE" )) {
2457+ sVariances = _Universe .findTypeParameterVariances (universe, sName);
2458+ hasVariances = sVariances != null ;
2459+ assert (! hasVariances || length == _Utils .arrayLength (sVariances));
2460+ }
2461+
24342462 for (int i = 0 ; i < length; i++ ) {
24352463 Rti sArg = _castToRti (_Utils .arrayAt (sArgs, i));
24362464 Rti tArg = _castToRti (_Utils .arrayAt (tArgs, i));
2437- if (! _isSubtype (universe, sArg, sEnv, tArg, tEnv)) return false ;
2465+ if (JS_GET_FLAG ("VARIANCE" )) {
2466+ int sVariance = hasVariances
2467+ ? _Utils .asInt (_Utils .arrayAt (sVariances, i))
2468+ : Variance .legacyCovariant;
2469+ switch (sVariance) {
2470+ case Variance .legacyCovariant:
2471+ case Variance .covariant :
2472+ if (! _isSubtype (universe, sArg, sEnv, tArg, tEnv)) return false ;
2473+ break ;
2474+ case Variance .contravariant:
2475+ if (! _isSubtype (universe, tArg, tEnv, sArg, sEnv)) return false ;
2476+ break ;
2477+ case Variance .invariant:
2478+ if (! _isSubtype (universe, sArg, sEnv, tArg, tEnv) ||
2479+ ! _isSubtype (universe, tArg, tEnv, sArg, sEnv)) return false ;
2480+ break ;
2481+ default :
2482+ throw StateError (
2483+ "Unknown variance given for subtype check: $sVariance " );
2484+ }
2485+ } else {
2486+ if (! _isSubtype (universe, sArg, sEnv, tArg, tEnv)) return false ;
2487+ }
24382488 }
24392489 return true ;
24402490 }
@@ -2665,6 +2715,10 @@ void testingAddRules(universe, rules) {
26652715 _Universe .addRules (universe, rules);
26662716}
26672717
2718+ void testingAddTypeParameterVariances (universe, variances) {
2719+ _Universe .addTypeParameterVariances (universe, variances);
2720+ }
2721+
26682722bool testingIsSubtype (universe, rti1, rti2) {
26692723 return isSubtype (universe, _castToRti (rti1), _castToRti (rti2));
26702724}
0 commit comments