From 3a7a4d4b51ed66e1bfd8a903c348c5303458c2af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Thu, 3 Aug 2023 19:56:08 +0200 Subject: [PATCH] Error on shadowed var declarations without initializers (#55228) --- src/compiler/checker.ts | 10 +--- tests/baselines/reference/for-of53.errors.txt | 9 ++++ ...copedVariablesByBlockScopedOnes.errors.txt | 48 +++++++++++++++++ ...onScopedVariablesByBlockScopedOnes.symbols | 51 ++++++++++++++++++ ...tionScopedVariablesByBlockScopedOnes.types | 53 +++++++++++++++++++ ...unctionScopedVariablesByBlockScopedOnes.ts | 31 +++++++++++ 6 files changed, 194 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/for-of53.errors.txt create mode 100644 tests/baselines/reference/shadowedFunctionScopedVariablesByBlockScopedOnes.errors.txt create mode 100644 tests/baselines/reference/shadowedFunctionScopedVariablesByBlockScopedOnes.symbols create mode 100644 tests/baselines/reference/shadowedFunctionScopedVariablesByBlockScopedOnes.types create mode 100644 tests/cases/compiler/shadowedFunctionScopedVariablesByBlockScopedOnes.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e6be98f9f15..670bd15ee46 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -41020,12 +41020,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } - // skip variable declarations that don't have initializers // NOTE: in ES6 spec initializer is required in variable declarations where name is binding pattern // so we'll always treat binding elements as initialized - if (node.kind === SyntaxKind.VariableDeclaration && !node.initializer) { - return; - } const symbol = getSymbolOfDeclaration(node); if (symbol.flags & SymbolFlags.FunctionScopedVariable) { @@ -41050,10 +41046,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { container.kind === SyntaxKind.ModuleDeclaration || container.kind === SyntaxKind.SourceFile); - // here we know that function scoped variable is shadowed by block scoped one - // if they are defined in the same scope - binder has already reported redeclaration error - // otherwise if variable has an initializer - show error that initialization will fail - // since LHS will be block scoped name instead of function scoped + // here we know that function scoped variable is "shadowed" by block scoped one + // a var declatation can't hoist past a lexical declaration and it results in a SyntaxError at runtime if (!namesShareScope) { const name = symbolToString(localDeclarationSymbol); error(node, Diagnostics.Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, name, name); diff --git a/tests/baselines/reference/for-of53.errors.txt b/tests/baselines/reference/for-of53.errors.txt new file mode 100644 index 00000000000..9ec61ad1091 --- /dev/null +++ b/tests/baselines/reference/for-of53.errors.txt @@ -0,0 +1,9 @@ +for-of53.ts(2,9): error TS2481: Cannot initialize outer scoped variable 'v' in the same scope as block scoped declaration 'v'. + + +==== for-of53.ts (1 errors) ==== + for (let v of []) { + var v; + ~ +!!! error TS2481: Cannot initialize outer scoped variable 'v' in the same scope as block scoped declaration 'v'. + } \ No newline at end of file diff --git a/tests/baselines/reference/shadowedFunctionScopedVariablesByBlockScopedOnes.errors.txt b/tests/baselines/reference/shadowedFunctionScopedVariablesByBlockScopedOnes.errors.txt new file mode 100644 index 00000000000..ad19d4c9699 --- /dev/null +++ b/tests/baselines/reference/shadowedFunctionScopedVariablesByBlockScopedOnes.errors.txt @@ -0,0 +1,48 @@ +shadowedFunctionScopedVariablesByBlockScopedOnes.ts(4,27): error TS2481: Cannot initialize outer scoped variable 'v' in the same scope as block scoped declaration 'v'. +shadowedFunctionScopedVariablesByBlockScopedOnes.ts(7,29): error TS2481: Cannot initialize outer scoped variable 'v' in the same scope as block scoped declaration 'v'. +shadowedFunctionScopedVariablesByBlockScopedOnes.ts(10,29): error TS2481: Cannot initialize outer scoped variable 'v' in the same scope as block scoped declaration 'v'. +shadowedFunctionScopedVariablesByBlockScopedOnes.ts(16,17): error TS2481: Cannot initialize outer scoped variable 'x' in the same scope as block scoped declaration 'x'. +shadowedFunctionScopedVariablesByBlockScopedOnes.ts(23,17): error TS2481: Cannot initialize outer scoped variable 'x' in the same scope as block scoped declaration 'x'. + + +==== shadowedFunctionScopedVariablesByBlockScopedOnes.ts (5 errors) ==== + // https://github.com/microsoft/TypeScript/issues/2185 + + function test1() { + for (let v; ; ) { var v; } + ~ +!!! error TS2481: Cannot initialize outer scoped variable 'v' in the same scope as block scoped declaration 'v'. + } + function test2() { + for (let v in []) { var v; } + ~ +!!! error TS2481: Cannot initialize outer scoped variable 'v' in the same scope as block scoped declaration 'v'. + } + function test3() { + for (let v of []) { var v; } + ~ +!!! error TS2481: Cannot initialize outer scoped variable 'v' in the same scope as block scoped declaration 'v'. + } + function test4() { + { + let x; + { + var x; + ~ +!!! error TS2481: Cannot initialize outer scoped variable 'x' in the same scope as block scoped declaration 'x'. + } + } + } + function test5() { + { + { + var x; + ~ +!!! error TS2481: Cannot initialize outer scoped variable 'x' in the same scope as block scoped declaration 'x'. + } + let x; + } + } + + + \ No newline at end of file diff --git a/tests/baselines/reference/shadowedFunctionScopedVariablesByBlockScopedOnes.symbols b/tests/baselines/reference/shadowedFunctionScopedVariablesByBlockScopedOnes.symbols new file mode 100644 index 00000000000..39c74442364 --- /dev/null +++ b/tests/baselines/reference/shadowedFunctionScopedVariablesByBlockScopedOnes.symbols @@ -0,0 +1,51 @@ +//// [tests/cases/compiler/shadowedFunctionScopedVariablesByBlockScopedOnes.ts] //// + +=== shadowedFunctionScopedVariablesByBlockScopedOnes.ts === +// https://github.com/microsoft/TypeScript/issues/2185 + +function test1() { +>test1 : Symbol(test1, Decl(shadowedFunctionScopedVariablesByBlockScopedOnes.ts, 0, 0)) + + for (let v; ; ) { var v; } +>v : Symbol(v, Decl(shadowedFunctionScopedVariablesByBlockScopedOnes.ts, 3, 12)) +>v : Symbol(v, Decl(shadowedFunctionScopedVariablesByBlockScopedOnes.ts, 3, 25)) +} +function test2() { +>test2 : Symbol(test2, Decl(shadowedFunctionScopedVariablesByBlockScopedOnes.ts, 4, 1)) + + for (let v in []) { var v; } +>v : Symbol(v, Decl(shadowedFunctionScopedVariablesByBlockScopedOnes.ts, 6, 12)) +>v : Symbol(v, Decl(shadowedFunctionScopedVariablesByBlockScopedOnes.ts, 6, 27)) +} +function test3() { +>test3 : Symbol(test3, Decl(shadowedFunctionScopedVariablesByBlockScopedOnes.ts, 7, 1)) + + for (let v of []) { var v; } +>v : Symbol(v, Decl(shadowedFunctionScopedVariablesByBlockScopedOnes.ts, 9, 12)) +>v : Symbol(v, Decl(shadowedFunctionScopedVariablesByBlockScopedOnes.ts, 9, 27)) +} +function test4() { +>test4 : Symbol(test4, Decl(shadowedFunctionScopedVariablesByBlockScopedOnes.ts, 10, 1)) + { + let x; +>x : Symbol(x, Decl(shadowedFunctionScopedVariablesByBlockScopedOnes.ts, 13, 11)) + { + var x; +>x : Symbol(x, Decl(shadowedFunctionScopedVariablesByBlockScopedOnes.ts, 15, 15)) + } + } +} +function test5() { +>test5 : Symbol(test5, Decl(shadowedFunctionScopedVariablesByBlockScopedOnes.ts, 18, 1)) + { + { + var x; +>x : Symbol(x, Decl(shadowedFunctionScopedVariablesByBlockScopedOnes.ts, 22, 15)) + } + let x; +>x : Symbol(x, Decl(shadowedFunctionScopedVariablesByBlockScopedOnes.ts, 24, 11)) + } +} + + + diff --git a/tests/baselines/reference/shadowedFunctionScopedVariablesByBlockScopedOnes.types b/tests/baselines/reference/shadowedFunctionScopedVariablesByBlockScopedOnes.types new file mode 100644 index 00000000000..b8e4b77c504 --- /dev/null +++ b/tests/baselines/reference/shadowedFunctionScopedVariablesByBlockScopedOnes.types @@ -0,0 +1,53 @@ +//// [tests/cases/compiler/shadowedFunctionScopedVariablesByBlockScopedOnes.ts] //// + +=== shadowedFunctionScopedVariablesByBlockScopedOnes.ts === +// https://github.com/microsoft/TypeScript/issues/2185 + +function test1() { +>test1 : () => void + + for (let v; ; ) { var v; } +>v : any +>v : any +} +function test2() { +>test2 : () => void + + for (let v in []) { var v; } +>v : string +>[] : undefined[] +>v : any +} +function test3() { +>test3 : () => void + + for (let v of []) { var v; } +>v : any +>[] : undefined[] +>v : any +} +function test4() { +>test4 : () => void + { + let x; +>x : any + { + var x; +>x : any + } + } +} +function test5() { +>test5 : () => void + { + { + var x; +>x : any + } + let x; +>x : any + } +} + + + diff --git a/tests/cases/compiler/shadowedFunctionScopedVariablesByBlockScopedOnes.ts b/tests/cases/compiler/shadowedFunctionScopedVariablesByBlockScopedOnes.ts new file mode 100644 index 00000000000..8aec755a0cd --- /dev/null +++ b/tests/cases/compiler/shadowedFunctionScopedVariablesByBlockScopedOnes.ts @@ -0,0 +1,31 @@ +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/2185 + +function test1() { + for (let v; ; ) { var v; } +} +function test2() { + for (let v in []) { var v; } +} +function test3() { + for (let v of []) { var v; } +} +function test4() { + { + let x; + { + var x; + } + } +} +function test5() { + { + { + var x; + } + let x; + } +} + +