Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1196,17 +1196,23 @@ namespace ts {
// local types not visible outside the function body
: false;
}
if (meaning & SymbolFlags.Value && result.flags & SymbolFlags.FunctionScopedVariable) {
// parameters are visible only inside function body, parameter list and return type
// technically for parameter list case here we might mix parameters and variables declared in function,
// however it is detected separately when checking initializers of parameters
// to make sure that they reference no variables declared after them.
useResult =
if (meaning & SymbolFlags.Value && result.flags & SymbolFlags.Variable) {
// parameter initializer will lookup as normal variable scope when targeting es2015+
if (compilerOptions.target && compilerOptions.target >= ScriptTarget.ES2015 && isParameter(lastLocation) && result.valueDeclaration !== lastLocation) {
useResult = false;
}
else if (result.flags & SymbolFlags.FunctionScopedVariable) {
// parameters are visible only inside function body, parameter list and return type
// technically for parameter list case here we might mix parameters and variables declared in function,
// however it is detected separately when checking initializers of parameters
// to make sure that they reference no variables declared after them.
useResult =
lastLocation.kind === SyntaxKind.Parameter ||
(
lastLocation === (<FunctionLikeDeclaration>location).type &&
!!findAncestor(result.valueDeclaration, isParameter)
);
}
}
}
else if (location.kind === SyntaxKind.ConditionalType) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(3,20): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it.
tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(8,27): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it.
tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(13,20): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it.
tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(21,18): error TS2372: Parameter 'a' cannot be referenced in its initializer.
tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(25,22): error TS2372: Parameter 'async' cannot be referenced in its initializer.
tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(29,15): error TS2448: Block-scoped variable 'foo' used before its declaration.


==== tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts (6 errors) ====
let foo: string = "";

function f1 (bar = foo) { // unexpected compiler error; works at runtime
~~~
!!! error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it.
var foo: number = 2;
return bar; // returns 1
}

function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime
~~~
!!! error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it.
var foo: number = 2;
return bar(); // returns 1
}

function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime
~~~
!!! error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it.
return bar;
}

function f4 (foo, bar = foo) {
return bar
}

function f5 (a = a) {
~
!!! error TS2372: Parameter 'a' cannot be referenced in its initializer.
return a
}

function f6 (async = async) {
~~~~~
!!! error TS2372: Parameter 'async' cannot be referenced in its initializer.
return async
}

function f7({[foo]: bar}: any[]) {
~~~
!!! error TS2448: Block-scoped variable 'foo' used before its declaration.
!!! related TS2728 tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts:30:9: 'foo' is declared here.
let foo: number = 2;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//// [parameterInitializersForwardReferencing1.ts]
let foo: string = "";

function f1 (bar = foo) { // unexpected compiler error; works at runtime
var foo: number = 2;
return bar; // returns 1
}

function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime
var foo: number = 2;
return bar(); // returns 1
}

function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime
return bar;
}

function f4 (foo, bar = foo) {
return bar
}

function f5 (a = a) {
return a
}

function f6 (async = async) {
return async
}

function f7({[foo]: bar}: any[]) {
let foo: number = 2;
}


//// [parameterInitializersForwardReferencing1.js]
var foo = "";
function f1(bar) {
if (bar === void 0) { bar = foo; }
var foo = 2;
return bar; // returns 1
}
function f2(bar) {
if (bar === void 0) { bar = function (baz) {
if (baz === void 0) { baz = foo; }
return baz;
}; }
var foo = 2;
return bar(); // returns 1
}
function f3(bar, foo) {
if (bar === void 0) { bar = foo; }
if (foo === void 0) { foo = 2; }
return bar;
}
function f4(foo, bar) {
if (bar === void 0) { bar = foo; }
return bar;
}
function f5(a) {
if (a === void 0) { a = a; }
return a;
}
function f6(async) {
if (async === void 0) { async = async; }
return async;
}
function f7(_a) {
var _b = foo, bar = _a[_b];
var foo = 2;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
=== tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts ===
let foo: string = "";
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 0, 3))

function f1 (bar = foo) { // unexpected compiler error; works at runtime
>f1 : Symbol(f1, Decl(parameterInitializersForwardReferencing1.ts, 0, 21))
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 2, 13))
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 3, 7))

var foo: number = 2;
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 3, 7))

return bar; // returns 1
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 2, 13))
}

