Skip to content

Commit

Permalink
Remove unnecessary check for misaligned complex rest parameters (#47934)
Browse files Browse the repository at this point in the history
* Remove unnecessary check for misaligned complex rest parameters

* Add tests
  • Loading branch information
ahejlsberg authored Feb 17, 2022
1 parent 1c06ef3 commit 53809d8
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 23 deletions.
4 changes: 0 additions & 4 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17671,10 +17671,6 @@ namespace ts {
if (sourceRestType || targetRestType) {
void instantiateType(sourceRestType || targetRestType, reportUnreliableMarkers);
}
if (sourceRestType && targetRestType && sourceCount !== targetCount) {
// We're not able to relate misaligned complex rest parameters
return Ternary.False;
}

const kind = target.declaration ? target.declaration.kind : SyntaxKind.Unknown;
const strictVariance = !(checkMode & SignatureCheckMode.Callback) && strictFunctionTypes && kind !== SyntaxKind.MethodDeclaration &&
Expand Down
31 changes: 22 additions & 9 deletions tests/baselines/reference/genericRestParameters3.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ tests/cases/conformance/types/rest/genericRestParameters3.ts(17,11): error TS234
tests/cases/conformance/types/rest/genericRestParameters3.ts(18,1): error TS2345: Argument of type '[]' is not assignable to parameter of type '[string] | [number, boolean]'.
Type '[]' is not assignable to type '[number, boolean]'.
Source has 0 element(s) but target requires 2.
tests/cases/conformance/types/rest/genericRestParameters3.ts(22,1): error TS2322: Type '(x: string, ...args: [string] | [number, boolean]) => void' is not assignable to type '(...args: [string, string] | [string, number, boolean]) => void'.
tests/cases/conformance/types/rest/genericRestParameters3.ts(23,1): error TS2322: Type '(x: string, y: string) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
Types of parameters 'y' and 'args' are incompatible.
Type '[string] | [number, boolean]' is not assignable to type '[y: string]'.
Expand All @@ -15,7 +14,6 @@ tests/cases/conformance/types/rest/genericRestParameters3.ts(24,1): error TS2322
Type '[string] | [number, boolean]' is not assignable to type '[y: number, z: boolean]'.
Type '[string]' is not assignable to type '[y: number, z: boolean]'.
Source has 1 element(s) but target requires 2.
tests/cases/conformance/types/rest/genericRestParameters3.ts(25,1): error TS2322: Type '(...args: [string, string] | [string, number, boolean]) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
tests/cases/conformance/types/rest/genericRestParameters3.ts(35,1): error TS2554: Expected 1 arguments, but got 0.
tests/cases/conformance/types/rest/genericRestParameters3.ts(36,21): error TS2345: Argument of type 'number' is not assignable to parameter of type '(...args: CoolArray<any>) => void'.
tests/cases/conformance/types/rest/genericRestParameters3.ts(37,21): error TS2345: Argument of type '<T extends any[]>(cb: (...args: T) => void) => void' is not assignable to parameter of type '(...args: CoolArray<any>) => void'.
Expand All @@ -36,7 +34,7 @@ tests/cases/conformance/types/rest/genericRestParameters3.ts(59,5): error TS2345
Source has 1 element(s) but target requires 2.


==== tests/cases/conformance/types/rest/genericRestParameters3.ts (15 errors) ====
==== tests/cases/conformance/types/rest/genericRestParameters3.ts (13 errors) ====
declare let f1: (x: string, ...args: [string] | [number, boolean]) => void;
declare let f2: (x: string, y: string) => void;
declare let f3: (x: string, y: number, z: boolean) => void;
Expand Down Expand Up @@ -66,9 +64,7 @@ tests/cases/conformance/types/rest/genericRestParameters3.ts(59,5): error TS2345

f2 = f1;
f3 = f1;
f4 = f1; // Error, misaligned complex rest types
~~
!!! error TS2322: Type '(x: string, ...args: [string] | [number, boolean]) => void' is not assignable to type '(...args: [string, string] | [string, number, boolean]) => void'.
f4 = f1;
f1 = f2; // Error
~~
!!! error TS2322: Type '(x: string, y: string) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
Expand All @@ -83,9 +79,7 @@ tests/cases/conformance/types/rest/genericRestParameters3.ts(59,5): error TS2345
!!! error TS2322: Type '[string] | [number, boolean]' is not assignable to type '[y: number, z: boolean]'.
!!! error TS2322: Type '[string]' is not assignable to type '[y: number, z: boolean]'.
!!! error TS2322: Source has 1 element(s) but target requires 2.
f1 = f4; // Error, misaligned complex rest types
~~
!!! error TS2322: Type '(...args: [string, string] | [string, number, boolean]) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
f1 = f4;

// Repro from #26110

Expand Down Expand Up @@ -159,4 +153,23 @@ tests/cases/conformance/types/rest/genericRestParameters3.ts(59,5): error TS2345
declare function foo2(...args: string[] | number[]): void;
let x2: ReadonlyArray<string> = ["hello"];
foo2(...x2);

// Repros from #47754

type RestParams = [y: string] | [y: number];

type Signature = (x: string, ...rest: RestParams) => void;

type MergedParams = Parameters<Signature>; // [x: string, y: string] | [x: string, y: number]

declare let ff1: (...rest: [string, string] | [string, number]) => void;
declare let ff2: (x: string, ...rest: [string] | [number]) => void;

ff1 = ff2;
ff2 = ff1;

function ff3<A extends unknown[]>(s1: (...args: [x: string, ...rest: A | [number]]) => void, s2: (x: string, ...rest: A | [number]) => void) {
s1 = s2;
s2 = s1;
}

39 changes: 35 additions & 4 deletions tests/baselines/reference/genericRestParameters3.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ f1("foo"); // Error

f2 = f1;
f3 = f1;
f4 = f1; // Error, misaligned complex rest types
f4 = f1;
f1 = f2; // Error
f1 = f3; // Error
f1 = f4; // Error, misaligned complex rest types
f1 = f4;

// Repro from #26110

Expand Down Expand Up @@ -64,6 +64,25 @@ hmm("what"); // no error? A = [] | [number, string] ?
declare function foo2(...args: string[] | number[]): void;
let x2: ReadonlyArray<string> = ["hello"];
foo2(...x2);

// Repros from #47754

type RestParams = [y: string] | [y: number];

type Signature = (x: string, ...rest: RestParams) => void;

type MergedParams = Parameters<Signature>; // [x: string, y: string] | [x: string, y: number]

declare let ff1: (...rest: [string, string] | [string, number]) => void;
declare let ff2: (x: string, ...rest: [string] | [number]) => void;

ff1 = ff2;
ff2 = ff1;

function ff3<A extends unknown[]>(s1: (...args: [x: string, ...rest: A | [number]]) => void, s2: (x: string, ...rest: A | [number]) => void) {
s1 = s2;
s2 = s1;
}


//// [genericRestParameters3.js]
Expand All @@ -87,10 +106,10 @@ f1("foo", 10); // Error
f1("foo"); // Error
f2 = f1;
f3 = f1;
f4 = f1; // Error, misaligned complex rest types
f4 = f1;
f1 = f2; // Error
f1 = f3; // Error
f1 = f4; // Error, misaligned complex rest types
f1 = f4;
foo(); // Error
foo(100); // Error
foo(foo); // Error
Expand All @@ -112,6 +131,12 @@ hmm(1, "s"); // okay, A = [1, "s"]
hmm("what"); // no error? A = [] | [number, string] ?
var x2 = ["hello"];
foo2.apply(void 0, x2);
ff1 = ff2;
ff2 = ff1;
function ff3(s1, s2) {
s1 = s2;
s2 = s1;
}


//// [genericRestParameters3.d.ts]
Expand All @@ -135,3 +160,9 @@ declare const ca: CoolArray<number>;
declare function hmm<A extends [] | [number, string]>(...args: A): void;
declare function foo2(...args: string[] | number[]): void;
declare let x2: ReadonlyArray<string>;
declare type RestParams = [y: string] | [y: number];
declare type Signature = (x: string, ...rest: RestParams) => void;
declare type MergedParams = Parameters<Signature>;
declare let ff1: (...rest: [string, string] | [string, number]) => void;
declare let ff2: (x: string, ...rest: [string] | [number]) => void;
declare function ff3<A extends unknown[]>(s1: (...args: [x: string, ...rest: A | [number]]) => void, s2: (x: string, ...rest: A | [number]) => void): void;
57 changes: 55 additions & 2 deletions tests/baselines/reference/genericRestParameters3.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ f3 = f1;
>f3 : Symbol(f3, Decl(genericRestParameters3.ts, 2, 11))
>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11))

