Skip to content

Commit 5e624e8

Browse files
committed
Separate unmeasurable from unreliable to reduce the impact of this change, for now
1 parent 093cc72 commit 5e624e8

8 files changed

+442
-61
lines changed

src/compiler/checker.ts

+48-44
Large diffs are not rendered by default.

src/compiler/types.ts

+12-9
Original file line numberDiff line numberDiff line change
@@ -3735,7 +3735,7 @@ namespace ts {
37353735
specifierCache?: Map<string>; // For symbols corresponding to external modules, a cache of incoming path -> module specifier name mappings
37363736
extendedContainers?: Symbol[]; // Containers (other than the parent) which this symbol is aliased in
37373737
extendedContainersByFile?: Map<Symbol[]>; // Containers (other than the parent) which this symbol is aliased in
3738-
variances?: Variance[]; // Alias symbol type argument variance cache
3738+
variances?: VarianceFlags[]; // Alias symbol type argument variance cache
37393739
}
37403740

37413741
/* @internal */
@@ -4131,21 +4131,24 @@ namespace ts {
41314131
}
41324132

41334133
/* @internal */
4134-
export const enum Variance {
4135-
Invariant = 0, // Neither covariant nor contravariant
4136-
Covariant = 1, // Covariant
4137-
Contravariant = 2, // Contravariant
4138-
Bivariant = 3, // Both covariant and contravariant
4139-
Independent = 4, // Unwitnessed type parameter
4140-
Unmeasurable = 5, // Variance result is unusable - relationship relies on structural comparisons which are not reflected in generic relationships
4134+
export const enum VarianceFlags {
4135+
Invariant = 0, // Neither covariant nor contravariant
4136+
Covariant = 1 << 0, // Covariant
4137+
Contravariant = 1 << 1, // Contravariant
4138+
Bivariant = Covariant | Contravariant, // Both covariant and contravariant
4139+
Independent = 1 << 2, // Unwitnessed type parameter
4140+
VarianceMask = Invariant | Covariant | Contravariant | Independent, // Mask containing all measured variances without the unmeasurable flag
4141+
Unmeasurable = 1 << 3, // Variance result is unusable - relationship relies on structural comparisons which are not reflected in generic relationships
4142+
Unreliable = 1 << 4, // Variance result is unreliable - relationship relies on structural comparisons which are not reflected in generic relationships
4143+
AllowsStructuralFallback = Unmeasurable | Unreliable,
41414144
}
41424145

41434146
// Generic class and interface types
41444147
export interface GenericType extends InterfaceType, TypeReference {
41454148
/* @internal */
41464149
instantiations: Map<TypeReference>; // Generic instantiation cache
41474150
/* @internal */
4148-
variances?: Variance[]; // Variance of each type parameter
4151+
variances?: VarianceFlags[]; // Variance of each type parameter
41494152
}
41504153

41514154
export interface TupleType extends GenericType {

tests/baselines/reference/conditionalTypes1.errors.txt

-8
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,8 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(103,5): error TS2
1717
tests/cases/conformance/types/conditional/conditionalTypes1.ts(104,5): error TS2322: Type 'Pick<T, { [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]>' is not assignable to type 'T'.
1818
tests/cases/conformance/types/conditional/conditionalTypes1.ts(106,5): error TS2322: Type 'Pick<T, { [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]>' is not assignable to type 'Pick<T, { [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]>'.
1919
Type 'T[keyof T] extends Function ? keyof T : never' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
20-
Type 'keyof T' is not assignable to type 'never'.
21-
Type 'string | number | symbol' is not assignable to type 'never'.
22-
Type 'string' is not assignable to type 'never'.
2320
tests/cases/conformance/types/conditional/conditionalTypes1.ts(108,5): error TS2322: Type 'Pick<T, { [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]>' is not assignable to type 'Pick<T, { [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]>'.
2421
Type 'T[keyof T] extends Function ? never : keyof T' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
25-
Type 'keyof T' is not assignable to type 'never'.
2622
tests/cases/conformance/types/conditional/conditionalTypes1.ts(114,5): error TS2322: Type 'keyof T' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
2723
Type 'string | number | symbol' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
2824
Type 'string' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
@@ -187,15 +183,11 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(288,43): error TS
187183
~
188184
!!! error TS2322: Type 'Pick<T, { [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]>' is not assignable to type 'Pick<T, { [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]>'.
189185
!!! error TS2322: Type 'T[keyof T] extends Function ? keyof T : never' is not assignable to type 'T[keyof T] extends Function ? never : keyof T'.
190-
!!! error TS2322: Type 'keyof T' is not assignable to type 'never'.
191-
!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'never'.
192-
!!! error TS2322: Type 'string' is not assignable to type 'never'.
193186
z = x;
194187
z = y; // Error
195188
~
196189
!!! error TS2322: Type 'Pick<T, { [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]>' is not assignable to type 'Pick<T, { [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]>'.
197190
!!! error TS2322: Type 'T[keyof T] extends Function ? never : keyof T' is not assignable to type 'T[keyof T] extends Function ? keyof T : never'.
198-
!!! error TS2322: Type 'keyof T' is not assignable to type 'never'.
199191
}
200192

201193
function f8<T>(x: keyof T, y: FunctionPropertyNames<T>, z: NonFunctionPropertyNames<T>) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
tests/cases/compiler/consistentAliasVsNonAliasRecordBehavior.ts(17,5): error TS2741: Property 'a' is missing in type 'Record<string, string>' but required in type 'Record2<"a", string>'.
2+
tests/cases/compiler/consistentAliasVsNonAliasRecordBehavior.ts(21,5): error TS2741: Property 'a' is missing in type 'Record2<string, string>' but required in type 'Record<"a", string>'.
3+
tests/cases/compiler/consistentAliasVsNonAliasRecordBehavior.ts(33,5): error TS2741: Property 'a' is missing in type 'Record<string, T>' but required in type 'Record2<"a", T>'.
4+
tests/cases/compiler/consistentAliasVsNonAliasRecordBehavior.ts(37,5): error TS2741: Property 'a' is missing in type 'Record2<string, T>' but required in type 'Record<"a", T>'.
5+
6+
7+
==== tests/cases/compiler/consistentAliasVsNonAliasRecordBehavior.ts (4 errors) ====
8+
// TODO: FIXME: All the below cases labeled `no error` _should be an error_, and are only prevented from so being
9+
// by incorrect variance-based relationships
10+
11+
type Record2<K extends keyof any, T> = {
12+
[P in K]: T;
13+
};
14+
15+
function defaultRecord(x: Record<'a', string>, y: Record<string, string>) {
16+
x = y; // no error, but error expected.
17+
}
18+
19+
function customRecord(x: Record2<'a', string>, y: Record2<string, string>) {
20+
x = y; // no error, but error expected.
21+
}
22+
23+
function mixed1(x: Record2<'a', string>, y: Record<string, string>) {
24+
x = y; // error
25+
~
26+
!!! error TS2741: Property 'a' is missing in type 'Record<string, string>' but required in type 'Record2<"a", string>'.
27+
}
28+
29+
function mixed2(x: Record<'a', string>, y: Record2<string, string>) {
30+
x = y; // error
31+
~
32+
!!! error TS2741: Property 'a' is missing in type 'Record2<string, string>' but required in type 'Record<"a", string>'.
33+
}
34+
35+
function defaultRecord2<T>(x: Record<'a', T>, y: Record<string, T>) {
36+
x = y; // no error, but error expected.
37+
}
38+
39+
function customRecord2<T>(x: Record2<'a', T>, y: Record2<string, T>) {
40+
x = y; // no error, but error expected.
41+
}
42+
43+
function mixed3<T>(x: Record2<'a', T>, y: Record<string, T>) {
44+
x = y; // error
45+
~
46+
!!! error TS2741: Property 'a' is missing in type 'Record<string, T>' but required in type 'Record2<"a", T>'.
47+
}
48+
49+
function mixed4<T>(x: Record<'a', T>, y: Record2<string, T>) {
50+
x = y; // error
51+
~
52+
!!! error TS2741: Property 'a' is missing in type 'Record2<string, T>' but required in type 'Record<"a", T>'.
53+
}
54+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//// [consistentAliasVsNonAliasRecordBehavior.ts]
2+
// TODO: FIXME: All the below cases labeled `no error` _should be an error_, and are only prevented from so being
3+
// by incorrect variance-based relationships
4+
5+
type Record2<K extends keyof any, T> = {
6+
[P in K]: T;
7+
};
8+
9+
function defaultRecord(x: Record<'a', string>, y: Record<string, string>) {
10+
x = y; // no error, but error expected.
11+
}
12+
13+
function customRecord(x: Record2<'a', string>, y: Record2<string, string>) {
14+
x = y; // no error, but error expected.
15+
}
16+
17+
function mixed1(x: Record2<'a', string>, y: Record<string, string>) {
18+
x = y; // error
19+
}
20+
21+
function mixed2(x: Record<'a', string>, y: Record2<string, string>) {
22+
x = y; // error
23+
}
24+
25+
function defaultRecord2<T>(x: Record<'a', T>, y: Record<string, T>) {
26+
x = y; // no error, but error expected.
27+
}
28+
29+
function customRecord2<T>(x: Record2<'a', T>, y: Record2<string, T>) {
30+
x = y; // no error, but error expected.
31+
}
32+
33+
function mixed3<T>(x: Record2<'a', T>, y: Record<string, T>) {
34+
x = y; // error
35+
}
36+
37+
function mixed4<T>(x: Record<'a', T>, y: Record2<string, T>) {
38+
x = y; // error
39+
}
40+
41+
42+
//// [consistentAliasVsNonAliasRecordBehavior.js]
43+
// TODO: FIXME: All the below cases labeled `no error` _should be an error_, and are only prevented from so being
44+
// by incorrect variance-based relationships
45+
function defaultRecord(x, y) {
46+
x = y; // no error, but error expected.
47+
}
48+
function customRecord(x, y) {
49+
x = y; // no error, but error expected.
50+
}
51+
function mixed1(x, y) {
52+
x = y; // error
53+
}
54+
function mixed2(x, y) {
55+
x = y; // error
56+
}
57+
function defaultRecord2(x, y) {
58+
x = y; // no error, but error expected.
59+
}
60+
function customRecord2(x, y) {
61+
x = y; // no error, but error expected.
62+
}
63+
function mixed3(x, y) {
64+
x = y; // error
65+
}
66+
function mixed4(x, y) {
67+
x = y; // error
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
=== tests/cases/compiler/consistentAliasVsNonAliasRecordBehavior.ts ===
2+
// TODO: FIXME: All the below cases labeled `no error` _should be an error_, and are only prevented from so being
3+
// by incorrect variance-based relationships
4+
5+
type Record2<K extends keyof any, T> = {
6+
>Record2 : Symbol(Record2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 0, 0))
7+
>K : Symbol(K, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 3, 13))
8+
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 3, 33))
9+
10+
[P in K]: T;
11+
>P : Symbol(P, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 4, 5))
12+
>K : Symbol(K, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 3, 13))
13+
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 3, 33))
14+
15+
};
16+
17+
function defaultRecord(x: Record<'a', string>, y: Record<string, string>) {
18+
>defaultRecord : Symbol(defaultRecord, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 5, 2))
19+
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 7, 23))
20+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
21+
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 7, 46))
22+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
23+
24+
x = y; // no error, but error expected.
25+
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 7, 23))
26+
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 7, 46))
27+
}
28+
29+
function customRecord(x: Record2<'a', string>, y: Record2<string, string>) {
30+
>customRecord : Symbol(customRecord, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 9, 1))
31+
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 11, 22))
32+
>Record2 : Symbol(Record2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 0, 0))
33+
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 11, 46))
34+
>Record2 : Symbol(Record2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 0, 0))
35+
36+
x = y; // no error, but error expected.
37+
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 11, 22))
38+
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 11, 46))
39+
}
40+
41+
function mixed1(x: Record2<'a', string>, y: Record<string, string>) {
42+
>mixed1 : Symbol(mixed1, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 13, 1))
43+
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 15, 16))
44+
>Record2 : Symbol(Record2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 0, 0))
45+
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 15, 40))
46+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
47+
48+
x = y; // error
49+
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 15, 16))
50+
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 15, 40))
51+
}
52+
53+
function mixed2(x: Record<'a', string>, y: Record2<string, string>) {
54+
>mixed2 : Symbol(mixed2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 17, 1))
55+
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 19, 16))
56+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
57+
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 19, 39))
58+
>Record2 : Symbol(Record2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 0, 0))
59+
60+
x = y; // error
61+
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 19, 16))
62+
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 19, 39))
63+
}
64+
65+
function defaultRecord2<T>(x: Record<'a', T>, y: Record<string, T>) {
66+
>defaultRecord2 : Symbol(defaultRecord2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 21, 1))
67+
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 23, 24))
68+
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 23, 27))
69+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
70+
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 23, 24))
71+
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 23, 45))
72+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
73+
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 23, 24))
74+
75+
x = y; // no error, but error expected.
76+
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 23, 27))
77+
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 23, 45))
78+
}
79+
80+
function customRecord2<T>(x: Record2<'a', T>, y: Record2<string, T>) {
81+
>customRecord2 : Symbol(customRecord2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 25, 1))
82+
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 27, 23))
83+
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 27, 26))
84+
>Record2 : Symbol(Record2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 0, 0))
85+
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 27, 23))
86+
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 27, 45))
87+
>Record2 : Symbol(Record2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 0, 0))
88+
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 27, 23))
89+
90+
x = y; // no error, but error expected.
91+
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 27, 26))
92+
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 27, 45))
93+
}
94+
95+
function mixed3<T>(x: Record2<'a', T>, y: Record<string, T>) {
96+
>mixed3 : Symbol(mixed3, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 29, 1))
97+
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 31, 16))
98+
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 31, 19))
99+
>Record2 : Symbol(Record2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 0, 0))
100+
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 31, 16))
101+
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 31, 38))
102+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
103+
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 31, 16))
104+
105+
x = y; // error
106+
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 31, 19))
107+
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 31, 38))
108+
}
109+
110+
function mixed4<T>(x: Record<'a', T>, y: Record2<string, T>) {
111+
>mixed4 : Symbol(mixed4, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 33, 1))
112+
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 35, 16))
113+
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 35, 19))
114+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
115+
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 35, 16))
116+
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 35, 37))
117+
>Record2 : Symbol(Record2, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 0, 0))
118+
>T : Symbol(T, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 35, 16))
119+
120+
x = y; // error
121+
>x : Symbol(x, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 35, 19))
122+
>y : Symbol(y, Decl(consistentAliasVsNonAliasRecordBehavior.ts, 35, 37))
123+
}
124+

0 commit comments

Comments
 (0)