-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Regression in variance measurements for aliased recursive types: not falling back to structural checks when measuring #33872
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
The issue is that the flags for identifying types instantiated with markers are not being propagated fully. The comparison ends up doing a default covariant check on type arguments when it should be falling back to a structural check (because we're in the middle of a variance measurement). In this case: function getAliasVariances(symbol: Symbol) {
const links = getSymbolLinks(symbol);
return getVariancesWorker(links.typeParameters, links, (_links, param, marker) => {
const type = getTypeAliasInstantiation(symbol, instantiateTypes(links.typeParameters!, makeUnaryTypeMapper(param, marker)));
type.aliasTypeArgumentsContainsMarker = true;
return type;
});
} Getting the alias variance for if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target &&
!(getObjectFlags(source) & ObjectFlags.MarkerType || getObjectFlags(target) & ObjectFlags.MarkerType)) {
// We have type references to the same generic type, and the type references are not marker
// type references (which are intended by be compared structurally). Obtain the variance
// information for the type parameters and relate the type arguments accordingly.
const variances = getVariances((<TypeReference>source).target);
const varianceResult = relateVariances(getTypeArguments(<TypeReference>source), getTypeArguments(<TypeReference>target), variances, isIntersectionConstituent);
if (varianceResult !== undefined) {
return varianceResult;
}
} Looking for |
Smaller repro: type A<T> = B<T>;
interface B<T> {
prop: A<T>;
}
declare let a: A<number>;
declare let b: A<3>;
b = a; // error |
That looks like a correct error, though ( |
The error is not correct because the type parameter is never materialised in the type, so the type-parameters of two instantiations of interface C {
prop: C;
}
declare let a: A<number>;
declare let b: A<3>;
const c1: C = a;
const c2: C = b;
a = c1;
b = c2; |
Version. 3.7-beta
Code
Expected behavior:
No error on the assignment to
x
.Actual behavior:
Error.
unknown
is not assignable toO
. The parameterO
is being measured as invariant.This works correctly on 3.6.3 and below. The usual tricks to avoid variance-based comparisons let the assignment pass.
Also, removing the type alias works too:
Probably caused by #33050.
Playground Link: link
The text was updated successfully, but these errors were encountered: