Skip to content

Commit cf7b19a

Browse files
TypeScript BotRyanCavanaugh
TypeScript Bot
authored andcommitted
🤖 Cherry-pick PR #31688 into release-3.5 (#31707)
Component commits: 20c928e Propegate saved variance flags from cached comparisons f21903b Propegate variance a bit more selectively a007f56 Add test c45f90f Remove now-redundant code b36246d Fix misspelling and remove unneeded branch
1 parent cf7b2d4 commit cf7b19a

5 files changed

+330
-6
lines changed

src/compiler/checker.ts

+22-6
Original file line numberDiff line numberDiff line change
@@ -12981,6 +12981,18 @@ namespace ts {
1298112981
return result;
1298212982
}
1298312983

12984+
function propagateSidebandVarianceFlags(typeArguments: readonly Type[], variances: VarianceFlags[]) {
12985+
for (let i = 0; i < variances.length; i++) {
12986+
const v = variances[i];
12987+
if (v & VarianceFlags.Unmeasurable) {
12988+
instantiateType(typeArguments[i], reportUnmeasurableMarkers);
12989+
}
12990+
if (v & VarianceFlags.Unreliable) {
12991+
instantiateType(typeArguments[i], reportUnreliableMarkers);
12992+
}
12993+
}
12994+
}
12995+
1298412996
// Determine if possibly recursive types are related. First, check if the result is already available in the global cache.
1298512997
// Second, check if we have already started a comparison of the given two types in which case we assume the result to be true.
1298612998
// Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are
@@ -12998,6 +13010,16 @@ namespace ts {
1299813010
// as a failure, and should be updated as a reported failure by the bottom of this function.
1299913011
}
1300013012
else {
13013+
if (outofbandVarianceMarkerHandler) {
13014+
// We're in the middle of variance checking - integrate any unmeasurable/unreliable flags from this cached component
13015+
if (source.flags & (TypeFlags.Object | TypeFlags.Conditional) && source.aliasSymbol &&
13016+
source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol) {
13017+
propagateSidebandVarianceFlags(source.aliasTypeArguments, getAliasVariances(source.aliasSymbol));
13018+
}
13019+
if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target && length((<TypeReference>source).typeArguments)) {
13020+
propagateSidebandVarianceFlags((<TypeReference>source).typeArguments!, getVariances((<TypeReference>source).target));
13021+
}
13022+
}
1300113023
return related === RelationComparisonResult.Succeeded ? Ternary.True : Ternary.False;
1300213024
}
1300313025
}
@@ -14070,12 +14092,6 @@ namespace ts {
1407014092
if (unreliable) {
1407114093
variance |= VarianceFlags.Unreliable;
1407214094
}
14073-
const covariantID = getRelationKey(typeWithSub, typeWithSuper, assignableRelation);
14074-
const contravariantID = getRelationKey(typeWithSuper, typeWithSub, assignableRelation);
14075-
// We delete the results of these checks, as we want them to actually be run, see the `Unmeasurable` variance we cache,
14076-
// And then fall back to a structural result.
14077-
assignableRelation.delete(covariantID);
14078-
assignableRelation.delete(contravariantID);
1407914095
}
1408014096
variances.push(variance);
1408114097
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//// [identicalTypesNoDifferByCheckOrder.ts]
2+
interface SomeProps {
3+
x?: string;
4+
y?: number;
5+
renderAs?: FunctionComponent1<SomeProps>
6+
}
7+
8+
type SomePropsX = Required<Pick<SomeProps, "x">> & Omit<SomeProps, "x">;
9+
10+
interface SomePropsClone {
11+
x?: string;
12+
y?: number;
13+
renderAs?: FunctionComponent2<SomeProps>
14+
}
15+
16+
type SomePropsCloneX = Required<Pick<SomePropsClone, "x">> & Omit<SomePropsClone, "x">;
17+
18+
type Validator<T> = {(): boolean, opt?: T};
19+
type WeakValidationMap<T> = {[K in keyof T]?: null extends T[K] ? Validator<T[K] | null | undefined> : Validator<T[K]>};
20+
21+
interface FunctionComponent1<P> {
22+
(props: P & { children?: unknown }): void;
23+
propTypes?: WeakValidationMap<P>;
24+
}
25+
26+
interface FunctionComponent2<P> {
27+
(props: P & { children?: unknown }): void;
28+
propTypes?: WeakValidationMap<P>;
29+
}
30+
31+
function needsComponentOfSomeProps3(...x: SomePropsClone[]): void {}
32+
const comp3: FunctionComponent2<SomePropsCloneX> = null as any;
33+
needsComponentOfSomeProps3({ renderAs: comp3 });
34+
35+
function needsComponentOfSomeProps2(...x: SomeProps[]): void {}
36+
const comp2: FunctionComponent1<SomePropsX> = null as any;
37+
needsComponentOfSomeProps2({ renderAs: comp2 });
38+
39+
//// [identicalTypesNoDifferByCheckOrder.js]
40+
function needsComponentOfSomeProps3() {
41+
var x = [];
42+
for (var _i = 0; _i < arguments.length; _i++) {
43+
x[_i] = arguments[_i];
44+
}
45+
}
46+
var comp3 = null;
47+
needsComponentOfSomeProps3({ renderAs: comp3 });
48+
function needsComponentOfSomeProps2() {
49+
var x = [];
50+
for (var _i = 0; _i < arguments.length; _i++) {
51+
x[_i] = arguments[_i];
52+
}
53+
}
54+
var comp2 = null;
55+
needsComponentOfSomeProps2({ renderAs: comp2 });
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
=== tests/cases/compiler/identicalTypesNoDifferByCheckOrder.ts ===
2+
interface SomeProps {
3+
>SomeProps : Symbol(SomeProps, Decl(identicalTypesNoDifferByCheckOrder.ts, 0, 0))
4+
5+
x?: string;
6+
>x : Symbol(SomeProps.x, Decl(identicalTypesNoDifferByCheckOrder.ts, 0, 21))
7+
8+
y?: number;
9+
>y : Symbol(SomeProps.y, Decl(identicalTypesNoDifferByCheckOrder.ts, 1, 15))
10+
11+
renderAs?: FunctionComponent1<SomeProps>
12+
>renderAs : Symbol(SomeProps.renderAs, Decl(identicalTypesNoDifferByCheckOrder.ts, 2, 15))
13+
>FunctionComponent1 : Symbol(FunctionComponent1, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 120))
14+
>SomeProps : Symbol(SomeProps, Decl(identicalTypesNoDifferByCheckOrder.ts, 0, 0))
15+
}
16+
17+
type SomePropsX = Required<Pick<SomeProps, "x">> & Omit<SomeProps, "x">;
18+
>SomePropsX : Symbol(SomePropsX, Decl(identicalTypesNoDifferByCheckOrder.ts, 4, 1))
19+
>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --))
20+
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
21+
>SomeProps : Symbol(SomeProps, Decl(identicalTypesNoDifferByCheckOrder.ts, 0, 0))
22+
>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --))
23+
>SomeProps : Symbol(SomeProps, Decl(identicalTypesNoDifferByCheckOrder.ts, 0, 0))
24+
25+
interface SomePropsClone {
26+
>SomePropsClone : Symbol(SomePropsClone, Decl(identicalTypesNoDifferByCheckOrder.ts, 6, 72))
27+
28+
x?: string;
29+
>x : Symbol(SomePropsClone.x, Decl(identicalTypesNoDifferByCheckOrder.ts, 8, 26))
30+
31+
y?: number;
32+
>y : Symbol(SomePropsClone.y, Decl(identicalTypesNoDifferByCheckOrder.ts, 9, 15))
33+
34+
renderAs?: FunctionComponent2<SomeProps>
35+
>renderAs : Symbol(SomePropsClone.renderAs, Decl(identicalTypesNoDifferByCheckOrder.ts, 10, 15))
36+
>FunctionComponent2 : Symbol(FunctionComponent2, Decl(identicalTypesNoDifferByCheckOrder.ts, 22, 1))
37+
>SomeProps : Symbol(SomeProps, Decl(identicalTypesNoDifferByCheckOrder.ts, 0, 0))
38+
}
39+
40+
type SomePropsCloneX = Required<Pick<SomePropsClone, "x">> & Omit<SomePropsClone, "x">;
41+
>SomePropsCloneX : Symbol(SomePropsCloneX, Decl(identicalTypesNoDifferByCheckOrder.ts, 12, 1))
42+
>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --))
43+
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
44+
>SomePropsClone : Symbol(SomePropsClone, Decl(identicalTypesNoDifferByCheckOrder.ts, 6, 72))
45+
>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --))
46+
>SomePropsClone : Symbol(SomePropsClone, Decl(identicalTypesNoDifferByCheckOrder.ts, 6, 72))
47+
48+
type Validator<T> = {(): boolean, opt?: T};
49+
>Validator : Symbol(Validator, Decl(identicalTypesNoDifferByCheckOrder.ts, 14, 87))
50+
>T : Symbol(T, Decl(identicalTypesNoDifferByCheckOrder.ts, 16, 15))
51+
>opt : Symbol(opt, Decl(identicalTypesNoDifferByCheckOrder.ts, 16, 33))
52+
>T : Symbol(T, Decl(identicalTypesNoDifferByCheckOrder.ts, 16, 15))
53+
54+
type WeakValidationMap<T> = {[K in keyof T]?: null extends T[K] ? Validator<T[K] | null | undefined> : Validator<T[K]>};
55+
>WeakValidationMap : Symbol(WeakValidationMap, Decl(identicalTypesNoDifferByCheckOrder.ts, 16, 43))
56+
>T : Symbol(T, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 23))
57+
>K : Symbol(K, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 30))
58+
>T : Symbol(T, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 23))
59+
>T : Symbol(T, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 23))
60+
>K : Symbol(K, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 30))
61+
>Validator : Symbol(Validator, Decl(identicalTypesNoDifferByCheckOrder.ts, 14, 87))
62+
>T : Symbol(T, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 23))
63+
>K : Symbol(K, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 30))
64+
>Validator : Symbol(Validator, Decl(identicalTypesNoDifferByCheckOrder.ts, 14, 87))
65+
>T : Symbol(T, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 23))
66+
>K : Symbol(K, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 30))
67+
68+
interface FunctionComponent1<P> {
69+
>FunctionComponent1 : Symbol(FunctionComponent1, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 120))
70+
>P : Symbol(P, Decl(identicalTypesNoDifferByCheckOrder.ts, 19, 29))
71+
72+
(props: P & { children?: unknown }): void;
73+
>props : Symbol(props, Decl(identicalTypesNoDifferByCheckOrder.ts, 20, 5))
74+
>P : Symbol(P, Decl(identicalTypesNoDifferByCheckOrder.ts, 19, 29))
75+
>children : Symbol(children, Decl(identicalTypesNoDifferByCheckOrder.ts, 20, 17))
76+
77+
propTypes?: WeakValidationMap<P>;
78+
>propTypes : Symbol(FunctionComponent1.propTypes, Decl(identicalTypesNoDifferByCheckOrder.ts, 20, 46))
79+
>WeakValidationMap : Symbol(WeakValidationMap, Decl(identicalTypesNoDifferByCheckOrder.ts, 16, 43))
80+
>P : Symbol(P, Decl(identicalTypesNoDifferByCheckOrder.ts, 19, 29))
81+
}
82+
83+
interface FunctionComponent2<P> {
84+
>FunctionComponent2 : Symbol(FunctionComponent2, Decl(identicalTypesNoDifferByCheckOrder.ts, 22, 1))
85+
>P : Symbol(P, Decl(identicalTypesNoDifferByCheckOrder.ts, 24, 29))
86+
87+
(props: P & { children?: unknown }): void;
88+
>props : Symbol(props, Decl(identicalTypesNoDifferByCheckOrder.ts, 25, 5))
89+
>P : Symbol(P, Decl(identicalTypesNoDifferByCheckOrder.ts, 24, 29))
90+
>children : Symbol(children, Decl(identicalTypesNoDifferByCheckOrder.ts, 25, 17))
91+
92+
propTypes?: WeakValidationMap<P>;
93+
>propTypes : Symbol(FunctionComponent2.propTypes, Decl(identicalTypesNoDifferByCheckOrder.ts, 25, 46))
94+
>WeakValidationMap : Symbol(WeakValidationMap, Decl(identicalTypesNoDifferByCheckOrder.ts, 16, 43))
95+
>P : Symbol(P, Decl(identicalTypesNoDifferByCheckOrder.ts, 24, 29))
96+
}
97+
98+
function needsComponentOfSomeProps3(...x: SomePropsClone[]): void {}
99+
>needsComponentOfSomeProps3 : Symbol(needsComponentOfSomeProps3, Decl(identicalTypesNoDifferByCheckOrder.ts, 27, 1))
100+
>x : Symbol(x, Decl(identicalTypesNoDifferByCheckOrder.ts, 29, 36))
101+
>SomePropsClone : Symbol(SomePropsClone, Decl(identicalTypesNoDifferByCheckOrder.ts, 6, 72))
102+
103+
const comp3: FunctionComponent2<SomePropsCloneX> = null as any;
104+
>comp3 : Symbol(comp3, Decl(identicalTypesNoDifferByCheckOrder.ts, 30, 5))
105+
>FunctionComponent2 : Symbol(FunctionComponent2, Decl(identicalTypesNoDifferByCheckOrder.ts, 22, 1))
106+
>SomePropsCloneX : Symbol(SomePropsCloneX, Decl(identicalTypesNoDifferByCheckOrder.ts, 12, 1))
107+
108+
needsComponentOfSomeProps3({ renderAs: comp3 });
109+
>needsComponentOfSomeProps3 : Symbol(needsComponentOfSomeProps3, Decl(identicalTypesNoDifferByCheckOrder.ts, 27, 1))
110+
>renderAs : Symbol(renderAs, Decl(identicalTypesNoDifferByCheckOrder.ts, 31, 28))
111+
>comp3 : Symbol(comp3, Decl(identicalTypesNoDifferByCheckOrder.ts, 30, 5))
112+
113+
function needsComponentOfSomeProps2(...x: SomeProps[]): void {}
114+
>needsComponentOfSomeProps2 : Symbol(needsComponentOfSomeProps2, Decl(identicalTypesNoDifferByCheckOrder.ts, 31, 48))
115+
>x : Symbol(x, Decl(identicalTypesNoDifferByCheckOrder.ts, 33, 36))
116+
>SomeProps : Symbol(SomeProps, Decl(identicalTypesNoDifferByCheckOrder.ts, 0, 0))
117+
118+
const comp2: FunctionComponent1<SomePropsX> = null as any;
119+
>comp2 : Symbol(comp2, Decl(identicalTypesNoDifferByCheckOrder.ts, 34, 5))
120+
>FunctionComponent1 : Symbol(FunctionComponent1, Decl(identicalTypesNoDifferByCheckOrder.ts, 17, 120))
121+
>SomePropsX : Symbol(SomePropsX, Decl(identicalTypesNoDifferByCheckOrder.ts, 4, 1))
122+
123+
needsComponentOfSomeProps2({ renderAs: comp2 });
124+
>needsComponentOfSomeProps2 : Symbol(needsComponentOfSomeProps2, Decl(identicalTypesNoDifferByCheckOrder.ts, 31, 48))
125+
>renderAs : Symbol(renderAs, Decl(identicalTypesNoDifferByCheckOrder.ts, 35, 28))
126+
>comp2 : Symbol(comp2, Decl(identicalTypesNoDifferByCheckOrder.ts, 34, 5))
127+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
=== tests/cases/compiler/identicalTypesNoDifferByCheckOrder.ts ===
2+
interface SomeProps {
3+
x?: string;
4+
>x : string | undefined
5+
6+
y?: number;
7+
>y : number | undefined
8+
9+
renderAs?: FunctionComponent1<SomeProps>
10+
>renderAs : FunctionComponent1<SomeProps> | undefined
11+
}
12+
13+
type SomePropsX = Required<Pick<SomeProps, "x">> & Omit<SomeProps, "x">;
14+
>SomePropsX : SomePropsX
15+
16+
interface SomePropsClone {
17+
x?: string;
18+
>x : string | undefined
19+
20+
y?: number;
21+
>y : number | undefined
22+
23+
renderAs?: FunctionComponent2<SomeProps>
24+
>renderAs : FunctionComponent2<SomeProps> | undefined
25+
}
26+
27+
type SomePropsCloneX = Required<Pick<SomePropsClone, "x">> & Omit<SomePropsClone, "x">;
28+
>SomePropsCloneX : SomePropsCloneX
29+
30+
type Validator<T> = {(): boolean, opt?: T};
31+
>Validator : Validator<T>
32+
>opt : T | undefined
33+
34+
type WeakValidationMap<T> = {[K in keyof T]?: null extends T[K] ? Validator<T[K] | null | undefined> : Validator<T[K]>};
35+
>WeakValidationMap : WeakValidationMap<T>
36+
>null : null
37+
>null : null
38+
39+
interface FunctionComponent1<P> {
40+
(props: P & { children?: unknown }): void;
41+
>props : P & { children?: unknown; }
42+
>children : unknown
43+
44+
propTypes?: WeakValidationMap<P>;
45+
>propTypes : WeakValidationMap<P> | undefined
46+
}
47+
48+
interface FunctionComponent2<P> {
49+
(props: P & { children?: unknown }): void;
50+
>props : P & { children?: unknown; }
51+
>children : unknown
52+
53+
propTypes?: WeakValidationMap<P>;
54+
>propTypes : WeakValidationMap<P> | undefined
55+
}
56+
57+
function needsComponentOfSomeProps3(...x: SomePropsClone[]): void {}
58+
>needsComponentOfSomeProps3 : (...x: SomePropsClone[]) => void
59+
>x : SomePropsClone[]
60+
61+
const comp3: FunctionComponent2<SomePropsCloneX> = null as any;
62+
>comp3 : FunctionComponent2<SomePropsCloneX>
63+
>null as any : any
64+
>null : null
65+
66+
needsComponentOfSomeProps3({ renderAs: comp3 });
67+
>needsComponentOfSomeProps3({ renderAs: comp3 }) : void
68+
>needsComponentOfSomeProps3 : (...x: SomePropsClone[]) => void
69+
>{ renderAs: comp3 } : { renderAs: FunctionComponent2<SomePropsCloneX>; }
70+
>renderAs : FunctionComponent2<SomePropsCloneX>
71+
>comp3 : FunctionComponent2<SomePropsCloneX>
72+
73+
function needsComponentOfSomeProps2(...x: SomeProps[]): void {}
74+
>needsComponentOfSomeProps2 : (...x: SomeProps[]) => void
75+
>x : SomeProps[]
76+
77+
const comp2: FunctionComponent1<SomePropsX> = null as any;
78+
>comp2 : FunctionComponent1<SomePropsX>
79+
>null as any : any
80+
>null : null
81+
82+
needsComponentOfSomeProps2({ renderAs: comp2 });
83+
>needsComponentOfSomeProps2({ renderAs: comp2 }) : void
84+
>needsComponentOfSomeProps2 : (...x: SomeProps[]) => void
85+
>{ renderAs: comp2 } : { renderAs: FunctionComponent1<SomePropsX>; }
86+
>renderAs : FunctionComponent1<SomePropsX>
87+
>comp2 : FunctionComponent1<SomePropsX>
88+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// @strictNullChecks: true
2+
3+
interface SomeProps {
4+
x?: string;
5+
y?: number;
6+
renderAs?: FunctionComponent1<SomeProps>
7+
}
8+
9+
type SomePropsX = Required<Pick<SomeProps, "x">> & Omit<SomeProps, "x">;
10+
11+
interface SomePropsClone {
12+
x?: string;
13+
y?: number;
14+
renderAs?: FunctionComponent2<SomeProps>
15+
}
16+
17+
type SomePropsCloneX = Required<Pick<SomePropsClone, "x">> & Omit<SomePropsClone, "x">;
18+
19+
type Validator<T> = {(): boolean, opt?: T};
20+
type WeakValidationMap<T> = {[K in keyof T]?: null extends T[K] ? Validator<T[K] | null | undefined> : Validator<T[K]>};
21+
22+
interface FunctionComponent1<P> {
23+
(props: P & { children?: unknown }): void;
24+
propTypes?: WeakValidationMap<P>;
25+
}
26+
27+
interface FunctionComponent2<P> {
28+
(props: P & { children?: unknown }): void;
29+
propTypes?: WeakValidationMap<P>;
30+
}
31+
32+
function needsComponentOfSomeProps3(...x: SomePropsClone[]): void {}
33+
const comp3: FunctionComponent2<SomePropsCloneX> = null as any;
34+
needsComponentOfSomeProps3({ renderAs: comp3 });
35+
36+
function needsComponentOfSomeProps2(...x: SomeProps[]): void {}
37+
const comp2: FunctionComponent1<SomePropsX> = null as any;
38+
needsComponentOfSomeProps2({ renderAs: comp2 });

0 commit comments

Comments
 (0)