mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-12-10 00:20:22 -06:00
Fixed an issue with "slow" sync iteration types spoiling cached value for async ones (#62676)
This commit is contained in:
parent
11ee01b22d
commit
2a90a739c1
@ -45924,7 +45924,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
let noCache = false;
|
||||
|
||||
if (use & IterationUse.AllowsAsyncIterablesFlag) {
|
||||
const iterationTypes = getIterationTypesOfIterableCached(type, asyncIterationTypesResolver) ||
|
||||
let iterationTypes = getIterationTypesOfIterableCached(type, asyncIterationTypesResolver) ||
|
||||
getIterationTypesOfIterableFast(type, asyncIterationTypesResolver);
|
||||
if (iterationTypes) {
|
||||
if (iterationTypes === noIterationTypes && errorNode) {
|
||||
@ -45937,6 +45937,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
iterationTypes;
|
||||
}
|
||||
}
|
||||
iterationTypes = getIterationTypesOfIterableSlow(type, asyncIterationTypesResolver, errorNode, errorOutputContainer, noCache);
|
||||
if (iterationTypes !== noIterationTypes) {
|
||||
return iterationTypes;
|
||||
}
|
||||
}
|
||||
|
||||
if (use & IterationUse.AllowsSyncIterablesFlag) {
|
||||
@ -45960,17 +45964,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (use & IterationUse.AllowsAsyncIterablesFlag) {
|
||||
const iterationTypes = getIterationTypesOfIterableSlow(type, asyncIterationTypesResolver, errorNode, errorOutputContainer, noCache);
|
||||
if (iterationTypes !== noIterationTypes) {
|
||||
return iterationTypes;
|
||||
}
|
||||
}
|
||||
|
||||
if (use & IterationUse.AllowsSyncIterablesFlag) {
|
||||
let iterationTypes = getIterationTypesOfIterableSlow(type, syncIterationTypesResolver, errorNode, errorOutputContainer, noCache);
|
||||
iterationTypes = getIterationTypesOfIterableSlow(type, syncIterationTypesResolver, errorNode, errorOutputContainer, noCache);
|
||||
if (iterationTypes !== noIterationTypes) {
|
||||
if (use & IterationUse.AllowsAsyncIterablesFlag) {
|
||||
iterationTypes = getAsyncFromSyncIterationTypes(iterationTypes, errorNode);
|
||||
|
||||
119
tests/baselines/reference/forAwaitForIntersection1.symbols
Normal file
119
tests/baselines/reference/forAwaitForIntersection1.symbols
Normal file
@ -0,0 +1,119 @@
|
||||
//// [tests/cases/compiler/forAwaitForIntersection1.ts] ////
|
||||
|
||||
=== forAwaitForIntersection1.ts ===
|
||||
type Stream1<T_Sync, T_Async> = Iterable<T_Sync> & AsyncIterable<T_Async>;
|
||||
>Stream1 : Symbol(Stream1, Decl(forAwaitForIntersection1.ts, 0, 0))
|
||||
>T_Sync : Symbol(T_Sync, Decl(forAwaitForIntersection1.ts, 0, 13))
|
||||
>T_Async : Symbol(T_Async, Decl(forAwaitForIntersection1.ts, 0, 20))
|
||||
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
|
||||
>T_Sync : Symbol(T_Sync, Decl(forAwaitForIntersection1.ts, 0, 13))
|
||||
>AsyncIterable : Symbol(AsyncIterable, Decl(lib.es2018.asynciterable.d.ts, --, --))
|
||||
>T_Async : Symbol(T_Async, Decl(forAwaitForIntersection1.ts, 0, 20))
|
||||
|
||||
class A1 {}
|
||||
>A1 : Symbol(A1, Decl(forAwaitForIntersection1.ts, 0, 74))
|
||||
|
||||
class B1 {}
|
||||
>B1 : Symbol(B1, Decl(forAwaitForIntersection1.ts, 2, 11))
|
||||
|
||||
async function loop1(stream: Stream1<A1, B1>) {
|
||||
>loop1 : Symbol(loop1, Decl(forAwaitForIntersection1.ts, 3, 11))
|
||||
>stream : Symbol(stream, Decl(forAwaitForIntersection1.ts, 5, 21))
|
||||
>Stream1 : Symbol(Stream1, Decl(forAwaitForIntersection1.ts, 0, 0))
|
||||
>A1 : Symbol(A1, Decl(forAwaitForIntersection1.ts, 0, 74))
|
||||
>B1 : Symbol(B1, Decl(forAwaitForIntersection1.ts, 2, 11))
|
||||
|
||||
for await (const b of stream) {}
|
||||
>b : Symbol(b, Decl(forAwaitForIntersection1.ts, 6, 18))
|
||||
>stream : Symbol(stream, Decl(forAwaitForIntersection1.ts, 5, 21))
|
||||
}
|
||||
|
||||
type Stream2<T_Sync, T_Async> = Iterable<T_Sync> & AsyncIterable<T_Async>;
|
||||
>Stream2 : Symbol(Stream2, Decl(forAwaitForIntersection1.ts, 7, 1))
|
||||
>T_Sync : Symbol(T_Sync, Decl(forAwaitForIntersection1.ts, 9, 13))
|
||||
>T_Async : Symbol(T_Async, Decl(forAwaitForIntersection1.ts, 9, 20))
|
||||
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
|
||||
>T_Sync : Symbol(T_Sync, Decl(forAwaitForIntersection1.ts, 9, 13))
|
||||
>AsyncIterable : Symbol(AsyncIterable, Decl(lib.es2018.asynciterable.d.ts, --, --))
|
||||
>T_Async : Symbol(T_Async, Decl(forAwaitForIntersection1.ts, 9, 20))
|
||||
|
||||
class A2 {}
|
||||
>A2 : Symbol(A2, Decl(forAwaitForIntersection1.ts, 9, 74))
|
||||
|
||||
class B2 {}
|
||||
>B2 : Symbol(B2, Decl(forAwaitForIntersection1.ts, 11, 11))
|
||||
|
||||
async function loop2(stream: Stream2<A2, B2>) {
|
||||
>loop2 : Symbol(loop2, Decl(forAwaitForIntersection1.ts, 12, 11))
|
||||
>stream : Symbol(stream, Decl(forAwaitForIntersection1.ts, 14, 21))
|
||||
>Stream2 : Symbol(Stream2, Decl(forAwaitForIntersection1.ts, 7, 1))
|
||||
>A2 : Symbol(A2, Decl(forAwaitForIntersection1.ts, 9, 74))
|
||||
>B2 : Symbol(B2, Decl(forAwaitForIntersection1.ts, 11, 11))
|
||||
|
||||
for (const a of stream) {}
|
||||
>a : Symbol(a, Decl(forAwaitForIntersection1.ts, 15, 12))
|
||||
>stream : Symbol(stream, Decl(forAwaitForIntersection1.ts, 14, 21))
|
||||
}
|
||||
|
||||
type Stream3<T_Sync, T_Async> = Iterable<T_Sync> & AsyncIterable<T_Async>;
|
||||
>Stream3 : Symbol(Stream3, Decl(forAwaitForIntersection1.ts, 16, 1))
|
||||
>T_Sync : Symbol(T_Sync, Decl(forAwaitForIntersection1.ts, 18, 13))
|
||||
>T_Async : Symbol(T_Async, Decl(forAwaitForIntersection1.ts, 18, 20))
|
||||
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
|
||||
>T_Sync : Symbol(T_Sync, Decl(forAwaitForIntersection1.ts, 18, 13))
|
||||
>AsyncIterable : Symbol(AsyncIterable, Decl(lib.es2018.asynciterable.d.ts, --, --))
|
||||
>T_Async : Symbol(T_Async, Decl(forAwaitForIntersection1.ts, 18, 20))
|
||||
|
||||
class A3 {}
|
||||
>A3 : Symbol(A3, Decl(forAwaitForIntersection1.ts, 18, 74))
|
||||
|
||||
class B3 {}
|
||||
>B3 : Symbol(B3, Decl(forAwaitForIntersection1.ts, 20, 11))
|
||||
|
||||
async function loop3(stream: Stream3<A3, B3>) {
|
||||
>loop3 : Symbol(loop3, Decl(forAwaitForIntersection1.ts, 21, 11))
|
||||
>stream : Symbol(stream, Decl(forAwaitForIntersection1.ts, 23, 21))
|
||||
>Stream3 : Symbol(Stream3, Decl(forAwaitForIntersection1.ts, 16, 1))
|
||||
>A3 : Symbol(A3, Decl(forAwaitForIntersection1.ts, 18, 74))
|
||||
>B3 : Symbol(B3, Decl(forAwaitForIntersection1.ts, 20, 11))
|
||||
|
||||
for await (const b of stream) {}
|
||||
>b : Symbol(b, Decl(forAwaitForIntersection1.ts, 24, 18))
|
||||
>stream : Symbol(stream, Decl(forAwaitForIntersection1.ts, 23, 21))
|
||||
|
||||
for (const a of stream) {}
|
||||
>a : Symbol(a, Decl(forAwaitForIntersection1.ts, 26, 12))
|
||||
>stream : Symbol(stream, Decl(forAwaitForIntersection1.ts, 23, 21))
|
||||
}
|
||||
|
||||
type Stream4<T_Sync, T_Async> = Iterable<T_Sync> & AsyncIterable<T_Async>;
|
||||
>Stream4 : Symbol(Stream4, Decl(forAwaitForIntersection1.ts, 27, 1))
|
||||
>T_Sync : Symbol(T_Sync, Decl(forAwaitForIntersection1.ts, 29, 13))
|
||||
>T_Async : Symbol(T_Async, Decl(forAwaitForIntersection1.ts, 29, 20))
|
||||
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
|
||||
>T_Sync : Symbol(T_Sync, Decl(forAwaitForIntersection1.ts, 29, 13))
|
||||
>AsyncIterable : Symbol(AsyncIterable, Decl(lib.es2018.asynciterable.d.ts, --, --))
|
||||
>T_Async : Symbol(T_Async, Decl(forAwaitForIntersection1.ts, 29, 20))
|
||||
|
||||
class A4 {}
|
||||
>A4 : Symbol(A4, Decl(forAwaitForIntersection1.ts, 29, 74))
|
||||
|
||||
class B4 {}
|
||||
>B4 : Symbol(B4, Decl(forAwaitForIntersection1.ts, 31, 11))
|
||||
|
||||
// verify that resolving sync iteration first doesn't spoil the type for async iteration
|
||||
async function loop4(stream: Stream4<A4, B4>) {
|
||||
>loop4 : Symbol(loop4, Decl(forAwaitForIntersection1.ts, 32, 11))
|
||||
>stream : Symbol(stream, Decl(forAwaitForIntersection1.ts, 35, 21))
|
||||
>Stream4 : Symbol(Stream4, Decl(forAwaitForIntersection1.ts, 27, 1))
|
||||
>A4 : Symbol(A4, Decl(forAwaitForIntersection1.ts, 29, 74))
|
||||
>B4 : Symbol(B4, Decl(forAwaitForIntersection1.ts, 31, 11))
|
||||
|
||||
for (const a of stream) {}
|
||||
>a : Symbol(a, Decl(forAwaitForIntersection1.ts, 36, 12))
|
||||
>stream : Symbol(stream, Decl(forAwaitForIntersection1.ts, 35, 21))
|
||||
|
||||
for await (const b of stream) {}
|
||||
>b : Symbol(b, Decl(forAwaitForIntersection1.ts, 38, 18))
|
||||
>stream : Symbol(stream, Decl(forAwaitForIntersection1.ts, 35, 21))
|
||||
}
|
||||
115
tests/baselines/reference/forAwaitForIntersection1.types
Normal file
115
tests/baselines/reference/forAwaitForIntersection1.types
Normal file
@ -0,0 +1,115 @@
|
||||
//// [tests/cases/compiler/forAwaitForIntersection1.ts] ////
|
||||
|
||||
=== forAwaitForIntersection1.ts ===
|
||||
type Stream1<T_Sync, T_Async> = Iterable<T_Sync> & AsyncIterable<T_Async>;
|
||||
>Stream1 : Stream1<T_Sync, T_Async>
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
class A1 {}
|
||||
>A1 : A1
|
||||
> : ^^
|
||||
|
||||
class B1 {}
|
||||
>B1 : B1
|
||||
> : ^^
|
||||
|
||||
async function loop1(stream: Stream1<A1, B1>) {
|
||||
>loop1 : (stream: Stream1<A1, B1>) => Promise<void>
|
||||
> : ^ ^^ ^^^^^^^^^^^^^^^^^^
|
||||
>stream : Stream1<A1, B1>
|
||||
> : ^^^^^^^^^^^^^^^
|
||||
|
||||
for await (const b of stream) {}
|
||||
>b : B1
|
||||
> : ^^
|
||||
>stream : Stream1<A1, B1>
|
||||
> : ^^^^^^^^^^^^^^^
|
||||
}
|
||||
|
||||
type Stream2<T_Sync, T_Async> = Iterable<T_Sync> & AsyncIterable<T_Async>;
|
||||
>Stream2 : Stream2<T_Sync, T_Async>
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
class A2 {}
|
||||
>A2 : A2
|
||||
> : ^^
|
||||
|
||||
class B2 {}
|
||||
>B2 : B2
|
||||
> : ^^
|
||||
|
||||
async function loop2(stream: Stream2<A2, B2>) {
|
||||
>loop2 : (stream: Stream2<A2, B2>) => Promise<void>
|
||||
> : ^ ^^ ^^^^^^^^^^^^^^^^^^
|
||||
>stream : Stream2<A2, B2>
|
||||
> : ^^^^^^^^^^^^^^^
|
||||
|
||||
for (const a of stream) {}
|
||||
>a : A2
|
||||
> : ^^
|
||||
>stream : Stream2<A2, B2>
|
||||
> : ^^^^^^^^^^^^^^^
|
||||
}
|
||||
|
||||
type Stream3<T_Sync, T_Async> = Iterable<T_Sync> & AsyncIterable<T_Async>;
|
||||
>Stream3 : Stream3<T_Sync, T_Async>
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
class A3 {}
|
||||
>A3 : A3
|
||||
> : ^^
|
||||
|
||||
class B3 {}
|
||||
>B3 : B3
|
||||
> : ^^
|
||||
|
||||
async function loop3(stream: Stream3<A3, B3>) {
|
||||
>loop3 : (stream: Stream3<A3, B3>) => Promise<void>
|
||||
> : ^ ^^ ^^^^^^^^^^^^^^^^^^
|
||||
>stream : Stream3<A3, B3>
|
||||
> : ^^^^^^^^^^^^^^^
|
||||
|
||||
for await (const b of stream) {}
|
||||
>b : B3
|
||||
> : ^^
|
||||
>stream : Stream3<A3, B3>
|
||||
> : ^^^^^^^^^^^^^^^
|
||||
|
||||
for (const a of stream) {}
|
||||
>a : A3
|
||||
> : ^^
|
||||
>stream : Stream3<A3, B3>
|
||||
> : ^^^^^^^^^^^^^^^
|
||||
}
|
||||
|
||||
type Stream4<T_Sync, T_Async> = Iterable<T_Sync> & AsyncIterable<T_Async>;
|
||||
>Stream4 : Stream4<T_Sync, T_Async>
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
class A4 {}
|
||||
>A4 : A4
|
||||
> : ^^
|
||||
|
||||
class B4 {}
|
||||
>B4 : B4
|
||||
> : ^^
|
||||
|
||||
// verify that resolving sync iteration first doesn't spoil the type for async iteration
|
||||
async function loop4(stream: Stream4<A4, B4>) {
|
||||
>loop4 : (stream: Stream4<A4, B4>) => Promise<void>
|
||||
> : ^ ^^ ^^^^^^^^^^^^^^^^^^
|
||||
>stream : Stream4<A4, B4>
|
||||
> : ^^^^^^^^^^^^^^^
|
||||
|
||||
for (const a of stream) {}
|
||||
>a : A4
|
||||
> : ^^
|
||||
>stream : Stream4<A4, B4>
|
||||
> : ^^^^^^^^^^^^^^^
|
||||
|
||||
for await (const b of stream) {}
|
||||
>b : B4
|
||||
> : ^^
|
||||
>stream : Stream4<A4, B4>
|
||||
> : ^^^^^^^^^^^^^^^
|
||||
}
|
||||
45
tests/cases/compiler/forAwaitForIntersection1.ts
Normal file
45
tests/cases/compiler/forAwaitForIntersection1.ts
Normal file
@ -0,0 +1,45 @@
|
||||
// @strict: true
|
||||
// @target: es2018
|
||||
// @lib: esnext
|
||||
// @noEmit: true
|
||||
|
||||
type Stream1<T_Sync, T_Async> = Iterable<T_Sync> & AsyncIterable<T_Async>;
|
||||
|
||||
class A1 {}
|
||||
class B1 {}
|
||||
|
||||
async function loop1(stream: Stream1<A1, B1>) {
|
||||
for await (const b of stream) {}
|
||||
}
|
||||
|
||||
type Stream2<T_Sync, T_Async> = Iterable<T_Sync> & AsyncIterable<T_Async>;
|
||||
|
||||
class A2 {}
|
||||
class B2 {}
|
||||
|
||||
async function loop2(stream: Stream2<A2, B2>) {
|
||||
for (const a of stream) {}
|
||||
}
|
||||
|
||||
type Stream3<T_Sync, T_Async> = Iterable<T_Sync> & AsyncIterable<T_Async>;
|
||||
|
||||
class A3 {}
|
||||
class B3 {}
|
||||
|
||||
async function loop3(stream: Stream3<A3, B3>) {
|
||||
for await (const b of stream) {}
|
||||
|
||||
for (const a of stream) {}
|
||||
}
|
||||
|
||||
type Stream4<T_Sync, T_Async> = Iterable<T_Sync> & AsyncIterable<T_Async>;
|
||||
|
||||
class A4 {}
|
||||
class B4 {}
|
||||
|
||||
// verify that resolving sync iteration first doesn't spoil the type for async iteration
|
||||
async function loop4(stream: Stream4<A4, B4>) {
|
||||
for (const a of stream) {}
|
||||
|
||||
for await (const b of stream) {}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user