Skip to content

Commit bf1ba58

Browse files
committed
Fixed an issue with an incorrect resolved signature being cached/returned sometimes for signatures depending on the contextual type/outer inference
1 parent 12718ad commit bf1ba58

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

src/compiler/checker.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33324,10 +33324,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3332433324
return cached;
3332533325
}
3332633326
links.resolvedSignature = resolvingSignature;
33327-
const result = resolveSignature(node, candidatesOutArray, checkMode || CheckMode.Normal);
33327+
let result = resolveSignature(node, candidatesOutArray, checkMode || CheckMode.Normal);
3332833328
// When CheckMode.SkipGenericFunctions is set we use resolvingSignature to indicate that call
3332933329
// resolution should be deferred.
3333033330
if (result !== resolvingSignature) {
33331+
// if the signature resolution originated on a node that itself depends on the contextual type
33332+
// then it's possible that the resolved signature might not be the same as the one that would be computed in source order
33333+
// since resolving such signature leads to resolving the potential outer signature, its arguments and thus the very same signature
33334+
// it's possible that this inner resolution sets the resolvedSignature first.
33335+
// In such a case we ignore the local result and reuse the correct one that was cached.
33336+
if (links.resolvedSignature !== resolvingSignature) {
33337+
result = links.resolvedSignature;
33338+
}
3333133339
// If signature resolution originated in control flow type analysis (for example to compute the
3333233340
// assigned type in a flow assignment) we don't cache the result as it may be based on temporary
3333333341
// types from the control flow analysis.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/// <reference path='fourslash.ts' />
2+
// @strict: true
3+
//// /*1*/m({ foo: /*2*/$("foo") });
4+
//// m({ foo: /*3*/$("foo") });
5+
//// declare const m: <S extends string>(s: { [_ in S]: { $: NoInfer<S> } }) => void
6+
//// declare const $: <S, T extends S>(s: T) => { $: S }
7+
//// type NoInfer<T> = [T][T extends any ? 0 : never];
8+
9+
verify.quickInfoAt("1", `const m: <"foo">(s: {
10+
foo: {
11+
$: "foo";
12+
};
13+
}) => void`);
14+
15+
// the exact generic type params are not important in this test (they could change with changes to the inference algorithm)
16+
// it's important though that they both display the same types
17+
verify.quickInfoAt("2", `const $: <unknown, string>(s: string) => {
18+
$: unknown;
19+
}`);
20+
verify.quickInfoAt("3", `const $: <unknown, string>(s: string) => {
21+
$: unknown;
22+
}`);

0 commit comments

Comments
 (0)