f4 = f1; // Error, misaligned complex rest types
f4 = f1;
>f4 : Symbol(f4, Decl(genericRestParameters3.ts, 3, 11))
>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11))

Expand All @@ -79,7 +79,7 @@ f1 = f3; // Error
>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11))
>f3 : Symbol(f3, Decl(genericRestParameters3.ts, 2, 11))

f1 = f4; // Error, misaligned complex rest types
f1 = f4;
>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11))
>f4 : Symbol(f4, Decl(genericRestParameters3.ts, 3, 11))

Expand Down Expand Up @@ -190,3 +190,56 @@ foo2(...x2);
>foo2 : Symbol(foo2, Decl(genericRestParameters3.ts, 58, 12))
>x2 : Symbol(x2, Decl(genericRestParameters3.ts, 63, 3))

// Repros from #47754

type RestParams = [y: string] | [y: number];
>RestParams : Symbol(RestParams, Decl(genericRestParameters3.ts, 64, 12))

type Signature = (x: string, ...rest: RestParams) => void;
>Signature : Symbol(Signature, Decl(genericRestParameters3.ts, 68, 44))
>x : Symbol(x, Decl(genericRestParameters3.ts, 70, 18))
>rest : Symbol(rest, Decl(genericRestParameters3.ts, 70, 28))
>RestParams : Symbol(RestParams, Decl(genericRestParameters3.ts, 64, 12))

