Merge pull request #14235 from Microsoft/master-fix14043

[Master] fix 14043 collect return type from return statement in generator function
This commit is contained in:
Yui 2017-03-21 11:06:11 -07:00 committed by GitHub
commit 46587c8dca
23 changed files with 532 additions and 26 deletions

View file

@ -15146,8 +15146,8 @@ namespace ts {
else {
let types: Type[];
if (functionFlags & FunctionFlags.Generator) { // Generator or AsyncGenerator function
types = checkAndAggregateYieldOperandTypes(func, checkMode);
if (types.length === 0) {
types = concatenate(checkAndAggregateYieldOperandTypes(func, checkMode), checkAndAggregateReturnExpressionTypes(func, checkMode));
if (!types || types.length === 0) {
const iterableIteratorAny = functionFlags & FunctionFlags.Async
? createAsyncIterableIteratorType(anyType) // AsyncGenerator function
: createIterableIteratorType(anyType); // Generator function

View file

@ -80,7 +80,7 @@ class C7 {
>C7 : C7
async * f() {
>f : () => AsyncIterableIterator<any>
>f : () => AsyncIterableIterator<1>
return 1;
>1 : 1

View file

@ -80,7 +80,7 @@ class C7 {
>C7 : C7
async * f() {
>f : () => AsyncIterableIterator<any>
>f : () => AsyncIterableIterator<1>
return 1;
>1 : 1

View file

@ -80,7 +80,7 @@ class C7 {
>C7 : C7
async * f() {
>f : () => AsyncIterableIterator<any>
>f : () => AsyncIterableIterator<1>
return 1;
>1 : 1

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
=== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck14.ts ===
function* g() {
>g : () => IterableIterator<0>
>g : () => IterableIterator<0 | "">
yield 0;
>yield 0 : any

View file

@ -1,6 +1,6 @@
=== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck15.ts ===
function* g() {
>g : () => IterableIterator<any>
>g : () => IterableIterator<"">
return "";
>"" : ""

View file

@ -7,7 +7,7 @@ function* g() {
>0 : 0
function* g2() {
>g2 : () => IterableIterator<any>
>g2 : () => IterableIterator<"">
return "";
>"" : ""

View file

@ -0,0 +1,63 @@
//// [generatorTypeCheck62.ts]
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) {
return state;
});
export const Nothing2: Strategy<State> = strategy("Nothing", function*(state: State) {
yield state;
});
export const Nothing3: Strategy<State> = strategy("Nothing", function* (state: State) {
yield ;
return state;
});
//// [generatorTypeCheck62.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function strategy(stratName, gen) {
return function* (state) {
for (const next of gen(state)) {
if (next) {
next.lastStrategyApplied = stratName;
}
yield next;
}
};
}
exports.strategy = strategy;
exports.Nothing1 = strategy("Nothing", function* (state) {
return state;
});
exports.Nothing2 = strategy("Nothing", function* (state) {
yield state;
});
exports.Nothing3 = strategy("Nothing", function* (state) {
yield;
return state;
});

View file

@ -0,0 +1,106 @@
=== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck62.ts ===
export interface StrategicState {
>StrategicState : Symbol(StrategicState, Decl(generatorTypeCheck62.ts, 0, 0))
lastStrategyApplied?: string;
>lastStrategyApplied : Symbol(StrategicState.lastStrategyApplied, Decl(generatorTypeCheck62.ts, 1, 33))
}
export function strategy<T extends StrategicState>(stratName: string, gen: (a: T) => IterableIterator<T | undefined>): (a: T) => IterableIterator<T | undefined> {
>strategy : Symbol(strategy, Decl(generatorTypeCheck62.ts, 3, 1))
>T : Symbol(T, Decl(generatorTypeCheck62.ts, 5, 25))
>StrategicState : Symbol(StrategicState, Decl(generatorTypeCheck62.ts, 0, 0))
>stratName : Symbol(stratName, Decl(generatorTypeCheck62.ts, 5, 51))
>gen : Symbol(gen, Decl(generatorTypeCheck62.ts, 5, 69))
>a : Symbol(a, Decl(generatorTypeCheck62.ts, 5, 76))
>T : Symbol(T, Decl(generatorTypeCheck62.ts, 5, 25))
>IterableIterator : Symbol(IterableIterator, Decl(lib.es2015.iterable.d.ts, --, --))
>T : Symbol(T, Decl(generatorTypeCheck62.ts, 5, 25))
>a : Symbol(a, Decl(generatorTypeCheck62.ts, 5, 120))
>T : Symbol(T, Decl(generatorTypeCheck62.ts, 5, 25))
>IterableIterator : Symbol(IterableIterator, Decl(lib.es2015.iterable.d.ts, --, --))
>T : Symbol(T, Decl(generatorTypeCheck62.ts, 5, 25))
return function*(state) {
>state : Symbol(state, Decl(generatorTypeCheck62.ts, 6, 21))
for (const next of gen(state)) {
>next : Symbol(next, Decl(generatorTypeCheck62.ts, 7, 18))
>gen : Symbol(gen, Decl(generatorTypeCheck62.ts, 5, 69))
>state : Symbol(state, Decl(generatorTypeCheck62.ts, 6, 21))
if (next) {
>next : Symbol(next, Decl(generatorTypeCheck62.ts, 7, 18))
next.lastStrategyApplied = stratName;
>next.lastStrategyApplied : Symbol(StrategicState.lastStrategyApplied, Decl(generatorTypeCheck62.ts, 1, 33))
>next : Symbol(next, Decl(generatorTypeCheck62.ts, 7, 18))
>lastStrategyApplied : Symbol(StrategicState.lastStrategyApplied, Decl(generatorTypeCheck62.ts, 1, 33))
>stratName : Symbol(stratName, Decl(generatorTypeCheck62.ts, 5, 51))
}
yield next;
>next : Symbol(next, Decl(generatorTypeCheck62.ts, 7, 18))
}
}
}
export interface Strategy<T> {
>Strategy : Symbol(Strategy, Decl(generatorTypeCheck62.ts, 14, 1))
>T : Symbol(T, Decl(generatorTypeCheck62.ts, 16, 26))
(a: T): IterableIterator<T | undefined>;
>a : Symbol(a, Decl(generatorTypeCheck62.ts, 17, 5))
>T : Symbol(T, Decl(generatorTypeCheck62.ts, 16, 26))
>IterableIterator : Symbol(IterableIterator, Decl(lib.es2015.iterable.d.ts, --, --))
>T : Symbol(T, Decl(generatorTypeCheck62.ts, 16, 26))
}
export interface State extends StrategicState {
>State : Symbol(State, Decl(generatorTypeCheck62.ts, 18, 1))
>StrategicState : Symbol(StrategicState, Decl(generatorTypeCheck62.ts, 0, 0))
foo: number;
>foo : Symbol(State.foo, Decl(generatorTypeCheck62.ts, 20, 47))
}
export const Nothing1: Strategy<State> = strategy("Nothing", function*(state: State) {
>Nothing1 : Symbol(Nothing1, Decl(generatorTypeCheck62.ts, 24, 12))
>Strategy : Symbol(Strategy, Decl(generatorTypeCheck62.ts, 14, 1))
>State : Symbol(State, Decl(generatorTypeCheck62.ts, 18, 1))
>strategy : Symbol(strategy, Decl(generatorTypeCheck62.ts, 3, 1))
>state : Symbol(state, Decl(generatorTypeCheck62.ts, 24, 71))
>State : Symbol(State, Decl(generatorTypeCheck62.ts, 18, 1))
return state;
>state : Symbol(state, Decl(generatorTypeCheck62.ts, 24, 71))
});
export const Nothing2: Strategy<State> = strategy("Nothing", function*(state: State) {
>Nothing2 : Symbol(Nothing2, Decl(generatorTypeCheck62.ts, 28, 12))
>Strategy : Symbol(Strategy, Decl(generatorTypeCheck62.ts, 14, 1))
>State : Symbol(State, Decl(generatorTypeCheck62.ts, 18, 1))
>strategy : Symbol(strategy, Decl(generatorTypeCheck62.ts, 3, 1))
>state : Symbol(state, Decl(generatorTypeCheck62.ts, 28, 71))
>State : Symbol(State, Decl(generatorTypeCheck62.ts, 18, 1))
yield state;
>state : Symbol(state, Decl(generatorTypeCheck62.ts, 28, 71))
});
export const Nothing3: Strategy<State> = strategy("Nothing", function* (state: State) {
>Nothing3 : Symbol(Nothing3, Decl(generatorTypeCheck62.ts, 32, 12))
>Strategy : Symbol(Strategy, Decl(generatorTypeCheck62.ts, 14, 1))
>State : Symbol(State, Decl(generatorTypeCheck62.ts, 18, 1))
>strategy : Symbol(strategy, Decl(generatorTypeCheck62.ts, 3, 1))
>state : Symbol(state, Decl(generatorTypeCheck62.ts, 32, 72))
>State : Symbol(State, Decl(generatorTypeCheck62.ts, 18, 1))
yield ;
return state;
>state : Symbol(state, Decl(generatorTypeCheck62.ts, 32, 72))
});

View file

@ -0,0 +1,122 @@
=== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck62.ts ===
export interface StrategicState {
>StrategicState : StrategicState
lastStrategyApplied?: string;
>lastStrategyApplied : string
}
export function strategy<T extends StrategicState>(stratName: string, gen: (a: T) => IterableIterator<T | undefined>): (a: T) => IterableIterator<T | undefined> {
>strategy : <T extends StrategicState>(stratName: string, gen: (a: T) => IterableIterator<T>) => (a: T) => IterableIterator<T>
>T : T
>StrategicState : StrategicState
>stratName : string
>gen : (a: T) => IterableIterator<T>
>a : T
>T : T
>IterableIterator : IterableIterator<T>
>T : T
>a : T
>T : T
>IterableIterator : IterableIterator<T>
>T : T
return function*(state) {
>function*(state) { for (const next of gen(state)) { if (next) { next.lastStrategyApplied = stratName; } yield next; } } : (state: T) => IterableIterator<T>
>state : T
for (const next of gen(state)) {
>next : T
>gen(state) : IterableIterator<T>
>gen : (a: T) => IterableIterator<T>
>state : T
if (next) {
>next : T
next.lastStrategyApplied = stratName;
>next.lastStrategyApplied = stratName : string
>next.lastStrategyApplied : string
>next : T
>lastStrategyApplied : string
>stratName : string
}
yield next;
>yield next : any
>next : T
}
}
}
export interface Strategy<T> {
>Strategy : Strategy<T>
>T : T
(a: T): IterableIterator<T | undefined>;
>a : T
>T : T
>IterableIterator : IterableIterator<T>
>T : T
}
export interface State extends StrategicState {
>State : State
>StrategicState : StrategicState
foo: number;
>foo : number
}
export const Nothing1: Strategy<State> = strategy("Nothing", function*(state: State) {
>Nothing1 : Strategy<State>
>Strategy : Strategy<T>
>State : State
>strategy("Nothing", function*(state: State) { return state;}) : (a: State) => IterableIterator<State>
>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>
>state : State
>State : State
return state;
>state : State
});
export const Nothing2: Strategy<State> = strategy("Nothing", function*(state: State) {
>Nothing2 : Strategy<State>
>Strategy : Strategy<T>
>State : State
>strategy("Nothing", function*(state: State) { yield state;}) : (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;} : (state: State) => IterableIterator<State>
>state : State
>State : State
yield state;
>yield state : any
>state : State
});
export const Nothing3: Strategy<State> = strategy("Nothing", function* (state: State) {
>Nothing3 : Strategy<State>
>Strategy : Strategy<T>
>State : State
>strategy("Nothing", function* (state: State) { yield ; return state;}) : (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 ; return state;} : (state: State) => IterableIterator<State>
>state : State
>State : State
yield ;
>yield : any
return state;
>state : State
});

View file

@ -0,0 +1,63 @@
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(25,14): error TS2322: Type '(a: State | 1) => IterableIterator<State | 1>' is not assignable to type 'Strategy<State>'.
Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<State>'.
Type 'State | 1' is not assignable to type 'State'.
Type '1' is not assignable to type 'State'.
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(30,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(33,42): error TS2453: The type argument for type parameter 'T' cannot be inferred from the usage. Consider specifying the type arguments explicitly.
Type argument candidate 'State' is not a valid type argument because it is not a supertype of candidate '1'.
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(37,14): error TS2322: Type '(a: State | 1) => IterableIterator<State | 1>' is not assignable to type 'Strategy<State>'.
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts (4 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 Nothing: Strategy<State> = strategy("Nothing", function* (state: State) {
~~~~~~~
!!! error TS2322: Type '(a: State | 1) => IterableIterator<State | 1>' is not assignable to type 'Strategy<State>'.
!!! error TS2322: Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<State>'.
!!! error TS2322: Type 'State | 1' is not assignable to type 'State'.
!!! error TS2322: Type '1' is not assignable to type 'State'.
yield 1;
return state;
});
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.
});
export const Nothing2: Strategy<State> = strategy("Nothing", function* (state: State) {
~~~~~~~~
!!! error TS2453: The type argument for type parameter 'T' cannot be inferred from the usage. Consider specifying the type arguments explicitly.
!!! error TS2453: Type argument candidate 'State' is not a valid type argument because it is not a supertype of candidate '1'.
return 1;
});
export const Nothing3: Strategy<State> = strategy("Nothing", function* (state: State) {
~~~~~~~~
!!! error TS2322: Type '(a: State | 1) => IterableIterator<State | 1>' is not assignable to type 'Strategy<State>'.
yield state;
return 1;
});

View file

@ -0,0 +1,69 @@
//// [generatorTypeCheck63.ts]
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 Nothing: Strategy<State> = strategy("Nothing", function* (state: State) {
yield 1;
return state;
});
export const Nothing1: Strategy<State> = strategy("Nothing", function* (state: State) {
});
export const Nothing2: Strategy<State> = strategy("Nothing", function* (state: State) {
return 1;
});
export const Nothing3: Strategy<State> = strategy("Nothing", function* (state: State) {
yield state;
return 1;
});
//// [generatorTypeCheck63.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function strategy(stratName, gen) {
return function* (state) {
for (const next of gen(state)) {
if (next) {
next.lastStrategyApplied = stratName;
}
yield next;
}
};
}
exports.strategy = strategy;
exports.Nothing = strategy("Nothing", function* (state) {
yield 1;
return state;
});
exports.Nothing1 = strategy("Nothing", function* (state) {
});
exports.Nothing2 = strategy("Nothing", function* (state) {
return 1;
});
exports.Nothing3 = strategy("Nothing", function* (state) {
yield state;
return 1;
});

View file

@ -0,0 +1,40 @@
// @module: commonjs
// @target: es6
// @noImplicitAny: true
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) {
return state;
});
export const Nothing2: Strategy<State> = strategy("Nothing", function*(state: State) {
yield state;
});
export const Nothing3: Strategy<State> = strategy("Nothing", function* (state: State) {
yield ;
return state;
});

View file

@ -0,0 +1,43 @@
// @module: commonjs
// @target: es6
// @noImplicitAny: true
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 Nothing: Strategy<State> = strategy("Nothing", function* (state: State) {
yield 1;
return state;
});
export const Nothing1: Strategy<State> = strategy("Nothing", function* (state: State) {
});
export const Nothing2: Strategy<State> = strategy("Nothing", function* (state: State) {
return 1;
});
export const Nothing3: Strategy<State> = strategy("Nothing", function* (state: State) {
yield state;
return 1;
});