diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 086be15190bca..0de0cb799d2db 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3972,12 +3972,10 @@ module ts { } // Aggregate the types of expressions within all the return statements. - var types: Type[] = []; - checkAndAggregateReturnExpressionTypes(func.body); + var types = checkAndAggregateReturnExpressionTypes(func.body, contextualType, contextualMapper); // Try to return the best common type if we have any return expressions. - if (types.length) { - + if (types.length > 0) { var commonType = getBestCommonType(types, /*contextualType:*/ undefined, /*candidatesOnly:*/ true); if (!commonType) { error(func, Diagnostics.No_best_common_type_exists_among_return_expressions); @@ -4003,16 +4001,18 @@ module ts { } return voidType; + } + + // WARNING: This has the same semantics as the forEach family of functions, + // in that traversal terminates in the event that 'visitor' supplies a truthy value. + function forEachReturnStatement(body: Block, visitor: (stmt: ReturnStatement) => T): T { + + return traverse(body); - function checkAndAggregateReturnExpressionTypes(node: Node) { + function traverse(node: Node): T { switch (node.kind) { case SyntaxKind.ReturnStatement: - var expr = (node).expression; - if (expr) { - var type = checkAndMarkExpression(expr, contextualType, contextualMapper); - if (!contains(types, type)) types.push(type); - } - break; + return visitor(node); case SyntaxKind.Block: case SyntaxKind.FunctionBlock: case SyntaxKind.IfStatement: @@ -4029,15 +4029,77 @@ module ts { case SyntaxKind.TryBlock: case SyntaxKind.CatchBlock: case SyntaxKind.FinallyBlock: - forEachChild(node, checkAndAggregateReturnExpressionTypes); - break; + return forEachChild(node, traverse); } } } + /// Returns a set of types relating to every return expression relating to a function block. + function checkAndAggregateReturnExpressionTypes(body: Block, contextualType?: Type, contextualMapper?: TypeMapper): Type[] { + var aggregatedTypes: Type[] = []; + + forEachReturnStatement(body, (returnStatement) => { + var expr = returnStatement.expression; + if (expr) { + var type = checkAndMarkExpression(expr, contextualType, contextualMapper); + if (!contains(aggregatedTypes, type)) { + aggregatedTypes.push(type); + } + } + }); + + return aggregatedTypes; + } + + function bodyContainsAReturnStatement(funcBody: Block) { + return forEachReturnStatement(funcBody, (returnStatement) => { + return true; + }); + } + + function bodyContainsSingleThrowStatement(body: Block) { + return (body.statements.length === 1) && (body.statements[0].kind === SyntaxKind.ThrowStatement) + } + + // TypeScript Specification 1.0 (6.3) - July 2014 + // An explicitly typed function whose return type isn't the Void or the Any type + // must have at least one return statement somewhere in its body. + // An exception to this rule is if the function implementation consists of a single 'throw' statement. + function checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(func: FunctionDeclaration, returnType: Type): void { + // Functions that return 'void' or 'any' don't need any return expressions. + if (returnType === voidType || returnType === anyType) { + return; + } + + // If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check. + if (!func.body || func.body.kind !== SyntaxKind.FunctionBlock) { + return; + } + + var bodyBlock = func.body; + + // Ensure the body has at least one return expression. + if (bodyContainsAReturnStatement(bodyBlock)) { + return; + } + + // If there are no return expressions, then we need to check if + // the function body consists solely of a throw statement; + // this is to make an exception for unimplemented functions. + if (bodyContainsSingleThrowStatement(bodyBlock)) { + return; + } + + // This function does not conform to the specification. + error(func.type, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement); + } + function checkFunctionExpression(node: FunctionExpression, contextualType?: Type, contextualMapper?: TypeMapper): Type { // The identityMapper object is used to indicate that function expressions are wildcards - if (contextualMapper === identityMapper) return anyFunctionType; + if (contextualMapper === identityMapper) { + return anyFunctionType; + } + var type = getTypeOfSymbol(node.symbol); var links = getNodeLinks(node); @@ -4055,6 +4117,9 @@ module ts { signature.resolvedReturnType = returnType; } } + else { + checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type)); + } } checkSignatureDeclaration(node); if (node.body.kind === SyntaxKind.FunctionBlock) { @@ -4627,28 +4692,9 @@ module ts { } function checkAccessorDeclaration(node: AccessorDeclaration) { - function checkGetterContainsSingleThrowStatement(node: AccessorDeclaration): boolean { - var block = node.body; - return block.statements.length === 1 && block.statements[0].kind === SyntaxKind.ThrowStatement; - } - - function checkGetterReturnsValue(n: Node): boolean { - switch (n.kind) { - case SyntaxKind.ReturnStatement: - return true; - // do not dive into function-like things - return statements there don't count - case SyntaxKind.FunctionExpression: - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.ArrowFunction: - case SyntaxKind.ObjectLiteral: - return false; - default: - return forEachChild(n, checkGetterReturnsValue); - } - } if (node.kind === SyntaxKind.GetAccessor) { - if (!isInAmbientContext(node) && node.body && !(checkGetterContainsSingleThrowStatement(node) || checkGetterReturnsValue(node))) { - error(node.name, Diagnostics.Getters_must_return_a_value); + if (!isInAmbientContext(node) && node.body && !(bodyContainsAReturnStatement(node.body) || bodyContainsSingleThrowStatement(node.body))) { + error(node.name, Diagnostics.A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement); } } @@ -4877,8 +4923,6 @@ module ts { } } } - - // TODO: Check at least one return statement in non-void/any function (except single throw) } function checkFunctionDeclaration(node: FunctionDeclaration) { @@ -4890,7 +4934,11 @@ module ts { if (node === firstDeclaration) { checkFunctionOrConstructorSymbol(symbol); } + checkSourceElement(node.body); + if (node.type) { + checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type)); + } // If there is no body and no explicit return type, then report an error. if (program.getCompilerOptions().noImplicitAny && !node.body && !node.type) { diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 8b47bd15e2b1c..1abf98883468f 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -114,8 +114,9 @@ module ts { The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2117, category: DiagnosticCategory.Error, key: "The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter." }, The_left_hand_side_of_an_in_expression_must_be_of_types_any_string_or_number: { code: 2118, category: DiagnosticCategory.Error, key: "The left-hand side of an 'in' expression must be of types 'any', 'string' or 'number'." }, The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2119, category: DiagnosticCategory.Error, key: "The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter" }, - Getters_must_return_a_value: { code: 2126, category: DiagnosticCategory.Error, key: "Getters must return a value." }, + A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement: { code: 2126, category: DiagnosticCategory.Error, key: "A 'get' accessor must return a value or consist of a single 'throw' statement." }, Getter_and_setter_accessors_do_not_agree_in_visibility: { code: 2127, category: DiagnosticCategory.Error, key: "Getter and setter accessors do not agree in visibility." }, + A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement: { code: 2131, category: DiagnosticCategory.Error, key: "A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement." }, Untyped_function_calls_may_not_accept_type_arguments: { code: 2158, category: DiagnosticCategory.Error, key: "Untyped function calls may not accept type arguments." }, The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2120, category: DiagnosticCategory.Error, key: "The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter." }, The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type: { code: 2121, category: DiagnosticCategory.Error, key: "The right-hand side of an 'instanceof' expression must be of type 'any' or of a type assignable to the 'Function' interface type." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 3114b1813632f..58b6d41099842 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -449,7 +449,7 @@ "category": "Error", "code": 2119 }, - "Getters must return a value.": { + "A 'get' accessor must return a value or consist of a single 'throw' statement.": { "category": "Error", "code": 2126 }, @@ -457,6 +457,10 @@ "category": "Error", "code": 2127 }, + "A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement.": { + "category": "Error", + "code": 2131 + }, "Untyped function calls may not accept type arguments.": { "category": "Error", "code": 2158 diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 6ce2ef1461f7a..0304586bbca2f 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1070,7 +1070,7 @@ module ts { return finishNode(node); } - function checkIndexSignature(node: SignatureDeclaration, indexerStart: number, indexerLength: number): boolean { + function checkIndexSignature(node: SignatureDeclaration, indexerStart: number, indexerLength: number): void { var parameter = node.parameters[0]; if (node.parameters.length !== 1) { var arityDiagnostic = Diagnostics.An_index_signature_must_have_exactly_one_parameter diff --git a/tests/baselines/reference/ParameterList5.errors.txt b/tests/baselines/reference/ParameterList5.errors.txt index 37487b5c3199d..412fb71eb1480 100644 --- a/tests/baselines/reference/ParameterList5.errors.txt +++ b/tests/baselines/reference/ParameterList5.errors.txt @@ -1,5 +1,7 @@ -==== tests/cases/compiler/ParameterList5.ts (2 errors) ==== +==== tests/cases/compiler/ParameterList5.ts (3 errors) ==== function A(): (public B) => C { + ~~~~~~~~~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. ~~~~~~~~ !!! A parameter property is only allowed in a constructor implementation. ~ diff --git a/tests/baselines/reference/ambientGetters.errors.txt b/tests/baselines/reference/ambientGetters.errors.txt index 05c405810740b..a8c913b66c7a6 100644 --- a/tests/baselines/reference/ambientGetters.errors.txt +++ b/tests/baselines/reference/ambientGetters.errors.txt @@ -1,9 +1,11 @@ -==== tests/cases/compiler/ambientGetters.ts (2 errors) ==== +==== tests/cases/compiler/ambientGetters.ts (3 errors) ==== declare class A { get length() : number; ~ !!! '{' expected. + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. } declare class B { diff --git a/tests/baselines/reference/conflictingTypeAnnotatedVar.errors.txt b/tests/baselines/reference/conflictingTypeAnnotatedVar.errors.txt index 85867f5e573e3..6bb45b67ee743 100644 --- a/tests/baselines/reference/conflictingTypeAnnotatedVar.errors.txt +++ b/tests/baselines/reference/conflictingTypeAnnotatedVar.errors.txt @@ -1,8 +1,12 @@ -==== tests/cases/compiler/conflictingTypeAnnotatedVar.ts (2 errors) ==== +==== tests/cases/compiler/conflictingTypeAnnotatedVar.ts (4 errors) ==== var foo: string; function foo(): number { } ~~~ !!! Duplicate identifier 'foo'. + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. function foo(): number { } ~~~ -!!! Duplicate identifier 'foo'. \ No newline at end of file +!!! Duplicate identifier 'foo'. + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. \ No newline at end of file diff --git a/tests/baselines/reference/errorOnContextuallyTypedReturnType.errors.txt b/tests/baselines/reference/errorOnContextuallyTypedReturnType.errors.txt index cb501a10e0640..414fa7dc4c2b1 100644 --- a/tests/baselines/reference/errorOnContextuallyTypedReturnType.errors.txt +++ b/tests/baselines/reference/errorOnContextuallyTypedReturnType.errors.txt @@ -1,7 +1,9 @@ -==== tests/cases/compiler/errorOnContextuallyTypedReturnType.ts (1 errors) ==== +==== tests/cases/compiler/errorOnContextuallyTypedReturnType.ts (2 errors) ==== var n1: () => boolean = function () { }; // expect an error here ~~ !!! Type '() => void' is not assignable to type '() => boolean': !!! Type 'void' is not assignable to type 'boolean'. var n2: () => boolean = function ():boolean { }; // expect an error here + ~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. \ No newline at end of file diff --git a/tests/baselines/reference/functionImplementationErrors.errors.txt b/tests/baselines/reference/functionImplementationErrors.errors.txt index d9d35c555ad9b..3da56bd681801 100644 --- a/tests/baselines/reference/functionImplementationErrors.errors.txt +++ b/tests/baselines/reference/functionImplementationErrors.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/conformance/functions/functionImplementationErrors.ts (6 errors) ==== +==== tests/cases/conformance/functions/functionImplementationErrors.ts (7 errors) ==== // FunctionExpression with no return type annotation with multiple return statements with unrelated types var f1 = function () { ~~~~~~~~~~~~~ @@ -47,6 +47,8 @@ // Function implemetnation with non -void return type annotation with no return function f5(): number { + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. } var m; diff --git a/tests/baselines/reference/functionWithThrowButNoReturn1.errors.txt b/tests/baselines/reference/functionWithThrowButNoReturn1.errors.txt new file mode 100644 index 0000000000000..b354a9f8852fe --- /dev/null +++ b/tests/baselines/reference/functionWithThrowButNoReturn1.errors.txt @@ -0,0 +1,8 @@ +==== tests/cases/compiler/functionWithThrowButNoReturn1.ts (1 errors) ==== + function fn(): number { + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + throw new Error('NYI'); + var t; + } + \ No newline at end of file diff --git a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.errors.txt b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.errors.txt new file mode 100644 index 0000000000000..6ddbc91db5701 --- /dev/null +++ b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.errors.txt @@ -0,0 +1,129 @@ +==== tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts (5 errors) ==== + + function f1(): string { + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + // errors because there are no return statements + } + + function f2(): string { + // Permissible; returns undefined. + return; + } + + function f3(): string { + return "Okay, because this is a return expression."; + } + + function f4(): void { + // Fine since we are typed void. + } + + function f5(): void { + // Fine since we are typed void. + return; + } + + function f6(): void { + // Fine since we are typed void and return undefined + return undefined; + } + + function f7(): void { + // Fine since we are typed void and return null + return null; + } + + function f8(): void { + // Fine since are typed any. + return; + } + + function f9(): void { + // Fine since we are typed any and return undefined + return undefined; + } + + function f10(): void { + // Fine since we are typed any and return null + return null; + } + + function f11(): string { + // Fine since we consist of a single throw statement. + throw undefined; + } + + function f12(): void { + // Fine since we consist of a single throw statement. + throw undefined; + } + + function f13(): any { + // Fine since we consist of a single throw statement. + throw undefined; + } + + function f14(): number { + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + // Not fine, since we can *only* consist of a single throw statement + // if no return statements are present but we are annotated. + throw undefined; + throw null; + } + + function f15(): number { + // Fine, since we have a return statement somewhere. + throw undefined; + throw null; + return; + } + + + function f16() { + // Okay; not type annotated. + } + + function f17() { + // Okay; not type annotated. + return; + } + + function f18() { + return "Okay, not type annotated."; + } + + + class C { + public get m1() { + ~~ +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. + // Errors; get accessors must return a value. + } + + public get m2() { + // Permissible; returns undefined. + return; + } + + public get m3() { + return "Okay, because this is a return expression."; + } + + public get m4() { + // Fine since this consists of a single throw statement. + throw null; + } + + public get m5() { + ~~ +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. + // Not fine, since we can *only* consist of a single throw statement + // if no return statements are present but we are a get accessor. + throw null; + throw undefined. + } + ~ +!!! Identifier expected. + } \ No newline at end of file diff --git a/tests/baselines/reference/genericRecursiveImplicitConstructorErrors3.errors.txt b/tests/baselines/reference/genericRecursiveImplicitConstructorErrors3.errors.txt index 71545ae7503c7..1320a21f46bfe 100644 --- a/tests/baselines/reference/genericRecursiveImplicitConstructorErrors3.errors.txt +++ b/tests/baselines/reference/genericRecursiveImplicitConstructorErrors3.errors.txt @@ -1,8 +1,10 @@ -==== tests/cases/compiler/genericRecursiveImplicitConstructorErrors3.ts (7 errors) ==== +==== tests/cases/compiler/genericRecursiveImplicitConstructorErrors3.ts (8 errors) ==== module TypeScript { export class MemberName { static create(arg1: any, arg2?: any, arg3?: any): MemberName { ~~~~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + ~~~~~~~~~~ !!! Generic type 'MemberName' requires 3 type argument(s). } } diff --git a/tests/baselines/reference/getterMissingReturnError.errors.txt b/tests/baselines/reference/getterMissingReturnError.errors.txt index cf4f9b6b1a7a7..ae560c5de8794 100644 --- a/tests/baselines/reference/getterMissingReturnError.errors.txt +++ b/tests/baselines/reference/getterMissingReturnError.errors.txt @@ -4,7 +4,7 @@ ~~ !!! Accessors are only available when targeting ECMAScript 5 and higher. ~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } } diff --git a/tests/baselines/reference/gettersAndSettersErrors.errors.txt b/tests/baselines/reference/gettersAndSettersErrors.errors.txt index 1cfefea5202ed..dbd06a744f0c4 100644 --- a/tests/baselines/reference/gettersAndSettersErrors.errors.txt +++ b/tests/baselines/reference/gettersAndSettersErrors.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/compiler/gettersAndSettersErrors.ts (9 errors) ==== +==== tests/cases/compiler/gettersAndSettersErrors.ts (10 errors) ==== class C { public get Foo() { return "foo";} // ok ~~~ @@ -16,6 +16,8 @@ public set Goo(v:string):string {} // error - setters must not specify a return type ~~~ !!! Accessors are only available when targeting ECMAScript 5 and higher. + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. } class E { diff --git a/tests/baselines/reference/giant.errors.txt b/tests/baselines/reference/giant.errors.txt index 35dddbb324e6d..f6b6dd5c7962c 100644 --- a/tests/baselines/reference/giant.errors.txt +++ b/tests/baselines/reference/giant.errors.txt @@ -26,7 +26,7 @@ ~~~ !!! Duplicate identifier 'pgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. public psF(param:any) { } ~~~~~~ !!! '{' expected. @@ -40,7 +40,7 @@ ~~~ !!! Duplicate identifier 'rgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. private rsF(param:any) { } ~~~~~~~ !!! '{' expected. @@ -62,7 +62,7 @@ ~~~ !!! Duplicate identifier 'tgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } ~ !!! '{' expected. @@ -128,7 +128,7 @@ ~~~ !!! Duplicate identifier 'pgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. public psF(param:any) { } ~~~~~~ !!! '{' expected. @@ -142,7 +142,7 @@ ~~~ !!! Duplicate identifier 'rgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. private rsF(param:any) { } ~~~~~~~ !!! '{' expected. @@ -164,7 +164,7 @@ ~~~ !!! Duplicate identifier 'tgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } ~ !!! '{' expected. @@ -247,7 +247,7 @@ ~~~ !!! Duplicate identifier 'pgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. public psF(param:any) { } ~~~~~~ !!! '{' expected. @@ -261,7 +261,7 @@ ~~~ !!! Duplicate identifier 'rgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. private rsF(param:any) { } ~~~~~~~ !!! '{' expected. @@ -283,7 +283,7 @@ ~~~ !!! Duplicate identifier 'tgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } ~ !!! '{' expected. @@ -456,7 +456,7 @@ ~~~ !!! Duplicate identifier 'pgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. public psF(param:any) { } ~~~~~~ !!! '{' expected. @@ -470,7 +470,7 @@ ~~~ !!! Duplicate identifier 'rgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. private rsF(param:any) { } ~~~~~~~ !!! '{' expected. @@ -492,7 +492,7 @@ ~~~ !!! Duplicate identifier 'tgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } ~ !!! '{' expected. @@ -558,7 +558,7 @@ ~~~ !!! Duplicate identifier 'pgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. public psF(param:any) { } ~~~~~~ !!! '{' expected. @@ -572,7 +572,7 @@ ~~~ !!! Duplicate identifier 'rgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. private rsF(param:any) { } ~~~~~~~ !!! '{' expected. @@ -594,7 +594,7 @@ ~~~ !!! Duplicate identifier 'tgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } ~ !!! '{' expected. @@ -677,7 +677,7 @@ ~~~ !!! Duplicate identifier 'pgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. public psF(param:any) { } ~~~~~~ !!! '{' expected. @@ -691,7 +691,7 @@ ~~~ !!! Duplicate identifier 'rgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. private rsF(param:any) { } ~~~~~~~ !!! '{' expected. @@ -713,7 +713,7 @@ ~~~ !!! Duplicate identifier 'tgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } ~ !!! '{' expected. diff --git a/tests/baselines/reference/invalidReturnStatements.errors.txt b/tests/baselines/reference/invalidReturnStatements.errors.txt index d870be638b998..ee371f5f000de 100644 --- a/tests/baselines/reference/invalidReturnStatements.errors.txt +++ b/tests/baselines/reference/invalidReturnStatements.errors.txt @@ -1,9 +1,17 @@ -==== tests/cases/conformance/statements/returnStatements/invalidReturnStatements.ts (2 errors) ==== +==== tests/cases/conformance/statements/returnStatements/invalidReturnStatements.ts (6 errors) ==== // all the following should be error function fn1(): number { } + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. function fn2(): string { } + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. function fn3(): boolean { } + ~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. function fn4(): Date { } + ~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. function fn7(): any { } // should be valid: any includes void interface I { id: number } diff --git a/tests/baselines/reference/missingReturnStatement.errors.txt b/tests/baselines/reference/missingReturnStatement.errors.txt new file mode 100644 index 0000000000000..9a92adf4c03f0 --- /dev/null +++ b/tests/baselines/reference/missingReturnStatement.errors.txt @@ -0,0 +1,10 @@ +==== tests/cases/compiler/missingReturnStatement.ts (1 errors) ==== + module Test { + export class Bug { + public foo():string { + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + } + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/missingReturnStatement1.errors.txt b/tests/baselines/reference/missingReturnStatement1.errors.txt new file mode 100644 index 0000000000000..d1d47368bb1f9 --- /dev/null +++ b/tests/baselines/reference/missingReturnStatement1.errors.txt @@ -0,0 +1,9 @@ +==== tests/cases/compiler/missingReturnStatement1.ts (1 errors) ==== + class Foo { + foo(): number { + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + //return 4; + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/multiLineErrors.errors.txt b/tests/baselines/reference/multiLineErrors.errors.txt index b01adc3bfb057..911c07731e328 100644 --- a/tests/baselines/reference/multiLineErrors.errors.txt +++ b/tests/baselines/reference/multiLineErrors.errors.txt @@ -1,10 +1,15 @@ -==== tests/cases/compiler/multiLineErrors.ts (1 errors) ==== +==== tests/cases/compiler/multiLineErrors.ts (2 errors) ==== var t = 32; function noReturn(): { + ~ n: string; + ~~~~~~~~~~~~~~ y: number; + ~~~~~~~~~~~~~~ } + ~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. { var x = 4; var y = 10; diff --git a/tests/baselines/reference/parserAccessors1.errors.txt b/tests/baselines/reference/parserAccessors1.errors.txt index 4621637b211cc..76747e3710476 100644 --- a/tests/baselines/reference/parserAccessors1.errors.txt +++ b/tests/baselines/reference/parserAccessors1.errors.txt @@ -2,5 +2,5 @@ class C { get Foo() { } ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserAccessors3.errors.txt b/tests/baselines/reference/parserAccessors3.errors.txt index 4d722dd1310f4..dd1f2075ae68a 100644 --- a/tests/baselines/reference/parserAccessors3.errors.txt +++ b/tests/baselines/reference/parserAccessors3.errors.txt @@ -1,4 +1,4 @@ ==== tests/cases/conformance/parser/ecmascript5/Accessors/parserAccessors3.ts (1 errors) ==== var v = { get Foo() { } }; ~~~ -!!! Getters must return a value. \ No newline at end of file +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. \ No newline at end of file diff --git a/tests/baselines/reference/parserAccessors7.errors.txt b/tests/baselines/reference/parserAccessors7.errors.txt index 13597d19f7104..cac6f016814b4 100644 --- a/tests/baselines/reference/parserAccessors7.errors.txt +++ b/tests/baselines/reference/parserAccessors7.errors.txt @@ -3,4 +3,4 @@ ~~~ !!! A 'get' accessor cannot have parameters. ~~~ -!!! Getters must return a value. \ No newline at end of file +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. \ No newline at end of file diff --git a/tests/baselines/reference/parserES3Accessors1.errors.txt b/tests/baselines/reference/parserES3Accessors1.errors.txt index 3ab21b3001e66..53bfc5e868e16 100644 --- a/tests/baselines/reference/parserES3Accessors1.errors.txt +++ b/tests/baselines/reference/parserES3Accessors1.errors.txt @@ -4,5 +4,5 @@ ~~~ !!! Accessors are only available when targeting ECMAScript 5 and higher. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES3Accessors3.errors.txt b/tests/baselines/reference/parserES3Accessors3.errors.txt index 3678eb94dc11a..74a79ccf6d89f 100644 --- a/tests/baselines/reference/parserES3Accessors3.errors.txt +++ b/tests/baselines/reference/parserES3Accessors3.errors.txt @@ -3,4 +3,4 @@ ~~~ !!! Accessors are only available when targeting ECMAScript 5 and higher. ~~~ -!!! Getters must return a value. \ No newline at end of file +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. \ No newline at end of file diff --git a/tests/baselines/reference/parserErrorRecovery_Block3.errors.txt b/tests/baselines/reference/parserErrorRecovery_Block3.errors.txt index 15bc9ad3385ae..354cfff1fdd1c 100644 --- a/tests/baselines/reference/parserErrorRecovery_Block3.errors.txt +++ b/tests/baselines/reference/parserErrorRecovery_Block3.errors.txt @@ -1,9 +1,13 @@ -==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/Blocks/parserErrorRecovery_Block3.ts (1 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/Blocks/parserErrorRecovery_Block3.ts (3 errors) ==== class C { private a(): boolean { + ~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. private b(): boolean { ~~~~~~~ !!! Statement expected. + ~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. } } \ No newline at end of file diff --git a/tests/baselines/reference/parserGenericsInTypeContexts1.errors.txt b/tests/baselines/reference/parserGenericsInTypeContexts1.errors.txt index 2239f1ff99313..574c03823dfe4 100644 --- a/tests/baselines/reference/parserGenericsInTypeContexts1.errors.txt +++ b/tests/baselines/reference/parserGenericsInTypeContexts1.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts (9 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts (10 errors) ==== class C extends A implements B { ~~~~ !!! Cannot find name 'A'. @@ -30,6 +30,8 @@ function f2(): F { ~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + ~~~~ !!! Cannot find name 'F'. } diff --git a/tests/baselines/reference/parserGenericsInTypeContexts2.errors.txt b/tests/baselines/reference/parserGenericsInTypeContexts2.errors.txt index b99d682616956..f3b47f0436898 100644 --- a/tests/baselines/reference/parserGenericsInTypeContexts2.errors.txt +++ b/tests/baselines/reference/parserGenericsInTypeContexts2.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts (9 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts (10 errors) ==== class C extends A, Y>> implements B, Y>> { ~~~~~~~~~~~~~~~~ !!! Cannot find name 'A'. @@ -30,6 +30,8 @@ function f2(): F, Y>> { ~~~~~~~~~~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + ~~~~~~~~~~~~~~~~ !!! Cannot find name 'F'. } diff --git a/tests/baselines/reference/parserGetAccessorWithTypeParameters1.errors.txt b/tests/baselines/reference/parserGetAccessorWithTypeParameters1.errors.txt index 33705621fb82f..0f290dbd8abd7 100644 --- a/tests/baselines/reference/parserGetAccessorWithTypeParameters1.errors.txt +++ b/tests/baselines/reference/parserGetAccessorWithTypeParameters1.errors.txt @@ -4,5 +4,5 @@ ~~~ !!! An accessor cannot have type parameters. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessor1.errors.txt b/tests/baselines/reference/parserMemberAccessor1.errors.txt index cc64233237bc9..c768b0ce2fe8e 100644 --- a/tests/baselines/reference/parserMemberAccessor1.errors.txt +++ b/tests/baselines/reference/parserMemberAccessor1.errors.txt @@ -2,6 +2,6 @@ class C { get foo() { } ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. set foo(a) { } } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration1.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration1.errors.txt index a052f03808ec8..403a30a67aed8 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration1.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration1.errors.txt @@ -2,5 +2,5 @@ class C { get a() { } ~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration10.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration10.errors.txt index 8ea973bbb2984..a1b29085f5d61 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration10.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration10.errors.txt @@ -4,5 +4,5 @@ ~~~~~~ !!! 'export' modifier cannot appear on a class element. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration12.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration12.errors.txt index d3ca95a6bc2ab..7cbf2606274ab 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration12.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration12.errors.txt @@ -4,5 +4,5 @@ ~~~ !!! A 'get' accessor cannot have parameters. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration2.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration2.errors.txt index 3cdd230ad6568..1a32d342f1b30 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration2.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration2.errors.txt @@ -2,5 +2,5 @@ class C { get "b"() { } ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration3.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration3.errors.txt index 53a0dd84fac83..dbf94b6420f0f 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration3.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration3.errors.txt @@ -2,5 +2,5 @@ class C { get 0() { } ~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration7.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration7.errors.txt index 614c1251aa483..20ebd2f358380 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration7.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration7.errors.txt @@ -4,5 +4,5 @@ ~~~~~~ !!! Accessibility modifier already seen. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration8.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration8.errors.txt index f28ee32f00ef7..f6d151bfb7fb4 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration8.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration8.errors.txt @@ -4,5 +4,5 @@ ~~~~~~ !!! 'static' modifier already seen. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration9.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration9.errors.txt index d2a52098aa755..e4c88dfd57d5f 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration9.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration9.errors.txt @@ -4,5 +4,5 @@ ~~~~~~ !!! 'public' modifier must precede 'static' modifier. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserParameterList5.errors.txt b/tests/baselines/reference/parserParameterList5.errors.txt index c8a9aa31b7836..ccc5d8c0dbf83 100644 --- a/tests/baselines/reference/parserParameterList5.errors.txt +++ b/tests/baselines/reference/parserParameterList5.errors.txt @@ -1,5 +1,7 @@ -==== tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList5.ts (2 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList5.ts (3 errors) ==== function A(): (public B) => C { + ~~~~~~~~~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. ~~~~~~~~ !!! A parameter property is only allowed in a constructor implementation. ~ diff --git a/tests/baselines/reference/parserSetAccessorWithTypeAnnotation1.errors.txt b/tests/baselines/reference/parserSetAccessorWithTypeAnnotation1.errors.txt index 135f06cf304b4..f4898163e0ff0 100644 --- a/tests/baselines/reference/parserSetAccessorWithTypeAnnotation1.errors.txt +++ b/tests/baselines/reference/parserSetAccessorWithTypeAnnotation1.errors.txt @@ -1,7 +1,9 @@ -==== tests/cases/conformance/parser/ecmascript5/Accessors/parserSetAccessorWithTypeAnnotation1.ts (1 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/Accessors/parserSetAccessorWithTypeAnnotation1.ts (2 errors) ==== class C { set foo(v): number { ~~~ !!! A 'set' accessor cannot have a return type annotation. + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. } } \ No newline at end of file diff --git a/tests/baselines/reference/recursiveFunctionTypes.errors.txt b/tests/baselines/reference/recursiveFunctionTypes.errors.txt index e14d3a38a5c35..833fcf386c07e 100644 --- a/tests/baselines/reference/recursiveFunctionTypes.errors.txt +++ b/tests/baselines/reference/recursiveFunctionTypes.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/compiler/recursiveFunctionTypes.ts (10 errors) ==== +==== tests/cases/compiler/recursiveFunctionTypes.ts (12 errors) ==== function fn(): typeof fn { return 1; } ~ !!! Type 'number' is not assignable to type '() => typeof fn'. @@ -17,7 +17,11 @@ function f1(d: typeof f1) { } function f2(): typeof g2 { } + ~~~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. function g2(): typeof f2 { } + ~~~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. interface I { } function f3(): I { return f3; } diff --git a/tests/baselines/reference/returnTypeParameter.errors.txt b/tests/baselines/reference/returnTypeParameter.errors.txt index 1490825c77a6c..f8927fef42727 100644 --- a/tests/baselines/reference/returnTypeParameter.errors.txt +++ b/tests/baselines/reference/returnTypeParameter.errors.txt @@ -1,5 +1,7 @@ -==== tests/cases/compiler/returnTypeParameter.ts (1 errors) ==== +==== tests/cases/compiler/returnTypeParameter.ts (2 errors) ==== function f(a: T): T { } // error, no return statement + ~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. function f2(a: T): T { return T; } // bug was that this satisfied the return statement requirement ~ !!! Cannot find name 'T'. \ No newline at end of file diff --git a/tests/baselines/reference/typeParameterUsedAsTypeParameterConstraint4.errors.txt b/tests/baselines/reference/typeParameterUsedAsTypeParameterConstraint4.errors.txt index 9903408f70bf5..da073522ae83e 100644 --- a/tests/baselines/reference/typeParameterUsedAsTypeParameterConstraint4.errors.txt +++ b/tests/baselines/reference/typeParameterUsedAsTypeParameterConstraint4.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/conformance/types/objectTypeLiteral/callSignatures/typeParameterUsedAsTypeParameterConstraint4.ts (25 errors) ==== +==== tests/cases/conformance/types/objectTypeLiteral/callSignatures/typeParameterUsedAsTypeParameterConstraint4.ts (29 errors) ==== // Type parameters are in scope in their own and other type parameter lists // Some negative cases @@ -35,9 +35,13 @@ ~~~~~~~~~~~ !!! Constraint of a type parameter cannot reference any type parameter from the same type parameter list. ~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + ~ !!! Cannot find name 'V'. function bar(): X { // error ~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + ~ !!! Cannot find name 'X'. function baz(a: X, b: Y): T { x = y; @@ -54,9 +58,13 @@ ~~~~~~~~~~~ !!! Constraint of a type parameter cannot reference any type parameter from the same type parameter list. ~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + ~ !!! Cannot find name 'W'. function bar(): Y { // error ~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + ~ !!! Cannot find name 'Y'. function baz(a: X, b: Y): T { x = y; diff --git a/tests/baselines/reference/unknownSymbols1.errors.txt b/tests/baselines/reference/unknownSymbols1.errors.txt index 220d7ba0ddb80..beb39743441af 100644 --- a/tests/baselines/reference/unknownSymbols1.errors.txt +++ b/tests/baselines/reference/unknownSymbols1.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/compiler/unknownSymbols1.ts (13 errors) ==== +==== tests/cases/compiler/unknownSymbols1.ts (14 errors) ==== var x = asdf; ~~~~ !!! Cannot find name 'asdf'. @@ -10,6 +10,8 @@ ~~~~ !!! Cannot find name 'asdf'. ~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + ~~~~ !!! Cannot find name 'asdf'. function foo2() { return asdf; diff --git a/tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts b/tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts new file mode 100644 index 0000000000000..81259fd7c0c7f --- /dev/null +++ b/tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts @@ -0,0 +1,119 @@ +// @target: es5 + +function f1(): string { + // errors because there are no return statements +} + +function f2(): string { + // Permissible; returns undefined. + return; +} + +function f3(): string { + return "Okay, because this is a return expression."; +} + +function f4(): void { + // Fine since we are typed void. +} + +function f5(): void { + // Fine since we are typed void. + return; +} + +function f6(): void { + // Fine since we are typed void and return undefined + return undefined; +} + +function f7(): void { + // Fine since we are typed void and return null + return null; +} + +function f8(): void { + // Fine since are typed any. + return; +} + +function f9(): void { + // Fine since we are typed any and return undefined + return undefined; +} + +function f10(): void { + // Fine since we are typed any and return null + return null; +} + +function f11(): string { + // Fine since we consist of a single throw statement. + throw undefined; +} + +function f12(): void { + // Fine since we consist of a single throw statement. + throw undefined; +} + +function f13(): any { + // Fine since we consist of a single throw statement. + throw undefined; +} + +function f14(): number { + // Not fine, since we can *only* consist of a single throw statement + // if no return statements are present but we are annotated. + throw undefined; + throw null; +} + +function f15(): number { + // Fine, since we have a return statement somewhere. + throw undefined; + throw null; + return; +} + + +function f16() { + // Okay; not type annotated. +} + +function f17() { + // Okay; not type annotated. + return; +} + +function f18() { + return "Okay, not type annotated."; +} + + +class C { + public get m1() { + // Errors; get accessors must return a value. + } + + public get m2() { + // Permissible; returns undefined. + return; + } + + public get m3() { + return "Okay, because this is a return expression."; + } + + public get m4() { + // Fine since this consists of a single throw statement. + throw null; + } + + public get m5() { + // Not fine, since we can *only* consist of a single throw statement + // if no return statements are present but we are a get accessor. + throw null; + throw undefined. + } +} \ No newline at end of file