From 36937c785c5ed65dd34067c40c7b421f3e465c6d Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 15 Jun 2022 13:26:28 -0700 Subject: [PATCH 1/4] Add failing test with temporary name --- tests/cases/compiler/issue49383.ts | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/cases/compiler/issue49383.ts diff --git a/tests/cases/compiler/issue49383.ts b/tests/cases/compiler/issue49383.ts new file mode 100644 index 0000000000000..2424b51a25bb6 --- /dev/null +++ b/tests/cases/compiler/issue49383.ts @@ -0,0 +1,2 @@ +function wrap(_: (...args: Args) => void) {} +wrap(({ cancelable } = {}) => {}); From 25bdb8a68709b4443a96fd044f9913e145f71e12 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 29 Jun 2022 15:54:37 -0700 Subject: [PATCH 2/4] Infer rest type without using assignContextualParameterTypes --- src/compiler/checker.ts | 14 ++++++++------ .../reference/getParameterNameAtPosition.types | 2 +- tests/baselines/reference/issue49383.js | 10 ++++++++++ tests/baselines/reference/issue49383.symbols | 12 ++++++++++++ tests/baselines/reference/issue49383.types | 13 +++++++++++++ ...meterWithTupleArgsHasCorrectAssignability.types | 4 ++-- 6 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 tests/baselines/reference/issue49383.js create mode 100644 tests/baselines/reference/issue49383.symbols create mode 100644 tests/baselines/reference/issue49383.types diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8e24fee20606d..204776e64840a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -32475,13 +32475,15 @@ namespace ts { const restType = getEffectiveRestType(context); if (restType && restType.flags & TypeFlags.TypeParameter) { // The contextual signature has a generic rest parameter. We first instantiate the contextual - // signature (without fixing type parameters) and assign types to contextually typed parameters. + // signature (without fixing type parameters) and infer types without calling assignContextualParameterTypes + // (which would fix parameter types). const instantiatedContext = instantiateSignature(context, inferenceContext.nonFixingMapper); - assignContextualParameterTypes(signature, instantiatedContext); - // We then infer from a tuple type representing the parameters that correspond to the contextual - // rest parameter. - const restPos = getParameterCount(context) - 1; - inferTypes(inferenceContext.inferences, getRestTypeAtPosition(signature, restPos), restType); + const instantiatedRestType = getEffectiveRestType(instantiatedContext); + if (instantiatedRestType) { + // We then infer from a tuple type representing the parameters that correspond to the contextual + // rest parameter. + inferTypes(inferenceContext.inferences, getRestTypeAtPosition(signature, len), instantiatedRestType); + } } } diff --git a/tests/baselines/reference/getParameterNameAtPosition.types b/tests/baselines/reference/getParameterNameAtPosition.types index 8eb527b41ec71..d74848ec3b39c 100644 --- a/tests/baselines/reference/getParameterNameAtPosition.types +++ b/tests/baselines/reference/getParameterNameAtPosition.types @@ -23,7 +23,7 @@ declare function fn(implementation?: (...args: Y) => any): Mock cases(fn(opts => { })); >cases(fn(opts => { })) : void >cases : (tester: Tester) => void ->fn(opts => { }) : Mock<[opts: any]> +>fn(opts => { }) : Mock<[opts: any, done: (...args: any[]) => any]> >fn : (implementation?: ((...args: Y) => any) | undefined) => Mock >opts => { } : (opts: any) => void >opts : any diff --git a/tests/baselines/reference/issue49383.js b/tests/baselines/reference/issue49383.js new file mode 100644 index 0000000000000..74062d9a91c32 --- /dev/null +++ b/tests/baselines/reference/issue49383.js @@ -0,0 +1,10 @@ +//// [issue49383.ts] +function wrap(_: (...args: Args) => void) {} +wrap(({ cancelable } = {}) => {}); + + +//// [issue49383.js] +function wrap(_) { } +wrap(function (_a) { + var _b = _a === void 0 ? {} : _a, cancelable = _b.cancelable; +}); diff --git a/tests/baselines/reference/issue49383.symbols b/tests/baselines/reference/issue49383.symbols new file mode 100644 index 0000000000000..9c5303ac034a4 --- /dev/null +++ b/tests/baselines/reference/issue49383.symbols @@ -0,0 +1,12 @@ +=== tests/cases/compiler/issue49383.ts === +function wrap(_: (...args: Args) => void) {} +>wrap : Symbol(wrap, Decl(issue49383.ts, 0, 0)) +>Args : Symbol(Args, Decl(issue49383.ts, 0, 14)) +>_ : Symbol(_, Decl(issue49383.ts, 0, 38)) +>args : Symbol(args, Decl(issue49383.ts, 0, 42)) +>Args : Symbol(Args, Decl(issue49383.ts, 0, 14)) + +wrap(({ cancelable } = {}) => {}); +>wrap : Symbol(wrap, Decl(issue49383.ts, 0, 0)) +>cancelable : Symbol(cancelable, Decl(issue49383.ts, 1, 7)) + diff --git a/tests/baselines/reference/issue49383.types b/tests/baselines/reference/issue49383.types new file mode 100644 index 0000000000000..e626617d32e08 --- /dev/null +++ b/tests/baselines/reference/issue49383.types @@ -0,0 +1,13 @@ +=== tests/cases/compiler/issue49383.ts === +function wrap(_: (...args: Args) => void) {} +>wrap : (_: (...args: Args) => void) => void +>_ : (...args: Args) => void +>args : Args + +wrap(({ cancelable } = {}) => {}); +>wrap(({ cancelable } = {}) => {}) : void +>wrap : (_: (...args: Args) => void) => void +>({ cancelable } = {}) => {} : ({ cancelable }?: { cancelable: any; }) => void +>cancelable : any +>{} : {} + diff --git a/tests/baselines/reference/lambdaParameterWithTupleArgsHasCorrectAssignability.types b/tests/baselines/reference/lambdaParameterWithTupleArgsHasCorrectAssignability.types index 539326ab1c791..558aa6081b146 100644 --- a/tests/baselines/reference/lambdaParameterWithTupleArgsHasCorrectAssignability.types +++ b/tests/baselines/reference/lambdaParameterWithTupleArgsHasCorrectAssignability.types @@ -33,7 +33,7 @@ function consumeClass(c: GenericClass<[string, boolean]>) { } consumeClass(createClass(str => console.log(str.length))); >consumeClass(createClass(str => console.log(str.length))) : void >consumeClass : (c: GenericClass<[string, boolean]>) => void ->createClass(str => console.log(str.length)) : GenericClass<[str: string]> +>createClass(str => console.log(str.length)) : GenericClass<[string, boolean]> >createClass : (f: GenericFunction) => GenericClass >str => console.log(str.length) : (str: string) => void >str : string @@ -49,7 +49,7 @@ consumeClass(createClass(str => console.log(str.length))); consumeClass(createClass((str, _unused_num) => console.log(str.length))); >consumeClass(createClass((str, _unused_num) => console.log(str.length))) : void >consumeClass : (c: GenericClass<[string, boolean]>) => void ->createClass((str, _unused_num) => console.log(str.length)) : GenericClass<[str: string, _unused_num: boolean]> +>createClass((str, _unused_num) => console.log(str.length)) : GenericClass<[string, boolean]> >createClass : (f: GenericFunction) => GenericClass >(str, _unused_num) => console.log(str.length) : (str: string, _unused_num: boolean) => void >str : string From 3ab0071e7809da132be8f87d14ecbdaac9fce573 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 29 Jun 2022 15:56:21 -0700 Subject: [PATCH 3/4] Rename test --- .../{issue49383.js => inferredRestTypeFixedOnce.js} | 4 ++-- .../reference/inferredRestTypeFixedOnce.symbols | 12 ++++++++++++ ...ue49383.types => inferredRestTypeFixedOnce.types} | 2 +- tests/baselines/reference/issue49383.symbols | 12 ------------ .../{issue49383.ts => inferredRestTypeFixedOnce.ts} | 0 5 files changed, 15 insertions(+), 15 deletions(-) rename tests/baselines/reference/{issue49383.js => inferredRestTypeFixedOnce.js} (73%) create mode 100644 tests/baselines/reference/inferredRestTypeFixedOnce.symbols rename tests/baselines/reference/{issue49383.types => inferredRestTypeFixedOnce.types} (85%) delete mode 100644 tests/baselines/reference/issue49383.symbols rename tests/cases/compiler/{issue49383.ts => inferredRestTypeFixedOnce.ts} (100%) diff --git a/tests/baselines/reference/issue49383.js b/tests/baselines/reference/inferredRestTypeFixedOnce.js similarity index 73% rename from tests/baselines/reference/issue49383.js rename to tests/baselines/reference/inferredRestTypeFixedOnce.js index 74062d9a91c32..0142365cc0ced 100644 --- a/tests/baselines/reference/issue49383.js +++ b/tests/baselines/reference/inferredRestTypeFixedOnce.js @@ -1,9 +1,9 @@ -//// [issue49383.ts] +//// [inferredRestTypeFixedOnce.ts] function wrap(_: (...args: Args) => void) {} wrap(({ cancelable } = {}) => {}); -//// [issue49383.js] +//// [inferredRestTypeFixedOnce.js] function wrap(_) { } wrap(function (_a) { var _b = _a === void 0 ? {} : _a, cancelable = _b.cancelable; diff --git a/tests/baselines/reference/inferredRestTypeFixedOnce.symbols b/tests/baselines/reference/inferredRestTypeFixedOnce.symbols new file mode 100644 index 0000000000000..56bc1ab941c98 --- /dev/null +++ b/tests/baselines/reference/inferredRestTypeFixedOnce.symbols @@ -0,0 +1,12 @@ +=== tests/cases/compiler/inferredRestTypeFixedOnce.ts === +function wrap(_: (...args: Args) => void) {} +>wrap : Symbol(wrap, Decl(inferredRestTypeFixedOnce.ts, 0, 0)) +>Args : Symbol(Args, Decl(inferredRestTypeFixedOnce.ts, 0, 14)) +>_ : Symbol(_, Decl(inferredRestTypeFixedOnce.ts, 0, 38)) +>args : Symbol(args, Decl(inferredRestTypeFixedOnce.ts, 0, 42)) +>Args : Symbol(Args, Decl(inferredRestTypeFixedOnce.ts, 0, 14)) + +wrap(({ cancelable } = {}) => {}); +>wrap : Symbol(wrap, Decl(inferredRestTypeFixedOnce.ts, 0, 0)) +>cancelable : Symbol(cancelable, Decl(inferredRestTypeFixedOnce.ts, 1, 7)) + diff --git a/tests/baselines/reference/issue49383.types b/tests/baselines/reference/inferredRestTypeFixedOnce.types similarity index 85% rename from tests/baselines/reference/issue49383.types rename to tests/baselines/reference/inferredRestTypeFixedOnce.types index e626617d32e08..718c82d919121 100644 --- a/tests/baselines/reference/issue49383.types +++ b/tests/baselines/reference/inferredRestTypeFixedOnce.types @@ -1,4 +1,4 @@ -=== tests/cases/compiler/issue49383.ts === +=== tests/cases/compiler/inferredRestTypeFixedOnce.ts === function wrap(_: (...args: Args) => void) {} >wrap : (_: (...args: Args) => void) => void >_ : (...args: Args) => void diff --git a/tests/baselines/reference/issue49383.symbols b/tests/baselines/reference/issue49383.symbols deleted file mode 100644 index 9c5303ac034a4..0000000000000 --- a/tests/baselines/reference/issue49383.symbols +++ /dev/null @@ -1,12 +0,0 @@ -=== tests/cases/compiler/issue49383.ts === -function wrap(_: (...args: Args) => void) {} ->wrap : Symbol(wrap, Decl(issue49383.ts, 0, 0)) ->Args : Symbol(Args, Decl(issue49383.ts, 0, 14)) ->_ : Symbol(_, Decl(issue49383.ts, 0, 38)) ->args : Symbol(args, Decl(issue49383.ts, 0, 42)) ->Args : Symbol(Args, Decl(issue49383.ts, 0, 14)) - -wrap(({ cancelable } = {}) => {}); ->wrap : Symbol(wrap, Decl(issue49383.ts, 0, 0)) ->cancelable : Symbol(cancelable, Decl(issue49383.ts, 1, 7)) - diff --git a/tests/cases/compiler/issue49383.ts b/tests/cases/compiler/inferredRestTypeFixedOnce.ts similarity index 100% rename from tests/cases/compiler/issue49383.ts rename to tests/cases/compiler/inferredRestTypeFixedOnce.ts From a475c5c47a6511c04219d834fac851a2cf9bb903 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 29 Jun 2022 19:25:48 -0700 Subject: [PATCH 4/4] Move code out of inferFromAnnotatedParameters, undo bad changes --- src/compiler/checker.ts | 20 ++++++------------- .../getParameterNameAtPosition.types | 2 +- ...WithTupleArgsHasCorrectAssignability.types | 4 ++-- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 204776e64840a..d619af3e745fd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -32472,19 +32472,6 @@ namespace ts { } } } - const restType = getEffectiveRestType(context); - if (restType && restType.flags & TypeFlags.TypeParameter) { - // The contextual signature has a generic rest parameter. We first instantiate the contextual - // signature (without fixing type parameters) and infer types without calling assignContextualParameterTypes - // (which would fix parameter types). - const instantiatedContext = instantiateSignature(context, inferenceContext.nonFixingMapper); - const instantiatedRestType = getEffectiveRestType(instantiatedContext); - if (instantiatedRestType) { - // We then infer from a tuple type representing the parameters that correspond to the contextual - // rest parameter. - inferTypes(inferenceContext.inferences, getRestTypeAtPosition(signature, len), instantiatedRestType); - } - } } function assignContextualParameterTypes(signature: Signature, context: Signature) { @@ -33000,10 +32987,15 @@ namespace ts { if (isContextSensitive(node)) { if (contextualSignature) { const inferenceContext = getInferenceContext(node); + let instantiatedContextualSignature: Signature | undefined; if (checkMode && checkMode & CheckMode.Inferential) { inferFromAnnotatedParameters(signature, contextualSignature, inferenceContext!); + const restType = getEffectiveRestType(contextualSignature); + if (restType && restType.flags & TypeFlags.TypeParameter) { + instantiatedContextualSignature = instantiateSignature(contextualSignature, inferenceContext!.nonFixingMapper); + } } - const instantiatedContextualSignature = inferenceContext ? + instantiatedContextualSignature ||= inferenceContext ? instantiateSignature(contextualSignature, inferenceContext.mapper) : contextualSignature; assignContextualParameterTypes(signature, instantiatedContextualSignature); } diff --git a/tests/baselines/reference/getParameterNameAtPosition.types b/tests/baselines/reference/getParameterNameAtPosition.types index d74848ec3b39c..8eb527b41ec71 100644 --- a/tests/baselines/reference/getParameterNameAtPosition.types +++ b/tests/baselines/reference/getParameterNameAtPosition.types @@ -23,7 +23,7 @@ declare function fn(implementation?: (...args: Y) => any): Mock cases(fn(opts => { })); >cases(fn(opts => { })) : void >cases : (tester: Tester) => void ->fn(opts => { }) : Mock<[opts: any, done: (...args: any[]) => any]> +>fn(opts => { }) : Mock<[opts: any]> >fn : (implementation?: ((...args: Y) => any) | undefined) => Mock >opts => { } : (opts: any) => void >opts : any diff --git a/tests/baselines/reference/lambdaParameterWithTupleArgsHasCorrectAssignability.types b/tests/baselines/reference/lambdaParameterWithTupleArgsHasCorrectAssignability.types index 558aa6081b146..539326ab1c791 100644 --- a/tests/baselines/reference/lambdaParameterWithTupleArgsHasCorrectAssignability.types +++ b/tests/baselines/reference/lambdaParameterWithTupleArgsHasCorrectAssignability.types @@ -33,7 +33,7 @@ function consumeClass(c: GenericClass<[string, boolean]>) { } consumeClass(createClass(str => console.log(str.length))); >consumeClass(createClass(str => console.log(str.length))) : void >consumeClass : (c: GenericClass<[string, boolean]>) => void ->createClass(str => console.log(str.length)) : GenericClass<[string, boolean]> +>createClass(str => console.log(str.length)) : GenericClass<[str: string]> >createClass : (f: GenericFunction) => GenericClass >str => console.log(str.length) : (str: string) => void >str : string @@ -49,7 +49,7 @@ consumeClass(createClass(str => console.log(str.length))); consumeClass(createClass((str, _unused_num) => console.log(str.length))); >consumeClass(createClass((str, _unused_num) => console.log(str.length))) : void >consumeClass : (c: GenericClass<[string, boolean]>) => void ->createClass((str, _unused_num) => console.log(str.length)) : GenericClass<[string, boolean]> +>createClass((str, _unused_num) => console.log(str.length)) : GenericClass<[str: string, _unused_num: boolean]> >createClass : (f: GenericFunction) => GenericClass >(str, _unused_num) => console.log(str.length) : (str: string, _unused_num: boolean) => void >str : string