Skip to content

Commit 3b6c859

Browse files
committed
Only report error in strict mode as per review feedback
Per @jakebailey's feedback, TypeScript does not assume strict mode at all times. The error should only be reported when inStrictMode is true, consistent with other strict mode checks like 'with' statements. Updated the error message to mention strict mode and updated baselines accordingly.
1 parent e1078dd commit 3b6c859

10 files changed

Lines changed: 71 additions & 90 deletions

src/compiler/binder.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2707,10 +2707,12 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
27072707
}
27082708
}
27092709

2710-
// Function declarations are not allowed as the direct child of a statement.
2710+
// Function declarations are not allowed as the direct child of a statement in strict mode.
27112711
// For example: `if (true) function f() {}` is a syntax error in strict mode.
2712-
// Since TypeScript assumes strict mode at all times, this is always an error.
2713-
function checkFunctionDeclarationStatementChild(node: FunctionDeclaration) {
2712+
function checkStrictModeFunctionDeclarationAsStatementChild(node: FunctionDeclaration) {
2713+
if (!inStrictMode) {
2714+
return;
2715+
}
27142716
const parent = node.parent;
27152717
switch (parent.kind) {
27162718
case SyntaxKind.IfStatement:
@@ -2722,7 +2724,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
27222724
case SyntaxKind.WithStatement:
27232725
case SyntaxKind.LabeledStatement:
27242726
const errorSpan = getErrorSpanForNode(file, node);
2725-
file.bindDiagnostics.push(createFileDiagnostic(file, errorSpan.start, errorSpan.length, Diagnostics.Function_declarations_are_not_allowed_inside_statements_Use_a_block_statement_to_wrap_the_function_declaration));
2727+
file.bindDiagnostics.push(createFileDiagnostic(file, errorSpan.start, errorSpan.length, Diagnostics.In_strict_mode_code_functions_can_only_be_declared_at_top_level_or_inside_a_block));
27262728
break;
27272729
}
27282730
}
@@ -3733,9 +3735,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
37333735
}
37343736

