@@ -4524,25 +4524,26 @@ module ts {
45244524 }
45254525 }
45264526 }
4527+ checkSignatureDeclaration ( node ) ;
45274528 }
45284529 }
4529- if ( fullTypeCheck && ! ( links . flags & NodeCheckFlags . TypeChecked ) ) {
4530- checkSignatureDeclaration ( node ) ;
4530+ return type ;
4531+ }
4532+
4533+ function checkFunctionExpressionBody ( node : FunctionExpression ) {
4534+ if ( node . type ) {
4535+ checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment ( node , getTypeFromTypeNode ( node . type ) ) ;
4536+ }
4537+ if ( node . body . kind === SyntaxKind . FunctionBlock ) {
4538+ checkSourceElement ( node . body ) ;
4539+ }
4540+ else {
4541+ var exprType = checkExpression ( node . body ) ;
45314542 if ( node . type ) {
4532- checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment ( node , getTypeFromTypeNode ( node . type ) ) ;
4533- }
4534- if ( node . body . kind === SyntaxKind . FunctionBlock ) {
4535- checkSourceElement ( node . body ) ;
4543+ checkTypeAssignableTo ( exprType , getTypeFromTypeNode ( node . type ) , node . body , undefined , undefined ) ;
45364544 }
4537- else {
4538- var exprType = checkExpression ( node . body ) ;
4539- if ( node . type ) {
4540- checkTypeAssignableTo ( exprType , getTypeFromTypeNode ( node . type ) , node . body , undefined , undefined ) ;
4541- }
4542- }
4543- links . flags |= NodeCheckFlags . TypeChecked ;
4545+ checkFunctionExpressionBodies ( node . body ) ;
45444546 }
4545- return type ;
45464547 }
45474548
45484549 function checkArithmeticOperandType ( operand : Node , type : Type , diagnostic : DiagnosticMessage ) : boolean {
@@ -6438,9 +6439,10 @@ module ts {
64386439 case SyntaxKind . FunctionDeclaration :
64396440 return checkFunctionDeclaration ( < FunctionDeclaration > node ) ;
64406441 case SyntaxKind . Block :
6442+ return checkBlock ( < Block > node ) ;
64416443 case SyntaxKind . FunctionBlock :
64426444 case SyntaxKind . ModuleBlock :
6443- return checkBlock ( < Block > node ) ;
6445+ return checkBody ( < Block > node ) ;
64446446 case SyntaxKind . VariableStatement :
64456447 return checkVariableStatement ( < VariableStatement > node ) ;
64466448 case SyntaxKind . ExpressionStatement :
@@ -6487,13 +6489,91 @@ module ts {
64876489 }
64886490 }
64896491
6492+ // Function expression bodies are checked after all statements in the enclosing body. This is to ensure
6493+ // constructs like the following are permitted:
6494+ // var foo = function () {
6495+ // var s = foo();
6496+ // return "hello";
6497+ // }
6498+ // Here, performing a full type check of the body of the function expression whilst in the process of
6499+ // determining the type of foo would cause foo to be given type any because of the recursive reference.
6500+ // Delaying the type check of the body ensures foo has been assigned a type.
6501+ function checkFunctionExpressionBodies ( node : Node ) : void {
6502+ switch ( node . kind ) {
6503+ case SyntaxKind . FunctionExpression :
6504+ case SyntaxKind . ArrowFunction :
6505+ forEach ( ( < FunctionDeclaration > node ) . parameters , checkFunctionExpressionBodies ) ;
6506+ checkFunctionExpressionBody ( < FunctionExpression > node ) ;
6507+ break ;
6508+ case SyntaxKind . Method :
6509+ case SyntaxKind . Constructor :
6510+ case SyntaxKind . GetAccessor :
6511+ case SyntaxKind . SetAccessor :
6512+ case SyntaxKind . FunctionDeclaration :
6513+ forEach ( ( < FunctionDeclaration > node ) . parameters , checkFunctionExpressionBodies ) ;
6514+ break ;
6515+ case SyntaxKind . WithStatement :
6516+ checkFunctionExpressionBodies ( ( < WithStatement > node ) . expression ) ;
6517+ break ;
6518+ case SyntaxKind . Parameter :
6519+ case SyntaxKind . Property :
6520+ case SyntaxKind . ArrayLiteral :
6521+ case SyntaxKind . ObjectLiteral :
6522+ case SyntaxKind . PropertyAssignment :
6523+ case SyntaxKind . PropertyAccess :
6524+ case SyntaxKind . IndexedAccess :
6525+ case SyntaxKind . CallExpression :
6526+ case SyntaxKind . NewExpression :
6527+ case SyntaxKind . TypeAssertion :
6528+ case SyntaxKind . ParenExpression :
6529+ case SyntaxKind . PrefixOperator :
6530+ case SyntaxKind . PostfixOperator :
6531+ case SyntaxKind . BinaryExpression :
6532+ case SyntaxKind . ConditionalExpression :
6533+ case SyntaxKind . Block :
6534+ case SyntaxKind . FunctionBlock :
6535+ case SyntaxKind . ModuleBlock :
6536+ case SyntaxKind . VariableStatement :
6537+ case SyntaxKind . ExpressionStatement :
6538+ case SyntaxKind . IfStatement :
6539+ case SyntaxKind . DoStatement :
6540+ case SyntaxKind . WhileStatement :
6541+ case SyntaxKind . ForStatement :
6542+ case SyntaxKind . ForInStatement :
6543+ case SyntaxKind . ContinueStatement :
6544+ case SyntaxKind . BreakStatement :
6545+ case SyntaxKind . ReturnStatement :
6546+ case SyntaxKind . SwitchStatement :
6547+ case SyntaxKind . CaseClause :
6548+ case SyntaxKind . DefaultClause :
6549+ case SyntaxKind . LabelledStatement :
6550+ case SyntaxKind . ThrowStatement :
6551+ case SyntaxKind . TryStatement :
6552+ case SyntaxKind . TryBlock :
6553+ case SyntaxKind . CatchBlock :
6554+ case SyntaxKind . FinallyBlock :
6555+ case SyntaxKind . VariableDeclaration :
6556+ case SyntaxKind . ClassDeclaration :
6557+ case SyntaxKind . EnumDeclaration :
6558+ case SyntaxKind . EnumMember :
6559+ case SyntaxKind . SourceFile :
6560+ forEachChild ( node , checkFunctionExpressionBodies ) ;
6561+ break ;
6562+ }
6563+ }
6564+
6565+ function checkBody ( node : Block ) {
6566+ checkBlock ( node ) ;
6567+ checkFunctionExpressionBodies ( node ) ;
6568+ }
6569+
64906570 // Fully type check a source file and collect the relevant diagnostics.
64916571 function checkSourceFile ( node : SourceFile ) {
64926572 var links = getNodeLinks ( node ) ;
64936573 if ( ! ( links . flags & NodeCheckFlags . TypeChecked ) ) {
64946574 emitExtends = false ;
64956575 potentialThisCollisions . length = 0 ;
6496- forEach ( node . statements , checkSourceElement ) ;
6576+ checkBody ( node ) ;
64976577 if ( isExternalModule ( node ) ) {
64986578 var symbol = getExportAssignmentSymbol ( node . symbol ) ;
64996579 if ( symbol && symbol . flags & SymbolFlags . Import ) {
0 commit comments