Skip to content

Fixed an issue with an incorrect resolved signature being cached/returned sometimes for signatures depending on the contextual type/outer inference #52146

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33324,10 +33324,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return cached;
}
links.resolvedSignature = resolvingSignature;
const result = resolveSignature(node, candidatesOutArray, checkMode || CheckMode.Normal);
let result = resolveSignature(node, candidatesOutArray, checkMode || CheckMode.Normal);
// When CheckMode.SkipGenericFunctions is set we use resolvingSignature to indicate that call
// resolution should be deferred.
if (result !== resolvingSignature) {
// if the signature resolution originated on a node that itself depends on the contextual type
// then it's possible that the resolved signature might not be the same as the one that would be computed in source order
// since resolving such signature leads to resolving the potential outer signature, its arguments and thus the very same signature
// it's possible that this inner resolution sets the resolvedSignature first.
// In such a case we ignore the local result and reuse the correct one that was cached.
if (links.resolvedSignature !== resolvingSignature) {
result = links.resolvedSignature;
}
// If signature resolution originated in control flow type analysis (for example to compute the
// assigned type in a flow assignment) we don't cache the result as it may be based on temporary
// types from the control flow analysis.
Expand Down
22 changes: 22 additions & 0 deletions tests/cases/fourslash/quickInfoNestedGenericCalls.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/// <reference path='fourslash.ts' />
// @strict: true
//// /*1*/m({ foo: /*2*/$("foo") });
//// m({ foo: /*3*/$("foo") });
//// declare const m: <S extends string>(s: { [_ in S]: { $: NoInfer<S> } }) => void
//// declare const $: <S, T extends S>(s: T) => { $: S }
//// type NoInfer<T> = [T][T extends any ? 0 : never];

verify.quickInfoAt("1", `const m: <"foo">(s: {
foo: {
$: "foo";
};
}) => void`);

// the exact generic type params are not important in this test (they could change with changes to the inference algorithm)
// it's important though that they both display the same types
verify.quickInfoAt("2", `const $: <unknown, string>(s: string) => {
$: unknown;
}`);
verify.quickInfoAt("3", `const $: <unknown, string>(s: string) => {
$: unknown;
}`);