37353737
checkStrictModeFunctionName(node);
3736-
// Function declarations as direct children of statements are always an error
3737-
// since TypeScript assumes strict mode at all times.
3738-
checkFunctionDeclarationStatementChild(node);
3738+
checkStrictModeFunctionDeclarationAsStatementChild(node);
37393739
if (inStrictMode) {
37403740
checkStrictModeFunctionDeclaration(node);
37413741
bindBlockScopedDeclaration(node, SymbolFlags.Function, SymbolFlags.FunctionExcludes);

src/compiler/diagnosticMessages.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@
823823
"category": "Error",
824824
"code": 1255
825825
},
826-
"Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.": {
826+
"In strict mode code, functions can only be declared at top level or inside a block.": {
827827
"category": "Error",
828828
"code": 1256
829829
},

tests/baselines/reference/functionDeclarationAsStatementInStrictMode.errors.txt

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,38 @@
1-
functionDeclarationAsStatementInStrictMode.ts(3,20): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
2-
functionDeclarationAsStatementInStrictMode.ts(4,23): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
3-
functionDeclarationAsStatementInStrictMode.ts(5,13): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
4-
functionDeclarationAsStatementInStrictMode.ts(6,19): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
5-
functionDeclarationAsStatementInStrictMode.ts(7,28): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
6-
functionDeclarationAsStatementInStrictMode.ts(8,28): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
7-
functionDeclarationAsStatementInStrictMode.ts(9,17): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
1+
functionDeclarationAsStatementInStrictMode.ts(2,20): error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
2+
functionDeclarationAsStatementInStrictMode.ts(3,23): error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
3+
functionDeclarationAsStatementInStrictMode.ts(4,13): error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
4+
functionDeclarationAsStatementInStrictMode.ts(5,19): error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
5+
functionDeclarationAsStatementInStrictMode.ts(6,28): error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
6+
functionDeclarationAsStatementInStrictMode.ts(7,28): error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
7+
functionDeclarationAsStatementInStrictMode.ts(8,1): error TS1344: 'A label is not allowed here.
8+
functionDeclarationAsStatementInStrictMode.ts(8,17): error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
89

910

10-
==== functionDeclarationAsStatementInStrictMode.ts (7 errors) ====
11-
// Error cases - function declarations as direct children of statements
12-
// TypeScript assumes strict mode at all times, so these are always errors
11+
==== functionDeclarationAsStatementInStrictMode.ts (8 errors) ====
12+
// Error cases - function declarations as direct children of statements in strict mode
1313
if (true) function f1() {}
1414
~~
15-
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
15+
!!! error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
1616
while (true) function f2() {}
1717
~~
18-
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
18+
!!! error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
1919
do function f3() {} while (false);
2020
~~
21-
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
21+
!!! error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
2222
for (;;) function f4() {}
2323
~~
24-
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
24+
!!! error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
2525
for (let x in {}) function f5() {}
2626
~~
27-
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
27+
!!! error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
2828
for (let x of []) function f6() {}
2929
~~
30-
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
30+
!!! error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
3131
label: function f7() {}
32+
~~~~~
33+
!!! error TS1344: 'A label is not allowed here.
3234
~~
33-
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
35+
!!! error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
3436

3537
// Valid cases - function declarations inside blocks
3638
if (true) { function g1() {} }

tests/baselines/reference/functionDeclarationAsStatementInStrictMode.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
//// [tests/cases/compiler/functionDeclarationAsStatementInStrictMode.ts] ////
22

33
//// [functionDeclarationAsStatementInStrictMode.ts]
4-
// Error cases - function declarations as direct children of statements
5-
// TypeScript assumes strict mode at all times, so these are always errors
4+
// Error cases - function declarations as direct children of statements in strict mode
65
if (true) function f1() {}
76
while (true) function f2() {}
87
do function f3() {} while (false);
@@ -30,8 +29,8 @@ function outer() {
3029

3130

3231
//// [functionDeclarationAsStatementInStrictMode.js]
33-
// Error cases - function declarations as direct children of statements
34-
// TypeScript assumes strict mode at all times, so these are always errors
32+
"use strict";
33+
// Error cases - function declarations as direct children of statements in strict mode
3534
if (true)
3635
function f1() { }
3736
while (true)
Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,63 @@
11
//// [tests/cases/compiler/functionDeclarationAsStatementInStrictMode.ts] ////
22

33
=== functionDeclarationAsStatementInStrictMode.ts ===
4-
// Error cases - function declarations as direct children of statements
5-
// TypeScript assumes strict mode at all times, so these are always errors
4+
// Error cases - function declarations as direct children of statements in strict mode
65
if (true) function f1() {}
7-
>f1 : Symbol(f1, Decl(functionDeclarationAsStatementInStrictMode.ts, 2, 9))
6+
>f1 : Symbol(f1, Decl(functionDeclarationAsStatementInStrictMode.ts, 1, 9))
87

98
while (true) function f2() {}
10-
>f2 : Symbol(f2, Decl(functionDeclarationAsStatementInStrictMode.ts, 3, 12))
9+
>f2 : Symbol(f2, Decl(functionDeclarationAsStatementInStrictMode.ts, 2, 12))
1110

1211
do function f3() {} while (false);
13-
>f3 : Symbol(f3, Decl(functionDeclarationAsStatementInStrictMode.ts, 4, 2))
12+
>f3 : Symbol(f3, Decl(functionDeclarationAsStatementInStrictMode.ts, 3, 2))
1413

1514
for (;;) function f4() {}
16-
>f4 : Symbol(f4, Decl(functionDeclarationAsStatementInStrictMode.ts, 5, 8))
15+
>f4 : Symbol(f4, Decl(functionDeclarationAsStatementInStrictMode.ts, 4, 8))
1716

1817
for (let x in {}) function f5() {}
19-
>x : Symbol(x, Decl(functionDeclarationAsStatementInStrictMode.ts, 6, 8))
20-
>f5 : Symbol(f5, Decl(functionDeclarationAsStatementInStrictMode.ts, 6, 17))
18+
>x : Symbol(x, Decl(functionDeclarationAsStatementInStrictMode.ts, 5, 8))
19+
>f5 : Symbol(f5, Decl(functionDeclarationAsStatementInStrictMode.ts, 5, 17))
2120

2221
for (let x of []) function f6() {}
23-
>x : Symbol(x, Decl(functionDeclarationAsStatementInStrictMode.ts, 7, 8))
24-
>f6 : Symbol(f6, Decl(functionDeclarationAsStatementInStrictMode.ts, 7, 17))
22+
>x : Symbol(x, Decl(functionDeclarationAsStatementInStrictMode.ts, 6, 8))
23+
>f6 : Symbol(f6, Decl(functionDeclarationAsStatementInStrictMode.ts, 6, 17))
2524

2625
label: function f7() {}
27-
>f7 : Symbol(f7, Decl(functionDeclarationAsStatementInStrictMode.ts, 8, 6))
26+
>f7 : Symbol(f7, Decl(functionDeclarationAsStatementInStrictMode.ts, 7, 6))
2827

2928
// Valid cases - function declarations inside blocks
3029
if (true) { function g1() {} }
31-
>g1 : Symbol(g1, Decl(functionDeclarationAsStatementInStrictMode.ts, 11, 11))
30+
>g1 : Symbol(g1, Decl(functionDeclarationAsStatementInStrictMode.ts, 10, 11))
3231

3332
while (true) { function g2() {} }
34-
>g2 : Symbol(g2, Decl(functionDeclarationAsStatementInStrictMode.ts, 12, 14))
33+
>g2 : Symbol(g2, Decl(functionDeclarationAsStatementInStrictMode.ts, 11, 14))
3534

3635
do { function g3() {} } while (false);
37-
>g3 : Symbol(g3, Decl(functionDeclarationAsStatementInStrictMode.ts, 13, 4))
36+
>g3 : Symbol(g3, Decl(functionDeclarationAsStatementInStrictMode.ts, 12, 4))
3837

3938
for (;;) { function g4() {} }
40-
>g4 : Symbol(g4, Decl(functionDeclarationAsStatementInStrictMode.ts, 14, 10))
39+
>g4 : Symbol(g4, Decl(functionDeclarationAsStatementInStrictMode.ts, 13, 10))
4140

4241
for (let x in {}) { function g5() {} }
43-
>x : Symbol(x, Decl(functionDeclarationAsStatementInStrictMode.ts, 15, 8))
44-
>g5 : Symbol(g5, Decl(functionDeclarationAsStatementInStrictMode.ts, 15, 19))
42+
>x : Symbol(x, Decl(functionDeclarationAsStatementInStrictMode.ts, 14, 8))
43+
>g5 : Symbol(g5, Decl(functionDeclarationAsStatementInStrictMode.ts, 14, 19))
4544

4645
for (let x of []) { function g6() {} }
47-
>x : Symbol(x, Decl(functionDeclarationAsStatementInStrictMode.ts, 16, 8))
48-
>g6 : Symbol(g6, Decl(functionDeclarationAsStatementInStrictMode.ts, 16, 19))
46+
>x : Symbol(x, Decl(functionDeclarationAsStatementInStrictMode.ts, 15, 8))
47+
>g6 : Symbol(g6, Decl(functionDeclarationAsStatementInStrictMode.ts, 15, 19))
4948

5049
label: { function g7() {} }
51-
>g7 : Symbol(g7, Decl(functionDeclarationAsStatementInStrictMode.ts, 17, 8))
50+
>g7 : Symbol(g7, Decl(functionDeclarationAsStatementInStrictMode.ts, 16, 8))
5251

5352
// Valid - top level
5453
function topLevel() {}
55-
>topLevel : Symbol(topLevel, Decl(functionDeclarationAsStatementInStrictMode.ts, 17, 27))
54+
>topLevel : Symbol(topLevel, Decl(functionDeclarationAsStatementInStrictMode.ts, 16, 27))
5655

5756
// Valid - inside function body
5857
function outer() {
59-
>outer : Symbol(outer, Decl(functionDeclarationAsStatementInStrictMode.ts, 20, 22))
58+
>outer : Symbol(outer, Decl(functionDeclarationAsStatementInStrictMode.ts, 19, 22))
6059

6160
function inner() {}
62-
>inner : Symbol(inner, Decl(functionDeclarationAsStatementInStrictMode.ts, 23, 18))
61+
>inner : Symbol(inner, Decl(functionDeclarationAsStatementInStrictMode.ts, 22, 18))
6362
}
6463

tests/baselines/reference/functionDeclarationAsStatementInStrictMode.types

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
//// [tests/cases/compiler/functionDeclarationAsStatementInStrictMode.ts] ////
22

33
=== functionDeclarationAsStatementInStrictMode.ts ===
4-
// Error cases - function declarations as direct children of statements
5-
// TypeScript assumes strict mode at all times, so these are always errors
4+
// Error cases - function declarations as direct children of statements in strict mode
65
if (true) function f1() {}
76
>true : true
87
> : ^^^^
@@ -34,10 +33,10 @@ for (let x in {}) function f5() {}
3433
> : ^^^^^^^^^^
3534

3635
for (let x of []) function f6() {}
37-
>x : any
38-
> : ^^^
39-
>[] : undefined[]
40-
> : ^^^^^^^^^^^
36+
>x : never
37+
> : ^^^^^
38+
>[] : never[]
39+
> : ^^^^^^^
4140
>f6 : () => void
4241
> : ^^^^^^^^^^
4342

@@ -79,10 +78,10 @@ for (let x in {}) { function g5() {} }
7978
> : ^^^^^^^^^^
8079

8180
for (let x of []) { function g6() {} }
82-
>x : any
83-
> : ^^^
84-
>[] : undefined[]
85-
> : ^^^^^^^^^^^
81+
>x : never
82+
> : ^^^^^
83+
>[] : never[]
84+
> : ^^^^^^^
8685
>g6 : () => void
8786
> : ^^^^^^^^^^
8887

tests/baselines/reference/labeledStatementWithLabel.errors.txt

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,11 @@
1-
labeledStatementWithLabel.ts(1,17): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
2-
labeledStatementWithLabel.ts(2,18): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
3-
labeledStatementWithLabel.ts(3,23): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
41
labeledStatementWithLabel.ts(11,8): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module.
52
labeledStatementWithLabel.ts(12,8): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module.
63

74

8-
==== labeledStatementWithLabel.ts (5 errors) ====
5+
==== labeledStatementWithLabel.ts (2 errors) ====
96
label: function fn() { }
10-
~~
11-
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
127
label: function* gen() { }
13-
~~~
14-
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
158
label: async function gen1() { }
16-
~~~~
17-
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
189
label: enum E {}
1910
label: interface I {}
2011
label: class C { }

tests/baselines/reference/labeledStatementWithLabel_es2015.errors.txt

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,11 @@
1-
labeledStatementWithLabel_es2015.ts(1,17): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
2-
labeledStatementWithLabel_es2015.ts(2,18): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
3-
labeledStatementWithLabel_es2015.ts(3,23): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
41
labeledStatementWithLabel_es2015.ts(11,8): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module.
52
labeledStatementWithLabel_es2015.ts(12,8): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module.
63

74

8-
==== labeledStatementWithLabel_es2015.ts (5 errors) ====
5+
==== labeledStatementWithLabel_es2015.ts (2 errors) ====
96
label: function fn() { }
10-
~~
11-
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
127
label: function* gen() { }
13-
~~~
14-
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
158
label: async function gen1() { }
16-
~~~~
17-
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
189
label: enum E {}
1910
label: interface I {}
2011
label: class C { }

tests/baselines/reference/labeledStatementWithLabel_strict.errors.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
labeledStatementWithLabel_strict.ts(2,1): error TS1344: 'A label is not allowed here.
2-
labeledStatementWithLabel_strict.ts(2,17): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
2+
labeledStatementWithLabel_strict.ts(2,17): error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
33
labeledStatementWithLabel_strict.ts(3,1): error TS1344: 'A label is not allowed here.
4-
labeledStatementWithLabel_strict.ts(3,18): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
4+
labeledStatementWithLabel_strict.ts(3,18): error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
55
labeledStatementWithLabel_strict.ts(4,1): error TS1344: 'A label is not allowed here.
6-
labeledStatementWithLabel_strict.ts(4,23): error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
6+
labeledStatementWithLabel_strict.ts(4,23): error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
77
labeledStatementWithLabel_strict.ts(5,1): error TS1344: 'A label is not allowed here.
88
labeledStatementWithLabel_strict.ts(6,1): error TS1344: 'A label is not allowed here.
99
labeledStatementWithLabel_strict.ts(7,1): error TS1344: 'A label is not allowed here.
@@ -23,17 +23,17 @@ labeledStatementWithLabel_strict.ts(14,1): error TS1344: 'A label is not allowed
2323
~~~~~
2424
!!! error TS1344: 'A label is not allowed here.
2525
~~
26-
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
26+
!!! error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
2727
label: function* gen() { }
2828
~~~~~
2929
!!! error TS1344: 'A label is not allowed here.
3030
~~~
31-
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
31+
!!! error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
3232
label: async function gen1() { }
3333
~~~~~
3434
!!! error TS1344: 'A label is not allowed here.
3535
~~~~
36-
!!! error TS1256: Function declarations are not allowed inside statements. Use a block statement to wrap the function declaration.
36+
!!! error TS1256: In strict mode code, functions can only be declared at top level or inside a block.
3737
label: enum E {}
3838
~~~~~
3939
!!! error TS1344: 'A label is not allowed here.

tests/cases/compiler/functionDeclarationAsStatementInStrictMode.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
// @strict: true
12
// @target: ES2020
23

3-
// Error cases - function declarations as direct children of statements
4-
// TypeScript assumes strict mode at all times, so these are always errors
4+
// Error cases - function declarations as direct children of statements in strict mode
55
if (true) function f1() {}
66
while (true) function f2() {}
77
do function f3() {} while (false);

0 commit comments

Comments
 (0)