Skip to content

Commit 71b98e0

Browse files
committed
apply 'noImplicitReturns' check for functions that don't have type annotations
1 parent 883b8d9 commit 71b98e0

File tree

4 files changed

+561
-23
lines changed

4 files changed

+561
-23
lines changed

src/compiler/checker.ts

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9815,13 +9815,19 @@ namespace ts {
98159815
// An explicitly typed function whose return type isn't the Void or the Any type
98169816
// must have at least one return statement somewhere in its body.
98179817
// An exception to this rule is if the function implementation consists of a single 'throw' statement.
9818+
// @param returnType - return type of the function, can be undefined if return type is not explicitly specified
98189819
function checkAllCodePathsInNonVoidFunctionReturnOrThrow(func: FunctionLikeDeclaration, returnType: Type): void {
98199820
if (!produceDiagnostics) {
98209821
return;
98219822
}
98229823

9823-
// Functions that return 'void' or 'any' don't need any return expressions.
9824-
if (returnType === voidType || isTypeAny(returnType)) {
9824+
// Functions with explicitly specified return type which is either 'void' or 'any' don't need any return expressions.
9825+
if (returnType && (returnType === voidType || isTypeAny(returnType))) {
9826+
return;
9827+
}
9828+
9829+
// if return type is not specified then we'll do the check only if 'noImplicitReturns' option is set
9830+
if (!returnType && !compilerOptions.noImplicitReturns) {
98259831
return;
98269832
}
98279833

@@ -9831,13 +9837,14 @@ namespace ts {
98319837
return;
98329838
}
98339839

9834-
if (func.flags & NodeFlags.HasExplicitReturn) {
9840+
if (!returnType || func.flags & NodeFlags.HasExplicitReturn) {
98359841
if (compilerOptions.noImplicitReturns) {
9836-
error(func.type, Diagnostics.Not_all_code_paths_return_a_value);
9842+
error(func.type || func, Diagnostics.Not_all_code_paths_return_a_value);
98379843
}
98389844
}
98399845
else {
98409846
// This function does not conform to the specification.
9847+
// NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present
98419848
error(func.type, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value);
98429849
}
98439850
}
@@ -9912,14 +9919,10 @@ namespace ts {
99129919
emitAwaiter = true;
99139920
}
99149921

9915-
const returnType = node.type && getTypeFromTypeNode(node.type);
9916-
let promisedType: Type;
9917-
if (returnType && isAsync) {
9918-
promisedType = checkAsyncFunctionReturnType(node);
9919-
}
9920-
9921-
if (returnType && !node.asteriskToken) {
9922-
checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, isAsync ? promisedType : returnType);
9922+
const returnOrPromisedType = node.type && (isAsync ? checkAsyncFunctionReturnType(node) : getTypeFromTypeNode(node.type));
9923+
if (!node.asteriskToken) {
9924+
// return is not necessary in the body of generators
9925+
checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType);
99239926
}
99249927

99259928
if (node.body) {
@@ -9942,13 +9945,13 @@ namespace ts {
99429945
// check assignability of the awaited type of the expression body against the promised type of
99439946
// its return type annotation.
99449947
const exprType = checkExpression(<Expression>node.body);
9945-
if (returnType) {
9948+
if (returnOrPromisedType) {
99469949
if (isAsync) {
99479950
const awaitedType = checkAwaitedType(exprType, node.body, Diagnostics.Expression_body_for_async_arrow_function_does_not_have_a_valid_callable_then_member);
9948-
checkTypeAssignableTo(awaitedType, promisedType, node.body);
9951+
checkTypeAssignableTo(awaitedType, returnOrPromisedType, node.body);
99499952
}
99509953
else {
9951-
checkTypeAssignableTo(exprType, returnType, node.body);
9954+
checkTypeAssignableTo(exprType, returnOrPromisedType, node.body);
99529955
}
99539956
}
99549957

@@ -12088,14 +12091,9 @@ namespace ts {
1208812091
}
1208912092

1209012093
checkSourceElement(node.body);
12091-
if (node.type && !isAccessor(node.kind) && !node.asteriskToken) {
12092-
const returnType = getTypeFromTypeNode(node.type);
12093-
let promisedType: Type;
12094-
if (isAsync) {
12095-
promisedType = checkAsyncFunctionReturnType(node);
12096-
}
12097-
12098-
checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, isAsync ? promisedType : returnType);
12094+
if (!isAccessor(node.kind) && !node.asteriskToken) {
12095+
const returnOrPromisedType = node.type && (isAsync ? checkAsyncFunctionReturnType(node) : getTypeFromTypeNode(node.type));
12096+
checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType);
1209912097
}
1210012098

1210112099
if (produceDiagnostics && !node.type) {
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
tests/cases/compiler/reachabilityChecks6.ts(6,10): error TS7030: Not all code paths return a value.
2+
tests/cases/compiler/reachabilityChecks6.ts(19,10): error TS7030: Not all code paths return a value.
3+
tests/cases/compiler/reachabilityChecks6.ts(31,10): error TS7030: Not all code paths return a value.
4+
tests/cases/compiler/reachabilityChecks6.ts(41,10): error TS7030: Not all code paths return a value.
5+
tests/cases/compiler/reachabilityChecks6.ts(52,10): error TS7030: Not all code paths return a value.
6+
tests/cases/compiler/reachabilityChecks6.ts(80,10): error TS7030: Not all code paths return a value.
7+
tests/cases/compiler/reachabilityChecks6.ts(86,13): error TS7027: Unreachable code detected.
8+
tests/cases/compiler/reachabilityChecks6.ts(94,10): error TS7030: Not all code paths return a value.
9+
tests/cases/compiler/reachabilityChecks6.ts(116,10): error TS7030: Not all code paths return a value.
10+
tests/cases/compiler/reachabilityChecks6.ts(123,13): error TS7027: Unreachable code detected.
11+
12+
13+
==== tests/cases/compiler/reachabilityChecks6.ts (10 errors) ====
14+
15+
function f0(x) {
16+
while (true);
17+
}
18+
19+
function f1(x) {
20+
~~
21+
!!! error TS7030: Not all code paths return a value.
22+
if (x) {
23+
return 1
24+
}
25+
}
26+
27+
function f2(x) {
28+
while (x) {
29+
throw new Error();
30+
}
31+
return 1;
32+
}
33+
34+
function f3(x) {
35+
~~
36+
!!! error TS7030: Not all code paths return a value.
37+
while (x) {
38+
throw new Error();
39+
}
40+
}
41+
42+
function f3_1 (x) {
43+
while (x) {
44+
}
45+
throw new Error();
46+
}
47+
48+
function f4(x) {
49+
~~
50+
!!! error TS7030: Not all code paths return a value.
51+
try {
52+
if (x) {
53+
return 1;
54+
}
55+
}
56+
catch (e) {
57+
}
58+
}
59+
60+
function f5(x) {
61+
~~
62+
!!! error TS7030: Not all code paths return a value.
63+
try {
64+
if (x) {
65+
return 1;
66+
}
67+
}
68+
catch (e) {
69+
return 2;
70+
}
71+
}
72+
73+
function f6(x) {
74+
~~
75+
!!! error TS7030: Not all code paths return a value.
76+
try {
77+
if (x) {
78+
return 1;
79+
}
80+
else
81+
{
82+
throw new Error();
83+
}
84+
}
85+
catch (e) {
86+
}
87+
}
88+
89+
function f7(x) {
90+
try {
91+
if (x) {
92+
return 1;
93+
}
94+
else {
95+
throw new Error();
96+
}
97+
}
98+
catch (e) {
99+
return 1;
100+
}
101+
}
102+
103+
function f8(x) {
104+
~~
105+
!!! error TS7030: Not all code paths return a value.
106+
try {
107+
if (true) {
108+
x++;
109+
}
110+
else {
111+
return 1;
112+
~~~~~~
113+
!!! error TS7027: Unreachable code detected.
114+
}
115+
}
116+
catch (e) {
117+
return 1;
118+
}
119+
}
120+
121+
function f9(x) {
122+
~~
123+
!!! error TS7030: Not all code paths return a value.
124+
try {
125+
while (false) {
126+
return 1;
127+
}
128+
}
129+
catch (e) {
130+
return 1;
131+
}
132+
}
133+
134+
function f10(x) {
135+
try {
136+
do {
137+
x++;
138+
} while (true);
139+
}
140+
catch (e) {
141+
return 1;
142+
}
143+
}
144+
145+
function f11(x) {
146+
~~~
147+
!!! error TS7030: Not all code paths return a value.
148+
test:
149+
try {
150+
do {
151+
do {
152+
break test;
153+
} while (true);
154+
x++;
155+
~
156+
!!! error TS7027: Unreachable code detected.
157+
} while (true);
158+
}
159+
catch (e) {
160+
return 1;
161+
}
162+
}

0 commit comments

Comments
 (0)