function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime
>f2 : Symbol(f2, Decl(parameterInitializersForwardReferencing1.ts, 5, 1))
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 7, 13))
>baz : Symbol(baz, Decl(parameterInitializersForwardReferencing1.ts, 7, 20))
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 8, 7))
>baz : Symbol(baz, Decl(parameterInitializersForwardReferencing1.ts, 7, 20))

var foo: number = 2;
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 8, 7))

return bar(); // returns 1
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 7, 13))
}

function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime
>f3 : Symbol(f3, Decl(parameterInitializersForwardReferencing1.ts, 10, 1))
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 12, 13))
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 12, 23))
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 12, 23))

return bar;
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 12, 13))
}

function f4 (foo, bar = foo) {
>f4 : Symbol(f4, Decl(parameterInitializersForwardReferencing1.ts, 14, 1))
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 16, 13))
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 16, 17))
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 16, 13))

return bar
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 16, 17))
}

function f5 (a = a) {
>f5 : Symbol(f5, Decl(parameterInitializersForwardReferencing1.ts, 18, 1))
>a : Symbol(a, Decl(parameterInitializersForwardReferencing1.ts, 20, 13))
>a : Symbol(a, Decl(parameterInitializersForwardReferencing1.ts, 20, 13))

return a
>a : Symbol(a, Decl(parameterInitializersForwardReferencing1.ts, 20, 13))
}

function f6 (async = async) {
>f6 : Symbol(f6, Decl(parameterInitializersForwardReferencing1.ts, 22, 1))
>async : Symbol(async, Decl(parameterInitializersForwardReferencing1.ts, 24, 13))
>async : Symbol(async, Decl(parameterInitializersForwardReferencing1.ts, 24, 13))

return async
>async : Symbol(async, Decl(parameterInitializersForwardReferencing1.ts, 24, 13))
}

function f7({[foo]: bar}: any[]) {
>f7 : Symbol(f7, Decl(parameterInitializersForwardReferencing1.ts, 26, 1))
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 29, 7))
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1.ts, 28, 13))

let foo: number = 2;
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1.ts, 29, 7))
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
=== tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts ===
let foo: string = "";
>foo : string
>"" : ""

function f1 (bar = foo) { // unexpected compiler error; works at runtime
>f1 : (bar?: number) => number
>bar : number
>foo : number

var foo: number = 2;
>foo : number
>2 : 2

return bar; // returns 1
>bar : number
}

function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime
>f2 : (bar?: (baz?: number) => number) => number
>bar : (baz?: number) => number
>(baz = foo) => baz : (baz?: number) => number
>baz : number
>foo : number
>baz : number

var foo: number = 2;
>foo : number
>2 : 2

return bar(); // returns 1
>bar() : number
>bar : (baz?: number) => number
}

function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime
>f3 : (bar?: number, foo?: number) => number
>bar : number
>foo : number
>foo : number
>2 : 2

return bar;
>bar : number
}

function f4 (foo, bar = foo) {
>f4 : (foo: any, bar?: any) => any
>foo : any
>bar : any
>foo : any

return bar
>bar : any
}

function f5 (a = a) {
>f5 : (a?: any) => any
>a : any
>a : any

return a
>a : any
}

function f6 (async = async) {
>f6 : (async?: any) => any
>async : any
>async : any

return async
>async : any
}

function f7({[foo]: bar}: any[]) {
>f7 : ({ [foo]: bar }: any[]) => void
>foo : number
>bar : any

let foo: number = 2;
>foo : number
>2 : 2
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts(21,18): error TS2372: Parameter 'a' cannot be referenced in its initializer.
tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts(25,22): error TS2372: Parameter 'async' cannot be referenced in its initializer.


==== tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts (2 errors) ====
let foo: string = "";

function f1 (bar = foo) { // unexpected compiler error; works at runtime
var foo: number = 2;
return bar; // returns 1
}

function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime
var foo: number = 2;
return bar(); // returns 1
}

function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime
return bar;
}

function f4 (foo, bar = foo) {
return bar
}

function f5 (a = a) {
~
!!! error TS2372: Parameter 'a' cannot be referenced in its initializer.
return a
}

function f6 (async = async) {
~~~~~
!!! error TS2372: Parameter 'async' cannot be referenced in its initializer.
return async
}

function f7({[foo]: bar}: any[]) {
let foo: number = 2;
}

Loading