Always call getReturnTypeOfSignature on a generator from checkFunctionLikeDeclaration

This commit is contained in:
Jason Freeman 2015-05-05 16:54:51 -07:00
parent ce9dc32704
commit 8c1f5da76a
27 changed files with 216 additions and 272 deletions

View File

@ -8014,18 +8014,23 @@ module ts {
let func = getContainingFunction(node);
// If this is correct code, the func should always have a star. After all,
// we are in a yield context.
// Also, there is no point in doing an assignability check if the function
// has no explicit return type, because the return type is directly computed
// from the yield expressions.
if (func && func.asteriskToken && func.type) {
let signatureElementType = getElementTypeFromIterableIterator(getTypeFromTypeNode(func.type), /*errorNode*/ undefined) || unknownType;
if (func && func.asteriskToken) {
let expressionType = checkExpressionCached(node.expression, /*contextualMapper*/ undefined);
let expressionElementType: Type;
if (node.asteriskToken) {
let expressionElementType = checkElementTypeOfIterable(expressionType, node.expression);
checkTypeAssignableTo(expressionElementType, signatureElementType, node.expression, /*headMessage*/ undefined);
expressionElementType = checkElementTypeOfIterable(expressionType, node.expression);
}
else {
checkTypeAssignableTo(expressionType, signatureElementType, node.expression, /*headMessage*/ undefined);
// There is no point in doing an assignability check if the function
// has no explicit return type, because the return type is directly computed
// from the yield expressions.
if (func.type) {
let signatureElementType = getElementTypeFromIterableIterator(getTypeFromTypeNode(func.type), /*errorNode*/ undefined) || unknownType;
if (node.asteriskToken) {
checkTypeAssignableTo(expressionElementType, signatureElementType, node.expression, /*headMessage*/ undefined);
}
else {
checkTypeAssignableTo(expressionType, signatureElementType, node.expression, /*headMessage*/ undefined);
}
}
}
}
@ -9108,16 +9113,17 @@ module ts {
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
}
// Report an implicit any error if there is no body, no explicit return type, and node is not a private method
// in an ambient context
if (produceDiagnostics && compilerOptions.noImplicitAny && !node.type && !isPrivateWithinAmbient(node)) {
if (nodeIsMissing(node.body)) {
if (produceDiagnostics && !node.type) {
// Report an implicit any error if there is no body, no explicit return type, and node is not a private method
// in an ambient context
if (compilerOptions.noImplicitAny && nodeIsMissing(node.body) && !isPrivateWithinAmbient(node)) {
reportImplicitAnyError(node, anyType);
}
else if (node.asteriskToken) {
// A generator with a body and no type annotation can still cause an implicit any if it is has
// no yield expressions, or its yield expressions do not have operands. The only way to find out
// is to try checking its return type.
if (node.asteriskToken && nodeIsPresent(node.body)) {
// A generator with a body and no type annotation can still cause errors. It can error if the
// yielded values have no common supertype, or it can give an implicit any error if it has no
// yielded values. The only way to trigger these errors is to try checking its return type.
getReturnTypeOfSignature(getSignatureFromDeclaration(node));
}
}

View File

@ -1,11 +1,14 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression10_es6.ts(1,11): error TS1219: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression10_es6.ts(2,11): error TS2304: Cannot find name 'foo'.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression10_es6.ts (1 errors) ====
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression10_es6.ts (2 errors) ====
var v = { * foo() {
~
!!! error TS1219: Generators are only available when targeting ECMAScript 6 or higher.
yield(foo);
~~~
!!! error TS2304: Cannot find name 'foo'.
}
}

View File

@ -1,11 +1,14 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts(2,3): error TS1219: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts(3,11): error TS2304: Cannot find name 'foo'.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts (1 errors) ====
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts (2 errors) ====
class C {
*foo() {
~
!!! error TS1219: Generators are only available when targeting ECMAScript 6 or higher.
yield(foo);
~~~
!!! error TS2304: Cannot find name 'foo'.
}
}

View File

@ -1,9 +1,12 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression6_es6.ts(1,9): error TS1219: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression6_es6.ts(2,9): error TS2488: Type must have a '[Symbol.iterator]()' method that returns an iterator.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression6_es6.ts (1 errors) ====
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression6_es6.ts (2 errors) ====
function* foo() {
~
!!! error TS1219: Generators are only available when targeting ECMAScript 6 or higher.
yield*foo
~~~
!!! error TS2488: Type must have a '[Symbol.iterator]()' method that returns an iterator.
}

View File

@ -1,9 +1,12 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression9_es6.ts(1,17): error TS1219: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression9_es6.ts(2,9): error TS2304: Cannot find name 'foo'.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression9_es6.ts (1 errors) ====
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression9_es6.ts (2 errors) ====
var v = function*() {
~
!!! error TS1219: Generators are only available when targeting ECMAScript 6 or higher.
yield(foo);
~~~
!!! error TS2304: Cannot find name 'foo'.
}

View File

@ -1,9 +1,12 @@
tests/cases/conformance/es6/yieldExpressions/YieldStarExpression4_es6.ts(1,10): error TS1219: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldStarExpression4_es6.ts(2,13): error TS2488: Type must have a '[Symbol.iterator]()' method that returns an iterator.
==== tests/cases/conformance/es6/yieldExpressions/YieldStarExpression4_es6.ts (1 errors) ====
==== tests/cases/conformance/es6/yieldExpressions/YieldStarExpression4_es6.ts (2 errors) ====
function *g() {
~
!!! error TS1219: Generators are only available when targeting ECMAScript 6 or higher.
yield * [];
~~
!!! error TS2488: Type must have a '[Symbol.iterator]()' method that returns an iterator.
}

View File

@ -0,0 +1,15 @@
tests/cases/compiler/generatorES6_5.ts(2,11): error TS2304: Cannot find name 'a'.
tests/cases/compiler/generatorES6_5.ts(2,15): error TS2304: Cannot find name 'b'.
tests/cases/compiler/generatorES6_5.ts(2,19): error TS2304: Cannot find name 'c'.
==== tests/cases/compiler/generatorES6_5.ts (3 errors) ====
function* foo() {
yield a ? b : c;
~
!!! error TS2304: Cannot find name 'a'.
~
!!! error TS2304: Cannot find name 'b'.
~
!!! error TS2304: Cannot find name 'c'.
}

View File

@ -1,6 +0,0 @@
=== tests/cases/compiler/generatorES6_5.ts ===
function* foo() {
>foo : Symbol(foo, Decl(generatorES6_5.ts, 0, 0))
yield a ? b : c;
}

View File

@ -1,11 +0,0 @@
=== tests/cases/compiler/generatorES6_5.ts ===
function* foo() {
>foo : () => IterableIterator<any>
yield a ? b : c;
>yield a ? b : c : any
>a ? b : c : any
>a : any
>b : any
>c : any
}

View File

@ -0,0 +1,16 @@
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck22.ts(4,11): error TS2503: No best common type exists among yield expressions.
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck22.ts (1 errors) ====
class Foo { x: number }
class Bar extends Foo { y: string }
class Baz { z: number }
function* g3() {
~~
!!! error TS2503: No best common type exists among yield expressions.
yield;
yield new Bar;
yield new Baz;
yield *[new Bar];
yield *[new Baz];
}

View File

@ -1,30 +0,0 @@
=== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck22.ts ===
class Foo { x: number }
>Foo : Symbol(Foo, Decl(generatorTypeCheck22.ts, 0, 0))
>x : Symbol(x, Decl(generatorTypeCheck22.ts, 0, 11))
class Bar extends Foo { y: string }
>Bar : Symbol(Bar, Decl(generatorTypeCheck22.ts, 0, 23))
>Foo : Symbol(Foo, Decl(generatorTypeCheck22.ts, 0, 0))
>y : Symbol(y, Decl(generatorTypeCheck22.ts, 1, 23))
class Baz { z: number }
>Baz : Symbol(Baz, Decl(generatorTypeCheck22.ts, 1, 35))
>z : Symbol(z, Decl(generatorTypeCheck22.ts, 2, 11))
function* g3() {
>g3 : Symbol(g3, Decl(generatorTypeCheck22.ts, 2, 23))
yield;
yield new Bar;
>Bar : Symbol(Bar, Decl(generatorTypeCheck22.ts, 0, 23))
yield new Baz;
>Baz : Symbol(Baz, Decl(generatorTypeCheck22.ts, 1, 35))
yield *[new Bar];
>Bar : Symbol(Bar, Decl(generatorTypeCheck22.ts, 0, 23))
yield *[new Baz];
>Baz : Symbol(Baz, Decl(generatorTypeCheck22.ts, 1, 35))
}

View File

@ -1,42 +0,0 @@
=== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck22.ts ===
class Foo { x: number }
>Foo : Foo
>x : number
class Bar extends Foo { y: string }
>Bar : Bar
>Foo : Foo
>y : string
class Baz { z: number }
>Baz : Baz
>z : number
function* g3() {
>g3 : () => IterableIterator<any>
yield;
>yield : any
yield new Bar;
>yield new Bar : any
>new Bar : Bar
>Bar : typeof Bar
yield new Baz;
>yield new Baz : any
>new Baz : Baz
>Baz : typeof Baz
yield *[new Bar];
>yield *[new Bar] : any
>[new Bar] : Bar[]
>new Bar : Bar
>Bar : typeof Bar
yield *[new Baz];
>yield *[new Baz] : any
>[new Baz] : Baz[]
>new Baz : Baz
>Baz : typeof Baz
}

View File

@ -0,0 +1,17 @@
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck23.ts(4,11): error TS2503: No best common type exists among yield expressions.
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck23.ts (1 errors) ====
class Foo { x: number }
class Bar extends Foo { y: string }
class Baz { z: number }
function* g3() {
~~
!!! error TS2503: No best common type exists among yield expressions.
yield;
yield new Foo;
yield new Bar;
yield new Baz;
yield *[new Bar];
yield *[new Baz];
}

View File

@ -1,33 +0,0 @@
=== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck23.ts ===
class Foo { x: number }
>Foo : Symbol(Foo, Decl(generatorTypeCheck23.ts, 0, 0))
>x : Symbol(x, Decl(generatorTypeCheck23.ts, 0, 11))
class Bar extends Foo { y: string }
>Bar : Symbol(Bar, Decl(generatorTypeCheck23.ts, 0, 23))
>Foo : Symbol(Foo, Decl(generatorTypeCheck23.ts, 0, 0))
>y : Symbol(y, Decl(generatorTypeCheck23.ts, 1, 23))
class Baz { z: number }
>Baz : Symbol(Baz, Decl(generatorTypeCheck23.ts, 1, 35))
>z : Symbol(z, Decl(generatorTypeCheck23.ts, 2, 11))
function* g3() {
>g3 : Symbol(g3, Decl(generatorTypeCheck23.ts, 2, 23))
yield;
yield new Foo;
>Foo : Symbol(Foo, Decl(generatorTypeCheck23.ts, 0, 0))
yield new Bar;
>Bar : Symbol(Bar, Decl(generatorTypeCheck23.ts, 0, 23))
yield new Baz;
>Baz : Symbol(Baz, Decl(generatorTypeCheck23.ts, 1, 35))
yield *[new Bar];
>Bar : Symbol(Bar, Decl(generatorTypeCheck23.ts, 0, 23))
yield *[new Baz];
>Baz : Symbol(Baz, Decl(generatorTypeCheck23.ts, 1, 35))
}

View File

@ -1,47 +0,0 @@
=== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck23.ts ===
class Foo { x: number }
>Foo : Foo
>x : number
class Bar extends Foo { y: string }
>Bar : Bar
>Foo : Foo
>y : string
class Baz { z: number }
>Baz : Baz
>z : number
function* g3() {
>g3 : () => IterableIterator<any>
yield;
>yield : any
yield new Foo;
>yield new Foo : any
>new Foo : Foo
>Foo : typeof Foo
yield new Bar;
>yield new Bar : any
>new Bar : Bar
>Bar : typeof Bar
yield new Baz;
>yield new Baz : any
>new Baz : Baz
>Baz : typeof Baz
yield *[new Bar];
>yield *[new Bar] : any
>[new Bar] : Bar[]
>new Bar : Bar
>Bar : typeof Bar
yield *[new Baz];
>yield *[new Baz] : any
>[new Baz] : Baz[]
>new Baz : Baz
>Baz : typeof Baz
}

View File

@ -0,0 +1,17 @@
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck24.ts(4,11): error TS2503: No best common type exists among yield expressions.
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck24.ts (1 errors) ====
class Foo { x: number }
class Bar extends Foo { y: string }
class Baz { z: number }
function* g3() {
~~
!!! error TS2503: No best common type exists among yield expressions.
yield;
yield * [new Foo];
yield new Bar;
yield new Baz;
yield *[new Bar];
yield *[new Baz];
}

View File

@ -1,33 +0,0 @@
=== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck24.ts ===
class Foo { x: number }
>Foo : Symbol(Foo, Decl(generatorTypeCheck24.ts, 0, 0))
>x : Symbol(x, Decl(generatorTypeCheck24.ts, 0, 11))
class Bar extends Foo { y: string }
>Bar : Symbol(Bar, Decl(generatorTypeCheck24.ts, 0, 23))
>Foo : Symbol(Foo, Decl(generatorTypeCheck24.ts, 0, 0))
>y : Symbol(y, Decl(generatorTypeCheck24.ts, 1, 23))
class Baz { z: number }
>Baz : Symbol(Baz, Decl(generatorTypeCheck24.ts, 1, 35))
>z : Symbol(z, Decl(generatorTypeCheck24.ts, 2, 11))
function* g3() {
>g3 : Symbol(g3, Decl(generatorTypeCheck24.ts, 2, 23))
yield;
yield * [new Foo];
>Foo : Symbol(Foo, Decl(generatorTypeCheck24.ts, 0, 0))
yield new Bar;
>Bar : Symbol(Bar, Decl(generatorTypeCheck24.ts, 0, 23))
yield new Baz;
>Baz : Symbol(Baz, Decl(generatorTypeCheck24.ts, 1, 35))
yield *[new Bar];
>Bar : Symbol(Bar, Decl(generatorTypeCheck24.ts, 0, 23))
yield *[new Baz];
>Baz : Symbol(Baz, Decl(generatorTypeCheck24.ts, 1, 35))
}

View File

@ -1,48 +0,0 @@
=== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck24.ts ===
class Foo { x: number }
>Foo : Foo
>x : number
class Bar extends Foo { y: string }
>Bar : Bar
>Foo : Foo
>y : string
class Baz { z: number }
>Baz : Baz
>z : number
function* g3() {
>g3 : () => IterableIterator<any>
yield;
>yield : any
yield * [new Foo];
>yield * [new Foo] : any
>[new Foo] : Foo[]
>new Foo : Foo
>Foo : typeof Foo
yield new Bar;
>yield new Bar : any
>new Bar : Bar
>Bar : typeof Bar
yield new Baz;
>yield new Baz : any
>new Baz : Baz
>Baz : typeof Baz
yield *[new Bar];
>yield *[new Bar] : any
>[new Bar] : Bar[]
>new Bar : Bar
>Bar : typeof Bar
yield *[new Baz];
>yield *[new Baz] : any
>[new Baz] : Baz[]
>new Baz : Baz
>Baz : typeof Baz
}

View File

@ -0,0 +1,12 @@
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck52.ts(3,11): error TS2503: No best common type exists among yield expressions.
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck52.ts (1 errors) ====
class Foo { x: number }
class Baz { z: number }
function* g() {
~
!!! error TS2503: No best common type exists among yield expressions.
yield new Foo;
yield new Baz;
}

View File

@ -0,0 +1,17 @@
//// [generatorTypeCheck52.ts]
class Foo { x: number }
class Baz { z: number }
function* g() {
yield new Foo;
yield new Baz;
}
//// [generatorTypeCheck52.js]
class Foo {
}
class Baz {
}
function* g() {
yield new Foo;
yield new Baz;
}

View File

@ -0,0 +1,12 @@
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck53.ts(3,11): error TS2503: No best common type exists among yield expressions.
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck53.ts (1 errors) ====
class Foo { x: number }
class Baz { z: number }
function* g() {
~
!!! error TS2503: No best common type exists among yield expressions.
yield new Foo;
yield* [new Baz];
}

View File

@ -0,0 +1,17 @@
//// [generatorTypeCheck53.ts]
class Foo { x: number }
class Baz { z: number }
function* g() {
yield new Foo;
yield* [new Baz];
}
//// [generatorTypeCheck53.js]
class Foo {
}
class Baz {
}
function* g() {
yield new Foo;
yield* [new Baz];
}

View File

@ -0,0 +1,12 @@
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck54.ts(3,11): error TS2503: No best common type exists among yield expressions.
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck54.ts (1 errors) ====
class Foo { x: number }
class Baz { z: number }
function* g() {
~
!!! error TS2503: No best common type exists among yield expressions.
yield* [new Foo];
yield* [new Baz];
}

View File

@ -0,0 +1,17 @@
//// [generatorTypeCheck54.ts]
class Foo { x: number }
class Baz { z: number }
function* g() {
yield* [new Foo];
yield* [new Baz];
}
//// [generatorTypeCheck54.js]
class Foo {
}
class Baz {
}
function* g() {
yield* [new Foo];
yield* [new Baz];
}

View File

@ -0,0 +1,7 @@
//@target: ES6
class Foo { x: number }
class Baz { z: number }
function* g() {
yield new Foo;
yield new Baz;
}

View File

@ -0,0 +1,7 @@
//@target: ES6
class Foo { x: number }
class Baz { z: number }
function* g() {
yield new Foo;
yield* [new Baz];
}

View File

@ -0,0 +1,7 @@
//@target: ES6
class Foo { x: number }
class Baz { z: number }
function* g() {
yield* [new Foo];
yield* [new Baz];
}