From a287ddc93bda8043ca4c6b5f1cbf15f25c50791c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 6 Nov 2017 09:25:41 -0800 Subject: [PATCH] Fix invariant generic error elaboration logic --- src/compiler/checker.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e2e45b2ccb0..4d5449a9526 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9432,6 +9432,7 @@ namespace ts { function structuredTypeRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary { let result: Ternary; + let originalErrorInfo: DiagnosticMessageChain; const saveErrorInfo = errorInfo; if (target.flags & TypeFlags.TypeParameter) { // A source type { [P in keyof T]: X } is related to a target type T if X is related to T[P]. @@ -9511,6 +9512,7 @@ namespace ts { // if we have indexed access types with identical index types, see if relationship holds for // the two object types. if (result = isRelatedTo((source).objectType, (target).objectType, reportErrors)) { + errorInfo = saveErrorInfo; return result; } } @@ -9542,6 +9544,10 @@ namespace ts { if (!(reportErrors && some(variances, v => v === Variance.Invariant))) { return Ternary.False; } + // We remember the original error information so we can restore it in case the structural + // comparison unexpectedly succeeds. This can happen when the structural comparison result + // is a Ternary.Maybe for example caused by the recursion depth limiter. + originalErrorInfo = errorInfo; errorInfo = saveErrorInfo; } } @@ -9580,8 +9586,11 @@ namespace ts { } } if (result) { - errorInfo = saveErrorInfo; - return result; + if (!originalErrorInfo) { + errorInfo = saveErrorInfo; + return result; + } + errorInfo = originalErrorInfo; } } }