diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 46e6dcb1138..d3194eb8aa9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9155,15 +9155,8 @@ namespace ts { return constraint && maybeTypeOfKind(constraint, TypeFlags.Primitive | TypeFlags.Index); } - function getSuppliedType(context: InferenceContext, index: number): Type | undefined { - if (context.suppliedTypes && index < context.suppliedTypes.length) { - return context.inferredTypes[index] = context.suppliedTypes[index]; - } - return undefined; - } - function getInferredType(context: InferenceContext, index: number): Type { - let inferredType = context.inferredTypes[index] || getSuppliedType(context, index); + let inferredType = context.inferredTypes[index]; let inferenceSucceeded: boolean; if (!inferredType) { const inferences = getInferenceCandidates(context, index); @@ -13417,7 +13410,6 @@ namespace ts { } } - const numTypeArguments = typeArguments ? typeArguments.length : 0; const candidates = candidatesOutArray || []; // reorderCandidates fills up the candidates array directly reorderCandidates(signatures, candidates); @@ -13593,16 +13585,13 @@ namespace ts { if (candidate.typeParameters) { let typeArgumentTypes: Type[] | undefined; if (typeArguments) { - // Check any supplied type arguments against the candidate. - typeArgumentTypes = map(typeArguments, getTypeFromTypeNode) + typeArgumentTypes = fillMissingTypeArguments(map(typeArguments, getTypeFromTypeNode), candidate.typeParameters, candidate.minTypeArgumentCount); typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false); } - if ((!typeArguments || typeArgumentsAreValid) && numTypeArguments < candidate.typeParameters.length) { - // Infer any unsupplied type arguments for the candidate. - inferenceContext.suppliedTypes = typeArgumentTypes; + else { inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); - typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex === undefined; typeArgumentTypes = inferenceContext.inferredTypes; + typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex === undefined; } if (!typeArgumentsAreValid) { break; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5a1078ec8ef..30a054d481e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3095,7 +3095,6 @@ namespace ts { inferUnionTypes: boolean; // Infer union types for disjoint candidates (otherwise undefinedType) inferences: TypeInferences[]; // Inferences made for each type parameter inferredTypes: Type[]; // Inferred type for each type parameter - suppliedTypes?: Type[]; // Supplied types for non-default type parameters mapper?: TypeMapper; // Type mapper for this inference context failedTypeParameterIndex?: number; // Index of type parameter for which inference failed // It is optional because in contextual signature instantiation, nothing fails diff --git a/tests/baselines/reference/genericDefaults.js b/tests/baselines/reference/genericDefaults.js index a2271681e13..496c3894817 100644 --- a/tests/baselines/reference/genericDefaults.js +++ b/tests/baselines/reference/genericDefaults.js @@ -15,7 +15,7 @@ const f01c01 = f01(1); const f01c02 = f01(1, "a"); const f01c03 = f01(); const f01c04 = f01(1); -const f01c05 = f01(1, "a"); +const f01c05 = f01(1, 2); const f01c06 = f01(); const f01c07 = f01(1); const f01c08 = f01(1, "a"); @@ -26,7 +26,7 @@ const f02c01 = f02(1); const f02c02 = f02(1, "a"); const f02c03 = f02(); const f02c04 = f02(1); -const f02c05 = f02(1, "a"); +const f02c05 = f02(1, 2); const f02c06 = f02(); const f02c07 = f02(1); const f02c08 = f02(1, "a"); @@ -53,13 +53,13 @@ const f04c06 = f04(); const f04c07 = f04(1); const f04c08 = f04(1, 2); -declare function f05(a?: T, b?: U): [T, U]; +declare function f05(a?: T, b?: U): [T, U]; const f05c00 = f05(); const f05c01 = f05(1); const f05c02 = f05(1, 1); const f05c03 = f05(); const f05c04 = f05(1); -const f05c05 = f05(1, 2); +const f05c05 = f05<{ a: number }>({ a: 1 }, { a: 2, b: 3}); const f05c06 = f05(); const f05c07 = f05(1); const f05c08 = f05(1, 2); @@ -125,7 +125,7 @@ var f01c01 = f01(1); var f01c02 = f01(1, "a"); var f01c03 = f01(); var f01c04 = f01(1); -var f01c05 = f01(1, "a"); +var f01c05 = f01(1, 2); var f01c06 = f01(); var f01c07 = f01(1); var f01c08 = f01(1, "a"); @@ -134,7 +134,7 @@ var f02c01 = f02(1); var f02c02 = f02(1, "a"); var f02c03 = f02(); var f02c04 = f02(1); -var f02c05 = f02(1, "a"); +var f02c05 = f02(1, 2); var f02c06 = f02(); var f02c07 = f02(1); var f02c08 = f02(1, "a"); @@ -161,7 +161,7 @@ var f05c01 = f05(1); var f05c02 = f05(1, 1); var f05c03 = f05(); var f05c04 = f05(1); -var f05c05 = f05(1, 2); +var f05c05 = f05({ a: 1 }, { a: 2, b: 3 }); var f05c06 = f05(); var f05c07 = f05(1); var f05c08 = f05(1, 2); @@ -208,7 +208,7 @@ declare const f01c01: [number, number]; declare const f01c02: [number, string]; declare const f01c03: [number, number]; declare const f01c04: [number, number]; -declare const f01c05: [number, string]; +declare const f01c05: [number, number]; declare const f01c06: [number, string]; declare const f01c07: [number, string]; declare const f01c08: [number, string]; @@ -218,7 +218,7 @@ declare const f02c01: [1, 1]; declare const f02c02: [1, string]; declare const f02c03: [number, number]; declare const f02c04: [number, number]; -declare const f02c05: [number, string]; +declare const f02c05: [number, number]; declare const f02c06: [number, string]; declare const f02c07: [number, string]; declare const f02c08: [number, string]; @@ -248,27 +248,35 @@ declare const f04c03: [number, number | { declare const f04c04: [number, number | { a: number; }]; -declare const f04c05: [number, number]; +declare const f04c05: [number, number | { + a: number; +}]; declare const f04c06: [number, number]; declare const f04c07: [number, number]; declare const f04c08: [number, number]; declare function f05(a?: T, b?: U): [T, U]; declare const f05c00: [{}, {} & { - a: number; + b: number; }]; declare const f05c01: [number, number & { - a: number; + b: number; }]; declare const f05c02: [number, number]; declare const f05c03: [number, number & { - a: number; + b: number; }]; declare const f05c04: [number, number & { - a: number; + b: number; +}]; +declare const f05c05: [{ + a: number; +}, { + a: number; +} & { + b: number; }]; -declare const f05c05: [number, number]; declare const f05c06: [number, number]; declare const f05c07: [number, number]; declare const f05c08: [number, number]; diff --git a/tests/baselines/reference/genericDefaults.symbols b/tests/baselines/reference/genericDefaults.symbols index 67b61a0a252..0a633e60612 100644 --- a/tests/baselines/reference/genericDefaults.symbols +++ b/tests/baselines/reference/genericDefaults.symbols @@ -65,7 +65,7 @@ const f01c04 = f01(1); >f01c04 : Symbol(f01c04, Decl(genericDefaults.ts, 15, 5)) >f01 : Symbol(f01, Decl(genericDefaults.ts, 8, 32)) -const f01c05 = f01(1, "a"); +const f01c05 = f01(1, 2); >f01c05 : Symbol(f01c05, Decl(genericDefaults.ts, 16, 5)) >f01 : Symbol(f01, Decl(genericDefaults.ts, 8, 32)) @@ -113,7 +113,7 @@ const f02c04 = f02(1); >f02c04 : Symbol(f02c04, Decl(genericDefaults.ts, 26, 5)) >f02 : Symbol(f02, Decl(genericDefaults.ts, 19, 43)) -const f02c05 = f02(1, "a"); +const f02c05 = f02(1, 2); >f02c05 : Symbol(f02c05, Decl(genericDefaults.ts, 27, 5)) >f02 : Symbol(f02, Decl(genericDefaults.ts, 19, 43)) @@ -227,12 +227,12 @@ const f04c08 = f04(1, 2); >f04c08 : Symbol(f04c08, Decl(genericDefaults.ts, 52, 5)) >f04 : Symbol(f04, Decl(genericDefaults.ts, 41, 41)) -declare function f05(a?: T, b?: U): [T, U]; +declare function f05(a?: T, b?: U): [T, U]; >f05 : Symbol(f05, Decl(genericDefaults.ts, 52, 41)) >T : Symbol(T, Decl(genericDefaults.ts, 54, 21)) >U : Symbol(U, Decl(genericDefaults.ts, 54, 23)) >T : Symbol(T, Decl(genericDefaults.ts, 54, 21)) ->a : Symbol(a, Decl(genericDefaults.ts, 54, 33)) +>b : Symbol(b, Decl(genericDefaults.ts, 54, 33)) >a : Symbol(a, Decl(genericDefaults.ts, 54, 47)) >T : Symbol(T, Decl(genericDefaults.ts, 54, 21)) >b : Symbol(b, Decl(genericDefaults.ts, 54, 53)) @@ -260,9 +260,13 @@ const f05c04 = f05(1); >f05c04 : Symbol(f05c04, Decl(genericDefaults.ts, 59, 5)) >f05 : Symbol(f05, Decl(genericDefaults.ts, 52, 41)) -const f05c05 = f05(1, 2); +const f05c05 = f05<{ a: number }>({ a: 1 }, { a: 2, b: 3}); >f05c05 : Symbol(f05c05, Decl(genericDefaults.ts, 60, 5)) >f05 : Symbol(f05, Decl(genericDefaults.ts, 52, 41)) +>a : Symbol(a, Decl(genericDefaults.ts, 60, 20)) +>a : Symbol(a, Decl(genericDefaults.ts, 60, 35)) +>a : Symbol(a, Decl(genericDefaults.ts, 60, 45)) +>b : Symbol(b, Decl(genericDefaults.ts, 60, 51)) const f05c06 = f05(); >f05c06 : Symbol(f05c06, Decl(genericDefaults.ts, 61, 5)) diff --git a/tests/baselines/reference/genericDefaults.types b/tests/baselines/reference/genericDefaults.types index 70f67497f21..4977d2d8896 100644 --- a/tests/baselines/reference/genericDefaults.types +++ b/tests/baselines/reference/genericDefaults.types @@ -84,12 +84,12 @@ const f01c04 = f01(1); >f01 : (a?: T, b?: U) => [T, U] >1 : 1 -const f01c05 = f01(1, "a"); ->f01c05 : [number, string] ->f01(1, "a") : [number, string] +const f01c05 = f01(1, 2); +>f01c05 : [number, number] +>f01(1, 2) : [number, number] >f01 : (a?: T, b?: U) => [T, U] >1 : 1 ->"a" : "a" +>2 : 2 const f01c06 = f01(); >f01c06 : [number, string] @@ -150,12 +150,12 @@ const f02c04 = f02(1); >f02 : (a?: T, b?: U) => [T, U] >1 : 1 -const f02c05 = f02(1, "a"); ->f02c05 : [number, string] ->f02(1, "a") : [number, string] +const f02c05 = f02(1, 2); +>f02c05 : [number, number] +>f02(1, 2) : [number, number] >f02 : (a?: T, b?: U) => [T, U] >1 : 1 ->"a" : "a" +>2 : 2 const f02c06 = f02(); >f02c06 : [number, string] @@ -285,8 +285,8 @@ const f04c04 = f04(1); >1 : 1 const f04c05 = f04(1, 2); ->f04c05 : [number, number] ->f04(1, 2) : [number, number] +>f04c05 : [number, number | { a: number; }] +>f04(1, 2) : [number, number | { a: number; }] >f04 : (a?: T, b?: U) => [T, U] >1 : 1 >2 : 2 @@ -309,12 +309,12 @@ const f04c08 = f04(1, 2); >1 : 1 >2 : 2 -declare function f05(a?: T, b?: U): [T, U]; ->f05 : (a?: T, b?: U) => [T, U] +declare function f05(a?: T, b?: U): [T, U]; +>f05 : (a?: T, b?: U) => [T, U] >T : T >U : U >T : T ->a : number +>b : number >a : T >T : T >b : U @@ -323,56 +323,63 @@ declare function f05(a?: T, b?: U): [T, U]; >U : U const f05c00 = f05(); ->f05c00 : [{}, {} & { a: number; }] ->f05() : [{}, {} & { a: number; }] ->f05 : (a?: T, b?: U) => [T, U] +>f05c00 : [{}, {} & { b: number; }] +>f05() : [{}, {} & { b: number; }] +>f05 : (a?: T, b?: U) => [T, U] const f05c01 = f05(1); ->f05c01 : [number, number & { a: number; }] ->f05(1) : [number, number & { a: number; }] ->f05 : (a?: T, b?: U) => [T, U] +>f05c01 : [number, number & { b: number; }] +>f05(1) : [number, number & { b: number; }] +>f05 : (a?: T, b?: U) => [T, U] >1 : 1 const f05c02 = f05(1, 1); >f05c02 : [number, number] >f05(1, 1) : [number, number] ->f05 : (a?: T, b?: U) => [T, U] +>f05 : (a?: T, b?: U) => [T, U] >1 : 1 >1 : 1 const f05c03 = f05(); ->f05c03 : [number, number & { a: number; }] ->f05() : [number, number & { a: number; }] ->f05 : (a?: T, b?: U) => [T, U] +>f05c03 : [number, number & { b: number; }] +>f05() : [number, number & { b: number; }] +>f05 : (a?: T, b?: U) => [T, U] const f05c04 = f05(1); ->f05c04 : [number, number & { a: number; }] ->f05(1) : [number, number & { a: number; }] ->f05 : (a?: T, b?: U) => [T, U] +>f05c04 : [number, number & { b: number; }] +>f05(1) : [number, number & { b: number; }] +>f05 : (a?: T, b?: U) => [T, U] >1 : 1 -const f05c05 = f05(1, 2); ->f05c05 : [number, number] ->f05(1, 2) : [number, number] ->f05 : (a?: T, b?: U) => [T, U] +const f05c05 = f05<{ a: number }>({ a: 1 }, { a: 2, b: 3}); +>f05c05 : [{ a: number; }, { a: number; } & { b: number; }] +>f05<{ a: number }>({ a: 1 }, { a: 2, b: 3}) : [{ a: number; }, { a: number; } & { b: number; }] +>f05 : (a?: T, b?: U) => [T, U] +>a : number +>{ a: 1 } : { a: number; } +>a : number >1 : 1 +>{ a: 2, b: 3} : { a: number; b: number; } +>a : number >2 : 2 +>b : number +>3 : 3 const f05c06 = f05(); >f05c06 : [number, number] >f05() : [number, number] ->f05 : (a?: T, b?: U) => [T, U] +>f05 : (a?: T, b?: U) => [T, U] const f05c07 = f05(1); >f05c07 : [number, number] >f05(1) : [number, number] ->f05 : (a?: T, b?: U) => [T, U] +>f05 : (a?: T, b?: U) => [T, U] >1 : 1 const f05c08 = f05(1, 2); >f05c08 : [number, number] >f05(1, 2) : [number, number] ->f05 : (a?: T, b?: U) => [T, U] +>f05 : (a?: T, b?: U) => [T, U] >1 : 1 >2 : 2 diff --git a/tests/baselines/reference/genericDefaultsErrors.errors.txt b/tests/baselines/reference/genericDefaultsErrors.errors.txt index ab2eb71e0ea..ad2e4068590 100644 --- a/tests/baselines/reference/genericDefaultsErrors.errors.txt +++ b/tests/baselines/reference/genericDefaultsErrors.errors.txt @@ -17,24 +17,25 @@ tests/cases/compiler/genericDefaultsErrors.ts(14,26): error TS2706: Type paramet tests/cases/compiler/genericDefaultsErrors.ts(14,33): error TS2706: Type parameter 'U' has a circular default. tests/cases/compiler/genericDefaultsErrors.ts(18,1): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/compiler/genericDefaultsErrors.ts(21,1): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/compiler/genericDefaultsErrors.ts(24,11): error TS2428: All declarations of 'i00' must have identical type parameters. -tests/cases/compiler/genericDefaultsErrors.ts(27,11): error TS2428: All declarations of 'i01' must have identical type parameters. -tests/cases/compiler/genericDefaultsErrors.ts(29,19): error TS2706: Type parameter 'T' has a circular default. -tests/cases/compiler/genericDefaultsErrors.ts(30,19): error TS2706: Type parameter 'T' has a circular default. -tests/cases/compiler/genericDefaultsErrors.ts(30,26): error TS2706: Type parameter 'U' has a circular default. -tests/cases/compiler/genericDefaultsErrors.ts(31,22): error TS2705: Required type parameters may not follow optional type parameters. -tests/cases/compiler/genericDefaultsErrors.ts(32,34): error TS2344: Type 'number' does not satisfy the constraint 'string'. -tests/cases/compiler/genericDefaultsErrors.ts(33,52): error TS2344: Type 'T' does not satisfy the constraint 'number'. +tests/cases/compiler/genericDefaultsErrors.ts(25,13): error TS2345: Argument of type '"a"' is not assignable to parameter of type 'number'. +tests/cases/compiler/genericDefaultsErrors.ts(28,11): error TS2428: All declarations of 'i00' must have identical type parameters. +tests/cases/compiler/genericDefaultsErrors.ts(31,11): error TS2428: All declarations of 'i01' must have identical type parameters. +tests/cases/compiler/genericDefaultsErrors.ts(33,19): error TS2706: Type parameter 'T' has a circular default. +tests/cases/compiler/genericDefaultsErrors.ts(34,19): error TS2706: Type parameter 'T' has a circular default. +tests/cases/compiler/genericDefaultsErrors.ts(34,26): error TS2706: Type parameter 'U' has a circular default. +tests/cases/compiler/genericDefaultsErrors.ts(35,22): error TS2705: Required type parameters may not follow optional type parameters. +tests/cases/compiler/genericDefaultsErrors.ts(36,34): error TS2344: Type 'number' does not satisfy the constraint 'string'. +tests/cases/compiler/genericDefaultsErrors.ts(37,52): error TS2344: Type 'T' does not satisfy the constraint 'number'. Type 'string' is not assignable to type 'number'. -tests/cases/compiler/genericDefaultsErrors.ts(34,37): error TS2344: Type 'T' does not satisfy the constraint 'number'. -tests/cases/compiler/genericDefaultsErrors.ts(35,32): error TS2344: Type 'number' does not satisfy the constraint 'T'. -tests/cases/compiler/genericDefaultsErrors.ts(38,15): error TS2707: Generic type 'i09' requires between 2 and 3 type arguments. -tests/cases/compiler/genericDefaultsErrors.ts(39,15): error TS2707: Generic type 'i09' requires between 2 and 3 type arguments. +tests/cases/compiler/genericDefaultsErrors.ts(38,37): error TS2344: Type 'T' does not satisfy the constraint 'number'. +tests/cases/compiler/genericDefaultsErrors.ts(39,32): error TS2344: Type 'number' does not satisfy the constraint 'T'. tests/cases/compiler/genericDefaultsErrors.ts(42,15): error TS2707: Generic type 'i09' requires between 2 and 3 type arguments. -tests/cases/compiler/genericDefaultsErrors.ts(44,17): error TS2367: Type parameter 'T' cannot be referenced outside of a declaration that defines it. +tests/cases/compiler/genericDefaultsErrors.ts(43,15): error TS2707: Generic type 'i09' requires between 2 and 3 type arguments. +tests/cases/compiler/genericDefaultsErrors.ts(46,15): error TS2707: Generic type 'i09' requires between 2 and 3 type arguments. +tests/cases/compiler/genericDefaultsErrors.ts(48,17): error TS2367: Type parameter 'T' cannot be referenced outside of a declaration that defines it. -==== tests/cases/compiler/genericDefaultsErrors.ts (32 errors) ==== +==== tests/cases/compiler/genericDefaultsErrors.ts (33 errors) ==== declare const x: any; @@ -94,6 +95,12 @@ tests/cases/compiler/genericDefaultsErrors.ts(44,17): error TS2367: Type paramet ~~~~~~~~~~~~~~~~~ !!! error TS2346: Supplied parameters do not match any signature of call target. + declare function f12(a?: U): void; + f12(); // ok + f12("a"); // error + ~~~ +!!! error TS2345: Argument of type '"a"' is not assignable to parameter of type 'number'. + interface i00 { } // ok interface i00 { } // error ~~~ diff --git a/tests/baselines/reference/genericDefaultsErrors.js b/tests/baselines/reference/genericDefaultsErrors.js index 12bac1a8ff4..d8ab04cdadf 100644 --- a/tests/baselines/reference/genericDefaultsErrors.js +++ b/tests/baselines/reference/genericDefaultsErrors.js @@ -21,6 +21,10 @@ f11<1, 2>(); // ok f11<1, 2, 3>(); // ok f11<1, 2, 3, 4>(); // error +declare function f12(a?: U): void; +f12(); // ok +f12("a"); // error + interface i00 { } // ok interface i00 { } // error @@ -51,6 +55,8 @@ f11(); // error f11(); // ok f11(); // ok f11(); // error +f12(); // ok +f12("a"); // error //// [genericDefaultsErrors.d.ts] @@ -75,6 +81,7 @@ declare function f10(): void; declare function f11(): void; +declare function f12(a?: U): void; interface i00 { } interface i00 { diff --git a/tests/cases/compiler/genericDefaults.ts b/tests/cases/compiler/genericDefaults.ts index 10dbcf1025e..df507a32a91 100644 --- a/tests/cases/compiler/genericDefaults.ts +++ b/tests/cases/compiler/genericDefaults.ts @@ -15,7 +15,7 @@ const f01c01 = f01(1); const f01c02 = f01(1, "a"); const f01c03 = f01(); const f01c04 = f01(1); -const f01c05 = f01(1, "a"); +const f01c05 = f01(1, 2); const f01c06 = f01(); const f01c07 = f01(1); const f01c08 = f01(1, "a"); @@ -26,7 +26,7 @@ const f02c01 = f02(1); const f02c02 = f02(1, "a"); const f02c03 = f02(); const f02c04 = f02(1); -const f02c05 = f02(1, "a"); +const f02c05 = f02(1, 2); const f02c06 = f02(); const f02c07 = f02(1); const f02c08 = f02(1, "a"); @@ -53,13 +53,13 @@ const f04c06 = f04(); const f04c07 = f04(1); const f04c08 = f04(1, 2); -declare function f05(a?: T, b?: U): [T, U]; +declare function f05(a?: T, b?: U): [T, U]; const f05c00 = f05(); const f05c01 = f05(1); const f05c02 = f05(1, 1); const f05c03 = f05(); const f05c04 = f05(1); -const f05c05 = f05(1, 2); +const f05c05 = f05<{ a: number }>({ a: 1 }, { a: 2, b: 3}); const f05c06 = f05(); const f05c07 = f05(1); const f05c08 = f05(1, 2); diff --git a/tests/cases/compiler/genericDefaultsErrors.ts b/tests/cases/compiler/genericDefaultsErrors.ts index 0e3cf3003b1..02b4fce9296 100644 --- a/tests/cases/compiler/genericDefaultsErrors.ts +++ b/tests/cases/compiler/genericDefaultsErrors.ts @@ -21,6 +21,10 @@ f11<1, 2>(); // ok f11<1, 2, 3>(); // ok f11<1, 2, 3, 4>(); // error +declare function f12(a?: U): void; +f12(); // ok +f12("a"); // error + interface i00 { } // ok interface i00 { } // error