Skip to content

Commit 1ed8ed6

Browse files
Preserve original type parameter names more often when shadowed (#55820)
Co-authored-by: Wesley Wigham <[email protected]>
1 parent b2fc883 commit 1ed8ed6

File tree

162 files changed

+1176
-619
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

162 files changed

+1176
-619
lines changed

src/compiler/checker.ts

Lines changed: 58 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6623,8 +6623,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
66236623
}
66246624
if (
66256625
context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams &&
6626-
type.flags & TypeFlags.TypeParameter &&
6627-
!isTypeSymbolAccessible(type.symbol, context.enclosingDeclaration)
6626+
type.flags & TypeFlags.TypeParameter
66286627
) {
66296628
const name = typeParameterToName(type, context);
66306629
context.approximateLength += idText(name).length;
@@ -7527,7 +7526,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
75277526
&& signature.declaration
75287527
&& signature.declaration !== context.enclosingDeclaration
75297528
&& !isInJSFile(signature.declaration)
7530-
&& some(expandedParams)
7529+
&& (some(expandedParams) || some(signature.typeParameters))
75317530
) {
75327531
// As a performance optimization, reuse the same fake scope within this chain.
75337532
// This is especially needed when we are working on an excessively deep type;
@@ -7545,32 +7544,64 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
75457544
// Note that we only check the most immediate enclosingDeclaration; the only place we
75467545
// could potentially add another fake scope into the chain is right here, so we don't
75477546
// traverse all ancestors.
7548-
const existingFakeScope = getNodeLinks(context.enclosingDeclaration).fakeScopeForSignatureDeclaration ? context.enclosingDeclaration : undefined;
7549-
Debug.assertOptionalNode(existingFakeScope, isBlock);
7547+
pushFakeScope(
7548+
"params",
7549+
add => {
7550+
for (const param of expandedParams) {
7551+
add(param.escapedName, param);
7552+
}
7553+
},
7554+
);
75507555

7551-
const locals = existingFakeScope?.locals ?? createSymbolTable();
7556+
if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams) {
7557+
// TODO(jakebailey): should this instead be done before walking type parameters?
7558+
pushFakeScope(
7559+
"typeParams",
7560+
add => {
7561+
for (const typeParam of signature.typeParameters ?? emptyArray) {
7562+
const typeParamName = typeParameterToName(typeParam, context).escapedText;
7563+
add(typeParamName, typeParam.symbol);
7564+
}
7565+
},
7566+
);
7567+
}
75527568

