Skip to content

Commit

Permalink
All Unmeasurable variances to still shortcut structural comparisons i…
Browse files Browse the repository at this point in the history
…n some cases
  • Loading branch information
weswigham committed Apr 25, 2019
1 parent 15f8c10 commit dc40484
Showing 1 changed file with 25 additions and 3 deletions.
28 changes: 25 additions & 3 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12842,6 +12842,22 @@ namespace ts {
related = isRelatedTo(s, t, reportErrors);
}
}
else if (variance === Variance.Unmeasurable) {
if (isTypeAny(s) || isTypeAny(t)) {
// If the `s` or `t` type is `any`, even if the structural desugaring says that the types _shouldn't_
// be relatable, it's very surprising if they're not - take `Component<Foo, any>` to `Component<Foo, Foo>` - even
// if the `any` position is unmeasurable, it's incredibly surprising that such a reference wouldn't check out.
// (In fact, any nonlinear relation involving `any` is usually surprising) Even if it's potentially not correct
// according to our underlying structural rules, we persist that assumption here.
related = Ternary.True;
}
else {
// Even an `Unmeasurable` variance works out without a structural check if the source and target are _identical_.
// We can't simply assume invariance, because `Unmeasurable` marks nonlinear relations, for example, a relation tained by
// the `-?` modifier in a mapped type (where, no matter how the inputs are related, the outputs still might not be)
related = relation === identityRelation ? isRelatedTo(s, t, /*reportErrors*/ false) : compareTypesIdentical(s, t);
}
}
else {
// In the invariant case we first compare covariantly, and only when that
// succeeds do we proceed to compare contravariantly. Thus, error elaboration
Expand Down Expand Up @@ -13200,12 +13216,18 @@ namespace ts {
return Ternary.False;

function relateVariances(sourceTypeArguments: ReadonlyArray<Type> | undefined, targetTypeArguments: ReadonlyArray<Type> | undefined, variances: Variance[]) {
if (some(variances, v => v === Variance.Unmeasurable)) {
return undefined;
}
if (result = typeArgumentsRelatedTo(sourceTypeArguments, targetTypeArguments, variances, reportErrors)) {
return result;
}
if (some(variances, v => v === Variance.Unmeasurable)) {
// If some type parameter was `Unmeasurable`, and we couldn't pass by assuming it was invariant, then we
// have to allow a structural fallback check
// We elide the variance-based error elaborations, since those might not be too helpful, since we'll potentially
// be assuming identity of the type parameter.
originalErrorInfo = undefined;
errorInfo = saveErrorInfo;
return undefined;
}
const allowStructuralFallback = targetTypeArguments && hasCovariantVoidArgument(targetTypeArguments, variances);
varianceCheckFailed = !allowStructuralFallback;
// The type arguments did not relate appropriately, but it may be because we have no variance
Expand Down

0 comments on commit dc40484

Please sign in to comment.