diff --git a/internal/checker/checker.go b/internal/checker/checker.go index cdbff642a0..24edc5d76c 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -470,7 +470,6 @@ const ( IterationUseSpreadFlag IterationUse = 1 << 5 IterationUseDestructuringFlag IterationUse = 1 << 6 IterationUsePossiblyOutOfBounds IterationUse = 1 << 7 - IterationUseReportError IterationUse = 1 << 8 // Spread, Destructuring, Array element assignment IterationUseElement = IterationUseAllowsSyncIterablesFlag IterationUseSpread = IterationUseAllowsSyncIterablesFlag | IterationUseSpreadFlag @@ -481,7 +480,7 @@ const ( IterationUseAsyncYieldStar = IterationUseAllowsSyncIterablesFlag | IterationUseAllowsAsyncIterablesFlag | IterationUseYieldStarFlag IterationUseGeneratorReturnType = IterationUseAllowsSyncIterablesFlag IterationUseAsyncGeneratorReturnType = IterationUseAllowsAsyncIterablesFlag - IterationUseCacheFlags = IterationUseAllowsSyncIterablesFlag | IterationUseAllowsAsyncIterablesFlag | IterationUseForOfFlag | IterationUseReportError + IterationUseCacheFlags = IterationUseAllowsSyncIterablesFlag | IterationUseAllowsAsyncIterablesFlag | IterationUseForOfFlag ) type IterationTypes struct { @@ -5900,18 +5899,26 @@ func (c *Checker) getIterationTypesOfIterable(t *Type, use IterationUse, errorNo if IsTypeAny(t) { return IterationTypes{c.anyType, c.anyType, c.anyType} } - key := IterationTypesKey{typeId: t.id, use: use&IterationUseCacheFlags | core.IfElse(errorNode != nil, IterationUseReportError, 0)} + key := IterationTypesKey{typeId: t.id, use: use & IterationUseCacheFlags} + // If we are reporting errors and encounter a cached `noIterationTypes`, we should ignore the cached value and continue as if nothing was cached. + // In addition, we should not cache any new results for this call. + noCache := false if cached, ok := c.iterationTypesCache[key]; ok { - return cached + if errorNode == nil || cached.hasTypes() { + return cached + } + noCache = true + } + result := c.getIterationTypesOfIterableWorker(t, use, errorNode, noCache) + if !noCache { + c.iterationTypesCache[key] = result } - result := c.getIterationTypesOfIterableWorker(t, use, errorNode) - c.iterationTypesCache[key] = result return result } -func (c *Checker) getIterationTypesOfIterableWorker(t *Type, use IterationUse, errorNode *ast.Node) IterationTypes { +func (c *Checker) getIterationTypesOfIterableWorker(t *Type, use IterationUse, errorNode *ast.Node, noCache bool) IterationTypes { if t.flags&TypeFlagsUnion != 0 { - return c.combineIterationTypes(core.Map(t.Types(), func(t *Type) IterationTypes { return c.getIterationTypesOfIterableWorker(t, use, errorNode) })) + return c.combineIterationTypes(core.Map(t.Types(), func(t *Type) IterationTypes { return c.getIterationTypesOfIterableWorker(t, use, errorNode, noCache) })) } if use&IterationUseAllowsAsyncIterablesFlag != 0 { iterationTypes := c.getIterationTypesOfIterableFast(t, c.asyncIterationTypesResolver) diff --git a/testdata/baselines/reference/submodule/compiler/omittedExpressionForOfLoop.errors.txt b/testdata/baselines/reference/submodule/compiler/omittedExpressionForOfLoop.errors.txt index 1bab467dde..257dcb21ae 100644 --- a/testdata/baselines/reference/submodule/compiler/omittedExpressionForOfLoop.errors.txt +++ b/testdata/baselines/reference/submodule/compiler/omittedExpressionForOfLoop.errors.txt @@ -1,9 +1,10 @@ omittedExpressionForOfLoop.ts(1,19): error TS2304: Cannot find name 'doesNotExist'. omittedExpressionForOfLoop.ts(4,19): error TS18050: The value 'undefined' cannot be used here. omittedExpressionForOfLoop.ts(7,12): error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator. +omittedExpressionForOfLoop.ts(10,12): error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator. -==== omittedExpressionForOfLoop.ts (3 errors) ==== +==== omittedExpressionForOfLoop.ts (4 errors) ==== for (const [,] of doesNotExist) { ~~~~~~~~~~~~ !!! error TS2304: Cannot find name 'doesNotExist'. @@ -20,4 +21,6 @@ omittedExpressionForOfLoop.ts(7,12): error TS2488: Type 'never' must have a '[Sy } for (const [] of []) { + ~~ +!!! error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator. } \ No newline at end of file diff --git a/testdata/baselines/reference/submodule/compiler/omittedExpressionForOfLoop.errors.txt.diff b/testdata/baselines/reference/submodule/compiler/omittedExpressionForOfLoop.errors.txt.diff deleted file mode 100644 index e2e84af17f..0000000000 --- a/testdata/baselines/reference/submodule/compiler/omittedExpressionForOfLoop.errors.txt.diff +++ /dev/null @@ -1,23 +0,0 @@ ---- old.omittedExpressionForOfLoop.errors.txt -+++ new.omittedExpressionForOfLoop.errors.txt -@@= skipped -0, +0 lines =@@ - omittedExpressionForOfLoop.ts(1,19): error TS2304: Cannot find name 'doesNotExist'. - omittedExpressionForOfLoop.ts(4,19): error TS18050: The value 'undefined' cannot be used here. - omittedExpressionForOfLoop.ts(7,12): error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator. --omittedExpressionForOfLoop.ts(10,12): error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator. -- -- --==== omittedExpressionForOfLoop.ts (4 errors) ==== -+ -+ -+==== omittedExpressionForOfLoop.ts (3 errors) ==== - for (const [,] of doesNotExist) { - ~~~~~~~~~~~~ - !!! error TS2304: Cannot find name 'doesNotExist'. -@@= skipped -20, +19 lines =@@ - } - - for (const [] of []) { -- ~~ --!!! error TS2488: Type 'never' must have a '[Symbol.iterator]()' method that returns an iterator. - } \ No newline at end of file diff --git a/testdata/baselines/reference/submodule/conformance/for-of16.errors.txt b/testdata/baselines/reference/submodule/conformance/for-of16.errors.txt index 2e7a31eef3..0af867a2c6 100644 --- a/testdata/baselines/reference/submodule/conformance/for-of16.errors.txt +++ b/testdata/baselines/reference/submodule/conformance/for-of16.errors.txt @@ -1,7 +1,8 @@ for-of16.ts(8,11): error TS2488: Type 'MyStringIterator' must have a '[Symbol.iterator]()' method that returns an iterator. +for-of16.ts(10,11): error TS2488: Type 'MyStringIterator' must have a '[Symbol.iterator]()' method that returns an iterator. -==== for-of16.ts (1 errors) ==== +==== for-of16.ts (2 errors) ==== class MyStringIterator { [Symbol.iterator]() { return this; @@ -14,4 +15,7 @@ for-of16.ts(8,11): error TS2488: Type 'MyStringIterator' must have a '[Symbol.it !!! error TS2488: Type 'MyStringIterator' must have a '[Symbol.iterator]()' method that returns an iterator. !!! related TS2489 for-of16.ts:8:11: An iterator must have a 'next()' method. - for (v of new MyStringIterator) { } // Should still fail (related errors should still be shown even though type is cached). \ No newline at end of file + for (v of new MyStringIterator) { } // Should still fail (related errors should still be shown even though type is cached). + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2488: Type 'MyStringIterator' must have a '[Symbol.iterator]()' method that returns an iterator. +!!! related TS2489 for-of16.ts:10:11: An iterator must have a 'next()' method. \ No newline at end of file diff --git a/testdata/baselines/reference/submodule/conformance/for-of16.errors.txt.diff b/testdata/baselines/reference/submodule/conformance/for-of16.errors.txt.diff deleted file mode 100644 index 0e4bfaa922..0000000000 --- a/testdata/baselines/reference/submodule/conformance/for-of16.errors.txt.diff +++ /dev/null @@ -1,21 +0,0 @@ ---- old.for-of16.errors.txt -+++ new.for-of16.errors.txt -@@= skipped -0, +0 lines =@@ - for-of16.ts(8,11): error TS2488: Type 'MyStringIterator' must have a '[Symbol.iterator]()' method that returns an iterator. --for-of16.ts(10,11): error TS2488: Type 'MyStringIterator' must have a '[Symbol.iterator]()' method that returns an iterator. -- -- --==== for-of16.ts (2 errors) ==== -+ -+ -+==== for-of16.ts (1 errors) ==== - class MyStringIterator { - [Symbol.iterator]() { - return this; -@@= skipped -15, +14 lines =@@ - !!! related TS2489 for-of16.ts:8:11: An iterator must have a 'next()' method. - - for (v of new MyStringIterator) { } // Should still fail (related errors should still be shown even though type is cached). -- ~~~~~~~~~~~~~~~~~~~~ --!!! error TS2488: Type 'MyStringIterator' must have a '[Symbol.iterator]()' method that returns an iterator. --!!! related TS2489 for-of16.ts:10:11: An iterator must have a 'next()' method. \ No newline at end of file diff --git a/testdata/baselines/reference/submodule/conformance/types.forAwait.es2018.2.errors.txt b/testdata/baselines/reference/submodule/conformance/types.forAwait.es2018.2.errors.txt index df9005679a..b0635928d4 100644 --- a/testdata/baselines/reference/submodule/conformance/types.forAwait.es2018.2.errors.txt +++ b/testdata/baselines/reference/submodule/conformance/types.forAwait.es2018.2.errors.txt @@ -3,9 +3,10 @@ types.forAwait.es2018.2.ts(8,21): error TS2504: Type '{}' must have a '[Symbol.a types.forAwait.es2018.2.ts(10,16): error TS2322: Type 'number' is not assignable to type 'string'. types.forAwait.es2018.2.ts(12,16): error TS2322: Type 'number' is not assignable to type 'string'. types.forAwait.es2018.2.ts(14,21): error TS2488: Type 'AsyncIterable' must have a '[Symbol.iterator]()' method that returns an iterator. +types.forAwait.es2018.2.ts(16,15): error TS2488: Type 'AsyncIterable' must have a '[Symbol.iterator]()' method that returns an iterator. -==== types.forAwait.es2018.2.ts (5 errors) ==== +==== types.forAwait.es2018.2.ts (6 errors) ==== declare const asyncIterable: AsyncIterable; declare const iterable: Iterable; async function f() { @@ -33,6 +34,9 @@ types.forAwait.es2018.2.ts(14,21): error TS2488: Type 'AsyncIterable' mu !!! related TS2773 types.forAwait.es2018.2.ts:14:21: Did you forget to use 'await'? } for (y of asyncIterable) { + ~~~~~~~~~~~~~ +!!! error TS2488: Type 'AsyncIterable' must have a '[Symbol.iterator]()' method that returns an iterator. +!!! related TS2773 types.forAwait.es2018.2.ts:16:15: Did you forget to use 'await'? } } \ No newline at end of file diff --git a/testdata/baselines/reference/submodule/conformance/types.forAwait.es2018.2.errors.txt.diff b/testdata/baselines/reference/submodule/conformance/types.forAwait.es2018.2.errors.txt.diff deleted file mode 100644 index 19233fc836..0000000000 --- a/testdata/baselines/reference/submodule/conformance/types.forAwait.es2018.2.errors.txt.diff +++ /dev/null @@ -1,26 +0,0 @@ ---- old.types.forAwait.es2018.2.errors.txt -+++ new.types.forAwait.es2018.2.errors.txt -@@= skipped -2, +2 lines =@@ - types.forAwait.es2018.2.ts(10,16): error TS2322: Type 'number' is not assignable to type 'string'. - types.forAwait.es2018.2.ts(12,16): error TS2322: Type 'number' is not assignable to type 'string'. - types.forAwait.es2018.2.ts(14,21): error TS2488: Type 'AsyncIterable' must have a '[Symbol.iterator]()' method that returns an iterator. --types.forAwait.es2018.2.ts(16,15): error TS2488: Type 'AsyncIterable' must have a '[Symbol.iterator]()' method that returns an iterator. -- -- --==== types.forAwait.es2018.2.ts (6 errors) ==== -+ -+ -+==== types.forAwait.es2018.2.ts (5 errors) ==== - declare const asyncIterable: AsyncIterable; - declare const iterable: Iterable; - async function f() { -@@= skipped -31, +30 lines =@@ - !!! related TS2773 types.forAwait.es2018.2.ts:14:21: Did you forget to use 'await'? - } - for (y of asyncIterable) { -- ~~~~~~~~~~~~~ --!!! error TS2488: Type 'AsyncIterable' must have a '[Symbol.iterator]()' method that returns an iterator. --!!! related TS2773 types.forAwait.es2018.2.ts:16:15: Did you forget to use 'await'? - } - } - \ No newline at end of file