Skip to content

Don't treat return as a yield #22299

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
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
9 changes: 5 additions & 4 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
@@ -18304,10 +18304,10 @@ namespace ts {
}
}
else {
let types = checkAndAggregateReturnExpressionTypes(func, checkMode);
let types: Type[];
if (functionFlags & FunctionFlags.Generator) { // Generator or AsyncGenerator function
types = concatenate(checkAndAggregateYieldOperandTypes(func, checkMode), types);
if (!types || types.length === 0) {
types = checkAndAggregateYieldOperandTypes(func, checkMode);
if (types.length === 0) {
const iterableIteratorAny = functionFlags & FunctionFlags.Async
? createAsyncIterableIteratorType(anyType) // AsyncGenerator function
: createIterableIteratorType(anyType); // Generator function
@@ -18319,6 +18319,7 @@ namespace ts {
}
}
else {
types = checkAndAggregateReturnExpressionTypes(func, checkMode);
if (!types) {
// For an async function, the return type will not be never, but rather a Promise for never.
return functionFlags & FunctionFlags.Async
@@ -18394,7 +18395,7 @@ namespace ts {
? Diagnostics.Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member
: Diagnostics.Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
}
pushIfUnique(aggregatedTypes, type);
aggregatedTypes.push(type);
}
});

Original file line number Diff line number Diff line change
@@ -80,7 +80,7 @@ class C7 {
>C7 : C7

async * f() {
>f : () => AsyncIterableIterator<number>
>f : () => AsyncIterableIterator<any>

return 1;
>1 : 1
Original file line number Diff line number Diff line change
@@ -80,7 +80,7 @@ class C7 {
>C7 : C7

async * f() {
>f : () => AsyncIterableIterator<number>
>f : () => AsyncIterableIterator<any>

return 1;
>1 : 1
Original file line number Diff line number Diff line change
@@ -80,7 +80,7 @@ class C7 {
>C7 : C7

async * f() {
>f : () => AsyncIterableIterator<number>
>f : () => AsyncIterableIterator<any>

return 1;
>1 : 1
Original file line number Diff line number Diff line change
@@ -53,7 +53,7 @@ async function * f6() {
}
=== tests/cases/conformance/emitter/es2015/asyncGenerators/F7.ts ===
async function * f7() {
>f7 : () => AsyncIterableIterator<number>
>f7 : () => AsyncIterableIterator<any>

return 1;
>1 : 1
Original file line number Diff line number Diff line change
@@ -53,7 +53,7 @@ async function * f6() {
}
=== tests/cases/conformance/emitter/es5/asyncGenerators/F7.ts ===
async function * f7() {
>f7 : () => AsyncIterableIterator<number>
>f7 : () => AsyncIterableIterator<any>

return 1;
>1 : 1
Original file line number Diff line number Diff line change
@@ -53,7 +53,7 @@ async function * f6() {
}
=== tests/cases/conformance/emitter/esnext/asyncGenerators/F7.ts ===
async function * f7() {
>f7 : () => AsyncIterableIterator<number>
>f7 : () => AsyncIterableIterator<any>

return 1;
>1 : 1
Original file line number Diff line number Diff line change
@@ -59,8 +59,8 @@ const f6 = async function * () {
}
=== tests/cases/conformance/emitter/es2015/asyncGenerators/F7.ts ===
const f7 = async function * () {
>f7 : () => AsyncIterableIterator<number>
>async function * () { return 1;} : () => AsyncIterableIterator<number>
>f7 : () => AsyncIterableIterator<any>
>async function * () { return 1;} : () => AsyncIterableIterator<any>

return 1;
>1 : 1
Original file line number Diff line number Diff line change
@@ -59,8 +59,8 @@ const f6 = async function * () {
}
=== tests/cases/conformance/emitter/es5/asyncGenerators/F7.ts ===
const f7 = async function * () {
>f7 : () => AsyncIterableIterator<number>
>async function * () { return 1;} : () => AsyncIterableIterator<number>
>f7 : () => AsyncIterableIterator<any>
>async function * () { return 1;} : () => AsyncIterableIterator<any>

return 1;
>1 : 1
Original file line number Diff line number Diff line change
@@ -59,8 +59,8 @@ const f6 = async function * () {
}
=== tests/cases/conformance/emitter/esnext/asyncGenerators/F7.ts ===
const f7 = async function * () {
>f7 : () => AsyncIterableIterator<number>
>async function * () { return 1;} : () => AsyncIterableIterator<number>
>f7 : () => AsyncIterableIterator<any>
>async function * () { return 1;} : () => AsyncIterableIterator<any>

return 1;
>1 : 1
Original file line number Diff line number Diff line change
@@ -83,11 +83,11 @@ const o6 = {
}
=== tests/cases/conformance/emitter/es2015/asyncGenerators/O7.ts ===
const o7 = {
>o7 : { f(): AsyncIterableIterator<number>; }
>{ async * f() { return 1; }} : { f(): AsyncIterableIterator<number>; }
>o7 : { f(): AsyncIterableIterator<any>; }
>{ async * f() { return 1; }} : { f(): AsyncIterableIterator<any>; }

async * f() {
>f : () => AsyncIterableIterator<number>
>f : () => AsyncIterableIterator<any>

return 1;
>1 : 1
Original file line number Diff line number Diff line change
@@ -83,11 +83,11 @@ const o6 = {
}
=== tests/cases/conformance/emitter/es5/asyncGenerators/O7.ts ===
const o7 = {
>o7 : { f(): AsyncIterableIterator<number>; }
>{ async * f() { return 1; }} : { f(): AsyncIterableIterator<number>; }
>o7 : { f(): AsyncIterableIterator<any>; }
>{ async * f() { return 1; }} : { f(): AsyncIterableIterator<any>; }

async * f() {
>f : () => AsyncIterableIterator<number>
>f : () => AsyncIterableIterator<any>

return 1;
>1 : 1
Original file line number Diff line number Diff line change
@@ -83,11 +83,11 @@ const o6 = {
}
=== tests/cases/conformance/emitter/esnext/asyncGenerators/O7.ts ===
const o7 = {
>o7 : { f(): AsyncIterableIterator<number>; }
>{ async * f() { return 1; }} : { f(): AsyncIterableIterator<number>; }
>o7 : { f(): AsyncIterableIterator<any>; }
>{ async * f() { return 1; }} : { f(): AsyncIterableIterator<any>; }

async * f() {
>f : () => AsyncIterableIterator<number>
>f : () => AsyncIterableIterator<any>

return 1;
>1 : 1
2 changes: 1 addition & 1 deletion tests/baselines/reference/generatorTypeCheck14.types
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
=== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck14.ts ===
function* g() {
>g : () => IterableIterator<0 | "">
>g : () => IterableIterator<number>

yield 0;
>yield 0 : any
2 changes: 1 addition & 1 deletion tests/baselines/reference/generatorTypeCheck15.types
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
=== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck15.ts ===
function* g() {
>g : () => IterableIterator<string>
>g : () => IterableIterator<any>

return "";
>"" : ""
2 changes: 1 addition & 1 deletion tests/baselines/reference/generatorTypeCheck34.types
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ function* g() {
>0 : 0

function* g2() {
>g2 : () => IterableIterator<string>
>g2 : () => IterableIterator<any>

return "";
>"" : ""
45 changes: 45 additions & 0 deletions tests/baselines/reference/generatorTypeCheck62.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck62.ts(24,70): error TS7025: Generator implicitly has type 'IterableIterator<any>' because it does not yield any values. Consider supplying a return type.
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck62.ts(32,70): error TS7025: Generator implicitly has type 'IterableIterator<any>' because it does not yield any values. Consider supplying a return type.


==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck62.ts (2 errors) ====
export interface StrategicState {
lastStrategyApplied?: string;
}

export function strategy<T extends StrategicState>(stratName: string, gen: (a: T) => IterableIterator<T | undefined>): (a: T) => IterableIterator<T | undefined> {
return function*(state) {
for (const next of gen(state)) {
if (next) {
next.lastStrategyApplied = stratName;
}
yield next;
}
}
}

export interface Strategy<T> {
(a: T): IterableIterator<T | undefined>;
}

export interface State extends StrategicState {
foo: number;
}

export const Nothing1: Strategy<State> = strategy("Nothing", function*(state: State) {
~
!!! error TS7025: Generator implicitly has type 'IterableIterator<any>' because it does not yield any values. Consider supplying a return type.
return state;
});

export const Nothing2: Strategy<State> = strategy("Nothing", function*(state: State) {
yield state;
});

export const Nothing3: Strategy<State> = strategy("Nothing", function* (state: State) {
~
!!! error TS7025: Generator implicitly has type 'IterableIterator<any>' because it does not yield any values. Consider supplying a return type.
yield ;
return state;
});

8 changes: 4 additions & 4 deletions tests/baselines/reference/generatorTypeCheck62.types
Original file line number Diff line number Diff line change
@@ -71,10 +71,10 @@ export const Nothing1: Strategy<State> = strategy("Nothing", function*(state: St
>Nothing1 : Strategy<State>
>Strategy : Strategy<T>
>State : State
>strategy("Nothing", function*(state: State) { return state;}) : (a: State) => IterableIterator<State>
>strategy("Nothing", function*(state: State) { return state;}) : (a: any) => IterableIterator<any>
>strategy : <T extends StrategicState>(stratName: string, gen: (a: T) => IterableIterator<T>) => (a: T) => IterableIterator<T>
>"Nothing" : "Nothing"
>function*(state: State) { return state;} : (state: State) => IterableIterator<State>
>function*(state: State) { return state;} : (state: State) => IterableIterator<any>
>state : State
>State : State

@@ -104,10 +104,10 @@ export const Nothing3: Strategy<State> = strategy("Nothing", function* (state: S
>Nothing3 : Strategy<State>
>Strategy : Strategy<T>
>State : State
>strategy("Nothing", function* (state: State) { yield ; return state;}) : (a: State) => IterableIterator<State>
>strategy("Nothing", function* (state: State) { yield ; return state;}) : (a: any) => IterableIterator<any>
>strategy : <T extends StrategicState>(stratName: string, gen: (a: T) => IterableIterator<T>) => (a: T) => IterableIterator<T>
>"Nothing" : "Nothing"
>function* (state: State) { yield ; return state;} : (state: State) => IterableIterator<State>
>function* (state: State) { yield ; return state;} : (state: State) => IterableIterator<any>
>state : State
>State : State

29 changes: 9 additions & 20 deletions tests/baselines/reference/generatorTypeCheck63.errors.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(24,61): error TS2345: Argument of type '(state: State) => IterableIterator<State | 1>' is not assignable to parameter of type '(a: StrategicState) => IterableIterator<StrategicState>'.
Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<StrategicState>'.
Type 'State | 1' is not assignable to type 'StrategicState'.
Type '1' has no properties in common with type 'StrategicState'.
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(29,70): error TS7025: Generator implicitly has type 'IterableIterator<any>' because it does not yield any values. Consider supplying a return type.
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(32,62): error TS2345: Argument of type '(state: State) => IterableIterator<number>' is not assignable to parameter of type '(a: State) => IterableIterator<State>'.
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(24,61): error TS2345: Argument of type '(state: State) => IterableIterator<number>' is not assignable to parameter of type '(a: State) => IterableIterator<State>'.
Type 'IterableIterator<number>' is not assignable to type 'IterableIterator<State>'.
Type 'number' is not assignable to type 'State'.
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(36,62): error TS2345: Argument of type '(state: State) => IterableIterator<State | 1>' is not assignable to parameter of type '(a: StrategicState) => IterableIterator<StrategicState>'.
Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<StrategicState>'.
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(29,70): error TS7025: Generator implicitly has type 'IterableIterator<any>' because it does not yield any values. Consider supplying a return type.
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(32,70): error TS7025: Generator implicitly has type 'IterableIterator<any>' because it does not yield any values. Consider supplying a return type.


==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts (4 errors) ====
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts (3 errors) ====
export interface StrategicState {
lastStrategyApplied?: string;
}
@@ -36,10 +31,9 @@ tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(36,62): err

export const Nothing: Strategy<State> = strategy("Nothing", function* (state: State) {
~~~~~~~~
!!! error TS2345: Argument of type '(state: State) => IterableIterator<State | 1>' is not assignable to parameter of type '(a: StrategicState) => IterableIterator<StrategicState>'.
!!! error TS2345: Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<StrategicState>'.
!!! error TS2345: Type 'State | 1' is not assignable to type 'StrategicState'.
!!! error TS2345: Type '1' has no properties in common with type 'StrategicState'.
!!! error TS2345: Argument of type '(state: State) => IterableIterator<number>' is not assignable to parameter of type '(a: State) => IterableIterator<State>'.
!!! error TS2345: Type 'IterableIterator<number>' is not assignable to type 'IterableIterator<State>'.
!!! error TS2345: Type 'number' is not assignable to type 'State'.
yield 1;
return state;
});
@@ -50,17 +44,12 @@ tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(36,62): err
});

export const Nothing2: Strategy<State> = strategy("Nothing", function* (state: State) {
~~~~~~~~
!!! error TS2345: Argument of type '(state: State) => IterableIterator<number>' is not assignable to parameter of type '(a: State) => IterableIterator<State>'.
!!! error TS2345: Type 'IterableIterator<number>' is not assignable to type 'IterableIterator<State>'.
!!! error TS2345: Type 'number' is not assignable to type 'State'.
~
!!! error TS7025: Generator implicitly has type 'IterableIterator<any>' because it does not yield any values. Consider supplying a return type.
return 1;
});

export const Nothing3: Strategy<State> = strategy("Nothing", function* (state: State) {
~~~~~~~~
!!! error TS2345: Argument of type '(state: State) => IterableIterator<State | 1>' is not assignable to parameter of type '(a: StrategicState) => IterableIterator<StrategicState>'.
!!! error TS2345: Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<StrategicState>'.
yield state;
return 1;
});
10 changes: 5 additions & 5 deletions tests/baselines/reference/generatorTypeCheck63.types
Original file line number Diff line number Diff line change
@@ -74,7 +74,7 @@ export const Nothing: Strategy<State> = strategy("Nothing", function* (state: St
>strategy("Nothing", function* (state: State) { yield 1; return state;}) : any
>strategy : <T extends StrategicState>(stratName: string, gen: (a: T) => IterableIterator<T>) => (a: T) => IterableIterator<T>
>"Nothing" : "Nothing"
>function* (state: State) { yield 1; return state;} : (state: State) => IterableIterator<State | 1>
>function* (state: State) { yield 1; return state;} : (state: State) => IterableIterator<number>
>state : State
>State : State

@@ -104,10 +104,10 @@ export const Nothing2: Strategy<State> = strategy("Nothing", function* (state: S
>Nothing2 : Strategy<State>
>Strategy : Strategy<T>
>State : State
>strategy("Nothing", function* (state: State) { return 1;}) : any
>strategy("Nothing", function* (state: State) { return 1;}) : (a: any) => IterableIterator<any>
>strategy : <T extends StrategicState>(stratName: string, gen: (a: T) => IterableIterator<T>) => (a: T) => IterableIterator<T>
>"Nothing" : "Nothing"
>function* (state: State) { return 1;} : (state: State) => IterableIterator<number>
>function* (state: State) { return 1;} : (state: State) => IterableIterator<any>
>state : State
>State : State

@@ -120,10 +120,10 @@ export const Nothing3: Strategy<State> = strategy("Nothing", function* (state: S
>Nothing3 : Strategy<State>
>Strategy : Strategy<T>
>State : State
>strategy("Nothing", function* (state: State) { yield state; return 1;}) : any
>strategy("Nothing", function* (state: State) { yield state; return 1;}) : (a: State) => IterableIterator<State>
>strategy : <T extends StrategicState>(stratName: string, gen: (a: T) => IterableIterator<T>) => (a: T) => IterableIterator<T>
>"Nothing" : "Nothing"
>function* (state: State) { yield state; return 1;} : (state: State) => IterableIterator<State | 1>
>function* (state: State) { yield state; return 1;} : (state: State) => IterableIterator<State>
>state : State
>State : State