@@ -9422,10 +9422,13 @@ namespace ts {
9422
9422
return result;
9423
9423
}
9424
9424
// The type arguments did not relate appropriately, but it may be because getVariances was
9425
- // invoked recursively and returned emptyArray (in which case typeArgumentsRelatedTo defaults
9426
- // to covariance for all type arguments). In that case we need to contine with a structural
9427
- // comparison. Otherwise, we know for certain the instantiations aren't related.
9428
- if (variances !== emptyArray) {
9425
+ // invoked recursively and returned emptyArray (in which case typeArgumentsRelatedTo defaulted
9426
+ // to covariance for all type arguments). It might also be the case that the target type has a
9427
+ // 'void' type argument for a covariant type parameter that is only used in return positions
9428
+ // within the generic type (in which case any type argument is permitted on the source side).
9429
+ // In those cases we proceed with a structural comparison. Otherwise, we know for certain the
9430
+ // instantiations aren't related and we can return here.
9431
+ if (variances !== emptyArray && !hasCovariantVoidArgument(<TypeReference>target, variances)) {
9429
9432
return Ternary.False;
9430
9433
}
9431
9434
}
@@ -9839,7 +9842,7 @@ namespace ts {
9839
9842
}
9840
9843
9841
9844
function getVarianceType(type: GenericType, source: TypeParameter, target: Type) {
9842
- return createTypeReference(type, map(type.typeParameters, t => t === source ? target: t));
9845
+ return createTypeReference(type, map(type.typeParameters, t => t === source ? target : t));
9843
9846
}
9844
9847
9845
9848
// Return an array containing the variance of each type parameter. The variance is effectively
@@ -9848,7 +9851,7 @@ namespace ts {
9848
9851
// instantiations of the generic type for type arguments with known relations. Note that the
9849
9852
// function returns the emptyArray singleton to signal that it has been invoked recursively for
9850
9853
// the given generic type.
9851
- function getVariances(type: GenericType) {
9854
+ function getVariances(type: GenericType): Variance[] {
9852
9855
const typeParameters = type.typeParameters || emptyArray;
9853
9856
let variances = type.variances;
9854
9857
if (!variances) {
@@ -9883,6 +9886,17 @@ namespace ts {
9883
9886
return variances;
9884
9887
}
9885
9888
9889
+ // Return true if the given type reference has a 'void' type argument for a covariant type parameter.
9890
+ // See comment at call in recursiveTypeRelatedTo for when this case matters.
9891
+ function hasCovariantVoidArgument(type: TypeReference, variances: Variance[]): boolean {
9892
+ for (let i = 0; i < variances.length; i++) {
9893
+ if (variances[i] === Variance.Covariant && type.typeArguments[i].flags & TypeFlags.Void) {
9894
+ return true;
9895
+ }
9896
+ }
9897
+ return false;
9898
+ }
9899
+
9886
9900
function isUnconstrainedTypeParameter(type: Type) {
9887
9901
return type.flags & TypeFlags.TypeParameter && !getConstraintFromTypeParameter(<TypeParameter>type);
9888
9902
}
0 commit comments