Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 6 additions & 11 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) {
Expand All @@ -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);
Expand Down
119 changes: 119 additions & 0 deletions tests/baselines/reference/forAwaitForIntersection1.symbols
Original file line number Diff line number Diff line change
@@ -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 changes: 115 additions & 0 deletions tests/baselines/reference/forAwaitForIntersection1.types
Original file line number Diff line number Diff line change
@@ -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 changes: 45 additions & 0 deletions tests/cases/compiler/forAwaitForIntersection1.ts
Original file line number Diff line number Diff line change
@@ -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) {}
}