@@ -15189,12 +15189,14 @@ namespace ts {
15189
15189
// is more predictable than other, interned types, which may or may not have an alias depending on
15190
15190
// the order in which things were checked.
15191
15191
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.
15194
15194
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
+ }
15198
15200
}
15199
15201
}
15200
15202
@@ -15383,7 +15385,7 @@ namespace ts {
15383
15385
return Ternary.False;
15384
15386
}
15385
15387
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)) )) {
15387
15389
// We have type references to the same generic type, and the type references are not marker
15388
15390
// type references (which are intended by be compared structurally). Obtain the variance
15389
15391
// information for the type parameters and relate the type arguments accordingly.
@@ -16157,21 +16159,24 @@ namespace ts {
16157
16159
return false;
16158
16160
}
16159
16161
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);
16166
16172
}
16167
16173
16168
16174
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));
16175
16180
}
16176
16181
16177
16182
// Return an array containing the variance of each type parameter. The variance is effectively
@@ -16180,12 +16185,13 @@ namespace ts {
16180
16185
// instantiations of the generic type for type arguments with known relations. The function
16181
16186
// returns the emptyArray singleton if we're not in strictFunctionTypes mode or if the function
16182
16187
// 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[] {
16184
16189
let variances = cache.variances;
16185
16190
if (!variances) {
16186
16191
// The emptyArray singleton is used to signal a recursive invocation.
16187
16192
cache.variances = emptyArray;
16188
16193
variances = [];
16194
+ const typeParameters = cache.typeParameters || emptyArray;
16189
16195
for (const tp of typeParameters) {
16190
16196
let unmeasurable = false;
16191
16197
let unreliable = false;
@@ -16194,15 +16200,15 @@ namespace ts {
16194
16200
// We first compare instantiations where the type parameter is replaced with
16195
16201
// marker types that have a known subtype relationship. From this we can infer
16196
16202
// 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) );
16199
16205
let variance = (isTypeAssignableTo(typeWithSub, typeWithSuper) ? VarianceFlags.Covariant : 0) |
16200
16206
(isTypeAssignableTo(typeWithSuper, typeWithSub) ? VarianceFlags.Contravariant : 0);
16201
16207
// If the instantiations appear to be related bivariantly it may be because the
16202
16208
// type parameter is independent (i.e. it isn't witnessed anywhere in the generic
16203
16209
// type). To determine this we compare instantiations where the type parameter is
16204
16210
// 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)) {
16206
16212
variance = VarianceFlags.Independent;
16207
16213
}
16208
16214
outofbandVarianceMarkerHandler = oldHandler;
@@ -16221,14 +16227,6 @@ namespace ts {
16221
16227
return variances;
16222
16228
}
16223
16229
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
-
16232
16230
// Return true if the given type reference has a 'void' type argument for a covariant type parameter.
16233
16231
// See comment at call in recursiveTypeRelatedTo for when this case matters.
16234
16232
function hasCovariantVoidArgument(typeArguments: readonly Type[], variances: VarianceFlags[]): boolean {
0 commit comments