Skip to content

Commit 34d1ea6

Browse files
authored
Fix type variable leaks and cache inconsistencies (#61668)
1 parent cb38d99 commit 34d1ea6

22 files changed

+1069
-105
lines changed

src/compiler/checker.ts

Lines changed: 37 additions & 77 deletions
Large diffs are not rendered by default.

src/compiler/types.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6539,7 +6539,7 @@ export const enum ObjectFlags {
65396539
CouldContainTypeVariablesComputed = 1 << 19, // CouldContainTypeVariables flag has been computed
65406540
/** @internal */
65416541
CouldContainTypeVariables = 1 << 20, // Type could contain a type variable
6542-
6542+
SingleSignatureType = 1 << 27, // A single signature type extracted from a potentially broader type
65436543
ClassOrInterface = Class | Interface,
65446544
/** @internal */
65456545
RequiresWidening = ContainsWideningType | ContainsObjectOrArrayLiteral,
@@ -6555,7 +6555,6 @@ export const enum ObjectFlags {
65556555
ContainsSpread = 1 << 21, // Object literal contains spread operation
65566556
ObjectRestType = 1 << 22, // Originates in object rest declaration
65576557
InstantiationExpressionType = 1 << 23, // Originates in instantiation expression
6558-
SingleSignatureType = 1 << 27, // A single signature type extracted from a potentially broader type
65596558
/** @internal */
65606559
IsClassInstanceClone = 1 << 24, // Type is a clone of a class instance type
65616560
// Flags that require TypeFlags.Object and ObjectFlags.Reference
@@ -6770,12 +6769,6 @@ export interface AnonymousType extends ObjectType {
67706769
instantiations?: Map<string, Type>; // Instantiations of generic type alias (undefined if non-generic)
67716770
}
67726771

6773-
/** @internal */
6774-
// A SingleSignatureType may have bespoke outer type parameters to handle free type variable inferences
6775-
export interface SingleSignatureType extends AnonymousType {
6776-
outerTypeParameters?: TypeParameter[];
6777-
}
6778-
67796772
/** @internal */
67806773
export interface InstantiationExpressionType extends AnonymousType {
67816774
node: NodeWithTypeArguments;
@@ -7061,8 +7054,6 @@ export interface Signature {
70617054
isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison
70627055
/** @internal */
70637056
instantiations?: Map<string, Signature>; // Generic signature instantiation cache
7064-
/** @internal */
7065-
implementationSignatureCache?: Signature; // Copy of the signature with fresh type parameters to use in checking the body of a potentially self-referential generic function (deferred)
70667057
}
70677058

70687059
export const enum IndexKind {
@@ -7170,6 +7161,7 @@ export interface InferenceContext {
71707161
mapper: TypeMapper; // Mapper that fixes inferences
71717162
nonFixingMapper: TypeMapper; // Mapper that doesn't fix inferences
71727163
returnMapper?: TypeMapper; // Type mapper for inferences from return types (if any)
7164+
outerReturnMapper?: TypeMapper; // Type mapper for inferences from return types of outer function (if any)
71737165
inferredTypeParameters?: readonly TypeParameter[]; // Inferred type parameters for function result
71747166
intraExpressionInferenceSites?: IntraExpressionInferenceSite[];
71757167
}

tests/baselines/reference/api/typescript.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6717,11 +6717,11 @@ declare namespace ts {
67176717
JSLiteral = 4096,
67186718
FreshLiteral = 8192,
67196719
ArrayLiteral = 16384,
6720+
SingleSignatureType = 134217728,
67206721
ClassOrInterface = 3,
67216722
ContainsSpread = 2097152,
67226723
ObjectRestType = 4194304,
67236724
InstantiationExpressionType = 8388608,
6724-
SingleSignatureType = 134217728,
67256725
}
67266726
interface ObjectType extends Type {
67276727
objectFlags: ObjectFlags;
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
//// [tests/cases/compiler/genericCallInferenceInConditionalTypes1.ts] ////
2+
3+
=== genericCallInferenceInConditionalTypes1.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/59937
5+
6+
type Ref<T> = {
7+
>Ref : Symbol(Ref, Decl(genericCallInferenceInConditionalTypes1.ts, 0, 0))
8+
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 2, 9))
9+
10+
current: T;
11+
>current : Symbol(current, Decl(genericCallInferenceInConditionalTypes1.ts, 2, 15))
12+
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 2, 9))
13+
14+
};
15+
16+
type FunctionComponent<P> = (props: P) => unknown;
17+
>FunctionComponent : Symbol(FunctionComponent, Decl(genericCallInferenceInConditionalTypes1.ts, 4, 2))
18+
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 6, 23))
19+
>props : Symbol(props, Decl(genericCallInferenceInConditionalTypes1.ts, 6, 29))
20+
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 6, 23))
21+
22+
type ComponentProps<T extends FunctionComponent<any>> =
23+
>ComponentProps : Symbol(ComponentProps, Decl(genericCallInferenceInConditionalTypes1.ts, 6, 50))
24+
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 8, 20))
25+
>FunctionComponent : Symbol(FunctionComponent, Decl(genericCallInferenceInConditionalTypes1.ts, 4, 2))
26+
27+
T extends FunctionComponent<infer P> ? P : {};
28+
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 8, 20))
29+
>FunctionComponent : Symbol(FunctionComponent, Decl(genericCallInferenceInConditionalTypes1.ts, 4, 2))
30+
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 9, 35))
31+
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 9, 35))
32+
33+
type PropsWithoutRef<P> = P extends any
34+
>PropsWithoutRef : Symbol(PropsWithoutRef, Decl(genericCallInferenceInConditionalTypes1.ts, 9, 48))
35+
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 11, 21))
36+
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 11, 21))
37+
38+
? "ref" extends keyof P
39+
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 11, 21))
40+
41+
? Omit<P, "ref">
42+
>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --))
43+
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 11, 21))
44+
45+
: P
46+
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 11, 21))
47+
48+
: P;
49+
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 11, 21))
50+
51+
type ComponentPropsWithoutRef<T extends FunctionComponent<any>> =
52+
>ComponentPropsWithoutRef : Symbol(ComponentPropsWithoutRef, Decl(genericCallInferenceInConditionalTypes1.ts, 15, 6))
53+
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 17, 30))
54+
>FunctionComponent : Symbol(FunctionComponent, Decl(genericCallInferenceInConditionalTypes1.ts, 4, 2))
55+
56+
PropsWithoutRef<ComponentProps<T>>;
57+
>PropsWithoutRef : Symbol(PropsWithoutRef, Decl(genericCallInferenceInConditionalTypes1.ts, 9, 48))
58+
>ComponentProps : Symbol(ComponentProps, Decl(genericCallInferenceInConditionalTypes1.ts, 6, 50))
59+
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 17, 30))
60+
61+
declare function forwardRef<T, P>(
62+
>forwardRef : Symbol(forwardRef, Decl(genericCallInferenceInConditionalTypes1.ts, 18, 37))
63+
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 20, 28))
64+
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 20, 30))
65+
66+
component: (props: P, ref: Ref<T>) => unknown,
67+
>component : Symbol(component, Decl(genericCallInferenceInConditionalTypes1.ts, 20, 34))
68+
>props : Symbol(props, Decl(genericCallInferenceInConditionalTypes1.ts, 21, 14))
69+
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 20, 30))
70+
>ref : Symbol(ref, Decl(genericCallInferenceInConditionalTypes1.ts, 21, 23))
71+
>Ref : Symbol(Ref, Decl(genericCallInferenceInConditionalTypes1.ts, 0, 0))
72+
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 20, 28))
73+
74+
): (props: P & { ref?: Ref<T> }) => unknown;
75+
>props : Symbol(props, Decl(genericCallInferenceInConditionalTypes1.ts, 22, 4))
76+
>P : Symbol(P, Decl(genericCallInferenceInConditionalTypes1.ts, 20, 30))
77+
>ref : Symbol(ref, Decl(genericCallInferenceInConditionalTypes1.ts, 22, 16))
78+
>Ref : Symbol(Ref, Decl(genericCallInferenceInConditionalTypes1.ts, 0, 0))
79+
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 20, 28))
80+
81+
const ComponentWithForwardRef = forwardRef(
82+
>ComponentWithForwardRef : Symbol(ComponentWithForwardRef, Decl(genericCallInferenceInConditionalTypes1.ts, 24, 5))
83+
>forwardRef : Symbol(forwardRef, Decl(genericCallInferenceInConditionalTypes1.ts, 18, 37))
84+
85+
<T extends FunctionComponent<any>>(
86+
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 25, 3))
87+
>FunctionComponent : Symbol(FunctionComponent, Decl(genericCallInferenceInConditionalTypes1.ts, 4, 2))
88+
89+
props: ComponentPropsWithoutRef<T>,
90+
>props : Symbol(props, Decl(genericCallInferenceInConditionalTypes1.ts, 25, 37))
91+
>ComponentPropsWithoutRef : Symbol(ComponentPropsWithoutRef, Decl(genericCallInferenceInConditionalTypes1.ts, 15, 6))
92+
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 25, 3))
93+
94+
ref: Ref<HTMLElement>,
95+
>ref : Symbol(ref, Decl(genericCallInferenceInConditionalTypes1.ts, 26, 39))
96+
>Ref : Symbol(Ref, Decl(genericCallInferenceInConditionalTypes1.ts, 0, 0))
97+
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
98+
99+
) => {
100+
return null;
101+
},
102+
);
103+
104+
type Test<T> = T extends { component?: infer Component }
105+
>Test : Symbol(Test, Decl(genericCallInferenceInConditionalTypes1.ts, 31, 2))
106+
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 33, 10))
107+
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 33, 10))
108+
>component : Symbol(component, Decl(genericCallInferenceInConditionalTypes1.ts, 33, 26))
109+
>Component : Symbol(Component, Decl(genericCallInferenceInConditionalTypes1.ts, 33, 44))
110+
111+
? Component extends FunctionComponent<any>
112+
>Component : Symbol(Component, Decl(genericCallInferenceInConditionalTypes1.ts, 33, 44))
113+
>FunctionComponent : Symbol(FunctionComponent, Decl(genericCallInferenceInConditionalTypes1.ts, 4, 2))
114+
115+
? ComponentProps<Component>
116+
>ComponentProps : Symbol(ComponentProps, Decl(genericCallInferenceInConditionalTypes1.ts, 6, 50))
117+
>Component : Symbol(Component, Decl(genericCallInferenceInConditionalTypes1.ts, 33, 44))
118+
119+
: never
120+
: never;
121+
122+
// the first one here has a chance to pollute the cache
123+
type Result1 = ComponentProps<typeof ComponentWithForwardRef>;
124+
>Result1 : Symbol(Result1, Decl(genericCallInferenceInConditionalTypes1.ts, 37, 10))
125+
>ComponentProps : Symbol(ComponentProps, Decl(genericCallInferenceInConditionalTypes1.ts, 6, 50))
126+
>ComponentWithForwardRef : Symbol(ComponentWithForwardRef, Decl(genericCallInferenceInConditionalTypes1.ts, 24, 5))
127+
128+
// that could be incorrectly reused by this one
129+
type Result2 = Test<{ component: typeof ComponentWithForwardRef }>; // no `T` leak
130+
>Result2 : Symbol(Result2, Decl(genericCallInferenceInConditionalTypes1.ts, 40, 62))
131+
>Test : Symbol(Test, Decl(genericCallInferenceInConditionalTypes1.ts, 31, 2))
132+
>component : Symbol(component, Decl(genericCallInferenceInConditionalTypes1.ts, 42, 21))
133+
>ComponentWithForwardRef : Symbol(ComponentWithForwardRef, Decl(genericCallInferenceInConditionalTypes1.ts, 24, 5))
134+
135+
// same as ComponentWithForwardRef above but using a resolved signature instead of a direct inferred result of `forwardRef`
136+
declare const ComponentWithForwardRef2: <T extends FunctionComponent<any>>(
137+
>ComponentWithForwardRef2 : Symbol(ComponentWithForwardRef2, Decl(genericCallInferenceInConditionalTypes1.ts, 45, 13))
138+
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 45, 41))
139+
>FunctionComponent : Symbol(FunctionComponent, Decl(genericCallInferenceInConditionalTypes1.ts, 4, 2))
140+
141+
props: PropsWithoutRef<ComponentProps<T>> & {
142+
>props : Symbol(props, Decl(genericCallInferenceInConditionalTypes1.ts, 45, 75))
143+
>PropsWithoutRef : Symbol(PropsWithoutRef, Decl(genericCallInferenceInConditionalTypes1.ts, 9, 48))
144+
>ComponentProps : Symbol(ComponentProps, Decl(genericCallInferenceInConditionalTypes1.ts, 6, 50))
145+
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 45, 41))
146+
147+
className?: string;
148+
>className : Symbol(className, Decl(genericCallInferenceInConditionalTypes1.ts, 46, 47))
149+
150+
as?: T | undefined;
151+
>as : Symbol(as, Decl(genericCallInferenceInConditionalTypes1.ts, 47, 23))
152+
>T : Symbol(T, Decl(genericCallInferenceInConditionalTypes1.ts, 45, 41))
153+
154+
} & {
155+
ref?: Ref<HTMLElement> | undefined;
156+
>ref : Symbol(ref, Decl(genericCallInferenceInConditionalTypes1.ts, 49, 7))
157+
>Ref : Symbol(Ref, Decl(genericCallInferenceInConditionalTypes1.ts, 0, 0))
158+
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
159+
160+
},
161+
) => unknown;
162+
163+
type Result3 = ComponentProps<typeof ComponentWithForwardRef2>;
164+
>Result3 : Symbol(Result3, Decl(genericCallInferenceInConditionalTypes1.ts, 52, 13))
165+
>ComponentProps : Symbol(ComponentProps, Decl(genericCallInferenceInConditionalTypes1.ts, 6, 50))
166+
>ComponentWithForwardRef2 : Symbol(ComponentWithForwardRef2, Decl(genericCallInferenceInConditionalTypes1.ts, 45, 13))
167+
168+
type Result4 = Test<{ component: typeof ComponentWithForwardRef2 }>;
169+
>Result4 : Symbol(Result4, Decl(genericCallInferenceInConditionalTypes1.ts, 54, 63))
170+
>Test : Symbol(Test, Decl(genericCallInferenceInConditionalTypes1.ts, 31, 2))
171+
>component : Symbol(component, Decl(genericCallInferenceInConditionalTypes1.ts, 55, 21))
172+
>ComponentWithForwardRef2 : Symbol(ComponentWithForwardRef2, Decl(genericCallInferenceInConditionalTypes1.ts, 45, 13))
173+

0 commit comments

Comments
 (0)