From ca93b24e2b24e8c92989ac2aa98a3205e344634e Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 17 Nov 2020 13:49:19 -0800 Subject: [PATCH] Revert "Don't relate unmatched parameter positions in signatures (#41308)" This reverts commit bd27bd8d479e72bdace946ff78861feecb66043a. --- src/compiler/checker.ts | 60 +++++++++---------- .../reference/unmatchedParameterPositions.js | 13 ---- .../unmatchedParameterPositions.symbols | 16 ----- .../unmatchedParameterPositions.types | 16 ----- .../compiler/unmatchedParameterPositions.ts | 7 --- 5 files changed, 29 insertions(+), 83 deletions(-) delete mode 100644 tests/baselines/reference/unmatchedParameterPositions.js delete mode 100644 tests/baselines/reference/unmatchedParameterPositions.symbols delete mode 100644 tests/baselines/reference/unmatchedParameterPositions.types delete mode 100644 tests/cases/compiler/unmatchedParameterPositions.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 249487956f4..ff063d08baa 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16186,38 +16186,36 @@ namespace ts { const restIndex = sourceRestType || targetRestType ? paramCount - 1 : -1; for (let i = 0; i < paramCount; i++) { - const sourceType = i === restIndex ? getRestTypeAtPosition(source, i) : tryGetTypeAtPosition(source, i); - const targetType = i === restIndex ? getRestTypeAtPosition(target, i) : tryGetTypeAtPosition(target, i); - if (sourceType && targetType) { - // In order to ensure that any generic type Foo is at least co-variant with respect to T no matter - // how Foo uses T, we need to relate parameters bi-variantly (given that parameters are input positions, - // they naturally relate only contra-variantly). However, if the source and target parameters both have - // function types with a single call signature, we know we are relating two callback parameters. In - // that case it is sufficient to only relate the parameters of the signatures co-variantly because, - // similar to return values, callback parameters are output positions. This means that a Promise, - // where T is used only in callback parameter positions, will be co-variant (as opposed to bi-variant) - // with respect to T. - const sourceSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(sourceType)); - const targetSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(targetType)); - const callbacks = sourceSig && targetSig && !getTypePredicateOfSignature(sourceSig) && !getTypePredicateOfSignature(targetSig) && - (getFalsyFlags(sourceType) & TypeFlags.Nullable) === (getFalsyFlags(targetType) & TypeFlags.Nullable); - let related = callbacks ? - compareSignaturesRelated(targetSig!, sourceSig!, (checkMode & SignatureCheckMode.StrictArity) | (strictVariance ? SignatureCheckMode.StrictCallback : SignatureCheckMode.BivariantCallback), reportErrors, errorReporter, incompatibleErrorReporter, compareTypes, reportUnreliableMarkers) : - !(checkMode & SignatureCheckMode.Callback) && !strictVariance && compareTypes(sourceType, targetType, /*reportErrors*/ false) || compareTypes(targetType, sourceType, reportErrors); - // With strict arity, (x: number | undefined) => void is a subtype of (x?: number | undefined) => void - if (related && checkMode & SignatureCheckMode.StrictArity && i >= getMinArgumentCount(source) && i < getMinArgumentCount(target) && compareTypes(sourceType, targetType, /*reportErrors*/ false)) { - related = Ternary.False; - } - if (!related) { - if (reportErrors) { - errorReporter!(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, - unescapeLeadingUnderscores(getParameterNameAtPosition(source, i)), - unescapeLeadingUnderscores(getParameterNameAtPosition(target, i))); - } - return Ternary.False; - } - result &= related; + const sourceType = i === restIndex ? getRestTypeAtPosition(source, i) : getTypeAtPosition(source, i); + const targetType = i === restIndex ? getRestTypeAtPosition(target, i) : getTypeAtPosition(target, i); + // In order to ensure that any generic type Foo is at least co-variant with respect to T no matter + // how Foo uses T, we need to relate parameters bi-variantly (given that parameters are input positions, + // they naturally relate only contra-variantly). However, if the source and target parameters both have + // function types with a single call signature, we know we are relating two callback parameters. In + // that case it is sufficient to only relate the parameters of the signatures co-variantly because, + // similar to return values, callback parameters are output positions. This means that a Promise, + // where T is used only in callback parameter positions, will be co-variant (as opposed to bi-variant) + // with respect to T. + const sourceSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(sourceType)); + const targetSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(targetType)); + const callbacks = sourceSig && targetSig && !getTypePredicateOfSignature(sourceSig) && !getTypePredicateOfSignature(targetSig) && + (getFalsyFlags(sourceType) & TypeFlags.Nullable) === (getFalsyFlags(targetType) & TypeFlags.Nullable); + let related = callbacks ? + compareSignaturesRelated(targetSig!, sourceSig!, (checkMode & SignatureCheckMode.StrictArity) | (strictVariance ? SignatureCheckMode.StrictCallback : SignatureCheckMode.BivariantCallback), reportErrors, errorReporter, incompatibleErrorReporter, compareTypes, reportUnreliableMarkers) : + !(checkMode & SignatureCheckMode.Callback) && !strictVariance && compareTypes(sourceType, targetType, /*reportErrors*/ false) || compareTypes(targetType, sourceType, reportErrors); + // With strict arity, (x: number | undefined) => void is a subtype of (x?: number | undefined) => void + if (related && checkMode & SignatureCheckMode.StrictArity && i >= getMinArgumentCount(source) && i < getMinArgumentCount(target) && compareTypes(sourceType, targetType, /*reportErrors*/ false)) { + related = Ternary.False; } + if (!related) { + if (reportErrors) { + errorReporter!(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, + unescapeLeadingUnderscores(getParameterNameAtPosition(source, i)), + unescapeLeadingUnderscores(getParameterNameAtPosition(target, i))); + } + return Ternary.False; + } + result &= related; } if (!(checkMode & SignatureCheckMode.IgnoreReturnTypes)) { diff --git a/tests/baselines/reference/unmatchedParameterPositions.js b/tests/baselines/reference/unmatchedParameterPositions.js deleted file mode 100644 index 5859091fb0e..00000000000 --- a/tests/baselines/reference/unmatchedParameterPositions.js +++ /dev/null @@ -1,13 +0,0 @@ -//// [unmatchedParameterPositions.ts] -// Repros from #40251 - -declare let s: (...items: never[]) => never[]; -let t1: () => unknown[] = s; -let t2: (...args: []) => unknown[] = s; - - -//// [unmatchedParameterPositions.js] -"use strict"; -// Repros from #40251 -var t1 = s; -var t2 = s; diff --git a/tests/baselines/reference/unmatchedParameterPositions.symbols b/tests/baselines/reference/unmatchedParameterPositions.symbols deleted file mode 100644 index cf7a7c19df6..00000000000 --- a/tests/baselines/reference/unmatchedParameterPositions.symbols +++ /dev/null @@ -1,16 +0,0 @@ -=== tests/cases/compiler/unmatchedParameterPositions.ts === -// Repros from #40251 - -declare let s: (...items: never[]) => never[]; ->s : Symbol(s, Decl(unmatchedParameterPositions.ts, 2, 11)) ->items : Symbol(items, Decl(unmatchedParameterPositions.ts, 2, 16)) - -let t1: () => unknown[] = s; ->t1 : Symbol(t1, Decl(unmatchedParameterPositions.ts, 3, 3)) ->s : Symbol(s, Decl(unmatchedParameterPositions.ts, 2, 11)) - -let t2: (...args: []) => unknown[] = s; ->t2 : Symbol(t2, Decl(unmatchedParameterPositions.ts, 4, 3)) ->args : Symbol(args, Decl(unmatchedParameterPositions.ts, 4, 9)) ->s : Symbol(s, Decl(unmatchedParameterPositions.ts, 2, 11)) - diff --git a/tests/baselines/reference/unmatchedParameterPositions.types b/tests/baselines/reference/unmatchedParameterPositions.types deleted file mode 100644 index 522ac7e0170..00000000000 --- a/tests/baselines/reference/unmatchedParameterPositions.types +++ /dev/null @@ -1,16 +0,0 @@ -=== tests/cases/compiler/unmatchedParameterPositions.ts === -// Repros from #40251 - -declare let s: (...items: never[]) => never[]; ->s : (...items: never[]) => never[] ->items : never[] - -let t1: () => unknown[] = s; ->t1 : () => unknown[] ->s : (...items: never[]) => never[] - -let t2: (...args: []) => unknown[] = s; ->t2 : () => unknown[] ->args : [] ->s : (...items: never[]) => never[] - diff --git a/tests/cases/compiler/unmatchedParameterPositions.ts b/tests/cases/compiler/unmatchedParameterPositions.ts deleted file mode 100644 index 91202eb49da..00000000000 --- a/tests/cases/compiler/unmatchedParameterPositions.ts +++ /dev/null @@ -1,7 +0,0 @@ -// @strict: true - -// Repros from #40251 - -declare let s: (...items: never[]) => never[]; -let t1: () => unknown[] = s; -let t2: (...args: []) => unknown[] = s;