Skip to content

Commit 2ab9e7e

Browse files
authored
fix(53011): Illegal declaration file can be emitted (duplicate parameter names) when spreading tuples into parameter positions (#53028)
1 parent d681520 commit 2ab9e7e

File tree

5 files changed

+160
-3
lines changed

5 files changed

+160
-3
lines changed

src/compiler/checker.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12644,11 +12644,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1264412644

1264512645
function expandSignatureParametersWithTupleMembers(restType: TupleTypeReference, restIndex: number) {
1264612646
const elementTypes = getTypeArguments(restType);
12647-
const associatedNames = restType.target.labeledElementDeclarations;
12647+
const associatedNames = getUniqAssociatedNamesFromTupleType(restType);
1264812648
const restParams = map(elementTypes, (t, i) => {
1264912649
// Lookup the label from the individual tuple passed in before falling back to the signature `rest` parameter name
12650-
const tupleLabelName = !!associatedNames && getTupleElementLabel(associatedNames[i]);
12651-
const name = tupleLabelName || getParameterNameAtPosition(sig, restIndex + i, restType);
12650+
const name = associatedNames && associatedNames[i] ? associatedNames[i] :
12651+
getParameterNameAtPosition(sig, restIndex + i, restType);
1265212652
const flags = restType.target.elementFlags[i];
1265312653
const checkFlags = flags & ElementFlags.Variable ? CheckFlags.RestParameter :
1265412654
flags & ElementFlags.Optional ? CheckFlags.OptionalParameter : 0;
@@ -12658,6 +12658,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1265812658
});
1265912659
return concatenate(sig.parameters.slice(0, restIndex), restParams);
1266012660
}
12661+
12662+
function getUniqAssociatedNamesFromTupleType(type: TupleTypeReference) {
12663+
const associatedNamesMap = new Map<__String, number>();
12664+
return map(type.target.labeledElementDeclarations, labeledElement => {
12665+
const name = getTupleElementLabel(labeledElement);
12666+
const prevCounter = associatedNamesMap.get(name);
12667+
if (prevCounter === undefined) {
12668+
associatedNamesMap.set(name, 1);
12669+
return name;
12670+
}
12671+
else {
12672+
associatedNamesMap.set(name, prevCounter + 1);
12673+
return `${name}_${prevCounter}` as __String;
12674+
}
12675+
});
12676+
}
1266112677
}
1266212678

