Skip to content

Commit 3267e42

Browse files
authored
Handle silentNeverType in iteration-related functions (#61317)
1 parent 5519be3 commit 3267e42

8 files changed

+564
-0
lines changed

src/compiler/checker.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2180,6 +2180,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
21802180
};
21812181

21822182
var anyIterationTypes = createIterationTypes(anyType, anyType, anyType);
2183+
var silentNeverIterationTypes = createIterationTypes(silentNeverType, silentNeverType, silentNeverType);
21832184

21842185
var asyncIterationTypesResolver: IterationTypesResolver = {
21852186
iterableCacheKey: "iterationTypesOfAsyncIterable",
@@ -39164,6 +39165,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3916439165
}
3916539166

3916639167
function getYieldedTypeOfYieldExpression(node: YieldExpression, expressionType: Type, sentType: Type, isAsync: boolean): Type | undefined {
39168+
if (expressionType === silentNeverType) {
39169+
return silentNeverType;
39170+
}
3916739171
const errorNode = node.expression || node;
3916839172
// A `yield*` expression effectively yields everything that its operand yields
3916939173
const yieldedType = node.asteriskToken ? checkIteratedTypeOrElementType(isAsync ? IterationUse.AsyncYieldStar : IterationUse.YieldStar, expressionType, sentType, errorNode) : expressionType;
@@ -45663,6 +45667,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4566345667
* the `[Symbol.asyncIterator]()` method first, and then the `[Symbol.iterator]()` method.
4566445668
*/
4566545669
function getIterationTypesOfIterable(type: Type, use: IterationUse, errorNode: Node | undefined) {
45670+
if (type === silentNeverType) {
45671+
return silentNeverIterationTypes;
45672+
}
4566645673
if (isTypeAny(type)) {
4566745674
return anyIterationTypes;
4566845675
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
genericCallAtYieldExpressionInGenericCall1.ts(26,25): error TS2488: Type '() => T' must have a '[Symbol.iterator]()' method that returns an iterator.
2+
3+
4+
==== genericCallAtYieldExpressionInGenericCall1.ts (1 errors) ====
5+
declare const inner: {
6+
<A>(value: A): {
7+
(): A;
8+
[Symbol.iterator](): {
9+
next(...args: ReadonlyArray<any>): IteratorResult<any, A>;
10+
};
11+
};
12+
};
13+
14+
declare function outer<A>(body: (value: A) => Generator<any, any, any>): void;
15+
16+
outer(function* <T>(value: T) {
17+
const result = yield* inner(value); // ok
18+
});
19+
20+
outer(function* <T>(value: T) {
21+
const x = inner(value);
22+
const result = yield* x; // ok
23+
});
24+
25+
declare const inner2: {
26+
<A>(value: A): () => A;
27+
};
28+
29+
outer(function* <T>(value: T) {
30+
const result = yield* inner2(value); // error
31+
~~~~~~~~~~~~~
32+
!!! error TS2488: Type '() => T' must have a '[Symbol.iterator]()' method that returns an iterator.
33+
});
34+
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
//// [tests/cases/compiler/genericCallAtYieldExpressionInGenericCall1.ts] ////
2+
3+
=== genericCallAtYieldExpressionInGenericCall1.ts ===
4+
declare const inner: {
5+
>inner : Symbol(inner, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 0, 13))
6+
7+
<A>(value: A): {
8+
>A : Symbol(A, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 1, 3))
9+
>value : Symbol(value, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 1, 6))
10+
>A : Symbol(A, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 1, 3))
11+
12+
(): A;
13+
>A : Symbol(A, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 1, 3))
14+
15+
[Symbol.iterator](): {
16+
>[Symbol.iterator] : Symbol([Symbol.iterator], Decl(genericCallAtYieldExpressionInGenericCall1.ts, 2, 10))
17+
>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --))
18+
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
19+
>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --))
20+
21+
next(...args: ReadonlyArray<any>): IteratorResult<any, A>;
22+
>next : Symbol(next, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 3, 26))
23+
>args : Symbol(args, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 4, 11))
24+
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2016.array.include.d.ts, --, --) ... and 3 more)
25+
>IteratorResult : Symbol(IteratorResult, Decl(lib.es2015.iterable.d.ts, --, --))
26+
>A : Symbol(A, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 1, 3))
27+
28+
};
29+
};
30+
};
31+
32+
declare function outer<A>(body: (value: A) => Generator<any, any, any>): void;
33+
>outer : Symbol(outer, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 7, 2))
34+
>A : Symbol(A, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 9, 23))
35+
>body : Symbol(body, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 9, 26))
36+
>value : Symbol(value, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 9, 33))
37+
>A : Symbol(A, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 9, 23))
38+
>Generator : Symbol(Generator, Decl(lib.es2015.generator.d.ts, --, --))
39+
40+
outer(function* <T>(value: T) {
41+
>outer : Symbol(outer, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 7, 2))
42+
>T : Symbol(T, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 11, 17))
43+
>value : Symbol(value, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 11, 20))
44+
>T : Symbol(T, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 11, 17))
45+
46+
const result = yield* inner(value); // ok
47+
>result : Symbol(result, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 12, 7))
48+
>inner : Symbol(inner, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 0, 13))
49+
>value : Symbol(value, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 11, 20))
50+
51+
});
52+
53+
outer(function* <T>(value: T) {
54+
>outer : Symbol(outer, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 7, 2))
55+
>T : Symbol(T, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 15, 17))
56+
>value : Symbol(value, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 15, 20))
57+
>T : Symbol(T, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 15, 17))
58+
59+
const x = inner(value);
60+
>x : Symbol(x, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 16, 7))
61+
>inner : Symbol(inner, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 0, 13))
62+
>value : Symbol(value, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 15, 20))
63+
64+
const result = yield* x; // ok
65+
>result : Symbol(result, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 17, 7))
66+
>x : Symbol(x, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 16, 7))
67+
68+
});
69+
70+
declare const inner2: {
71+
>inner2 : Symbol(inner2, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 20, 13))
72+
73+
<A>(value: A): () => A;
74+
>A : Symbol(A, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 21, 3))
75+
>value : Symbol(value, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 21, 6))
76+
>A : Symbol(A, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 21, 3))
77+
>A : Symbol(A, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 21, 3))
78+
79+
};
80+
81+
outer(function* <T>(value: T) {
82+
>outer : Symbol(outer, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 7, 2))
83+
>T : Symbol(T, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 24, 17))
84+
>value : Symbol(value, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 24, 20))
85+
>T : Symbol(T, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 24, 17))
86+
87+
const result = yield* inner2(value); // error
88+
>result : Symbol(result, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 25, 7))
89+
>inner2 : Symbol(inner2, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 20, 13))
90+
>value : Symbol(value, Decl(genericCallAtYieldExpressionInGenericCall1.ts, 24, 20))
91+
92+
});
93+
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
//// [tests/cases/compiler/genericCallAtYieldExpressionInGenericCall1.ts] ////
2+
3+
=== Performance Stats ===
4+
Type Count: 1,000
5+
Instantiation count: 2,500
6+
7+
=== genericCallAtYieldExpressionInGenericCall1.ts ===
8+
declare const inner: {
9+
>inner : <A>(value: A) => { (): A; [Symbol.iterator](): { next(...args: ReadonlyArray<any>): IteratorResult<any, A>; }; }
10+
> : ^ ^^ ^^ ^^^^^
11+
12+
<A>(value: A): {
13+
>value : A
14+
> : ^
15+
16+
(): A;
17+
[Symbol.iterator](): {
18+
>[Symbol.iterator] : () => { next(...args: ReadonlyArray<any>): IteratorResult<any, A>; }
19+
> : ^^^^^^
20+
>Symbol.iterator : unique symbol
21+
> : ^^^^^^^^^^^^^
22+
>Symbol : SymbolConstructor
23+
> : ^^^^^^^^^^^^^^^^^
24+
>iterator : unique symbol
25+
> : ^^^^^^^^^^^^^
26+
27+
next(...args: ReadonlyArray<any>): IteratorResult<any, A>;
28+
>next : (...args: ReadonlyArray<any>) => IteratorResult<any, A>
29+
> : ^^^^ ^^ ^^^^^
30+
>args : readonly any[]
31+
> : ^^^^^^^^^^^^^^
32+
33+
};
34+
};
35+
};
36+
37+
declare function outer<A>(body: (value: A) => Generator<any, any, any>): void;
38+
>outer : <A>(body: (value: A) => Generator<any, any, any>) => void
39+
> : ^ ^^ ^^ ^^^^^
40+
>body : (value: A) => Generator<any, any, any>
41+
> : ^ ^^ ^^^^^
42+
>value : A
43+
> : ^
44+
45+
outer(function* <T>(value: T) {
46+
>outer(function* <T>(value: T) { const result = yield* inner(value); // ok}) : void
47+
> : ^^^^
48+
>outer : <A>(body: (value: A) => Generator<any, any, any>) => void
49+
> : ^ ^^ ^^ ^^^^^
50+
>function* <T>(value: T) { const result = yield* inner(value); // ok} : <T>(value: T) => Generator<never, void, never>
51+
> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
52+
>value : T
53+
> : ^
54+
55+
const result = yield* inner(value); // ok
56+
>result : T
57+
> : ^
58+
>yield* inner(value) : T
59+
> : ^
60+
>inner(value) : { (): T; [Symbol.iterator](): { next(...args: ReadonlyArray<any>): IteratorResult<any, T>; }; }
61+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
62+
>inner : <A>(value: A) => { (): A; [Symbol.iterator](): { next(...args: ReadonlyArray<any>): IteratorResult<any, A>; }; }
63+
> : ^ ^^ ^^ ^^^^^
64+
>value : T
65+
> : ^
66+
67+
});
68+
69+
outer(function* <T>(value: T) {
70+
>outer(function* <T>(value: T) { const x = inner(value); const result = yield* x; // ok}) : void
71+
> : ^^^^
72+
>outer : <A>(body: (value: A) => Generator<any, any, any>) => void
73+
> : ^ ^^ ^^ ^^^^^
74+
>function* <T>(value: T) { const x = inner(value); const result = yield* x; // ok} : <T>(value: T) => Generator<any, void, any>
75+
> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
76+
>value : T
77+
> : ^
78+
79+
const x = inner(value);
80+
>x : { (): T; [Symbol.iterator](): { next(...args: ReadonlyArray<any>): IteratorResult<any, T>; }; }
81+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
82+
>inner(value) : { (): T; [Symbol.iterator](): { next(...args: ReadonlyArray<any>): IteratorResult<any, T>; }; }
83+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
84+
>inner : <A>(value: A) => { (): A; [Symbol.iterator](): { next(...args: ReadonlyArray<any>): IteratorResult<any, A>; }; }
85+
> : ^ ^^ ^^ ^^^^^
86+
>value : T
87+
> : ^
88+
89+
const result = yield* x; // ok
90+
>result : T
91+
> : ^
92+
>yield* x : T
93+
> : ^
94+
>x : { (): T; [Symbol.iterator](): { next(...args: ReadonlyArray<any>): IteratorResult<any, T>; }; }
95+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
96+
97+
});
98+
99+
declare const inner2: {
100+
>inner2 : <A>(value: A) => () => A
101+
> : ^ ^^ ^^ ^^^^^
102+
103+
<A>(value: A): () => A;
104+
>value : A
105+
> : ^
106+
107+
};
108+
109+
outer(function* <T>(value: T) {
110+
>outer(function* <T>(value: T) { const result = yield* inner2(value); // error}) : void
111+
> : ^^^^
112+
>outer : <A>(body: (value: A) => Generator<any, any, any>) => void
113+
> : ^ ^^ ^^ ^^^^^
114+
>function* <T>(value: T) { const result = yield* inner2(value); // error} : <T>(value: T) => Generator<never, void, never>
115+
> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
116+
>value : T
117+
> : ^
118+
119+
const result = yield* inner2(value); // error
120+
>result : any
121+
> : ^^^
122+
>yield* inner2(value) : any
123+
> : ^^^
124+
>inner2(value) : () => T
125+
> : ^^^^^^^
126+
>inner2 : <A>(value: A) => () => A
127+
> : ^ ^^ ^^ ^^^^^
128+
>value : T
129+
> : ^
130+
131+
});
132+

0 commit comments

Comments
 (0)