@@ -7636,35 +7636,35 @@ namespace ts {
76367636 * @param typeParameters The requested type parameters.
76377637 * @param minTypeArgumentCount The minimum number of required type arguments.
76387638 */
7639- function fillMissingTypeArguments(typeArguments: Type[] , typeParameters: ReadonlyArray<TypeParameter> | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[];
7640- function fillMissingTypeArguments(typeArguments: Type[] | undefined, typeParameters: ReadonlyArray<TypeParameter> | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[] | undefined;
7641- function fillMissingTypeArguments(typeArguments: Type[] | undefined, typeParameters: ReadonlyArray<TypeParameter> | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean) {
7639+ function fillMissingTypeArguments(typeArguments: ReadonlyArray< Type> , typeParameters: ReadonlyArray<TypeParameter> | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[];
7640+ function fillMissingTypeArguments(typeArguments: ReadonlyArray< Type> | undefined, typeParameters: ReadonlyArray<TypeParameter> | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[] | undefined;
7641+ function fillMissingTypeArguments(typeArguments: ReadonlyArray< Type> | undefined, typeParameters: ReadonlyArray<TypeParameter> | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean) {
76427642 const numTypeParameters = length(typeParameters);
7643- if (numTypeParameters) {
7644- const numTypeArguments = length(typeArguments) ;
7645- if (isJavaScriptImplicitAny || (numTypeArguments >= minTypeArgumentCount && numTypeArguments <= numTypeParameters)) {
7646- if (! typeArguments) {
7647- typeArguments = [];
7648- }
7643+ if (! numTypeParameters) {
7644+ return [] ;
7645+ }
7646+ const numTypeArguments = length( typeArguments);
7647+ if (isJavaScriptImplicitAny || (numTypeArguments >= minTypeArgumentCount && numTypeArguments <= numTypeParameters)) {
7648+ const result = typeArguments ? typeArguments.slice() : [];
76497649
7650- // Map an unsatisfied type parameter with a default type.
7651- // If a type parameter does not have a default type, or if the default type
7652- // is a forward reference, the empty object type is used.
7653- for (let i = numTypeArguments; i < numTypeParameters; i++) {
7654- typeArguments[i] = getDefaultTypeArgumentType(isJavaScriptImplicitAny);
7655- }
7656- for (let i = numTypeArguments; i < numTypeParameters; i++) {
7657- const mapper = createTypeMapper(typeParameters!, typeArguments);
7658- let defaultType = getDefaultFromTypeParameter(typeParameters![i]);
7659- if (isJavaScriptImplicitAny && defaultType && isTypeIdenticalTo(defaultType, emptyObjectType)) {
7660- defaultType = anyType;
7661- }
7662- typeArguments[i] = defaultType ? instantiateType(defaultType, mapper) : getDefaultTypeArgumentType(isJavaScriptImplicitAny);
7650+ // Map an unsatisfied type parameter with a default type.
7651+ // If a type parameter does not have a default type, or if the default type
7652+ // is a forward reference, the empty object type is used.
7653+ for (let i = numTypeArguments; i < numTypeParameters; i++) {
7654+ result[i] = getDefaultTypeArgumentType(isJavaScriptImplicitAny);
7655+ }
7656+ for (let i = numTypeArguments; i < numTypeParameters; i++) {
7657+ const mapper = createTypeMapper(typeParameters!, result);
7658+ let defaultType = getDefaultFromTypeParameter(typeParameters![i]);
7659+ if (isJavaScriptImplicitAny && defaultType && isTypeIdenticalTo(defaultType, emptyObjectType)) {
7660+ defaultType = anyType;
76637661 }
7664- typeArguments.length = typeParameters!.length ;
7662+ result[i] = defaultType ? instantiateType(defaultType, mapper) : getDefaultTypeArgumentType(isJavaScriptImplicitAny) ;
76657663 }
7664+ result.length = typeParameters!.length;
7665+ return result;
76667666 }
7667- return typeArguments;
7667+ return typeArguments && typeArguments.slice() ;
76687668 }
76697669
76707670 function getSignatureFromDeclaration(declaration: SignatureDeclaration | JSDocSignature): Signature {
@@ -8262,7 +8262,7 @@ namespace ts {
82628262 return checkNoTypeArguments(node, symbol) ? type : errorType;
82638263 }
82648264
8265- function getTypeAliasInstantiation(symbol: Symbol, typeArguments: Type[] | undefined): Type {
8265+ function getTypeAliasInstantiation(symbol: Symbol, typeArguments: ReadonlyArray< Type> | undefined): Type {
82668266 const type = getDeclaredTypeOfSymbol(symbol);
82678267 const links = getSymbolLinks(symbol);
82688268 const typeParameters = links.typeParameters!;
@@ -11783,9 +11783,7 @@ namespace ts {
1178311783 return result;
1178411784 }
1178511785
11786- function typeArgumentsRelatedTo(source: TypeReference, target: TypeReference, variances: Variance[], reportErrors: boolean): Ternary {
11787- const sources = source.typeArguments || emptyArray;
11788- const targets = target.typeArguments || emptyArray;
11786+ function typeArgumentsRelatedTo(sources: ReadonlyArray<Type> = emptyArray, targets: ReadonlyArray<Type> = emptyArray, variances: ReadonlyArray<Variance> = emptyArray, reportErrors: boolean): Ternary {
1178911787 if (sources.length !== targets.length && relation === identityRelation) {
1179011788 return Ternary.False;
1179111789 }
@@ -11938,9 +11936,25 @@ namespace ts {
1193811936 }
1193911937 return Ternary.False;
1194011938 }
11939+
1194111940 let result: Ternary;
1194211941 let originalErrorInfo: DiagnosticMessageChain | undefined;
1194311942 const saveErrorInfo = errorInfo;
11943+
11944+ // We limit alias variance probing to only object and conditional types since their alias behavior
11945+ // is more predictable than other, interned types, which may or may not have an alias depending on
11946+ // the order in which things were checked.
11947+ if (source.flags & (TypeFlags.Object | TypeFlags.Conditional) && source.aliasSymbol &&
11948+ source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol &&
11949+ !(source.aliasTypeArgumentsContainsMarker || target.aliasTypeArgumentsContainsMarker)) {
11950+ const variances = getAliasVariances(source.aliasSymbol);
11951+ if (result = typeArgumentsRelatedTo(source.aliasTypeArguments, target.aliasTypeArguments, variances, reportErrors)) {
11952+ return result;
11953+ }
11954+ originalErrorInfo = errorInfo;
11955+ errorInfo = saveErrorInfo;
11956+ }
11957+
1194411958 if (target.flags & TypeFlags.TypeParameter) {
1194511959 // A source type { [P in keyof T]: X } is related to a target type T if X is related to T[P].
1194611960 if (getObjectFlags(source) & ObjectFlags.Mapped && getConstraintTypeFromMappedType(<MappedType>source) === getIndexType(target)) {
@@ -12101,7 +12115,7 @@ namespace ts {
1210112115 // type references (which are intended by be compared structurally). Obtain the variance
1210212116 // information for the type parameters and relate the type arguments accordingly.
1210312117 const variances = getVariances((<TypeReference>source).target);
12104- if (result = typeArgumentsRelatedTo(<TypeReference>source, <TypeReference>target, variances, reportErrors)) {
12118+ if (result = typeArgumentsRelatedTo(( <TypeReference>source).typeArguments, ( <TypeReference>target).typeArguments , variances, reportErrors)) {
1210512119 return result;
1210612120 }
1210712121 // The type arguments did not relate appropriately, but it may be because we have no variance
@@ -12608,48 +12622,58 @@ namespace ts {
1260812622 return result;
1260912623 }
1261012624
12625+ function getAliasVariances(symbol: Symbol) {
12626+ const links = getSymbolLinks(symbol);
12627+ return getVariancesWorker(links.typeParameters, links, (_links, param, marker) => {
12628+ const type = getTypeAliasInstantiation(symbol, instantiateTypes(links.typeParameters!, makeUnaryTypeMapper(param, marker)));
12629+ type.aliasTypeArgumentsContainsMarker = true;
12630+ return type;
12631+ });
12632+ }
12633+
1261112634 // Return an array containing the variance of each type parameter. The variance is effectively
1261212635 // a digest of the type comparisons that occur for each type argument when instantiations of the
1261312636 // generic type are structurally compared. We infer the variance information by comparing
1261412637 // instantiations of the generic type for type arguments with known relations. The function
1261512638 // returns the emptyArray singleton if we're not in strictFunctionTypes mode or if the function
1261612639 // has been invoked recursively for the given generic type.
12640+ function getVariancesWorker<TCache extends { variances?: Variance[] }>(typeParameters: ReadonlyArray<TypeParameter> = emptyArray, cache: TCache, createMarkerType: (input: TCache, param: TypeParameter, marker: Type) => Type): Variance[] {
12641+ let variances = cache.variances;
12642+ if (!variances) {
12643+ // The emptyArray singleton is used to signal a recursive invocation.
12644+ cache.variances = emptyArray;
12645+ variances = [];
12646+ for (const tp of typeParameters) {
12647+ // We first compare instantiations where the type parameter is replaced with
12648+ // marker types that have a known subtype relationship. From this we can infer
12649+ // invariance, covariance, contravariance or bivariance.
12650+ const typeWithSuper = createMarkerType(cache, tp, markerSuperType);
12651+ const typeWithSub = createMarkerType(cache, tp, markerSubType);
12652+ let variance = (isTypeAssignableTo(typeWithSub, typeWithSuper) ? Variance.Covariant : 0) |
12653+ (isTypeAssignableTo(typeWithSuper, typeWithSub) ? Variance.Contravariant : 0);
12654+ // If the instantiations appear to be related bivariantly it may be because the
12655+ // type parameter is independent (i.e. it isn't witnessed anywhere in the generic
12656+ // type). To determine this we compare instantiations where the type parameter is
12657+ // replaced with marker types that are known to be unrelated.
12658+ if (variance === Variance.Bivariant && isTypeAssignableTo(createMarkerType(cache, tp, markerOtherType), typeWithSuper)) {
12659+ variance = Variance.Independent;
12660+ }
12661+ variances.push(variance);
12662+ }
12663+ cache.variances = variances;
12664+ }
12665+ return variances;
12666+ }
12667+
1261712668 function getVariances(type: GenericType): Variance[] {
1261812669 if (!strictFunctionTypes) {
1261912670 return emptyArray;
1262012671 }
12621- const typeParameters = type.typeParameters || emptyArray;
12622- let variances = type.variances;
12623- if (!variances) {
12624- if (type === globalArrayType || type === globalReadonlyArrayType) {
12625- // Arrays are known to be covariant, no need to spend time computing this
12626- variances = [Variance.Covariant];
12627- }
12628- else {
12629- // The emptyArray singleton is used to signal a recursive invocation.
12630- type.variances = emptyArray;
12631- variances = [];
12632- for (const tp of typeParameters) {
12633- // We first compare instantiations where the type parameter is replaced with
12634- // marker types that have a known subtype relationship. From this we can infer
12635- // invariance, covariance, contravariance or bivariance.
12636- const typeWithSuper = getMarkerTypeReference(type, tp, markerSuperType);
12637- const typeWithSub = getMarkerTypeReference(type, tp, markerSubType);
12638- let variance = (isTypeAssignableTo(typeWithSub, typeWithSuper) ? Variance.Covariant : 0) |
12639- (isTypeAssignableTo(typeWithSuper, typeWithSub) ? Variance.Contravariant : 0);
12640- // If the instantiations appear to be related bivariantly it may be because the
12641- // type parameter is independent (i.e. it isn't witnessed anywhere in the generic
12642- // type). To determine this we compare instantiations where the type parameter is
12643- // replaced with marker types that are known to be unrelated.
12644- if (variance === Variance.Bivariant && isTypeAssignableTo(getMarkerTypeReference(type, tp, markerOtherType), typeWithSuper)) {
12645- variance = Variance.Independent;
12646- }
12647- variances.push(variance);
12648- }
12649- }
12650- type.variances = variances;
12672+ if (type === globalArrayType || type === globalReadonlyArrayType) {
12673+ // Arrays are known to be covariant, no need to spend time computing this (emptyArray implies covariance for all parameters)
12674+ return emptyArray;
1265112675 }
12652- return variances ;
12676+ return getVariancesWorker(type.typeParameters, type, getMarkerTypeReference) ;
1265312677 }
1265412678
1265512679 // Return true if the given type reference has a 'void' type argument for a covariant type parameter.
0 commit comments