diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 25f8483a40a..da1af15dfa4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1211,23 +1211,17 @@ namespace ts { // local types not visible outside the function body : false; } - if (meaning & SymbolFlags.Value && result.flags & SymbolFlags.Variable) { - // expression inside parameter will lookup as normal variable scope when targeting es2015+ - if (compilerOptions.target && compilerOptions.target >= ScriptTarget.ES2015 && isParameter(lastLocation) && !isParameterPropertyDeclaration(lastLocation) && result.valueDeclaration.pos > lastLocation.end) { - 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 = + 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 = lastLocation.kind === SyntaxKind.Parameter || ( lastLocation === (location).type && !!findAncestor(result.valueDeclaration, isParameter) ); - } } } else if (location.kind === SyntaxKind.ConditionalType) { diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt index 90390fbe3a4..ce4368081f1 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.errors.txt @@ -1,21 +1,31 @@ +tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts(3,20): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts(8,27): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it. +tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts(13,20): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it. 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(29,15): error TS2448: Block-scoped variable 'foo' used before its declaration. -==== tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts (2 errors) ==== +==== tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.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; } @@ -36,6 +46,9 @@ tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.t } function f7({[foo]: bar}: any[]) { + ~~~ +!!! error TS2448: Block-scoped variable 'foo' used before its declaration. +!!! related TS2728 tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts:30:9: 'foo' is declared here. let foo: number = 2; } diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.symbols b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.symbols index c0d42ab8b11..b44c91e8afd 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.symbols +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.symbols @@ -5,7 +5,7 @@ let foo: string = ""; function f1 (bar = foo) { // unexpected compiler error; works at runtime >f1 : Symbol(f1, Decl(parameterInitializersForwardReferencing1_es6.ts, 0, 21)) >bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 2, 13)) ->foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 0, 3)) +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 3, 7)) var foo: number = 2; >foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 3, 7)) @@ -18,7 +18,7 @@ function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at >f2 : Symbol(f2, Decl(parameterInitializersForwardReferencing1_es6.ts, 5, 1)) >bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 7, 13)) >baz : Symbol(baz, Decl(parameterInitializersForwardReferencing1_es6.ts, 7, 20)) ->foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 0, 3)) +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 8, 7)) >baz : Symbol(baz, Decl(parameterInitializersForwardReferencing1_es6.ts, 7, 20)) var foo: number = 2; @@ -31,7 +31,7 @@ function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime >f3 : Symbol(f3, Decl(parameterInitializersForwardReferencing1_es6.ts, 10, 1)) >bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 12, 13)) ->foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 0, 3)) +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 12, 23)) >foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 12, 23)) return bar; @@ -68,7 +68,7 @@ function f6 (async = async) { function f7({[foo]: bar}: any[]) { >f7 : Symbol(f7, Decl(parameterInitializersForwardReferencing1_es6.ts, 26, 1)) ->foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 0, 3)) +>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 29, 7)) >bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 28, 13)) let foo: number = 2; diff --git a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.types b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.types index 009ec47ddb8..a58d19c5755 100644 --- a/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.types +++ b/tests/baselines/reference/parameterInitializersForwardReferencing1_es6.types @@ -4,44 +4,44 @@ let foo: string = ""; >"" : "" function f1 (bar = foo) { // unexpected compiler error; works at runtime ->f1 : (bar?: string) => string ->bar : string ->foo : string +>f1 : (bar?: number) => number +>bar : number +>foo : number var foo: number = 2; >foo : number >2 : 2 return bar; // returns 1 ->bar : string +>bar : number } function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime ->f2 : (bar?: (baz?: string) => string) => string ->bar : (baz?: string) => string ->(baz = foo) => baz : (baz?: string) => string ->baz : string ->foo : string ->baz : string +>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() : string ->bar : (baz?: string) => string +>bar() : number +>bar : (baz?: number) => number } function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime ->f3 : (bar?: string, foo?: number) => string ->bar : string ->foo : string +>f3 : (bar?: number, foo?: number) => number +>bar : number +>foo : number >foo : number >2 : 2 return bar; ->bar : string +>bar : number } function f4 (foo, bar = foo) { @@ -74,7 +74,7 @@ function f6 (async = async) { function f7({[foo]: bar}: any[]) { >f7 : ({ [foo]: bar }: any[]) => void ->foo : string +>foo : number >bar : any let foo: number = 2;