7553-
let newLocals: __String[] | undefined;
7554-
for (const param of expandedParams) {
7555-
if (!locals.has(param.escapedName)) {
7556-
newLocals = append(newLocals, param.escapedName);
7557-
locals.set(param.escapedName, param);
7569+
function pushFakeScope(kind: "params" | "typeParams", addAll: (addSymbol: (name: __String, symbol: Symbol) => void) => void) {
7570+
// We only ever need to look two declarations upward.
7571+
Debug.assert(context.enclosingDeclaration);
7572+
let existingFakeScope: Node | undefined;
7573+
if (getNodeLinks(context.enclosingDeclaration).fakeScopeForSignatureDeclaration === kind) {
7574+
existingFakeScope = context.enclosingDeclaration;
75587575
}
7559-
}
7576+
else if (context.enclosingDeclaration.parent && getNodeLinks(context.enclosingDeclaration.parent).fakeScopeForSignatureDeclaration === kind) {
7577+
existingFakeScope = context.enclosingDeclaration.parent;
7578+
}
7579+
Debug.assertOptionalNode(existingFakeScope, isBlock);
75607580

7561-
if (newLocals) {
7562-
function removeNewLocals() {
7581+
const locals = existingFakeScope?.locals ?? createSymbolTable();
7582+
let newLocals: __String[] | undefined;
7583+
addAll((name, symbol) => {
7584+
if (!locals.has(name)) {
7585+
newLocals = append(newLocals, name);
7586+
locals.set(name, symbol);
7587+
}
7588+
});
7589+
if (!newLocals) return;
7590+
7591+
const oldCleanup = cleanup;
7592+
function undo() {
75637593
forEach(newLocals, s => locals.delete(s));
7594+
oldCleanup?.();
75647595
}
75657596

75667597
if (existingFakeScope) {
7567-
cleanup = removeNewLocals;
7598+
cleanup = undo;
75687599
}
75697600
else {
75707601
// Use a Block for this; the type of the node doesn't matter so long as it
75717602
// has locals, and this is cheaper/easier than using a function-ish Node.
75727603
const fakeScope = parseNodeFactory.createBlock(emptyArray);
7573-
getNodeLinks(fakeScope).fakeScopeForSignatureDeclaration = true;
7604+
getNodeLinks(fakeScope).fakeScopeForSignatureDeclaration = kind;
75747605
fakeScope.locals = locals;
75757606

75767607
const saveEnclosingDeclaration = context.enclosingDeclaration;
@@ -7579,7 +7610,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
75797610

75807611
cleanup = () => {
75817612
context.enclosingDeclaration = saveEnclosingDeclaration;
7582-
removeNewLocals();
7613+
undo();
75837614
};
75847615
}
75857616
}
@@ -8127,13 +8158,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
81278158
}
81288159
}
81298160

8130-
function typeParameterShadowsNameInScope(escapedName: __String, context: NodeBuilderContext, type: TypeParameter) {
8161+
function typeParameterShadowsOtherTypeParameterInScope(escapedName: __String, context: NodeBuilderContext, type: TypeParameter) {
81318162
const result = resolveName(context.enclosingDeclaration, escapedName, SymbolFlags.Type, /*nameNotFoundMessage*/ undefined, escapedName, /*isUse*/ false);
8132-
if (result) {
8133-
if (result.flags & SymbolFlags.TypeParameter && result === type.symbol) {
8134-
return false;
8135-
}
8136-
return true;
8163+
if (result && result.flags & SymbolFlags.TypeParameter) {
8164+
return result !== type.symbol;
81378165
}
81388166
return false;
81398167
}
@@ -8153,7 +8181,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
81538181
const rawtext = result.escapedText as string;
81548182
let i = context.typeParameterNamesByTextNextNameCount?.get(rawtext) || 0;
81558183
let text = rawtext;
8156-
while (context.typeParameterNamesByText?.has(text) || typeParameterShadowsNameInScope(text as __String, context, type)) {
8184+
while (context.typeParameterNamesByText?.has(text) || typeParameterShadowsOtherTypeParameterInScope(text as __String, context, type)) {
81578185
i++;
81588186
text = `${rawtext}_${i}`;
81598187
}
@@ -8166,7 +8194,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
81668194
// `i` we've used thus far, to save work later
81678195
(context.typeParameterNamesByTextNextNameCount ||= new Map()).set(rawtext, i);
81688196
(context.typeParameterNames ||= new Map()).set(getTypeId(type), result);
8169-
(context.typeParameterNamesByText ||= new Set()).add(rawtext);
8197+
(context.typeParameterNamesByText ||= new Set()).add(text);
81708198
}
81718199
return result;
81728200
}
@@ -8345,7 +8373,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
83458373
}
83468374

83478375
function getEnclosingDeclarationIgnoringFakeScope(enclosingDeclaration: Node) {
8348-
return getNodeLinks(enclosingDeclaration).fakeScopeForSignatureDeclaration ? enclosingDeclaration.parent : enclosingDeclaration;
8376+
while (getNodeLinks(enclosingDeclaration).fakeScopeForSignatureDeclaration) {
8377+
enclosingDeclaration = enclosingDeclaration.parent;
8378+
}
8379+
return enclosingDeclaration;
83498380
}
83508381

83518382
/**
@@ -8425,7 +8456,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
84258456
}
84268457
if (isIdentifier(node)) {
84278458
const type = getDeclaredTypeOfSymbol(sym);
8428-
const name = sym.flags & SymbolFlags.TypeParameter && !isTypeSymbolAccessible(type.symbol, context.enclosingDeclaration) ? typeParameterToName(type, context) : factory.cloneNode(node);
8459+
const name = sym.flags & SymbolFlags.TypeParameter ? typeParameterToName(type, context) : factory.cloneNode(node);
84298460
name.symbol = sym; // for quickinfo, which uses identifier symbol information
84308461
return { introducesError, node: setEmitFlags(setOriginalNode(name, node), EmitFlags.NoAsciiEscaping) };
84318462
}

src/compiler/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6047,7 +6047,7 @@ export interface NodeLinks {
60476047
decoratorSignature?: Signature; // Signature for decorator as if invoked by the runtime.
60486048
spreadIndices?: { first: number | undefined, last: number | undefined }; // Indices of first and last spread elements in array literal
60496049
parameterInitializerContainsUndefined?: boolean; // True if this is a parameter declaration whose type annotation contains "undefined".
6050-
fakeScopeForSignatureDeclaration?: boolean; // True if this is a fake scope injected into an enclosing declaration chain.
6050+
fakeScopeForSignatureDeclaration?: "params" | "typeParams"; // If present, this is a fake scope injected into an enclosing declaration chain.
60516051
assertionExpressionType?: Type; // Cached type of the expression of a type assertion
60526052
}
60536053

tests/baselines/reference/assignmentCompatWithCallSignatures.types

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ a = a2;
5656
>a2 : (x: number) => string
5757

5858
t = <T>(x: T) => 1;
59-
>t = <T>(x: T) => 1 : <T_1>(x: T_1) => number
59+
>t = <T>(x: T) => 1 : <T>(x: T) => number
6060
>t : T
61-
><T>(x: T) => 1 : <T_1>(x: T_1) => number
61+
><T>(x: T) => 1 : <T>(x: T) => number
6262
>x : T
6363
>1 : 1
6464

@@ -76,9 +76,9 @@ t = function (x: number) { return ''; }
7676
>'' : ""
7777

7878
a = <T>(x: T) => 1;
79-
>a = <T>(x: T) => 1 : <T_1>(x: T_1) => number
79+
>a = <T>(x: T) => 1 : <T>(x: T) => number
8080
>a : (x: number) => void
81-
><T>(x: T) => 1 : <T_1>(x: T_1) => number
81+
><T>(x: T) => 1 : <T>(x: T) => number
8282
>x : T
8383
>1 : 1
8484

tests/baselines/reference/assignmentCompatWithCallSignatures2.types

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ t = { f: () => 1 };
6868
>1 : 1
6969

7070
t = { f: <T>(x:T) => 1 };
71-
>t = { f: <T>(x:T) => 1 } : { f: <T_1>(x: T_1) => number; }
71+
>t = { f: <T>(x:T) => 1 } : { f: <T>(x: T) => number; }
7272
>t : T
73-
>{ f: <T>(x:T) => 1 } : { f: <T_1>(x: T_1) => number; }
74-
>f : <T_1>(x: T_1) => number
75-
><T>(x:T) => 1 : <T_1>(x: T_1) => number
73+
>{ f: <T>(x:T) => 1 } : { f: <T>(x: T) => number; }
74+
>f : <T>(x: T) => number
75+
><T>(x:T) => 1 : <T>(x: T) => number
7676
>x : T
7777
>1 : 1
7878

@@ -102,11 +102,11 @@ a = { f: () => 1 }
102102
>1 : 1
103103

104104
a = { f: <T>(x: T) => 1 };
105-
>a = { f: <T>(x: T) => 1 } : { f: <T_1>(x: T_1) => number; }
105+
>a = { f: <T>(x: T) => 1 } : { f: <T>(x: T) => number; }
106106
>a : { f(x: number): void; }
107-
>{ f: <T>(x: T) => 1 } : { f: <T_1>(x: T_1) => number; }
108-
>f : <T_1>(x: T_1) => number
109-
><T>(x: T) => 1 : <T_1>(x: T_1) => number
107+
>{ f: <T>(x: T) => 1 } : { f: <T>(x: T) => number; }
108+
>f : <T>(x: T) => number
109+
><T>(x: T) => 1 : <T>(x: T) => number
110110
>x : T
111111
>1 : 1
112112

tests/baselines/reference/assignmentCompatWithCallSignatures3.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ b13 = a13; // ok
355355
>a13 : (x: Base[], y: Derived[]) => Derived[]
356356

357357
var b14: <T>(x: { a: T; b: T }) => T;
358-
>b14 : <T>(x: { a: T; b: T; }) => T
358+
>b14 : <T>(x: { a: T; b: T;}) => T
359359
>x : { a: T; b: T; }
360360
>a : T
361361
>b : T

tests/baselines/reference/assignmentCompatWithCallSignatures4.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ module Errors {
224224
>a12 : (x: Base[], y: Derived2[]) => Derived[]
225225

226226
var b15: <T>(x: { a: T; b: T }) => T;
227-
>b15 : <T>(x: { a: T; b: T; }) => T
227+
>b15 : <T>(x: { a: T; b: T;}) => T
228228
>x : { a: T; b: T; }
229229
>a : T
230230
>b : T
@@ -240,7 +240,7 @@ module Errors {
240240
>a15 : (x: { a: string; b: number; }) => number
241241

242242
var b15a: <T extends Base>(x: { a: T; b: T }) => number;
243-
>b15a : <T extends Base>(x: { a: T; b: T; }) => number
243+
>b15a : <T extends Base>(x: { a: T; b: T;}) => number
244244
>x : { a: T; b: T; }
245245
>a : T
246246
>b : T

tests/baselines/reference/assignmentCompatWithCallSignatures5.types

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,21 +50,21 @@ var a6: <T extends Base>(x: (arg: T) => Derived) => T;
5050
>arg : T
5151

5252
var a11: <T>(x: { foo: T }, y: { foo: T; bar: T }) => Base;
53-
>a11 : <T>(x: { foo: T; }, y: { foo: T; bar: T; }) => Base
53+
>a11 : <T>(x: { foo: T;}, y: { foo: T; bar: T;}) => Base
5454
>x : { foo: T; }
5555
>foo : T
5656
>y : { foo: T; bar: T; }
5757
>foo : T
5858
>bar : T
5959

6060
var a15: <T>(x: { a: T; b: T }) => T[];
61-
>a15 : <T>(x: { a: T; b: T; }) => T[]
61+
>a15 : <T>(x: { a: T; b: T;}) => T[]
6262
>x : { a: T; b: T; }
6363
>a : T
6464
>b : T
6565

6666
var a16: <T extends Base>(x: { a: T; b: T }) => T[];
67-
>a16 : <T extends Base>(x: { a: T; b: T; }) => T[]
67+
>a16 : <T extends Base>(x: { a: T; b: T;}) => T[]
6868
>x : { a: T; b: T; }
6969
>a : T
7070
>b : T
@@ -194,7 +194,7 @@ b6 = a6; // ok
194194
>a6 : <T extends Base>(x: (arg: T) => Derived) => T
195195

196196
var b11: <T, U>(x: { foo: T }, y: { foo: U; bar: U }) => Base;
197-
>b11 : <T, U>(x: { foo: T; }, y: { foo: U; bar: U; }) => Base
197+
>b11 : <T, U>(x: { foo: T;}, y: { foo: U; bar: U;}) => Base
198198
>x : { foo: T; }
199199
>foo : T
200200
>y : { foo: U; bar: U; }
@@ -212,7 +212,7 @@ b11 = a11; // ok
212212
>a11 : <T>(x: { foo: T; }, y: { foo: T; bar: T; }) => Base
213213

214214
var b15: <U, V>(x: { a: U; b: V; }) => U[];
215-
>b15 : <U, V>(x: { a: U; b: V; }) => U[]
215+
>b15 : <U, V>(x: { a: U; b: V;}) => U[]
216216
>x : { a: U; b: V; }
217217
>a : U
218218
>b : V
@@ -228,7 +228,7 @@ b15 = a15; // ok
228228
>a15 : <T>(x: { a: T; b: T; }) => T[]
229229

230230
var b16: <T>(x: { a: T; b: T }) => T[];
231-
>b16 : <T>(x: { a: T; b: T; }) => T[]
231+
>b16 : <T>(x: { a: T; b: T;}) => T[]
232232
>x : { a: T; b: T; }
233233
>a : T
234234
>b : T

tests/baselines/reference/assignmentCompatWithCallSignatures6.types

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,21 +51,21 @@ interface A {
5151
>arg : T
5252

5353
a11: <T>(x: { foo: T }, y: { foo: T; bar: T }) => Base;
54-
>a11 : <T>(x: { foo: T; }, y: { foo: T; bar: T; }) => Base
54+
>a11 : <T>(x: { foo: T;}, y: { foo: T; bar: T;}) => Base
5555
>x : { foo: T; }
5656
>foo : T
5757
>y : { foo: T; bar: T; }
5858
>foo : T
5959
>bar : T
6060

6161
a15: <T>(x: { a: T; b: T }) => T[];
62-
>a15 : <T>(x: { a: T; b: T; }) => T[]
62+
>a15 : <T>(x: { a: T; b: T;}) => T[]
6363
>x : { a: T; b: T; }
6464
>a : T
6565
>b : T
6666

6767
a16: <T extends Base>(x: { a: T; b: T }) => T[];
68-
>a16 : <T extends Base>(x: { a: T; b: T; }) => T[]
68+
>a16 : <T extends Base>(x: { a: T; b: T;}) => T[]
6969
>x : { a: T; b: T; }
7070
>a : T
7171
>b : T
@@ -167,7 +167,7 @@ b5 = x.a5;
167167
>a5 : <T, U>(x: (arg: T) => U) => T
168168

169169
var b11: <T, U>(x: { foo: T }, y: { foo: U; bar: U }) => Base;
170-
>b11 : <T, U>(x: { foo: T; }, y: { foo: U; bar: U; }) => Base
170+
>b11 : <T, U>(x: { foo: T;}, y: { foo: U; bar: U;}) => Base
171171
>x : { foo: T; }
172172
>foo : T
173173
>y : { foo: U; bar: U; }
@@ -189,7 +189,7 @@ b11 = x.a11;
189189
>a11 : <T>(x: { foo: T; }, y: { foo: T; bar: T; }) => Base
190190

191191
var b16: <T>(x: { a: T; b: T }) => T[];
192-
>b16 : <T>(x: { a: T; b: T; }) => T[]
192+
>b16 : <T>(x: { a: T; b: T;}) => T[]
193193
>x : { a: T; b: T; }
194194
>a : T
195195
>b : T

tests/baselines/reference/assignmentCompatWithConstructSignatures3.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ b13 = a13; // ok
355355
>a13 : new (x: Base[], y: Derived[]) => Derived[]
356356

357357
var b14: new <T>(x: { a: T; b: T }) => T;
358-
>b14 : new <T>(x: { a: T; b: T; }) => T
358+
>b14 : new <T>(x: { a: T; b: T;}) => T
359359
>x : { a: T; b: T; }
360360
>a : T
361361
>b : T

tests/baselines/reference/assignmentCompatWithConstructSignatures4.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ module Errors {
224224
>a12 : new (x: Base[], y: Derived2[]) => Derived[]
225225

226226
var b15: new <T>(x: { a: T; b: T }) => T;
227-
>b15 : new <T>(x: { a: T; b: T; }) => T
227+
>b15 : new <T>(x: { a: T; b: T;}) => T
228228
>x : { a: T; b: T; }
229229
>a : T
230230
>b : T
@@ -240,7 +240,7 @@ module Errors {
240240
>a15 : new (x: { a: string; b: number; }) => number
241241

242242
var b15a: new <T extends Base>(x: { a: T; b: T }) => number;
243-
>b15a : new <T extends Base>(x: { a: T; b: T; }) => number
243+
>b15a : new <T extends Base>(x: { a: T; b: T;}) => number
244244
>x : { a: T; b: T; }
245245
>a : T
246246
>b : T

0 commit comments

Comments
 (0)