@@ -282,9 +282,9 @@ namespace ts {
282
282
const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
283
283
const circularConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
284
284
285
- const markerSuperType = createType(TypeFlags.MarkerType );
286
- const markerSubType = createType(TypeFlags.MarkerType );
287
- const markerOtherType = createType(TypeFlags.MarkerType) ;
285
+ const markerSuperType = <TypeParameter> createType(TypeFlags.TypeParameter );
286
+ const markerSubType = <TypeParameter> createType(TypeFlags.TypeParameter );
287
+ markerSubType.constraint = markerSuperType ;
288
288
289
289
const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
290
290
const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
@@ -8948,10 +8948,6 @@ namespace ts {
8948
8948
8949
8949
if (isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True;
8950
8950
8951
- if (source.flags & TypeFlags.MarkerType && target.flags & TypeFlags.MarkerType && !(source.flags & TypeFlags.Object || target.flags & TypeFlags.Object)) {
8952
- return source === markerSubType && target === markerSuperType ? Ternary.True : Ternary.False;
8953
- }
8954
-
8955
8951
if (getObjectFlags(source) & ObjectFlags.ObjectLiteral && source.flags & TypeFlags.FreshLiteral) {
8956
8952
if (hasExcessProperties(<FreshObjectLiteralType>source, target, reportErrors)) {
8957
8953
if (reportErrors) {
@@ -9219,41 +9215,15 @@ namespace ts {
9219
9215
// in the process of computing variance information for recursive types and when
9220
9216
// comparing 'this' type arguments.
9221
9217
const variance = i < variances.length ? variances[i] : Variance.Covariant;
9222
- // We simply ignore omnivariant type arguments (because they're never witnessed).
9223
- if (variance !== Variance.Omnivariant) {
9224
- const s = sources[i];
9225
- const t = targets[i];
9226
- let related = Ternary.True;
9227
- if (variance === Variance.Covariant) {
9228
- related = isRelatedTo(s, t, reportErrors);
9229
- }
9230
- else if (variance === Variance.Contravariant) {
9231
- related = isRelatedTo(t, s, reportErrors);
9232
- }
9233
- else if (variance === Variance.Bivariant) {
9234
- // In the bivariant case we first compare contravariantly without reporting
9235
- // errors. Then, if that doesn't succeed, we compare covariantly with error
9236
- // reporting. Thus, error elaboration will be based on the the covariant check,
9237
- // which is generally easier to reason about.
9238
- related = isRelatedTo(t, s, /*reportErrors*/ false);
9239
- if (!related) {
9240
- related = isRelatedTo(s, t, reportErrors);
9241
- }
9242
- }
9243
- else {
9244
- // In the invariant case we first compare covariantly, and only when that
9245
- // succeeds do we proceed to compare contravariantly. Thus, error elaboration
9246
- // will typically be based on the covariant check.
9247
- related = isRelatedTo(s, t, reportErrors);
9248
- if (related) {
9249
- related &= isRelatedTo(t, s, reportErrors);
9250
- }
9251
- }
9252
- if (!related) {
9253
- return Ternary.False;
9254
- }
9255
- result &= related;
9218
+ const s = sources[i];
9219
+ const t = targets[i];
9220
+ const related = variance === Variance.Covariant ? isRelatedTo(s, t, reportErrors) :
9221
+ variance === Variance.Contravariant ? isRelatedTo(t, s, reportErrors) :
9222
+ Ternary.False;
9223
+ if (!related) {
9224
+ return Ternary.False;
9256
9225
}
9226
+ result &= related;
9257
9227
}
9258
9228
return result;
9259
9229
}
@@ -9418,21 +9388,14 @@ namespace ts {
9418
9388
!(source.flags & TypeFlags.MarkerType || target.flags & TypeFlags.MarkerType)) {
9419
9389
// We have type references to the same generic type, and the type references are not marker
9420
9390
// type references (which are intended by be compared structurally). Obtain the variance
9421
- // information for the type parameters and relate the type arguments accordingly.
9391
+ // information for the type parameters and relate the type arguments accordingly. If we do
9392
+ // not succeed, fall through and do a structural comparison instead (there are instances
9393
+ // where the variance information isn't accurate, e.g. when type parameters are used only
9394
+ // in bivariant positions or when a type argument is 'any' or 'void'.)
9422
9395
const variances = getVariances((<TypeReference>source).target);
9423
9396
if (result = typeArgumentsRelatedTo(<TypeReference>source, <TypeReference>target, variances, reportErrors)) {
9424
9397
return result;
9425
9398
}
9426
- // The type arguments did not relate appropriately, but it may be because getVariances was
9427
- // invoked recursively and returned emptyArray (in which case typeArgumentsRelatedTo defaulted
9428
- // to covariance for all type arguments). It might also be the case that the target type has a
9429
- // 'void' type argument for a covariant type parameter that is only used in return positions
9430
- // within the generic type (in which case any type argument is permitted on the source side).
9431
- // In those cases we proceed with a structural comparison. Otherwise, we know for certain the
9432
- // instantiations aren't related and we can return here.
9433
- if (variances !== emptyArray && !hasCovariantVoidArgument(<TypeReference>target, variances)) {
9434
- return Ternary.False;
9435
- }
9436
9399
}
9437
9400
// Even if relationship doesn't hold for unions, intersections, or generic type references,
9438
9401
// it may hold in a structural comparison.
@@ -9851,13 +9814,18 @@ namespace ts {
9851
9814
return result;
9852
9815
}
9853
9816
9854
- // Return an array containing the variance of each type parameter. The variance is effectively
9855
- // a digest of the type comparisons that occur for each type argument when instantiations of the
9856
- // generic type are structurally compared. We infer the variance information by comparing
9857
- // instantiations of the generic type for type arguments with known relations. Note that the
9858
- // function returns the emptyArray singleton to signal that it has been invoked recursively for
9859
- // the given generic type.
9817
+ // Return an array containing the variance of each type parameter. The variance information is
9818
+ // computed by comparing instantiations of the generic type for type arguments with known relations.
9819
+ // A type parameter is marked as covariant if a covariant comparison succeeds; otherwise, it is
9820
+ // marked contravariant if a contravarint comparison succeeds; otherwise, it is marked invariant.
9821
+ // One form of variance doesn't exclude another, so this information simply serves to indicate
9822
+ // a "primary" relationship that can be checked as an optimization ahead of a full structural
9823
+ // comparison. The function returns the emptyArray singleton if we're not in strictFunctionTypes
9824
+ // mode or if the function has been invoked recursively for the given generic type.
9860
9825
function getVariances(type: GenericType): Variance[] {
9826
+ if (!strictFunctionTypes) {
9827
+ return emptyArray;
9828
+ }
9861
9829
const typeParameters = type.typeParameters || emptyArray;
9862
9830
let variances = type.variances;
9863
9831
if (!variances) {
@@ -9870,20 +9838,14 @@ namespace ts {
9870
9838
type.variances = emptyArray;
9871
9839
variances = [];
9872
9840
for (const tp of typeParameters) {
9873
- // We first compare instantiations where the type parameter is replaced with
9874
- // marker types that have a known subtype relationship. From this we can infer
9875
- // invariance, covariance, contravariance or bivariance .
9841
+ // We compare instantiations where the type parameter is replaced with marker types
9842
+ // that have a known subtype relationship. From this we infer covariance, contravariance
9843
+ // or invariance .
9876
9844
const typeWithSuper = getMarkerTypeReference(type, tp, markerSuperType);
9877
9845
const typeWithSub = getMarkerTypeReference(type, tp, markerSubType);
9878
- let variance = (isTypeAssignableTo(typeWithSub, typeWithSuper) ? Variance.Covariant : 0) |
9879
- (isTypeAssignableTo(typeWithSuper, typeWithSub) ? Variance.Contravariant : 0);
9880
- // If the instantiations appear to be related bivariantly, it may be because the
9881
- // type parameter is omnivariant (i.e. it isn't witnessed anywhere in the generic
9882
- // type). To determine this we compare instantiations where the type parameter is
9883
- // replaced with marker types that are known to be unrelated.
9884
- if (variance === Variance.Bivariant && isTypeAssignableTo(getMarkerTypeReference(type, tp, markerOtherType), typeWithSuper)) {
9885
- variance = Variance.Omnivariant;
9886
- }
9846
+ const variance = isTypeAssignableTo(typeWithSub, typeWithSuper) ? Variance.Covariant :
9847
+ isTypeAssignableTo(typeWithSuper, typeWithSub) ? Variance.Contravariant :
9848
+ Variance.Invariant;
9887
9849
variances.push(variance);
9888
9850
}
9889
9851
}
@@ -9892,17 +9854,6 @@ namespace ts {
9892
9854
return variances;
9893
9855
}
9894
9856
9895
- // Return true if the given type reference has a 'void' type argument for a covariant type parameter.
9896
- // See comment at call in recursiveTypeRelatedTo for when this case matters.
9897
- function hasCovariantVoidArgument(type: TypeReference, variances: Variance[]): boolean {
9898
- for (let i = 0; i < variances.length; i++) {
9899
- if (variances[i] === Variance.Covariant && type.typeArguments[i].flags & TypeFlags.Void) {
9900
- return true;
9901
- }
9902
- }
9903
- return false;
9904
- }
9905
-
9906
9857
function isUnconstrainedTypeParameter(type: Type) {
9907
9858
return type.flags & TypeFlags.TypeParameter && !getConstraintFromTypeParameter(<TypeParameter>type);
9908
9859
}
@@ -10709,9 +10660,9 @@ namespace ts {
10709
10660
const sourceTypes = (<TypeReference>source).typeArguments || emptyArray;
10710
10661
const targetTypes = (<TypeReference>target).typeArguments || emptyArray;
10711
10662
const count = sourceTypes.length < targetTypes.length ? sourceTypes.length : targetTypes.length;
10712
- const variances = strictFunctionTypes ? getVariances((<TypeReference>source).target) : undefined ;
10663
+ const variances = getVariances((<TypeReference>source).target);
10713
10664
for (let i = 0; i < count; i++) {
10714
- if (variances && i < variances.length && variances[i] === Variance.Contravariant) {
10665
+ if (i < variances.length && variances[i] === Variance.Contravariant) {
10715
10666
inferFromContravariantTypes(sourceTypes[i], targetTypes[i]);
10716
10667
}
10717
10668
else {
0 commit comments