@@ -439,6 +439,9 @@ var #staticStateDeclaration = {};
439439// Adds the subtype rules for the new RTI.
440440#typeRules;
441441
442+ // Adds the variance table for the new RTI.
443+ #variances;
444+
442445// Shared types need to be initialized before constants.
443446#sharedTypeRtis;
444447
@@ -540,6 +543,9 @@ var #typesOffset = hunkHelpers.updateTypes(#types);
540543// Adds the subtype rules for the new RTI.
541544#typeRules;
542545
546+ // Adds the variance table for the new RTI.
547+ #variances;
548+
543549#sharedTypeRtis;
544550// Instantiates all constants of this deferred fragment.
545551// Note that the constant-holder has been updated earlier and storing the
@@ -702,6 +708,7 @@ class FragmentEmitter {
702708 'embeddedGlobalsPart2' :
703709 emitEmbeddedGlobalsPart2 (program, deferredLoadingState),
704710 'typeRules' : emitTypeRules (fragment),
711+ 'variances' : emitVariances (fragment),
705712 'sharedTypeRtis' :
706713 _options.experimentNewRti ? TypeReferenceResource () : [],
707714 'nativeSupport' : program.needsNativeSupport
@@ -786,6 +793,7 @@ class FragmentEmitter {
786793 var tearOffs = emitInstallTearOffs (fragment);
787794 var constants = emitConstants (fragment);
788795 var typeRules = emitTypeRules (fragment);
796+ var variances = emitVariances (fragment);
789797 var staticNonFinalFields = emitStaticNonFinalFields (fragment);
790798 var lazyInitializers = emitLazilyInitializedStatics (fragment);
791799 // TODO(floitsch): only call emitNativeSupport if we need native.
@@ -828,6 +836,7 @@ class FragmentEmitter {
828836 'aliases' : methodAliases,
829837 'tearOffs' : tearOffs,
830838 'typeRules' : typeRules,
839+ 'variances' : variances,
831840 'constants' : constants,
832841 'staticNonFinalFields' : staticNonFinalFields,
833842 'lazyStatics' : lazyInitializers,
@@ -2041,6 +2050,41 @@ class FragmentEmitter {
20412050 return js.Block (statements);
20422051 }
20432052
2053+ js.Statement emitVariances (Fragment fragment) {
2054+ if (! _options.enableVariance || ! _options.experimentNewRti) {
2055+ return js.EmptyStatement ();
2056+ }
2057+
2058+ Map <ClassEntity , List <Variance >> typeParameterVariances = {};
2059+ Iterable <Class > classes =
2060+ fragment.libraries.expand ((Library library) => library.classes);
2061+ classes.forEach ((Class cls) {
2062+ ClassEntity element = cls.element;
2063+ List <Variance > classVariances =
2064+ _elementEnvironment.getTypeVariableVariances (element);
2065+
2066+ // Emit variances for a class only if there is at least one explicit
2067+ // variance defined.
2068+ bool hasOnlyLegacyVariance = classVariances
2069+ .every ((variance) => variance == Variance .legacyCovariant);
2070+ if (! hasOnlyLegacyVariance) {
2071+ typeParameterVariances[element] = classVariances;
2072+ }
2073+ });
2074+
2075+ if (typeParameterVariances.isNotEmpty) {
2076+ FunctionEntity addVariances =
2077+ _closedWorld.commonElements.rtiAddTypeParameterVariancesMethod;
2078+ return js.js.statement ('#(init.#,JSON.parse(#));' , [
2079+ _emitter.staticFunctionAccess (addVariances),
2080+ RTI_UNIVERSE ,
2081+ _rulesetEncoder.encodeTypeParameterVariances (typeParameterVariances),
2082+ ]);
2083+ }
2084+
2085+ return js.EmptyStatement ();
2086+ }
2087+
20442088 /// Returns an expression that creates the initial Rti Universe.
20452089 ///
20462090 /// This needs to be kept in sync with `_Universe.create` in `dart:_rti` .
0 commit comments