type MergedParams = Parameters<Signature>; // [x: string, y: string] | [x: string, y: number]
>MergedParams : Symbol(MergedParams, Decl(genericRestParameters3.ts, 70, 58))
>Parameters : Symbol(Parameters, Decl(lib.es5.d.ts, --, --))
>Signature : Symbol(Signature, Decl(genericRestParameters3.ts, 68, 44))

declare let ff1: (...rest: [string, string] | [string, number]) => void;
>ff1 : Symbol(ff1, Decl(genericRestParameters3.ts, 74, 11))
>rest : Symbol(rest, Decl(genericRestParameters3.ts, 74, 18))

declare let ff2: (x: string, ...rest: [string] | [number]) => void;
>ff2 : Symbol(ff2, Decl(genericRestParameters3.ts, 75, 11))
>x : Symbol(x, Decl(genericRestParameters3.ts, 75, 18))
>rest : Symbol(rest, Decl(genericRestParameters3.ts, 75, 28))

ff1 = ff2;
>ff1 : Symbol(ff1, Decl(genericRestParameters3.ts, 74, 11))
>ff2 : Symbol(ff2, Decl(genericRestParameters3.ts, 75, 11))

ff2 = ff1;
>ff2 : Symbol(ff2, Decl(genericRestParameters3.ts, 75, 11))
>ff1 : Symbol(ff1, Decl(genericRestParameters3.ts, 74, 11))

function ff3<A extends unknown[]>(s1: (...args: [x: string, ...rest: A | [number]]) => void, s2: (x: string, ...rest: A | [number]) => void) {
>ff3 : Symbol(ff3, Decl(genericRestParameters3.ts, 78, 10))
>A : Symbol(A, Decl(genericRestParameters3.ts, 80, 13))
>s1 : Symbol(s1, Decl(genericRestParameters3.ts, 80, 34))
>args : Symbol(args, Decl(genericRestParameters3.ts, 80, 39))
>A : Symbol(A, Decl(genericRestParameters3.ts, 80, 13))
>s2 : Symbol(s2, Decl(genericRestParameters3.ts, 80, 92))
>x : Symbol(x, Decl(genericRestParameters3.ts, 80, 98))
>rest : Symbol(rest, Decl(genericRestParameters3.ts, 80, 108))
>A : Symbol(A, Decl(genericRestParameters3.ts, 80, 13))

s1 = s2;
>s1 : Symbol(s1, Decl(genericRestParameters3.ts, 80, 34))
>s2 : Symbol(s2, Decl(genericRestParameters3.ts, 80, 92))

s2 = s1;
>s2 : Symbol(s2, Decl(genericRestParameters3.ts, 80, 92))
>s1 : Symbol(s1, Decl(genericRestParameters3.ts, 80, 34))
}

55 changes: 53 additions & 2 deletions tests/baselines/reference/genericRestParameters3.types
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ f3 = f1;
>f3 : (x: string, y: number, z: boolean) => void
>f1 : (x: string, ...args: [string] | [number, boolean]) => void

