From 539f45a4cf67e2b64db822c64af24216298eaf4e Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Fri, 2 Mar 2018 09:15:45 -0800 Subject: [PATCH] Don't treat `return` as a `yield` --- src/compiler/checker.ts | 9 ++-- ....asyncGenerators.classMethods.es2015.types | 2 +- ...ter.asyncGenerators.classMethods.es5.types | 2 +- ....asyncGenerators.classMethods.esnext.types | 2 +- ...nerators.functionDeclarations.es2015.types | 2 +- ...cGenerators.functionDeclarations.es5.types | 2 +- ...nerators.functionDeclarations.esnext.types | 2 +- ...enerators.functionExpressions.es2015.types | 4 +- ...ncGenerators.functionExpressions.es5.types | 4 +- ...enerators.functionExpressions.esnext.types | 4 +- ...nerators.objectLiteralMethods.es2015.types | 6 +-- ...cGenerators.objectLiteralMethods.es5.types | 6 +-- ...nerators.objectLiteralMethods.esnext.types | 6 +-- .../reference/generatorTypeCheck14.types | 2 +- .../reference/generatorTypeCheck15.types | 2 +- .../reference/generatorTypeCheck34.types | 2 +- .../reference/generatorTypeCheck62.errors.txt | 45 +++++++++++++++++++ .../reference/generatorTypeCheck62.types | 8 ++-- .../reference/generatorTypeCheck63.errors.txt | 29 ++++-------- .../reference/generatorTypeCheck63.types | 10 ++--- 20 files changed, 92 insertions(+), 57 deletions(-) create mode 100644 tests/baselines/reference/generatorTypeCheck62.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 515789a3fd767..9a0bf1b243a1d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -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); } }); diff --git a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.types b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.types index c6d6fb6758d13..d4d741f566aba 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.types +++ b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.types @@ -80,7 +80,7 @@ class C7 { >C7 : C7 async * f() { ->f : () => AsyncIterableIterator +>f : () => AsyncIterableIterator return 1; >1 : 1 diff --git a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.types b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.types index 5d636d2400c6f..4c8866755ac4a 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.types +++ b/tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.types @@ -80,7 +80,7 @@ class C7 { >C7 : C7 async * f() { ->f : () => AsyncIterableIterator +>f : () => AsyncIterableIterator return 1; >1 : 1 diff --git a/tests/baselines/reference/emitter.asyncGenerators.classMethods.esnext.types b/tests/baselines/reference/emitter.asyncGenerators.classMethods.esnext.types index f2f5f4d7503bd..90630563c36cd 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.classMethods.esnext.types +++ b/tests/baselines/reference/emitter.asyncGenerators.classMethods.esnext.types @@ -80,7 +80,7 @@ class C7 { >C7 : C7 async * f() { ->f : () => AsyncIterableIterator +>f : () => AsyncIterableIterator return 1; >1 : 1 diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.types b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.types index 15ff1298b21ac..db937418962ce 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.types +++ b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es2015.types @@ -53,7 +53,7 @@ async function * f6() { } === tests/cases/conformance/emitter/es2015/asyncGenerators/F7.ts === async function * f7() { ->f7 : () => AsyncIterableIterator +>f7 : () => AsyncIterableIterator return 1; >1 : 1 diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.types b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.types index 6220f5efd1eca..fb2f5a88675e9 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.types +++ b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.es5.types @@ -53,7 +53,7 @@ async function * f6() { } === tests/cases/conformance/emitter/es5/asyncGenerators/F7.ts === async function * f7() { ->f7 : () => AsyncIterableIterator +>f7 : () => AsyncIterableIterator return 1; >1 : 1 diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.esnext.types b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.esnext.types index c0d8011774655..57d64406615e2 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.esnext.types +++ b/tests/baselines/reference/emitter.asyncGenerators.functionDeclarations.esnext.types @@ -53,7 +53,7 @@ async function * f6() { } === tests/cases/conformance/emitter/esnext/asyncGenerators/F7.ts === async function * f7() { ->f7 : () => AsyncIterableIterator +>f7 : () => AsyncIterableIterator return 1; >1 : 1 diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.types b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.types index 1db2126b7ed83..4c9757e8cc7db 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.types +++ b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es2015.types @@ -59,8 +59,8 @@ const f6 = async function * () { } === tests/cases/conformance/emitter/es2015/asyncGenerators/F7.ts === const f7 = async function * () { ->f7 : () => AsyncIterableIterator ->async function * () { return 1;} : () => AsyncIterableIterator +>f7 : () => AsyncIterableIterator +>async function * () { return 1;} : () => AsyncIterableIterator return 1; >1 : 1 diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.types b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.types index e9da600bdbf1c..16f10366dffaa 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.types +++ b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.es5.types @@ -59,8 +59,8 @@ const f6 = async function * () { } === tests/cases/conformance/emitter/es5/asyncGenerators/F7.ts === const f7 = async function * () { ->f7 : () => AsyncIterableIterator ->async function * () { return 1;} : () => AsyncIterableIterator +>f7 : () => AsyncIterableIterator +>async function * () { return 1;} : () => AsyncIterableIterator return 1; >1 : 1 diff --git a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.esnext.types b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.esnext.types index 5802bc10a2d9e..0044d50eb00d5 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.esnext.types +++ b/tests/baselines/reference/emitter.asyncGenerators.functionExpressions.esnext.types @@ -59,8 +59,8 @@ const f6 = async function * () { } === tests/cases/conformance/emitter/esnext/asyncGenerators/F7.ts === const f7 = async function * () { ->f7 : () => AsyncIterableIterator ->async function * () { return 1;} : () => AsyncIterableIterator +>f7 : () => AsyncIterableIterator +>async function * () { return 1;} : () => AsyncIterableIterator return 1; >1 : 1 diff --git a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.types b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.types index 9e47fc9d98932..2927796c68aa4 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.types +++ b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es2015.types @@ -83,11 +83,11 @@ const o6 = { } === tests/cases/conformance/emitter/es2015/asyncGenerators/O7.ts === const o7 = { ->o7 : { f(): AsyncIterableIterator; } ->{ async * f() { return 1; }} : { f(): AsyncIterableIterator; } +>o7 : { f(): AsyncIterableIterator; } +>{ async * f() { return 1; }} : { f(): AsyncIterableIterator; } async * f() { ->f : () => AsyncIterableIterator +>f : () => AsyncIterableIterator return 1; >1 : 1 diff --git a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.types b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.types index 390007605083d..aefb7775ec27d 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.types +++ b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.es5.types @@ -83,11 +83,11 @@ const o6 = { } === tests/cases/conformance/emitter/es5/asyncGenerators/O7.ts === const o7 = { ->o7 : { f(): AsyncIterableIterator; } ->{ async * f() { return 1; }} : { f(): AsyncIterableIterator; } +>o7 : { f(): AsyncIterableIterator; } +>{ async * f() { return 1; }} : { f(): AsyncIterableIterator; } async * f() { ->f : () => AsyncIterableIterator +>f : () => AsyncIterableIterator return 1; >1 : 1 diff --git a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.esnext.types b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.esnext.types index a05b5326b2c8e..4465770931b4e 100644 --- a/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.esnext.types +++ b/tests/baselines/reference/emitter.asyncGenerators.objectLiteralMethods.esnext.types @@ -83,11 +83,11 @@ const o6 = { } === tests/cases/conformance/emitter/esnext/asyncGenerators/O7.ts === const o7 = { ->o7 : { f(): AsyncIterableIterator; } ->{ async * f() { return 1; }} : { f(): AsyncIterableIterator; } +>o7 : { f(): AsyncIterableIterator; } +>{ async * f() { return 1; }} : { f(): AsyncIterableIterator; } async * f() { ->f : () => AsyncIterableIterator +>f : () => AsyncIterableIterator return 1; >1 : 1 diff --git a/tests/baselines/reference/generatorTypeCheck14.types b/tests/baselines/reference/generatorTypeCheck14.types index 28401e68567a2..a8a5586f7ffce 100644 --- a/tests/baselines/reference/generatorTypeCheck14.types +++ b/tests/baselines/reference/generatorTypeCheck14.types @@ -1,6 +1,6 @@ === tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck14.ts === function* g() { ->g : () => IterableIterator<0 | ""> +>g : () => IterableIterator yield 0; >yield 0 : any diff --git a/tests/baselines/reference/generatorTypeCheck15.types b/tests/baselines/reference/generatorTypeCheck15.types index 33537836c120f..eb14208009a5a 100644 --- a/tests/baselines/reference/generatorTypeCheck15.types +++ b/tests/baselines/reference/generatorTypeCheck15.types @@ -1,6 +1,6 @@ === tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck15.ts === function* g() { ->g : () => IterableIterator +>g : () => IterableIterator return ""; >"" : "" diff --git a/tests/baselines/reference/generatorTypeCheck34.types b/tests/baselines/reference/generatorTypeCheck34.types index f25eefb72f7be..6eb836f74d2df 100644 --- a/tests/baselines/reference/generatorTypeCheck34.types +++ b/tests/baselines/reference/generatorTypeCheck34.types @@ -7,7 +7,7 @@ function* g() { >0 : 0 function* g2() { ->g2 : () => IterableIterator +>g2 : () => IterableIterator return ""; >"" : "" diff --git a/tests/baselines/reference/generatorTypeCheck62.errors.txt b/tests/baselines/reference/generatorTypeCheck62.errors.txt new file mode 100644 index 0000000000000..59c1afc7d3d14 --- /dev/null +++ b/tests/baselines/reference/generatorTypeCheck62.errors.txt @@ -0,0 +1,45 @@ +tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck62.ts(24,70): error TS7025: Generator implicitly has type 'IterableIterator' 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' 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(stratName: string, gen: (a: T) => IterableIterator): (a: T) => IterableIterator { + return function*(state) { + for (const next of gen(state)) { + if (next) { + next.lastStrategyApplied = stratName; + } + yield next; + } + } + } + + export interface Strategy { + (a: T): IterableIterator; + } + + export interface State extends StrategicState { + foo: number; + } + + export const Nothing1: Strategy = strategy("Nothing", function*(state: State) { + ~ +!!! error TS7025: Generator implicitly has type 'IterableIterator' because it does not yield any values. Consider supplying a return type. + return state; + }); + + export const Nothing2: Strategy = strategy("Nothing", function*(state: State) { + yield state; + }); + + export const Nothing3: Strategy = strategy("Nothing", function* (state: State) { + ~ +!!! error TS7025: Generator implicitly has type 'IterableIterator' because it does not yield any values. Consider supplying a return type. + yield ; + return state; + }); + \ No newline at end of file diff --git a/tests/baselines/reference/generatorTypeCheck62.types b/tests/baselines/reference/generatorTypeCheck62.types index f8b3a9117b137..914ee9bee0ee6 100644 --- a/tests/baselines/reference/generatorTypeCheck62.types +++ b/tests/baselines/reference/generatorTypeCheck62.types @@ -71,10 +71,10 @@ export const Nothing1: Strategy = strategy("Nothing", function*(state: St >Nothing1 : Strategy >Strategy : Strategy >State : State ->strategy("Nothing", function*(state: State) { return state;}) : (a: State) => IterableIterator +>strategy("Nothing", function*(state: State) { return state;}) : (a: any) => IterableIterator >strategy : (stratName: string, gen: (a: T) => IterableIterator) => (a: T) => IterableIterator >"Nothing" : "Nothing" ->function*(state: State) { return state;} : (state: State) => IterableIterator +>function*(state: State) { return state;} : (state: State) => IterableIterator >state : State >State : State @@ -104,10 +104,10 @@ export const Nothing3: Strategy = strategy("Nothing", function* (state: S >Nothing3 : Strategy >Strategy : Strategy >State : State ->strategy("Nothing", function* (state: State) { yield ; return state;}) : (a: State) => IterableIterator +>strategy("Nothing", function* (state: State) { yield ; return state;}) : (a: any) => IterableIterator >strategy : (stratName: string, gen: (a: T) => IterableIterator) => (a: T) => IterableIterator >"Nothing" : "Nothing" ->function* (state: State) { yield ; return state;} : (state: State) => IterableIterator +>function* (state: State) { yield ; return state;} : (state: State) => IterableIterator >state : State >State : State diff --git a/tests/baselines/reference/generatorTypeCheck63.errors.txt b/tests/baselines/reference/generatorTypeCheck63.errors.txt index 2a1935fd90633..edee52a2ff78c 100644 --- a/tests/baselines/reference/generatorTypeCheck63.errors.txt +++ b/tests/baselines/reference/generatorTypeCheck63.errors.txt @@ -1,16 +1,11 @@ -tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(24,61): error TS2345: Argument of type '(state: State) => IterableIterator' is not assignable to parameter of type '(a: StrategicState) => IterableIterator'. - Type 'IterableIterator' is not assignable to type 'IterableIterator'. - 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' 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' is not assignable to parameter of type '(a: State) => IterableIterator'. +tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(24,61): error TS2345: Argument of type '(state: State) => IterableIterator' is not assignable to parameter of type '(a: State) => IterableIterator'. Type 'IterableIterator' is not assignable to type 'IterableIterator'. 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' is not assignable to parameter of type '(a: StrategicState) => IterableIterator'. - Type 'IterableIterator' is not assignable to type 'IterableIterator'. +tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(29,70): error TS7025: Generator implicitly has type 'IterableIterator' 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' 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 = strategy("Nothing", function* (state: State) { ~~~~~~~~ -!!! error TS2345: Argument of type '(state: State) => IterableIterator' is not assignable to parameter of type '(a: StrategicState) => IterableIterator'. -!!! error TS2345: Type 'IterableIterator' is not assignable to type 'IterableIterator'. -!!! 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' is not assignable to parameter of type '(a: State) => IterableIterator'. +!!! error TS2345: Type 'IterableIterator' is not assignable to type 'IterableIterator'. +!!! 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 = strategy("Nothing", function* (state: State) { - ~~~~~~~~ -!!! error TS2345: Argument of type '(state: State) => IterableIterator' is not assignable to parameter of type '(a: State) => IterableIterator'. -!!! error TS2345: Type 'IterableIterator' is not assignable to type 'IterableIterator'. -!!! error TS2345: Type 'number' is not assignable to type 'State'. + ~ +!!! error TS7025: Generator implicitly has type 'IterableIterator' because it does not yield any values. Consider supplying a return type. return 1; }); export const Nothing3: Strategy = strategy("Nothing", function* (state: State) { - ~~~~~~~~ -!!! error TS2345: Argument of type '(state: State) => IterableIterator' is not assignable to parameter of type '(a: StrategicState) => IterableIterator'. -!!! error TS2345: Type 'IterableIterator' is not assignable to type 'IterableIterator'. yield state; return 1; }); \ No newline at end of file diff --git a/tests/baselines/reference/generatorTypeCheck63.types b/tests/baselines/reference/generatorTypeCheck63.types index 8fc2054bd6e74..e4a41cba66c5e 100644 --- a/tests/baselines/reference/generatorTypeCheck63.types +++ b/tests/baselines/reference/generatorTypeCheck63.types @@ -74,7 +74,7 @@ export const Nothing: Strategy = strategy("Nothing", function* (state: St >strategy("Nothing", function* (state: State) { yield 1; return state;}) : any >strategy : (stratName: string, gen: (a: T) => IterableIterator) => (a: T) => IterableIterator >"Nothing" : "Nothing" ->function* (state: State) { yield 1; return state;} : (state: State) => IterableIterator +>function* (state: State) { yield 1; return state;} : (state: State) => IterableIterator >state : State >State : State @@ -104,10 +104,10 @@ export const Nothing2: Strategy = strategy("Nothing", function* (state: S >Nothing2 : Strategy >Strategy : Strategy >State : State ->strategy("Nothing", function* (state: State) { return 1;}) : any +>strategy("Nothing", function* (state: State) { return 1;}) : (a: any) => IterableIterator >strategy : (stratName: string, gen: (a: T) => IterableIterator) => (a: T) => IterableIterator >"Nothing" : "Nothing" ->function* (state: State) { return 1;} : (state: State) => IterableIterator +>function* (state: State) { return 1;} : (state: State) => IterableIterator >state : State >State : State @@ -120,10 +120,10 @@ export const Nothing3: Strategy = strategy("Nothing", function* (state: S >Nothing3 : Strategy >Strategy : Strategy >State : State ->strategy("Nothing", function* (state: State) { yield state; return 1;}) : any +>strategy("Nothing", function* (state: State) { yield state; return 1;}) : (a: State) => IterableIterator >strategy : (stratName: string, gen: (a: T) => IterableIterator) => (a: T) => IterableIterator >"Nothing" : "Nothing" ->function* (state: State) { yield state; return 1;} : (state: State) => IterableIterator +>function* (state: State) { yield state; return 1;} : (state: State) => IterableIterator >state : State >State : State