Ensure resolved signature is cached before processing call errors (#49598)

This commit is contained in:
Jake Bailey
2022-06-21 13:15:03 -07:00
committed by GitHub
parent 9f2ab7fc31
commit 71b5bdf980
8 changed files with 204 additions and 15 deletions
+11 -1
View File
@@ -30736,6 +30736,16 @@ namespace ts {
return result;
}
result = getCandidateForOverloadFailure(node, candidates, args, !!candidatesOutArray, checkMode);
// Preemptively cache the result; getResolvedSignature will do this after we return, but
// we need to ensure that the result is present for the error checks below so that if
// this signature is encountered again, we handle the circularity (rather than producing a
// different result which may produce no errors and assert). Callers of getResolvedSignature
// don't hit this issue because they only observe this result after it's had a chance to
// be cached, but the error reporting code below executes before getResolvedSignature sets
// resolvedSignature.
getNodeLinks(node).resolvedSignature = result;
// No signatures were applicable. Now report errors based on the last applicable signature with
// no arguments excluded from assignability checks.
// If candidate is undefined, it means that no candidates had a suitable arity. In that case,
@@ -30826,7 +30836,7 @@ namespace ts {
}
}
return getCandidateForOverloadFailure(node, candidates, args, !!candidatesOutArray, checkMode);
return result;
function addImplementationSuccessElaboration(failed: Signature, diagnostic: Diagnostic) {
const oldCandidatesForArgumentError = candidatesForArgumentError;
@@ -0,0 +1,23 @@
tests/cases/compiler/circularResolvedSignature.ts(11,9): error TS2322: Type 'string' is not assignable to type 'number'.
==== tests/cases/compiler/circularResolvedSignature.ts (1 errors) ====
declare function useState<S>(initialState: (() => S)): [S, (s: S) => void];
type Data = Readonly<{
value: number;
foo: (arg: any) => void;
bar: (arg: any) => void;
}>;
export function Component() {
const [state, setState] = useState<Data>(() => ({
value: "string", // this should be a number
~~~~~
!!! error TS2322: Type 'string' is not assignable to type 'number'.
!!! related TS6500 tests/cases/compiler/circularResolvedSignature.ts:4:5: The expected type comes from property 'value' which is declared here on type 'Readonly<{ value: number; foo: (arg: any) => void; bar: (arg: any) => void; }>'
foo: (arg) => setState(arg),
bar: (arg) => setState(arg),
}));
}
@@ -0,0 +1,30 @@
//// [circularResolvedSignature.ts]
declare function useState<S>(initialState: (() => S)): [S, (s: S) => void];
type Data = Readonly<{
value: number;
foo: (arg: any) => void;
bar: (arg: any) => void;
}>;
export function Component() {
const [state, setState] = useState<Data>(() => ({
value: "string", // this should be a number
foo: (arg) => setState(arg),
bar: (arg) => setState(arg),
}));
}
//// [circularResolvedSignature.js]
"use strict";
exports.__esModule = true;
exports.Component = void 0;
function Component() {
var _a = useState(function () { return ({
value: "string",
foo: function (arg) { return setState(arg); },
bar: function (arg) { return setState(arg); }
}); }), state = _a[0], setState = _a[1];
}
exports.Component = Component;
@@ -0,0 +1,54 @@
=== tests/cases/compiler/circularResolvedSignature.ts ===
declare function useState<S>(initialState: (() => S)): [S, (s: S) => void];
>useState : Symbol(useState, Decl(circularResolvedSignature.ts, 0, 0))
>S : Symbol(S, Decl(circularResolvedSignature.ts, 0, 26))
>initialState : Symbol(initialState, Decl(circularResolvedSignature.ts, 0, 29))
>S : Symbol(S, Decl(circularResolvedSignature.ts, 0, 26))
>S : Symbol(S, Decl(circularResolvedSignature.ts, 0, 26))
>s : Symbol(s, Decl(circularResolvedSignature.ts, 0, 60))
>S : Symbol(S, Decl(circularResolvedSignature.ts, 0, 26))
type Data = Readonly<{
>Data : Symbol(Data, Decl(circularResolvedSignature.ts, 0, 75))
>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --))
value: number;
>value : Symbol(value, Decl(circularResolvedSignature.ts, 2, 22))
foo: (arg: any) => void;
>foo : Symbol(foo, Decl(circularResolvedSignature.ts, 3, 18))
>arg : Symbol(arg, Decl(circularResolvedSignature.ts, 4, 10))
bar: (arg: any) => void;
>bar : Symbol(bar, Decl(circularResolvedSignature.ts, 4, 28))
>arg : Symbol(arg, Decl(circularResolvedSignature.ts, 5, 10))
}>;
export function Component() {
>Component : Symbol(Component, Decl(circularResolvedSignature.ts, 6, 3))
const [state, setState] = useState<Data>(() => ({
>state : Symbol(state, Decl(circularResolvedSignature.ts, 9, 11))
>setState : Symbol(setState, Decl(circularResolvedSignature.ts, 9, 17))
>useState : Symbol(useState, Decl(circularResolvedSignature.ts, 0, 0))
>Data : Symbol(Data, Decl(circularResolvedSignature.ts, 0, 75))
value: "string", // this should be a number
>value : Symbol(value, Decl(circularResolvedSignature.ts, 9, 53))
foo: (arg) => setState(arg),
>foo : Symbol(foo, Decl(circularResolvedSignature.ts, 10, 24))
>arg : Symbol(arg, Decl(circularResolvedSignature.ts, 11, 14))
>setState : Symbol(setState, Decl(circularResolvedSignature.ts, 9, 17))
>arg : Symbol(arg, Decl(circularResolvedSignature.ts, 11, 14))
bar: (arg) => setState(arg),
>bar : Symbol(bar, Decl(circularResolvedSignature.ts, 11, 36))
>arg : Symbol(arg, Decl(circularResolvedSignature.ts, 12, 14))
>setState : Symbol(setState, Decl(circularResolvedSignature.ts, 9, 17))
>arg : Symbol(arg, Decl(circularResolvedSignature.ts, 12, 14))
}));
}
@@ -0,0 +1,57 @@
=== tests/cases/compiler/circularResolvedSignature.ts ===
declare function useState<S>(initialState: (() => S)): [S, (s: S) => void];
>useState : <S>(initialState: (() => S)) => [S, (s: S) => void]
>initialState : () => S
>s : S
type Data = Readonly<{
>Data : Readonly<{ value: number; foo: (arg: any) => void; bar: (arg: any) => void; }>
value: number;
>value : number
foo: (arg: any) => void;
>foo : (arg: any) => void
>arg : any
bar: (arg: any) => void;
>bar : (arg: any) => void
>arg : any
}>;
export function Component() {
>Component : () => void
const [state, setState] = useState<Data>(() => ({
>state : Readonly<{ value: number; foo: (arg: any) => void; bar: (arg: any) => void; }>
>setState : (s: Readonly<{ value: number; foo: (arg: any) => void; bar: (arg: any) => void; }>) => void
>useState<Data>(() => ({ value: "string", // this should be a number foo: (arg) => setState(arg), bar: (arg) => setState(arg), })) : [Readonly<{ value: number; foo: (arg: any) => void; bar: (arg: any) => void; }>, (s: Readonly<{ value: number; foo: (arg: any) => void; bar: (arg: any) => void; }>) => void]
>useState : <S>(initialState: () => S) => [S, (s: S) => void]
>() => ({ value: "string", // this should be a number foo: (arg) => setState(arg), bar: (arg) => setState(arg), }) : () => { value: string; foo: (arg: any) => void; bar: (arg: any) => void; }
>({ value: "string", // this should be a number foo: (arg) => setState(arg), bar: (arg) => setState(arg), }) : { value: string; foo: (arg: any) => void; bar: (arg: any) => void; }
>{ value: "string", // this should be a number foo: (arg) => setState(arg), bar: (arg) => setState(arg), } : { value: string; foo: (arg: any) => void; bar: (arg: any) => void; }
value: "string", // this should be a number
>value : string
>"string" : "string"
foo: (arg) => setState(arg),
>foo : (arg: any) => void
>(arg) => setState(arg) : (arg: any) => void
>arg : any
>setState(arg) : void
>setState : (s: Readonly<{ value: number; foo: (arg: any) => void; bar: (arg: any) => void; }>) => void
>arg : any
bar: (arg) => setState(arg),
>bar : (arg: any) => void
>(arg) => setState(arg) : (arg: any) => void
>arg : any
>setState(arg) : void
>setState : (s: Readonly<{ value: number; foo: (arg: any) => void; bar: (arg: any) => void; }>) => void
>arg : any
}));
}
@@ -1,8 +1,8 @@
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithGenericSignatureArguments3.ts(32,19): error TS2345: Argument of type '(a1: (y: string) => string) => (n: Object) => number' is not assignable to parameter of type '(x: (a: string) => boolean) => (n: Object) => number'.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithGenericSignatureArguments3.ts(32,19): error TS2345: Argument of type '(a1: (y: string) => string) => (n: Object) => 1' is not assignable to parameter of type '(x: (a: string) => boolean) => (n: Object) => 1'.
Types of parameters 'a1' and 'x' are incompatible.
Type 'boolean' is not assignable to type 'string'.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithGenericSignatureArguments3.ts(33,69): error TS2345: Argument of type '(a2: (z: string) => boolean) => number' is not assignable to parameter of type '(x: (z: string) => boolean) => (n: Object) => number'.
Type 'number' is not assignable to type '(n: Object) => number'.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithGenericSignatureArguments3.ts(33,69): error TS2345: Argument of type '(a2: (z: string) => boolean) => number' is not assignable to parameter of type '(x: (z: string) => boolean) => (n: Object) => 1'.
Type 'number' is not assignable to type '(n: Object) => 1'.
==== tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithGenericSignatureArguments3.ts (2 errors) ====
@@ -39,10 +39,10 @@ tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithGen
var x: (a: string) => boolean;
var r11 = foo2(x, (a1: (y: string) => string) => (n: Object) => 1, (a2: (z: string) => string) => 2); // error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2345: Argument of type '(a1: (y: string) => string) => (n: Object) => number' is not assignable to parameter of type '(x: (a: string) => boolean) => (n: Object) => number'.
!!! error TS2345: Argument of type '(a1: (y: string) => string) => (n: Object) => 1' is not assignable to parameter of type '(x: (a: string) => boolean) => (n: Object) => 1'.
!!! error TS2345: Types of parameters 'a1' and 'x' are incompatible.
!!! error TS2345: Type 'boolean' is not assignable to type 'string'.
var r12 = foo2(x, (a1: (y: string) => boolean) => (n: Object) => 1, (a2: (z: string) => boolean) => 2); // error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2345: Argument of type '(a2: (z: string) => boolean) => number' is not assignable to parameter of type '(x: (z: string) => boolean) => (n: Object) => number'.
!!! error TS2345: Type 'number' is not assignable to type '(n: Object) => number'.
!!! error TS2345: Argument of type '(a2: (z: string) => boolean) => number' is not assignable to parameter of type '(x: (z: string) => boolean) => (n: Object) => 1'.
!!! error TS2345: Type 'number' is not assignable to type '(n: Object) => 1'.
@@ -175,14 +175,14 @@ var x: (a: string) => boolean;
>a : string
var r11 = foo2(x, (a1: (y: string) => string) => (n: Object) => 1, (a2: (z: string) => string) => 2); // error
>r11 : (x: (a: string) => boolean) => (n: Object) => number
>foo2(x, (a1: (y: string) => string) => (n: Object) => 1, (a2: (z: string) => string) => 2) : (x: (a: string) => boolean) => (n: Object) => number
>r11 : (x: (a: string) => boolean) => (n: Object) => 1
>foo2(x, (a1: (y: string) => string) => (n: Object) => 1, (a2: (z: string) => string) => 2) : (x: (a: string) => boolean) => (n: Object) => 1
>foo2 : <T, U>(x: T, a: (x: T) => U, b: (x: T) => U) => (x: T) => U
>x : (a: string) => boolean
>(a1: (y: string) => string) => (n: Object) => 1 : (a1: (y: string) => string) => (n: Object) => number
>(a1: (y: string) => string) => (n: Object) => 1 : (a1: (y: string) => string) => (n: Object) => 1
>a1 : (y: string) => string
>y : string
>(n: Object) => 1 : (n: Object) => number
>(n: Object) => 1 : (n: Object) => 1
>n : Object
>1 : 1
>(a2: (z: string) => string) => 2 : (a2: (z: string) => string) => number
@@ -191,14 +191,14 @@ var r11 = foo2(x, (a1: (y: string) => string) => (n: Object) => 1, (a2: (z: stri
>2 : 2
var r12 = foo2(x, (a1: (y: string) => boolean) => (n: Object) => 1, (a2: (z: string) => boolean) => 2); // error
>r12 : (x: (z: string) => boolean) => (n: Object) => number
>foo2(x, (a1: (y: string) => boolean) => (n: Object) => 1, (a2: (z: string) => boolean) => 2) : (x: (z: string) => boolean) => (n: Object) => number
>r12 : (x: (z: string) => boolean) => (n: Object) => 1
>foo2(x, (a1: (y: string) => boolean) => (n: Object) => 1, (a2: (z: string) => boolean) => 2) : (x: (z: string) => boolean) => (n: Object) => 1
>foo2 : <T, U>(x: T, a: (x: T) => U, b: (x: T) => U) => (x: T) => U
>x : (a: string) => boolean
>(a1: (y: string) => boolean) => (n: Object) => 1 : (a1: (y: string) => boolean) => (n: Object) => number
>(a1: (y: string) => boolean) => (n: Object) => 1 : (a1: (y: string) => boolean) => (n: Object) => 1
>a1 : (y: string) => boolean
>y : string
>(n: Object) => 1 : (n: Object) => number
>(n: Object) => 1 : (n: Object) => 1
>n : Object
>1 : 1
>(a2: (z: string) => boolean) => 2 : (a2: (z: string) => boolean) => number
@@ -0,0 +1,15 @@
declare function useState<S>(initialState: (() => S)): [S, (s: S) => void];
type Data = Readonly<{
value: number;
foo: (arg: any) => void;
bar: (arg: any) => void;
}>;
export function Component() {
const [state, setState] = useState<Data>(() => ({
value: "string", // this should be a number
foo: (arg) => setState(arg),
bar: (arg) => setState(arg),
}));
}