Merge pull request #26317 from Kingwl/parameter-initializer-lookup-fix

add special check for parameter initializer lookup if targeting es2015+
This commit is contained in:
Ryan Cavanaugh
2018-08-28 11:33:58 -07:00
committed by GitHub
11 changed files with 622 additions and 6 deletions

View File

@@ -1208,17 +1208,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) {

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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))
}

View File

@@ -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
}

View File

@@ -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;
}

View File

@@ -0,0 +1,59 @@
//// [parameterInitializersForwardReferencing1_es6.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_es6.js]
let foo = "";
function f1(bar = foo) {
var foo = 2;
return bar; // returns 1
}
function f2(bar = (baz = foo) => baz) {
var foo = 2;
return bar(); // returns 1
}
function f3(bar = foo, foo = 2) {
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 }) {
let foo = 2;
}

View File

@@ -0,0 +1,77 @@
=== tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts ===
let foo: string = "";
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 0, 3))
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))
var foo: number = 2;
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 3, 7))
return bar; // returns 1
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 2, 13))
}
function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime
>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))
>baz : Symbol(baz, Decl(parameterInitializersForwardReferencing1_es6.ts, 7, 20))
var foo: number = 2;
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 8, 7))
return bar(); // returns 1
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 7, 13))
}
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))
return bar;
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 12, 13))
}
function f4 (foo, bar = foo) {
>f4 : Symbol(f4, Decl(parameterInitializersForwardReferencing1_es6.ts, 14, 1))
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 16, 13))
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 16, 17))
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 0, 3))
return bar
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 16, 17))
}
function f5 (a = a) {
>f5 : Symbol(f5, Decl(parameterInitializersForwardReferencing1_es6.ts, 18, 1))
>a : Symbol(a, Decl(parameterInitializersForwardReferencing1_es6.ts, 20, 13))
>a : Symbol(a, Decl(parameterInitializersForwardReferencing1_es6.ts, 20, 13))
return a
>a : Symbol(a, Decl(parameterInitializersForwardReferencing1_es6.ts, 20, 13))
}
function f6 (async = async) {
>f6 : Symbol(f6, Decl(parameterInitializersForwardReferencing1_es6.ts, 22, 1))
>async : Symbol(async, Decl(parameterInitializersForwardReferencing1_es6.ts, 24, 13))
>async : Symbol(async, Decl(parameterInitializersForwardReferencing1_es6.ts, 24, 13))
return async
>async : Symbol(async, Decl(parameterInitializersForwardReferencing1_es6.ts, 24, 13))
}
function f7({[foo]: bar}: any[]) {
>f7 : Symbol(f7, Decl(parameterInitializersForwardReferencing1_es6.ts, 26, 1))
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 0, 3))
>bar : Symbol(bar, Decl(parameterInitializersForwardReferencing1_es6.ts, 28, 13))
let foo: number = 2;
>foo : Symbol(foo, Decl(parameterInitializersForwardReferencing1_es6.ts, 29, 7))
}

View File

@@ -0,0 +1,84 @@
=== tests/cases/conformance/functions/parameterInitializersForwardReferencing1_es6.ts ===
let foo: string = "";
>foo : string
>"" : ""
function f1 (bar = foo) { // unexpected compiler error; works at runtime
>f1 : (bar?: string) => string
>bar : string
>foo : string
var foo: number = 2;
>foo : number
>2 : 2
return bar; // returns 1
>bar : string
}
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
var foo: number = 2;
>foo : number
>2 : 2
return bar(); // returns 1
>bar() : string
>bar : (baz?: string) => string
}
function f3 (bar = foo, foo = 2) { // correct compiler error, error at runtime
>f3 : (bar?: string, foo?: number) => string
>bar : string
>foo : string
>foo : number
>2 : 2
return bar;
>bar : string
}
function f4 (foo, bar = foo) {
>f4 : (foo: any, bar?: string) => string
>foo : any
>bar : string
>foo : string
return bar
>bar : string
}
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 : string
>bar : any
let foo: number = 2;
>foo : number
>2 : 2
}

View File

@@ -0,0 +1,31 @@
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;
}

View File

@@ -0,0 +1,33 @@
// @target: es2015
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;
}