1266312679
function getDefaultConstructSignatures(classType: InterfaceType): Signature[] {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//// [spreadParameterTupleType.ts]
2+
function f1() {
3+
type A = [s: string];
4+
type C = [...A, ...A];
5+
6+
return function fn(...args: C) { }
7+
}
8+
9+
function f2() {
10+
type A = [a: string];
11+
type B = [b: string];
12+
type C = [c: string];
13+
type D = [...A, ...A, ...B, ...A, ...B, ...B, ...A, ...C];
14+
15+
return function fn(...args: D) { }
16+
}
17+
18+
19+
//// [spreadParameterTupleType.js]
20+
function f1() {
21+
return function fn() {
22+
var args = [];
23+
for (var _i = 0; _i < arguments.length; _i++) {
24+
args[_i] = arguments[_i];
25+
}
26+
};
27+
}
28+
function f2() {
29+
return function fn() {
30+
var args = [];
31+
for (var _i = 0; _i < arguments.length; _i++) {
32+
args[_i] = arguments[_i];
33+
}
34+
};
35+
}
36+
37+
38+
//// [spreadParameterTupleType.d.ts]
39+
declare function f1(): (s: string, s_1: string) => void;
40+
declare function f2(): (a: string, a_1: string, b: string, a_2: string, b_1: string, b_2: string, a_3: string, c: string) => void;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
=== tests/cases/compiler/spreadParameterTupleType.ts ===
2+
function f1() {
3+
>f1 : Symbol(f1, Decl(spreadParameterTupleType.ts, 0, 0))
4+
5+
type A = [s: string];
6+
>A : Symbol(A, Decl(spreadParameterTupleType.ts, 0, 15))
7+
8+
type C = [...A, ...A];
9+
>C : Symbol(C, Decl(spreadParameterTupleType.ts, 1, 25))
10+
>A : Symbol(A, Decl(spreadParameterTupleType.ts, 0, 15))
11+
>A : Symbol(A, Decl(spreadParameterTupleType.ts, 0, 15))
12+
13+
return function fn(...args: C) { }
14+
>fn : Symbol(fn, Decl(spreadParameterTupleType.ts, 4, 10))
15+
>args : Symbol(args, Decl(spreadParameterTupleType.ts, 4, 23))
16+
>C : Symbol(C, Decl(spreadParameterTupleType.ts, 1, 25))
17+
}
18+
19+
function f2() {
20+
>f2 : Symbol(f2, Decl(spreadParameterTupleType.ts, 5, 1))
21+
22+
type A = [a: string];
23+
>A : Symbol(A, Decl(spreadParameterTupleType.ts, 7, 15))
24+
25+
type B = [b: string];
26+
>B : Symbol(B, Decl(spreadParameterTupleType.ts, 8, 25))
27+
28+
type C = [c: string];
29+
>C : Symbol(C, Decl(spreadParameterTupleType.ts, 9, 25))
30+
31+
type D = [...A, ...A, ...B, ...A, ...B, ...B, ...A, ...C];
32+
>D : Symbol(D, Decl(spreadParameterTupleType.ts, 10, 25))
33+
>A : Symbol(A, Decl(spreadParameterTupleType.ts, 7, 15))
34+
>A : Symbol(A, Decl(spreadParameterTupleType.ts, 7, 15))
35+
>B : Symbol(B, Decl(spreadParameterTupleType.ts, 8, 25))
36+
>A : Symbol(A, Decl(spreadParameterTupleType.ts, 7, 15))
37+
>B : Symbol(B, Decl(spreadParameterTupleType.ts, 8, 25))
38+
>B : Symbol(B, Decl(spreadParameterTupleType.ts, 8, 25))
39+
>A : Symbol(A, Decl(spreadParameterTupleType.ts, 7, 15))
40+
>C : Symbol(C, Decl(spreadParameterTupleType.ts, 9, 25))
41+
42+
return function fn(...args: D) { }
43+
>fn : Symbol(fn, Decl(spreadParameterTupleType.ts, 13, 10))
44+
>args : Symbol(args, Decl(spreadParameterTupleType.ts, 13, 23))
45+
>D : Symbol(D, Decl(spreadParameterTupleType.ts, 10, 25))
46+
}
47+
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
=== tests/cases/compiler/spreadParameterTupleType.ts ===
2+
function f1() {
3+
>f1 : () => (s: string, s_1: string) => void
4+
5+
type A = [s: string];
6+
>A : [s: string]
7+
8+
type C = [...A, ...A];
9+
>C : [s: string, s: string]
10+
11+
return function fn(...args: C) { }
12+
>function fn(...args: C) { } : (s: string, s_1: string) => void
13+
>fn : (s: string, s_1: string) => void
14+
>args : [s: string, s: string]
15+
}
16+
17+
function f2() {
18+
>f2 : () => (a: string, a_1: string, b: string, a_2: string, b_1: string, b_2: string, a_3: string, c: string) => void
19+
20+
type A = [a: string];
21+
>A : [a: string]
22+
23+
type B = [b: string];
24+
>B : [b: string]
25+
26+
type C = [c: string];
27+
>C : [c: string]
28+
29+
type D = [...A, ...A, ...B, ...A, ...B, ...B, ...A, ...C];
30+
>D : [a: string, a: string, b: string, a: string, b: string, b: string, a: string, c: string]
31+
32+
return function fn(...args: D) { }
33+
>function fn(...args: D) { } : (a: string, a_1: string, b: string, a_2: string, b_1: string, b_2: string, a_3: string, c: string) => void
34+
>fn : (a: string, a_1: string, b: string, a_2: string, b_1: string, b_2: string, a_3: string, c: string) => void
35+
>args : [a: string, a: string, b: string, a: string, b: string, b: string, a: string, c: string]
36+
}
37+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// @declaration: true
2+
3+
function f1() {
4+
type A = [s: string];
5+
type C = [...A, ...A];
6+
7+
return function fn(...args: C) { }
8+
}
9+
10+
function f2() {
11+
type A = [a: string];
12+
type B = [b: string];
13+
type C = [c: string];
14+
type D = [...A, ...A, ...B, ...A, ...B, ...B, ...A, ...C];
15+
16+
return function fn(...args: D) { }
17+
}

0 commit comments

Comments
 (0)