Skip to content

Commit c2351f5

Browse files
committed
add special check for parameter initializer lookup if targeting es2015+
1 parent 1a05f13 commit c2351f5

11 files changed

+540
-5
lines changed

src/compiler/checker.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,16 +1191,22 @@ namespace ts {
11911191
: false;
11921192
}
11931193
if (meaning & SymbolFlags.Value && result.flags & SymbolFlags.FunctionScopedVariable) {
1194-
// parameters are visible only inside function body, parameter list and return type
1195-
// technically for parameter list case here we might mix parameters and variables declared in function,
1196-
// however it is detected separately when checking initializers of parameters
1197-
// to make sure that they reference no variables declared after them.
1198-
useResult =
1194+
// parameter initializer will lookup as normal variable scope when targeting es2015+
1195+
if (compilerOptions.target && compilerOptions.target >= ScriptTarget.ES2015 && isParameter(lastLocation) && lastLocation.initializer === originalLocation && result.valueDeclaration !== lastLocation) {
1196+
useResult = false;
1197+
}
1198+
else {
1199+
// parameters are visible only inside function body, parameter list and return type
1200+
// technically for parameter list case here we might mix parameters and variables declared in function,
1201+
// however it is detected separately when checking initializers of parameters
1202+
// to make sure that they reference no variables declared after them.
1203+
useResult =
11991204
lastLocation.kind === SyntaxKind.Parameter ||
12001205
(
12011206
lastLocation === (<FunctionLikeDeclaration>location).type &&
12021207
!!findAncestor(result.valueDeclaration, isParameter)
12031208
);
1209+
}
12041210
}
12051211
}
12061212
else if (location.kind === SyntaxKind.ConditionalType) {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(3,20): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it.
2+
tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(8,27): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it.
3+
tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(13,20): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it.
4+
tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(21,18): error TS2372: Parameter 'a' cannot be referenced in its initializer.
5+
tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(25,22): error TS2372: Parameter 'async' cannot be referenced in its initializer.
6+
7+
8+
==== tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts (5 errors) ====
9+
let foo: string = "";
10+
11+
function f1 (bar = foo) { // unexpected compiler error; works at runtime
12+
~~~
13+
!!! error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it.
14+
var foo: number = 2;
15+
return bar; // returns 1
16+
}
17+
18+
function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime
19+
~~~
20+
!!! error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it.
21+
var foo: number = 2;
22+
return bar(); // returns 1
23+
}
24+
25+
function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime
26+
~~~
27+
!!! error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it.
28+
return bar;
29+
}
30+
31+
function f4 (foo, bar = foo) {
32+
return bar
33+
}
34+
35+
function f5 (a = a) {
36+
~
37+
!!! error TS2372: Parameter 'a' cannot be referenced in its initializer.
38+
return a
39+
}
40+
41+
function f6 (async = async) {
42+
~~~~~
43+
!!! error TS2372: Parameter 'async' cannot be referenced in its initializer.
44+
return async
45+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//// [parameterInitializersForwardReferencing1.ts]
2+
let foo: string = "";
3+
4+
function f1 (bar = foo) { // unexpected compiler error; works at runtime
5+
var foo: number = 2;
6+
return bar; // returns 1
7+
}
8+
9+
function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime
10+
var foo: number = 2;
11+
return bar(); // returns 1
12+
}
13+
14+
function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime
15+
return bar;
16+
}
17+
18+
function f4 (foo, bar = foo) {
19+
return bar
20+
}
21+
22+
function f5 (a = a) {
23+
return a
24+
}
25+
26+
function f6 (async = async) {
27+
return async
28+
}
29+
30+
//// [parameterInitializersForwardReferencing1.js]
31+
var foo = "";
32+
function f1(bar) {
33+
if (bar === void 0) { bar = foo; }
34+
var foo = 2;
35+
return bar; // returns 1
36+
}
37+
function f2(bar) {
38+
if (bar === void 0) { bar = function (baz) {
39+
if (baz === void 0) { baz = foo; }
40+
return baz;
41+
}; }
42+
var foo = 2;
43+
return bar(); // returns 1
44+
}
45+
function f3(bar, foo) {
46+
if (bar === void 0) { bar = foo; }
47+
if (foo === void 0) { foo = 2; }
48+
return bar;
49+
}
50+
function f4(foo, bar) {
51+
if (bar === void 0) { bar = foo; }
52+
return bar;
53+
}
54+
function f5(a) {
55+
if (a === void 0) { a = a; }
56+
return a;
57+
}
58+
function f6(async) {
59+
if (async === void 0) { async = async; }
60+
return async;
61+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
=== tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts ===
2+
let foo: string = "";
3+
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 0, 3))
4+
5+
function f1 (bar = foo) { // unexpected compiler error; works at runtime
6+
>f1 : Symbol(f1, Decl(parameterInitializersForwardReferencing1.ts, 0, 21))
7+
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 2, 13))
8+
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 3, 7))
9+
10+
var foo: number = 2;
11+
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 3, 7))
12+
13+
return bar; // returns 1
14+
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 2, 13))
15+
}
16+
17+
function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime
18+
>f2 : Symbol(f2, Decl(parameterInitializersForwardReferencing1.ts, 5, 1))
19+
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 7, 13))
20+
>baz : Symbol(baz, Decl(parameterInitializersForwardReferencing1.ts, 7, 20))
21+
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 8, 7))
22+
>baz : Symbol(baz, Decl(parameterInitializersForwardReferencing1.ts, 7, 20))
23+
24+
var foo: number = 2;
25+
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 8, 7))
26+
27+
return bar(); // returns 1
28+
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 7, 13))
29+
}
30+
31+
function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime
32+
>f3 : Symbol(f3, Decl(parameterInitializersForwardReferencing1.ts, 10, 1))
33+
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 12, 13))
34+
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 12, 23))
35+
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 12, 23))
36+
37+
return bar;
38+
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 12, 13))
39+
}
40+
41+
function f4 (foo, bar = foo) {
42+
>f4 : Symbol(f4, Decl(parameterInitializersForwardReferencing1.ts, 14, 1))
43+
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 16, 13))
44+
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 16, 17))
45+
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 16, 13))
46+
47+
return bar
48+
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 16, 17))
49+
}
50+
51+
function f5 (a = a) {
52+
>f5 : Symbol(f5, Decl(parameterInitializersForwardReferencing1.ts, 18, 1))
53+
>a : Symbol(a, Decl(parameterInitializersForwardReferencing1.ts, 20, 13))
54+
>a : Symbol(a, Decl(parameterInitializersForwardReferencing1.ts, 20, 13))
55+
56+
return a
57+
>a : Symbol(a, Decl(parameterInitializersForwardReferencing1.ts, 20, 13))
58+
}
59+
60+
function f6 (async = async) {
61+
>f6 : Symbol(f6, Decl(parameterInitializersForwardReferencing1.ts, 22, 1))
62+
>async : Symbol(async, Decl(parameterInitializersForwardReferencing1.ts, 24, 13))
63+
>async : Symbol(async, Decl(parameterInitializersForwardReferencing1.ts, 24, 13))
64+
65+
return async
66+
>async : Symbol(async, Decl(parameterInitializersForwardReferencing1.ts, 24, 13))
67+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
=== tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts ===
2+
let foo: string = "";
3+
>foo : string
4+
>"" : ""
5+
6+
function f1 (bar = foo) { // unexpected compiler error; works at runtime
7+
>f1 : (bar?: number) => number
8+
>bar : number
9+
>foo : number
10+
11+
var foo: number = 2;
12+
>foo : number
13+
>2 : 2
14+
15+
return bar; // returns 1
16+
>bar : number
17+
}
18+
19+
function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime
20+
>f2 : (bar?: (baz?: number) => number) => number
21+
>bar : (baz?: number) => number
22+
>(baz = foo) => baz : (baz?: number) => number
23+
>baz : number
24+
>foo : number
25+
>baz : number
26+
27+
var foo: number = 2;
28+
>foo : number
29+
>2 : 2
30+
31+
return bar(); // returns 1
32+
>bar() : number
33+
>bar : (baz?: number) => number
34+
}
35+
36+
function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime
37+
>f3 : (bar?: number, foo?: number) => number
38+
>bar : number
39+
>foo : number
40+
>foo : number
41+
>2 : 2
42+
43+
return bar;
44+
>bar : number
45+
}
46+
47+
function f4 (foo, bar = foo) {
48+
>f4 : (foo: any, bar?: any) => any
49+
>foo : any
50+
>bar : any
51+
>foo : any
52+
53+
return bar
54+
>bar : any
55+
}
56+
57+
function f5 (a = a) {
58+
>f5 : (a?: any) => any
59+
>a : any
60+
>a : any
61+
62+
return a
63+
>a : any
64+
}
65+
66+
function f6 (async = async) {
67+
>f6 : (async?: any) => any
68+
>async : any
69+
>async : any
70+
71+
return async
72+
>async : any
73+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts(21,18): error TS2372: Parameter 'a' cannot be referenced in its initializer.
2+
tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts(25,22): error TS2372: Parameter 'async' cannot be referenced in its initializer.
3+
4+
5+
==== tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts (2 errors) ====
6+
let foo: string = "";
7+
8+
function f1 (bar = foo) { // unexpected compiler error; works at runtime
9+
var foo: number = 2;
10+
return bar; // returns 1
11+
}
12+
13+
function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime
14+
var fooo: number = 2;
15+
return bar(); // returns 1
16+
}
17+
18+
function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime
19+
return bar;
20+
}
21+
22+
function f4 (foo, bar = foo) {
23+
return bar
24+
}
25+
26+
function f5 (a = a) {
27+
~
28+
!!! error TS2372: Parameter 'a' cannot be referenced in its initializer.
29+
return a
30+
}
31+
32+
function f6 (async = async) {
33+
~~~~~
34+
!!! error TS2372: Parameter 'async' cannot be referenced in its initializer.
35+
return async
36+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//// [parameterInitializersForwardReferencing1_es6.ts]
2+
let foo: string = "";
3+
4+
function f1 (bar = foo) { // unexpected compiler error; works at runtime
5+
var foo: number = 2;
6+
return bar; // returns 1
7+
}
8+
9+
function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime
10+
var fooo: number = 2;
11+
return bar(); // returns 1
12+
}
13+
14+
function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime
15+
return bar;
16+
}
17+
18+
function f4 (foo, bar = foo) {
19+
return bar
20+
}
21+
22+
function f5 (a = a) {
23+
return a
24+
}
25+
26+
function f6 (async = async) {
27+
return async
28+
}
29+
30+
//// [parameterInitializersForwardReferencing1_es6.js]
31+
let foo = "";
32+
function f1(bar = foo) {
33+
var foo = 2;
34+
return bar; // returns 1
35+
}
36+
function f2(bar = (baz = foo) => baz) {
37+
var fooo = 2;
38+
return bar(); // returns 1
39+
}
40+
function f3(bar = foo, foo = 2) {
41+
return bar;
42+
}
43+
function f4(foo, bar = foo) {
44+
return bar;
45+
}
46+
function f5(a = a) {
47+
return a;
48+
}
49+
function f6(async = async) {
50+
return async;
51+
}

0 commit comments

Comments
 (0)