@@ -15189,12 +15189,14 @@ namespace ts {
1518915189 // is more predictable than other, interned types, which may or may not have an alias depending on
1519015190 // the order in which things were checked.
1519115191 if (source.flags & (TypeFlags.Object | TypeFlags.Conditional) && source.aliasSymbol &&
15192- source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol &&
15193- !(source.aliasTypeArgumentsContainsMarker || target.aliasTypeArgumentsContainsMarker)) {
15192+ source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol) {
15193+ // Compute variances eagerly to ensure reliability flags are properly propagated.
1519415194 const variances = getAliasVariances(source.aliasSymbol);
15195- const varianceResult = relateVariances(source.aliasTypeArguments, target.aliasTypeArguments, variances, isIntersectionConstituent);
15196- if (varianceResult !== undefined) {
15197- return varianceResult;
15195+ if (!(containsMarkerType(source.aliasTypeArguments) || containsMarkerType(target.aliasTypeArguments))) {
15196+ const varianceResult = relateVariances(source.aliasTypeArguments, target.aliasTypeArguments, variances, isIntersectionConstituent);
15197+ if (varianceResult !== undefined) {
15198+ return varianceResult;
15199+ }
1519815200 }
1519915201 }
1520015202
@@ -15383,7 +15385,7 @@ namespace ts {
1538315385 return Ternary.False;
1538415386 }
1538515387 if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target &&
15386- !(getObjectFlags( source) & ObjectFlags.MarkerType || getObjectFlags( target) & ObjectFlags.MarkerType )) {
15388+ !(containsMarkerType(getTypeArguments(<TypeReference> source)) || containsMarkerType(getTypeArguments(<TypeReference> target)) )) {
1538715389 // We have type references to the same generic type, and the type references are not marker
1538815390 // type references (which are intended by be compared structurally). Obtain the variance
1538915391 // information for the type parameters and relate the type arguments accordingly.
@@ -16157,21 +16159,24 @@ namespace ts {
1615716159 return false;
1615816160 }
1615916161
16160- // Return a type reference where the source type parameter is replaced with the target marker
16161- // type, and flag the result as a marker type reference.
16162- function getMarkerTypeReference(type: GenericType, source: TypeParameter, target: Type) {
16163- const result = createTypeReference(type, map(type.typeParameters, t => t === source ? target : t));
16164- result.objectFlags |= ObjectFlags.MarkerType;
16165- return result;
16162+ function containsMarkerType(types: readonly Type[] | undefined) {
16163+ return some(types, t => t === markerSuperType || t === markerSubType || t === markerOtherType);
16164+ }
16165+
16166+ function getVariances(type: GenericType): VarianceFlags[] {
16167+ // Arrays and tuples are known to be covariant, no need to spend time computing this (emptyArray implies covariance for all parameters)
16168+ if (type === globalArrayType || type === globalReadonlyArrayType || type.objectFlags & ObjectFlags.Tuple) {
16169+ return emptyArray;
16170+ }
16171+ return getVariancesWorker(type, type, createTypeReference);
1616616172 }
1616716173
1616816174 function getAliasVariances(symbol: Symbol) {
16169- const links = getSymbolLinks(symbol);
16170- return getVariancesWorker(links.typeParameters, links, (_links, param, marker) => {
16171- const type = getTypeAliasInstantiation(symbol, instantiateTypes(links.typeParameters!, makeUnaryTypeMapper(param, marker)));
16172- type.aliasTypeArgumentsContainsMarker = true;
16173- return type;
16174- });
16175+ return getVariancesWorker(symbol, getSymbolLinks(symbol), getTypeAliasInstantiation);
16176+ }
16177+
16178+ function getTypeArgumentsWithMarker(typeParameters: TypeParameter[], source: TypeParameter, marker: TypeParameter) {
16179+ return map(typeParameters, makeUnaryTypeMapper(source, marker));
1617516180 }
1617616181
1617716182 // Return an array containing the variance of each type parameter. The variance is effectively
@@ -16180,12 +16185,13 @@ namespace ts {
1618016185 // instantiations of the generic type for type arguments with known relations. The function
1618116186 // returns the emptyArray singleton if we're not in strictFunctionTypes mode or if the function
1618216187 // has been invoked recursively for the given generic type.
16183- function getVariancesWorker<TCache extends { variances?: VarianceFlags[] }>(typeParameters: readonly TypeParameter[] = emptyArray , cache: TCache, createMarkerType : (input: TCache, param: TypeParameter, marker: Type) => Type): VarianceFlags[] {
16188+ function getVariancesWorker<T extends GenericType | Symbol>(target: T , cache: GenericType | SymbolLinks, getInstance : (target: T, typeArguments: readonly Type[] ) => Type): VarianceFlags[] {
1618416189 let variances = cache.variances;
1618516190 if (!variances) {
1618616191 // The emptyArray singleton is used to signal a recursive invocation.
1618716192 cache.variances = emptyArray;
1618816193 variances = [];
16194+ const typeParameters = cache.typeParameters || emptyArray;
1618916195 for (const tp of typeParameters) {
1619016196 let unmeasurable = false;
1619116197 let unreliable = false;
@@ -16194,15 +16200,15 @@ namespace ts {
1619416200 // We first compare instantiations where the type parameter is replaced with
1619516201 // marker types that have a known subtype relationship. From this we can infer
1619616202 // invariance, covariance, contravariance or bivariance.
16197- const typeWithSuper = createMarkerType(cache, tp, markerSuperType);
16198- const typeWithSub = createMarkerType(cache, tp, markerSubType);
16203+ const typeWithSuper = getInstance(target, getTypeArgumentsWithMarker(typeParameters, tp, markerSuperType) );
16204+ const typeWithSub = getInstance(target, getTypeArgumentsWithMarker(typeParameters, tp, markerSubType) );
1619916205 let variance = (isTypeAssignableTo(typeWithSub, typeWithSuper) ? VarianceFlags.Covariant : 0) |
1620016206 (isTypeAssignableTo(typeWithSuper, typeWithSub) ? VarianceFlags.Contravariant : 0);
1620116207 // If the instantiations appear to be related bivariantly it may be because the
1620216208 // type parameter is independent (i.e. it isn't witnessed anywhere in the generic
1620316209 // type). To determine this we compare instantiations where the type parameter is
1620416210 // replaced with marker types that are known to be unrelated.
16205- if (variance === VarianceFlags.Bivariant && isTypeAssignableTo(createMarkerType(cache, tp, markerOtherType), typeWithSuper)) {
16211+ if (variance === VarianceFlags.Bivariant && isTypeAssignableTo(getInstance(target, getTypeArgumentsWithMarker(typeParameters, tp, markerOtherType) ), typeWithSuper)) {
1620616212 variance = VarianceFlags.Independent;
1620716213 }
1620816214 outofbandVarianceMarkerHandler = oldHandler;
@@ -16221,14 +16227,6 @@ namespace ts {
1622116227 return variances;
1622216228 }
1622316229
16224- function getVariances(type: GenericType): VarianceFlags[] {
16225- // Arrays and tuples are known to be covariant, no need to spend time computing this (emptyArray implies covariance for all parameters)
16226- if (type === globalArrayType || type === globalReadonlyArrayType || type.objectFlags & ObjectFlags.Tuple) {
16227- return emptyArray;
16228- }
16229- return getVariancesWorker(type.typeParameters, type, getMarkerTypeReference);
16230- }
16231-
1623216230 // Return true if the given type reference has a 'void' type argument for a covariant type parameter.
1623316231 // See comment at call in recursiveTypeRelatedTo for when this case matters.
1623416232 function hasCovariantVoidArgument(typeArguments: readonly Type[], variances: VarianceFlags[]): boolean {
0 commit comments