diff --git a/tsc/internal/checker/flow.go b/tsc/internal/checker/flow.go index 03b226c9315f0..d08254cc8ef88 100644 --- a/tsc/internal/checker/flow.go +++ b/tsc/internal/checker/flow.go @@ -2672,9 +2672,6 @@ func (c *Checker) isPastLastAssignment(symbol *ast.Symbol, location *ast.Node) b } func (c *Checker) ensureAssignmentsMarked(symbol *ast.Symbol) { - if c.markedAssignmentSymbolLinks.Get(symbol).lastAssignmentPos != 0 { - return - } parent := ast.FindAncestor(symbol.ValueDeclaration, ast.IsFunctionOrSourceFile) if parent == nil { return diff --git a/tsc/testdata/baselines/reference/compiler/definiteAssignmentOfClosedOverVariable.errors.txt b/tsc/testdata/baselines/reference/compiler/definiteAssignmentOfClosedOverVariable.errors.txt new file mode 100644 index 0000000000000..333bc85b16a0f --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/definiteAssignmentOfClosedOverVariable.errors.txt @@ -0,0 +1,42 @@ +definiteAssignmentOfClosedOverVariable.ts(32,9): error TS2454: Variable 'count3' is used before being assigned. + + +==== definiteAssignmentOfClosedOverVariable.ts (1 errors) ==== + // Repro for #63981 + + export {}; + + let count: number; + + function makeCallback(p: string) { + return () => { + count += 1; + return p; + }; + } + + count = 0; + makeCallback('x')(); + + let count2: number; + + function makeCallback2(p: string) { + const f = () => p; + return () => { + count2 += 1; + }; + } + + count2 = 0; + + let count3: number; + + function makeCallback3(p: string) { + return () => { + count3 += 1; + ~~~~~~ +!!! error TS2454: Variable 'count3' is used before being assigned. + return p; + }; + } + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/definiteAssignmentOfClosedOverVariable.symbols b/tsc/testdata/baselines/reference/compiler/definiteAssignmentOfClosedOverVariable.symbols new file mode 100644 index 0000000000000..ba5f5a0a5e72e --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/definiteAssignmentOfClosedOverVariable.symbols @@ -0,0 +1,68 @@ +//// [tests/cases/compiler/definiteAssignmentOfClosedOverVariable.ts] //// + +=== definiteAssignmentOfClosedOverVariable.ts === +// Repro for #63981 + +export {}; + +let count: number; +>count : Symbol(count, Decl(definiteAssignmentOfClosedOverVariable.ts, 4, 3)) + +function makeCallback(p: string) { +>makeCallback : Symbol(makeCallback, Decl(definiteAssignmentOfClosedOverVariable.ts, 4, 18)) +>p : Symbol(p, Decl(definiteAssignmentOfClosedOverVariable.ts, 6, 22)) + + return () => { + count += 1; +>count : Symbol(count, Decl(definiteAssignmentOfClosedOverVariable.ts, 4, 3)) + + return p; +>p : Symbol(p, Decl(definiteAssignmentOfClosedOverVariable.ts, 6, 22)) + + }; +} + +count = 0; +>count : Symbol(count, Decl(definiteAssignmentOfClosedOverVariable.ts, 4, 3)) + +makeCallback('x')(); +>makeCallback : Symbol(makeCallback, Decl(definiteAssignmentOfClosedOverVariable.ts, 4, 18)) + +let count2: number; +>count2 : Symbol(count2, Decl(definiteAssignmentOfClosedOverVariable.ts, 16, 3)) + +function makeCallback2(p: string) { +>makeCallback2 : Symbol(makeCallback2, Decl(definiteAssignmentOfClosedOverVariable.ts, 16, 19)) +>p : Symbol(p, Decl(definiteAssignmentOfClosedOverVariable.ts, 18, 23)) + + const f = () => p; +>f : Symbol(f, Decl(definiteAssignmentOfClosedOverVariable.ts, 19, 9)) +>p : Symbol(p, Decl(definiteAssignmentOfClosedOverVariable.ts, 18, 23)) + + return () => { + count2 += 1; +>count2 : Symbol(count2, Decl(definiteAssignmentOfClosedOverVariable.ts, 16, 3)) + + }; +} + +count2 = 0; +>count2 : Symbol(count2, Decl(definiteAssignmentOfClosedOverVariable.ts, 16, 3)) + +let count3: number; +>count3 : Symbol(count3, Decl(definiteAssignmentOfClosedOverVariable.ts, 27, 3)) + +function makeCallback3(p: string) { +>makeCallback3 : Symbol(makeCallback3, Decl(definiteAssignmentOfClosedOverVariable.ts, 27, 19)) +>p : Symbol(p, Decl(definiteAssignmentOfClosedOverVariable.ts, 29, 23)) + + return () => { + count3 += 1; +>count3 : Symbol(count3, Decl(definiteAssignmentOfClosedOverVariable.ts, 27, 3)) + + return p; +>p : Symbol(p, Decl(definiteAssignmentOfClosedOverVariable.ts, 29, 23)) + + }; +} + diff --git a/tsc/testdata/baselines/reference/compiler/definiteAssignmentOfClosedOverVariable.types b/tsc/testdata/baselines/reference/compiler/definiteAssignmentOfClosedOverVariable.types new file mode 100644 index 0000000000000..c4820a21d711d --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/definiteAssignmentOfClosedOverVariable.types @@ -0,0 +1,88 @@ +//// [tests/cases/compiler/definiteAssignmentOfClosedOverVariable.ts] //// + +=== definiteAssignmentOfClosedOverVariable.ts === +// Repro for #63981 + +export {}; + +let count: number; +>count : number + +function makeCallback(p: string) { +>makeCallback : (p: string) => () => string +>p : string + + return () => { +>() => { count += 1; return p; } : () => string + + count += 1; +>count += 1 : number +>count : number +>1 : 1 + + return p; +>p : string + + }; +} + +count = 0; +>count = 0 : 0 +>count : number +>0 : 0 + +makeCallback('x')(); +>makeCallback('x')() : string +>makeCallback('x') : () => string +>makeCallback : (p: string) => () => string +>'x' : "x" + +let count2: number; +>count2 : number + +function makeCallback2(p: string) { +>makeCallback2 : (p: string) => () => void +>p : string + + const f = () => p; +>f : () => string +>() => p : () => string +>p : string + + return () => { +>() => { count2 += 1; } : () => void + + count2 += 1; +>count2 += 1 : number +>count2 : number +>1 : 1 + + }; +} + +count2 = 0; +>count2 = 0 : 0 +>count2 : number +>0 : 0 + +let count3: number; +>count3 : number + +function makeCallback3(p: string) { +>makeCallback3 : (p: string) => () => string +>p : string + + return () => { +>() => { count3 += 1; return p; } : () => string + + count3 += 1; +>count3 += 1 : number +>count3 : number +>1 : 1 + + return p; +>p : string + + }; +} + diff --git a/tsc/testdata/tests/cases/compiler/definiteAssignmentOfClosedOverVariable.ts b/tsc/testdata/tests/cases/compiler/definiteAssignmentOfClosedOverVariable.ts new file mode 100644 index 0000000000000..ecc10a70fd054 --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/definiteAssignmentOfClosedOverVariable.ts @@ -0,0 +1,40 @@ +// @strict: true +// @noEmit: true +// @target: esnext +// @module: esnext + +// Repro for #63981 + +export {}; + +let count: number; + +function makeCallback(p: string) { + return () => { + count += 1; + return p; + }; +} + +count = 0; +makeCallback('x')(); + +let count2: number; + +function makeCallback2(p: string) { + const f = () => p; + return () => { + count2 += 1; + }; +} + +count2 = 0; + +let count3: number; + +function makeCallback3(p: string) { + return () => { + count3 += 1; + return p; + }; +}