f4 = f1; // Error, misaligned complex rest types
f4 = f1;
>f4 = f1 : (x: string, ...args: [string] | [number, boolean]) => void
>f4 : (...args: [string, string] | [string, number, boolean]) => void
>f1 : (x: string, ...args: [string] | [number, boolean]) => void
Expand All @@ -108,7 +108,7 @@ f1 = f3; // Error
>f1 : (x: string, ...args: [string] | [number, boolean]) => void
>f3 : (x: string, y: number, z: boolean) => void

f1 = f4; // Error, misaligned complex rest types
f1 = f4;
>f1 = f4 : (...args: [string, string] | [string, number, boolean]) => void
>f1 : (x: string, ...args: [string] | [number, boolean]) => void
>f4 : (...args: [string, string] | [string, number, boolean]) => void
Expand Down Expand Up @@ -227,3 +227,54 @@ foo2(...x2);
>...x2 : string
>x2 : readonly string[]

// Repros from #47754

type RestParams = [y: string] | [y: number];
>RestParams : RestParams

type Signature = (x: string, ...rest: RestParams) => void;
>Signature : Signature
>x : string
>rest : RestParams

type MergedParams = Parameters<Signature>; // [x: string, y: string] | [x: string, y: number]
>MergedParams : [x: string, y: string] | [x: string, y: number]

declare let ff1: (...rest: [string, string] | [string, number]) => void;
>ff1 : (...rest: [string, string] | [string, number]) => void
>rest : [string, string] | [string, number]

declare let ff2: (x: string, ...rest: [string] | [number]) => void;
>ff2 : (x: string, ...rest: [string] | [number]) => void
>x : string
>rest : [string] | [number]

ff1 = ff2;
>ff1 = ff2 : (x: string, ...rest: [string] | [number]) => void
>ff1 : (...rest: [string, string] | [string, number]) => void
>ff2 : (x: string, ...rest: [string] | [number]) => void

ff2 = ff1;
>ff2 = ff1 : (...rest: [string, string] | [string, number]) => void
>ff2 : (x: string, ...rest: [string] | [number]) => void
>ff1 : (...rest: [string, string] | [string, number]) => void

function ff3<A extends unknown[]>(s1: (...args: [x: string, ...rest: A | [number]]) => void, s2: (x: string, ...rest: A | [number]) => void) {
>ff3 : <A extends unknown[]>(s1: (...args: [x: string, ...rest: A | [number]]) => void, s2: (x: string, ...rest: A | [number]) => void) => void
>s1 : (...args: [x: string, ...rest: A | [number]]) => void
>args : [string, number] | [x: string, ...rest: A]
>s2 : (x: string, ...rest: A | [number]) => void
>x : string
>rest : [number] | A

s1 = s2;
>s1 = s2 : (x: string, ...rest: [number] | A) => void
>s1 : (...args: [string, number] | [x: string, ...rest: A]) => void
>s2 : (x: string, ...rest: [number] | A) => void

s2 = s1;
>s2 = s1 : (...args: [string, number] | [x: string, ...rest: A]) => void
>s2 : (x: string, ...rest: [number] | A) => void
>s1 : (...args: [string, number] | [x: string, ...rest: A]) => void
}

23 changes: 21 additions & 2 deletions tests/cases/conformance/types/rest/genericRestParameters3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ f1("foo"); // Error

f2 = f1;
f3 = f1;
f4 = f1; // Error, misaligned complex rest types
f4 = f1;
f1 = f2; // Error
f1 = f3; // Error
f1 = f4; // Error, misaligned complex rest types
f1 = f4;

// Repro from #26110

Expand Down Expand Up @@ -66,3 +66,22 @@ hmm("what"); // no error? A = [] | [number, string] ?
declare function foo2(...args: string[] | number[]): void;
let x2: ReadonlyArray<string> = ["hello"];
foo2(...x2);

// Repros from #47754

type RestParams = [y: string] | [y: number];

type Signature = (x: string, ...rest: RestParams) => void;

type MergedParams = Parameters<Signature>; // [x: string, y: string] | [x: string, y: number]

declare let ff1: (...rest: [string, string] | [string, number]) => void;
declare let ff2: (x: string, ...rest: [string] | [number]) => void;

ff1 = ff2;
ff2 = ff1;

function ff3<A extends unknown[]>(s1: (...args: [x: string, ...rest: A | [number]]) => void, s2: (x: string, ...rest: A | [number]) => void) {
s1 = s2;
s2 = s1;
}

0 comments on commit 53809d8

Please sign in to comment.