error on variables that are used but never initialized (#55887)

Co-authored-by: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com>
This commit is contained in:
Zzzen 2024-08-21 04:02:54 +08:00 committed by GitHub
parent 627fbcbd69
commit 533ed3d665
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 1970 additions and 23 deletions

View File

@ -29602,7 +29602,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
node.kind === SyntaxKind.PropertyDeclaration)!;
}
// Check if a parameter or catch variable is assigned anywhere
// Check if a parameter, catch variable, or mutable local variable is assigned anywhere definitely
function isSymbolAssignedDefinitely(symbol: Symbol) {
if (symbol.lastAssignmentPos !== undefined) {
return symbol.lastAssignmentPos < 0;
}
return isSymbolAssigned(symbol) && symbol.lastAssignmentPos !== undefined && symbol.lastAssignmentPos < 0;
}
// Check if a parameter, catch variable, or mutable local variable is assigned anywhere
function isSymbolAssigned(symbol: Symbol) {
return !isPastLastAssignment(symbol, /*location*/ undefined);
}
@ -29621,7 +29629,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
markNodeAssignments(parent);
}
}
return !symbol.lastAssignmentPos || location && symbol.lastAssignmentPos < location.pos;
return !symbol.lastAssignmentPos || location && Math.abs(symbol.lastAssignmentPos) < location.pos;
}
// Check if a parameter or catch variable (or their bindings elements) is assigned anywhere
@ -29655,12 +29663,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
function markNodeAssignments(node: Node) {
switch (node.kind) {
case SyntaxKind.Identifier:
if (isAssignmentTarget(node)) {
const assigmentTarget = getAssignmentTargetKind(node);
if (assigmentTarget !== AssignmentKind.None) {
const symbol = getResolvedSymbol(node as Identifier);
if (isParameterOrMutableLocalVariable(symbol) && symbol.lastAssignmentPos !== Number.MAX_VALUE) {
const referencingFunction = findAncestor(node, isFunctionOrSourceFile);
const declaringFunction = findAncestor(symbol.valueDeclaration, isFunctionOrSourceFile);
symbol.lastAssignmentPos = referencingFunction === declaringFunction ? extendAssignmentPosition(node, symbol.valueDeclaration!) : Number.MAX_VALUE;
const hasDefiniteAssignment = assigmentTarget === AssignmentKind.Definite || (symbol.lastAssignmentPos !== undefined && symbol.lastAssignmentPos < 0);
if (isParameterOrMutableLocalVariable(symbol)) {
if (symbol.lastAssignmentPos === undefined || Math.abs(symbol.lastAssignmentPos) !== Number.MAX_VALUE) {
const referencingFunction = findAncestor(node, isFunctionOrSourceFile);
const declaringFunction = findAncestor(symbol.valueDeclaration, isFunctionOrSourceFile);
symbol.lastAssignmentPos = referencingFunction === declaringFunction ? extendAssignmentPosition(node, symbol.valueDeclaration!) : Number.MAX_VALUE;
}
if (hasDefiniteAssignment && symbol.lastAssignmentPos > 0) {
symbol.lastAssignmentPos *= -1;
}
}
}
return;
@ -29670,7 +29685,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (!(node as ExportSpecifier).isTypeOnly && !exportDeclaration.isTypeOnly && !exportDeclaration.moduleSpecifier && name.kind !== SyntaxKind.StringLiteral) {
const symbol = resolveEntityName(name, SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ true);
if (symbol && isParameterOrMutableLocalVariable(symbol)) {
symbol.lastAssignmentPos = Number.MAX_VALUE;
const sign = symbol.lastAssignmentPos !== undefined && symbol.lastAssignmentPos < 0 ? -1 : 1;
symbol.lastAssignmentPos = sign * Number.MAX_VALUE;
}
}
return;
@ -30414,6 +30430,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const localOrExportSymbol = getExportSymbolOfValueSymbolIfExported(symbol);
let declaration = localOrExportSymbol.valueDeclaration;
const immediateDeclaration = declaration;
// If the identifier is declared in a binding pattern for which we're currently computing the implied type and the
// reference occurs with the same binding pattern, return the non-inferrable any type. This for example occurs in
@ -30503,7 +30520,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// We only look for uninitialized variables in strict null checking mode, and only when we can analyze
// the entire control flow graph from the variable's declaration (i.e. when the flow container and
// declaration container are the same).
const assumeInitialized = isParameter || isAlias || isOuterVariable || isSpreadDestructuringAssignmentTarget || isModuleExports || isSameScopedBindingElement(node, declaration) ||
const isNeverInitialized = immediateDeclaration && isVariableDeclaration(immediateDeclaration) && !immediateDeclaration.initializer && !immediateDeclaration.exclamationToken && isMutableLocalVariableDeclaration(immediateDeclaration) && !isSymbolAssignedDefinitely(symbol);
const assumeInitialized = isParameter || isAlias ||
(isOuterVariable && !isNeverInitialized) ||
isSpreadDestructuringAssignmentTarget || isModuleExports || isSameScopedBindingElement(node, declaration) ||
type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Void)) !== 0 ||
isInTypeQuery(node) || isInAmbientOrTypeNode(node) || node.parent.kind === SyntaxKind.ExportSpecifier) ||
node.parent.kind === SyntaxKind.NonNullExpression ||
@ -43495,7 +43515,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
if (node.body) { // Don't report unused parameters in overloads
// Only report unused parameters on the implementation, not overloads.
if (node.body) {
checkUnusedLocalsAndParameters(node, addDiagnostic);
}
checkUnusedTypeParameters(node, addDiagnostic);

View File

@ -228,6 +228,7 @@ import {
} from "../_namespaces/ts.js";
const enum ClassPropertySubstitutionFlags {
None = 0,
/**
* Enables substitutions for class expressions with static fields
* which have initializers that reference the class name.
@ -401,7 +402,7 @@ export function transformClassFields(context: TransformationContext): (x: Source
context.onEmitNode = onEmitNode;
let shouldTransformPrivateStaticElementsInFile = false;
let enabledSubstitutions: ClassPropertySubstitutionFlags;
let enabledSubstitutions = ClassPropertySubstitutionFlags.None;
let classAliases: Identifier[];

View File

@ -218,6 +218,7 @@ import {
} from "../_namespaces/ts.js";
const enum ES2015SubstitutionFlags {
None = 0,
/** Enables substitutions for captured `this` */
CapturedThis = 1 << 0,
/** Enables substitutions for block-scoped bindings. */
@ -523,7 +524,7 @@ export function transformES2015(context: TransformationContext): (x: SourceFile
* They are persisted between each SourceFile transformation and should not
* be reset.
*/
let enabledSubstitutions: ES2015SubstitutionFlags;
let enabledSubstitutions = ES2015SubstitutionFlags.None;
return chainBundle(context, transformSourceFile);

View File

@ -104,6 +104,7 @@ import {
type SuperContainer = ClassDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration;
const enum ES2017SubstitutionFlags {
None = 0,
/** Enables substitutions for async methods with `super` calls. */
AsyncMethodsWithSuper = 1 << 0,
}
@ -132,7 +133,7 @@ export function transformES2017(context: TransformationContext): (x: SourceFile
* Keeps track of whether expression substitution has been enabled for specific edge cases.
* They are persisted between each SourceFile transformation and should not be reset.
*/
let enabledSubstitutions: ES2017SubstitutionFlags;
let enabledSubstitutions = ES2017SubstitutionFlags.None;
/**
* This keeps track of containers where `super` is valid, for use with

View File

@ -113,6 +113,7 @@ import {
} from "../_namespaces/ts.js";
const enum ESNextSubstitutionFlags {
None = 0,
/** Enables substitutions for async methods with `super` calls. */
AsyncMethodsWithSuper = 1 << 0,
}
@ -170,7 +171,7 @@ export function transformES2018(context: TransformationContext): (x: SourceFile
context.onSubstituteNode = onSubstituteNode;
let exportedVariableStatement = false;
let enabledSubstitutions: ESNextSubstitutionFlags;
let enabledSubstitutions = ESNextSubstitutionFlags.None;
let enclosingFunctionFlags: FunctionFlags;
let parametersWithPrecedingObjectRestOrSpread: Set<ParameterDeclaration> | undefined;
let enclosingSuperContainerFlags: NodeCheckFlags = 0;

View File

@ -208,6 +208,7 @@ import {
const USE_NEW_TYPE_METADATA_FORMAT = false;
const enum TypeScriptSubstitutionFlags {
None = 0,
/** Enables substitutions for namespace exports. */
NamespaceExports = 1 << 1,
/* Enables substitutions for unqualified enum members */
@ -270,7 +271,7 @@ export function transformTypeScript(context: TransformationContext) {
* Keeps track of whether expression substitution has been enabled for specific edge cases.
* They are persisted between each SourceFile transformation and should not be reset.
*/
let enabledSubstitutions: TypeScriptSubstitutionFlags;
let enabledSubstitutions = TypeScriptSubstitutionFlags.None;
/**
* Keeps track of whether we are within any containing namespaces when performing

View File

@ -5970,7 +5970,7 @@ export interface Symbol {
/** @internal */ exportSymbol?: Symbol; // Exported symbol associated with this symbol
/** @internal */ constEnumOnlyModule: boolean | undefined; // True if module contains only const enums or other modules with only const enums
/** @internal */ isReferenced?: SymbolFlags; // True if the symbol is referenced elsewhere. Keeps track of the meaning of a reference in case a symbol is both a type parameter and parameter.
/** @internal */ lastAssignmentPos?: number; // Source position of last node that assigns value to symbol
/** @internal */ lastAssignmentPos?: number; // Source position of last node that assigns value to symbol. Negative if it is assigned anywhere definitely
/** @internal */ isReplaceableByMethod?: boolean; // Can this Javascript class property be replaced by a method symbol?
/** @internal */ assignmentDeclarationMembers?: Map<number, Declaration>; // detected late-bound assignment declarations associated with the symbol
}

View File

@ -153,6 +153,8 @@ import {
forEachChild,
forEachChildRecursively,
ForInOrOfStatement,
ForInStatement,
ForOfStatement,
ForStatement,
FunctionBody,
FunctionDeclaration,
@ -7906,6 +7908,9 @@ function accessKind(node: Node): AccessKind {
return node === (parent as ShorthandPropertyAssignment).objectAssignmentInitializer ? AccessKind.Read : accessKind(parent.parent);
case SyntaxKind.ArrayLiteralExpression:
return accessKind(parent);
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
return node === (parent as ForInStatement | ForOfStatement).initializer ? AccessKind.Write : AccessKind.Read;
default:
return AccessKind.Read;
}

View File

@ -13,7 +13,7 @@
// for (<|var { [|property1|]: p1 } of elems|>) {
// }
// var p2;
// for (<|{ [|{| isWriteAccess: true |}property1|] : p2 } of elems|>) {
// for (<|{ [|property1|] : p2 } of elems|>) {
// }
// === Definitions ===
@ -94,7 +94,7 @@
// for (<|var { [|property1|]: p1 } of elems|>) {
// }
// var p2;
// for (<|{ [|{| isWriteAccess: true |}property1|] : p2 } of elems|>) {
// for (<|{ [|property1|] : p2 } of elems|>) {
// }
// === Definitions ===
@ -180,7 +180,7 @@
// for (<|var { /*FIND ALL REFS*/[|property1|]: p1 } of elems|>) {
// }
// var p2;
// for (<|{ [|{| isWriteAccess: true |}property1|] : p2 } of elems|>) {
// for (<|{ [|property1|] : p2 } of elems|>) {
// }
// === Definitions ===
@ -270,7 +270,7 @@
// for (<|var { [|property1|]: p1 } of elems|>) {
// }
// var p2;
// for (<|{ /*FIND ALL REFS*/[|{| isWriteAccess: true, isDefinition: true |}property1|] : p2 } of elems|>) {
// for (<|{ /*FIND ALL REFS*/[|{| isDefinition: true |}property1|] : p2 } of elems|>) {
// }
// === Definitions ===
@ -358,7 +358,7 @@
// for (<|var { [|{| defId: 0 |}property1|]: p1 } of elems|>) {
// }
// var p2;
// for (<|{ [|{| defId: 0, isWriteAccess: true |}property1|] : p2 } of elems|>) {
// for (<|{ [|{| defId: 0 |}property1|] : p2 } of elems|>) {
// }
// === Definitions ===

View File

@ -1,8 +1,9 @@
narrowingPastLastAssignment.ts(88,9): error TS7034: Variable 'x' implicitly has type 'any' in some locations where its type cannot be determined.
narrowingPastLastAssignment.ts(90,20): error TS7005: Variable 'x' implicitly has an 'any' type.
narrowingPastLastAssignment.ts(161,9): error TS18048: 'foo' is possibly 'undefined'.
==== narrowingPastLastAssignment.ts (2 errors) ====
==== narrowingPastLastAssignment.ts (3 errors) ====
function action(f: Function) {}
// Narrowings are preserved in closures created past last assignment
@ -160,4 +161,15 @@ narrowingPastLastAssignment.ts(90,20): error TS7005: Variable 'x' implicitly has
}
values.forEach(v => foo.push(v));
}
function f13() {
// Test for captured 'var' declaration (as opposed to parameters, let, const).
var foo: string | undefined;
foo = '';
return () => {
foo.toLocaleLowerCase();
~~~
!!! error TS18048: 'foo' is possibly 'undefined'.
}
}

View File

@ -363,3 +363,20 @@ function f12() {
>v : Symbol(v, Decl(narrowingPastLastAssignment.ts, 151, 19))
}
function f13() {
>f13 : Symbol(f13, Decl(narrowingPastLastAssignment.ts, 152, 1))
// Test for captured 'var' declaration (as opposed to parameters, let, const).
var foo: string | undefined;
>foo : Symbol(foo, Decl(narrowingPastLastAssignment.ts, 156, 7))
foo = '';
>foo : Symbol(foo, Decl(narrowingPastLastAssignment.ts, 156, 7))
return () => {
foo.toLocaleLowerCase();
>foo.toLocaleLowerCase : Symbol(String.toLocaleLowerCase, Decl(lib.es5.d.ts, --, --), Decl(lib.es2020.string.d.ts, --, --))
>foo : Symbol(foo, Decl(narrowingPastLastAssignment.ts, 156, 7))
>toLocaleLowerCase : Symbol(String.toLocaleLowerCase, Decl(lib.es5.d.ts, --, --), Decl(lib.es2020.string.d.ts, --, --))
}
}

View File

@ -731,3 +731,35 @@ function f12() {
> : ^^^^^^
}
function f13() {
>f13 : () => () => void
> : ^^^^^^^^^^^^^^^^
// Test for captured 'var' declaration (as opposed to parameters, let, const).
var foo: string | undefined;
>foo : string | undefined
> : ^^^^^^^^^^^^^^^^^^
foo = '';
>foo = '' : ""
> : ^^
>foo : string | undefined
> : ^^^^^^^^^^^^^^^^^^
>'' : ""
> : ^^
return () => {
>() => { foo.toLocaleLowerCase(); } : () => void
> : ^^^^^^^^^^
foo.toLocaleLowerCase();
>foo.toLocaleLowerCase() : string
> : ^^^^^^
>foo.toLocaleLowerCase : { (locales?: string | string[]): string; (locales?: Intl.LocalesArgument): string; }
> : ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^
>foo : string | undefined
> : ^^^^^^^^^^^^^^^^^^
>toLocaleLowerCase : { (locales?: string | string[]): string; (locales?: Intl.LocalesArgument): string; }
> : ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^
}
}

View File

@ -0,0 +1,138 @@
typeGuardsAsAssertions.ts(23,12): error TS2454: Variable 'cond' is used before being assigned.
typeGuardsAsAssertions.ts(33,12): error TS2454: Variable 'cond' is used before being assigned.
typeGuardsAsAssertions.ts(44,12): error TS2454: Variable 'cond' is used before being assigned.
==== typeGuardsAsAssertions.ts (3 errors) ====
// Repro from #8513
let cond: boolean;
export type Optional<a> = Some<a> | None;
export interface None { readonly none: string; }
export interface Some<a> { readonly some: a; }
export const none : None = { none: '' };
export function isSome<a>(value: Optional<a>): value is Some<a> {
return 'some' in value;
}
function someFrom<a>(some: a) {
return { some };
}
export function fn<r>(makeSome: () => r): void {
let result: Optional<r> = none;
result; // None
while (cond) {
~~~~
!!! error TS2454: Variable 'cond' is used before being assigned.
result; // Some<r> | None
result = someFrom(isSome(result) ? result.some : makeSome());
result; // Some<r>
}
}
function foo1() {
let x: string | number | boolean = 0;
x; // number
while (cond) {
~~~~
!!! error TS2454: Variable 'cond' is used before being assigned.
x; // number, then string | number
x = typeof x === "string" ? x.slice() : "abc";
x; // string
}
x;
}
function foo2() {
let x: string | number | boolean = 0;
x; // number
while (cond) {
~~~~
!!! error TS2454: Variable 'cond' is used before being assigned.
x; // number, then string | number
if (typeof x === "string") {
x = x.slice();
}
else {
x = "abc";
}
x; // string
}
x;
}
// Type guards as assertions
function f1() {
let x: string | number | undefined = undefined;
x; // undefined
if (x) {
x; // string | number (guard as assertion)
}
x; // string | number | undefined
}
function f2() {
let x: string | number | undefined = undefined;
x; // undefined
if (typeof x === "string") {
x; // string (guard as assertion)
}
x; // string | undefined
}
function f3() {
let x: string | number | undefined = undefined;
x; // undefined
if (!x) {
return;
}
x; // string | number (guard as assertion)
}
function f4() {
let x: string | number | undefined = undefined;
x; // undefined
if (typeof x === "boolean") {
x; // nothing (boolean not in declared type)
}
x; // undefined
}
function f5(x: string | number) {
if (typeof x === "string" && typeof x === "number") {
x; // number (guard as assertion)
}
else {
x; // string | number
}
x; // string | number
}
function f6() {
let x: string | undefined | null;
x!.slice();
x = "";
x!.slice();
x = undefined;
x!.slice();
x = null;
x!.slice();
x = <undefined | null>undefined;
x!.slice();
x = <string | undefined>"";
x!.slice();
x = <string | null>"";
x!.slice();
}
function f7() {
let x: string;
x!.slice();
}

View File

@ -0,0 +1,191 @@
unusedLocalsInMethod4.ts(15,21): error TS2454: Variable 'x1' is used before being assigned.
unusedLocalsInMethod4.ts(16,21): error TS2454: Variable 'x2' is used before being assigned.
unusedLocalsInMethod4.ts(22,21): error TS2454: Variable 'x8' is used before being assigned.
unusedLocalsInMethod4.ts(23,21): error TS2454: Variable 'x9' is used before being assigned.
unusedLocalsInMethod4.ts(44,17): error TS2454: Variable 'x1' is used before being assigned.
unusedLocalsInMethod4.ts(45,17): error TS2454: Variable 'x2' is used before being assigned.
unusedLocalsInMethod4.ts(51,17): error TS2454: Variable 'x8' is used before being assigned.
unusedLocalsInMethod4.ts(52,17): error TS2454: Variable 'x9' is used before being assigned.
unusedLocalsInMethod4.ts(58,9): error TS2454: Variable 'x' is used before being assigned.
unusedLocalsInMethod4.ts(67,20): error TS2454: Variable 'x' is used before being assigned.
unusedLocalsInMethod4.ts(103,11): error TS1155: 'const' declarations must be initialized.
unusedLocalsInMethod4.ts(113,9): error TS2454: Variable 'i' is used before being assigned.
unusedLocalsInMethod4.ts(114,21): error TS2454: Variable 'i' is used before being assigned.
unusedLocalsInMethod4.ts(139,9): error TS2454: Variable 'enabledSubstitutions' is used before being assigned.
unusedLocalsInMethod4.ts(141,9): error TS2454: Variable 'enabledSubstitutions' is used before being assigned.
==== unusedLocalsInMethod4.ts (15 errors) ====
function f<T, NonNull extends {}>() {
let x1: number[]; // should error
let x2: number[] | null; // should error
let x3: number[] | undefined; // should not error
let x4: number[] | undefined | null; // should not error
let x5!: number[]; // should not error
let x6: any; // should not error
let x7: unknown; // should not error
let x8: T; // should error
let x9: NonNull; // should error
var x10: NonNull; // should not error
let x11: NonNull; // should not error
function foo() {
console.log(x1);
~~
!!! error TS2454: Variable 'x1' is used before being assigned.
console.log(x2);
~~
!!! error TS2454: Variable 'x2' is used before being assigned.
console.log(x3);
console.log(x4);
console.log(x5);
console.log(x6);
console.log(x7);
console.log(x8);
~~
!!! error TS2454: Variable 'x8' is used before being assigned.
console.log(x9);
~~
!!! error TS2454: Variable 'x9' is used before being assigned.
console.log(x10);
console.log(x11);
}
function bar() {
x11 = {} as any;
}
foo();
}
function f2<T, NonNull extends {}>() {
let x1: number[]; // should error
let x2: number[] | null; // should error
let x3: number[] | undefined; // should not error
let x4: number[] | undefined | null; // should not error
let x5!: number[]; // should not error
let x6: any; // should not error
let x7: unknown; // should not error
let x8: T; // should error
let x9: NonNull; // should error
console.log(x1);
~~
!!! error TS2454: Variable 'x1' is used before being assigned.
console.log(x2);
~~
!!! error TS2454: Variable 'x2' is used before being assigned.
console.log(x3);
console.log(x4);
console.log(x5);
console.log(x6);
console.log(x7);
console.log(x8);
~~
!!! error TS2454: Variable 'x8' is used before being assigned.
console.log(x9);
~~
!!! error TS2454: Variable 'x9' is used before being assigned.
}
function f3() {
let x: number[]; // should error
function foo() {
x.toString();
~
!!! error TS2454: Variable 'x' is used before being assigned.
}
foo();
}
function f4() {
let x: number; // should error
return {
foo() {
return x.toString();
~
!!! error TS2454: Variable 'x' is used before being assigned.
}
};
}
declare let x: number; // should not error
function f5() {
x.toString();
}
export default {};
function f6() {
let key: string; // should not error
for (key in {}) {
console.log(key);
}
}
function f7() {
let key: string; // should not error
for (key of []) {
console.log(key);
}
}
function f8() {
function ff() {
let _;
let rest: {}; // should not error
[_, ...rest] = bar();
}
}
declare function bar(): [number, ...string[]];
function f9() {
const x: number; // should have only one error
~
!!! error TS1155: 'const' declarations must be initialized.
function bar() {
let y = x;
}
}
function rw() {
let i: number; // should error
function inside() {
i++;
~
!!! error TS2454: Variable 'i' is used before being assigned.
console.log(i); // NaN
~
!!! error TS2454: Variable 'i' is used before being assigned.
}
inside();
}
rw();
function createBinder() {
var file: string; // should not error
function bindSourceFile(f: string) {
file = f;
file.toString();
}
}
function transformClassFields() {
enum ClassPropertySubstitutionFlags {
ClassAliases = 1 << 0,
ClassStaticThisOrSuperReference = 1 << 1,
}
let enabledSubstitutions: ClassPropertySubstitutionFlags; // should error
function enableSubstitutionForClassAliases() {
enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassAliases;
~~~~~~~~~~~~~~~~~~~~
!!! error TS2454: Variable 'enabledSubstitutions' is used before being assigned.
enabledSubstitutions.toString();
~~~~~~~~~~~~~~~~~~~~
!!! error TS2454: Variable 'enabledSubstitutions' is used before being assigned.
}
}

View File

@ -0,0 +1,274 @@
//// [tests/cases/compiler/unusedLocalsInMethod4.ts] ////
//// [unusedLocalsInMethod4.ts]
function f<T, NonNull extends {}>() {
let x1: number[]; // should error
let x2: number[] | null; // should error
let x3: number[] | undefined; // should not error
let x4: number[] | undefined | null; // should not error
let x5!: number[]; // should not error
let x6: any; // should not error
let x7: unknown; // should not error
let x8: T; // should error
let x9: NonNull; // should error
var x10: NonNull; // should not error
let x11: NonNull; // should not error
function foo() {
console.log(x1);
console.log(x2);
console.log(x3);
console.log(x4);
console.log(x5);
console.log(x6);
console.log(x7);
console.log(x8);
console.log(x9);
console.log(x10);
console.log(x11);
}
function bar() {
x11 = {} as any;
}
foo();
}
function f2<T, NonNull extends {}>() {
let x1: number[]; // should error
let x2: number[] | null; // should error
let x3: number[] | undefined; // should not error
let x4: number[] | undefined | null; // should not error
let x5!: number[]; // should not error
let x6: any; // should not error
let x7: unknown; // should not error
let x8: T; // should error
let x9: NonNull; // should error
console.log(x1);
console.log(x2);
console.log(x3);
console.log(x4);
console.log(x5);
console.log(x6);
console.log(x7);
console.log(x8);
console.log(x9);
}
function f3() {
let x: number[]; // should error
function foo() {
x.toString();
}
foo();
}
function f4() {
let x: number; // should error
return {
foo() {
return x.toString();
}
};
}
declare let x: number; // should not error
function f5() {
x.toString();
}
export default {};
function f6() {
let key: string; // should not error
for (key in {}) {
console.log(key);
}
}
function f7() {
let key: string; // should not error
for (key of []) {
console.log(key);
}
}
function f8() {
function ff() {
let _;
let rest: {}; // should not error
[_, ...rest] = bar();
}
}
declare function bar(): [number, ...string[]];
function f9() {
const x: number; // should have only one error
function bar() {
let y = x;
}
}
function rw() {
let i: number; // should error
function inside() {
i++;
console.log(i); // NaN
}
inside();
}
rw();
function createBinder() {
var file: string; // should not error
function bindSourceFile(f: string) {
file = f;
file.toString();
}
}
function transformClassFields() {
enum ClassPropertySubstitutionFlags {
ClassAliases = 1 << 0,
ClassStaticThisOrSuperReference = 1 << 1,
}
let enabledSubstitutions: ClassPropertySubstitutionFlags; // should error
function enableSubstitutionForClassAliases() {
enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassAliases;
enabledSubstitutions.toString();
}
}
//// [unusedLocalsInMethod4.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function f() {
var x1; // should error
var x2; // should error
var x3; // should not error
var x4; // should not error
var x5; // should not error
var x6; // should not error
var x7; // should not error
var x8; // should error
var x9; // should error
var x10; // should not error
var x11; // should not error
function foo() {
console.log(x1);
console.log(x2);
console.log(x3);
console.log(x4);
console.log(x5);
console.log(x6);
console.log(x7);
console.log(x8);
console.log(x9);
console.log(x10);
console.log(x11);
}
function bar() {
x11 = {};
}
foo();
}
function f2() {
var x1; // should error
var x2; // should error
var x3; // should not error
var x4; // should not error
var x5; // should not error
var x6; // should not error
var x7; // should not error
var x8; // should error
var x9; // should error
console.log(x1);
console.log(x2);
console.log(x3);
console.log(x4);
console.log(x5);
console.log(x6);
console.log(x7);
console.log(x8);
console.log(x9);
}
function f3() {
var x; // should error
function foo() {
x.toString();
}
foo();
}
function f4() {
var x; // should error
return {
foo: function () {
return x.toString();
}
};
}
function f5() {
x.toString();
}
exports.default = {};
function f6() {
var key; // should not error
for (key in {}) {
console.log(key);
}
}
function f7() {
var key; // should not error
for (var _i = 0, _a = []; _i < _a.length; _i++) {
key = _a[_i];
console.log(key);
}
}
function f8() {
function ff() {
var _a;
var _;
var rest; // should not error
_a = bar(), _ = _a[0], rest = _a.slice(1);
}
}
function f9() {
var x; // should have only one error
function bar() {
var y = x;
}
}
function rw() {
var i; // should error
function inside() {
i++;
console.log(i); // NaN
}
inside();
}
rw();
function createBinder() {
var file; // should not error
function bindSourceFile(f) {
file = f;
file.toString();
}
}
function transformClassFields() {
var ClassPropertySubstitutionFlags;
(function (ClassPropertySubstitutionFlags) {
ClassPropertySubstitutionFlags[ClassPropertySubstitutionFlags["ClassAliases"] = 1] = "ClassAliases";
ClassPropertySubstitutionFlags[ClassPropertySubstitutionFlags["ClassStaticThisOrSuperReference"] = 2] = "ClassStaticThisOrSuperReference";
})(ClassPropertySubstitutionFlags || (ClassPropertySubstitutionFlags = {}));
var enabledSubstitutions; // should error
function enableSubstitutionForClassAliases() {
enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassAliases;
enabledSubstitutions.toString();
}
}

View File

@ -0,0 +1,410 @@
//// [tests/cases/compiler/unusedLocalsInMethod4.ts] ////
=== unusedLocalsInMethod4.ts ===
function f<T, NonNull extends {}>() {
>f : Symbol(f, Decl(unusedLocalsInMethod4.ts, 0, 0))
>T : Symbol(T, Decl(unusedLocalsInMethod4.ts, 0, 11))
>NonNull : Symbol(NonNull, Decl(unusedLocalsInMethod4.ts, 0, 13))
let x1: number[]; // should error
>x1 : Symbol(x1, Decl(unusedLocalsInMethod4.ts, 1, 7))
let x2: number[] | null; // should error
>x2 : Symbol(x2, Decl(unusedLocalsInMethod4.ts, 2, 7))
let x3: number[] | undefined; // should not error
>x3 : Symbol(x3, Decl(unusedLocalsInMethod4.ts, 3, 7))
let x4: number[] | undefined | null; // should not error
>x4 : Symbol(x4, Decl(unusedLocalsInMethod4.ts, 4, 7))
let x5!: number[]; // should not error
>x5 : Symbol(x5, Decl(unusedLocalsInMethod4.ts, 5, 7))
let x6: any; // should not error
>x6 : Symbol(x6, Decl(unusedLocalsInMethod4.ts, 6, 7))
let x7: unknown; // should not error
>x7 : Symbol(x7, Decl(unusedLocalsInMethod4.ts, 7, 7))
let x8: T; // should error
>x8 : Symbol(x8, Decl(unusedLocalsInMethod4.ts, 8, 7))
>T : Symbol(T, Decl(unusedLocalsInMethod4.ts, 0, 11))
let x9: NonNull; // should error
>x9 : Symbol(x9, Decl(unusedLocalsInMethod4.ts, 9, 7))
>NonNull : Symbol(NonNull, Decl(unusedLocalsInMethod4.ts, 0, 13))
var x10: NonNull; // should not error
>x10 : Symbol(x10, Decl(unusedLocalsInMethod4.ts, 10, 7))
>NonNull : Symbol(NonNull, Decl(unusedLocalsInMethod4.ts, 0, 13))
let x11: NonNull; // should not error
>x11 : Symbol(x11, Decl(unusedLocalsInMethod4.ts, 11, 7))
>NonNull : Symbol(NonNull, Decl(unusedLocalsInMethod4.ts, 0, 13))
function foo() {
>foo : Symbol(foo, Decl(unusedLocalsInMethod4.ts, 11, 21))
console.log(x1);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x1 : Symbol(x1, Decl(unusedLocalsInMethod4.ts, 1, 7))
console.log(x2);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x2 : Symbol(x2, Decl(unusedLocalsInMethod4.ts, 2, 7))
console.log(x3);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x3 : Symbol(x3, Decl(unusedLocalsInMethod4.ts, 3, 7))
console.log(x4);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x4 : Symbol(x4, Decl(unusedLocalsInMethod4.ts, 4, 7))
console.log(x5);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x5 : Symbol(x5, Decl(unusedLocalsInMethod4.ts, 5, 7))
console.log(x6);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x6 : Symbol(x6, Decl(unusedLocalsInMethod4.ts, 6, 7))
console.log(x7);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x7 : Symbol(x7, Decl(unusedLocalsInMethod4.ts, 7, 7))
console.log(x8);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x8 : Symbol(x8, Decl(unusedLocalsInMethod4.ts, 8, 7))
console.log(x9);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x9 : Symbol(x9, Decl(unusedLocalsInMethod4.ts, 9, 7))
console.log(x10);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x10 : Symbol(x10, Decl(unusedLocalsInMethod4.ts, 10, 7))
console.log(x11);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x11 : Symbol(x11, Decl(unusedLocalsInMethod4.ts, 11, 7))
}
function bar() {
>bar : Symbol(bar, Decl(unusedLocalsInMethod4.ts, 25, 5))
x11 = {} as any;
>x11 : Symbol(x11, Decl(unusedLocalsInMethod4.ts, 11, 7))
}
foo();
>foo : Symbol(foo, Decl(unusedLocalsInMethod4.ts, 11, 21))
}
function f2<T, NonNull extends {}>() {
>f2 : Symbol(f2, Decl(unusedLocalsInMethod4.ts, 30, 1))
>T : Symbol(T, Decl(unusedLocalsInMethod4.ts, 32, 12))
>NonNull : Symbol(NonNull, Decl(unusedLocalsInMethod4.ts, 32, 14))
let x1: number[]; // should error
>x1 : Symbol(x1, Decl(unusedLocalsInMethod4.ts, 33, 7))
let x2: number[] | null; // should error
>x2 : Symbol(x2, Decl(unusedLocalsInMethod4.ts, 34, 7))
let x3: number[] | undefined; // should not error
>x3 : Symbol(x3, Decl(unusedLocalsInMethod4.ts, 35, 7))
let x4: number[] | undefined | null; // should not error
>x4 : Symbol(x4, Decl(unusedLocalsInMethod4.ts, 36, 7))
let x5!: number[]; // should not error
>x5 : Symbol(x5, Decl(unusedLocalsInMethod4.ts, 37, 7))
let x6: any; // should not error
>x6 : Symbol(x6, Decl(unusedLocalsInMethod4.ts, 38, 7))
let x7: unknown; // should not error
>x7 : Symbol(x7, Decl(unusedLocalsInMethod4.ts, 39, 7))
let x8: T; // should error
>x8 : Symbol(x8, Decl(unusedLocalsInMethod4.ts, 40, 7))
>T : Symbol(T, Decl(unusedLocalsInMethod4.ts, 32, 12))
let x9: NonNull; // should error
>x9 : Symbol(x9, Decl(unusedLocalsInMethod4.ts, 41, 7))
>NonNull : Symbol(NonNull, Decl(unusedLocalsInMethod4.ts, 32, 14))
console.log(x1);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x1 : Symbol(x1, Decl(unusedLocalsInMethod4.ts, 33, 7))
console.log(x2);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x2 : Symbol(x2, Decl(unusedLocalsInMethod4.ts, 34, 7))
console.log(x3);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x3 : Symbol(x3, Decl(unusedLocalsInMethod4.ts, 35, 7))
console.log(x4);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x4 : Symbol(x4, Decl(unusedLocalsInMethod4.ts, 36, 7))
console.log(x5);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x5 : Symbol(x5, Decl(unusedLocalsInMethod4.ts, 37, 7))
console.log(x6);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x6 : Symbol(x6, Decl(unusedLocalsInMethod4.ts, 38, 7))
console.log(x7);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x7 : Symbol(x7, Decl(unusedLocalsInMethod4.ts, 39, 7))
console.log(x8);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x8 : Symbol(x8, Decl(unusedLocalsInMethod4.ts, 40, 7))
console.log(x9);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x9 : Symbol(x9, Decl(unusedLocalsInMethod4.ts, 41, 7))
}
function f3() {
>f3 : Symbol(f3, Decl(unusedLocalsInMethod4.ts, 52, 1))
let x: number[]; // should error
>x : Symbol(x, Decl(unusedLocalsInMethod4.ts, 55, 7))
function foo() {
>foo : Symbol(foo, Decl(unusedLocalsInMethod4.ts, 55, 20))
x.toString();
>x.toString : Symbol(Array.toString, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(unusedLocalsInMethod4.ts, 55, 7))
>toString : Symbol(Array.toString, Decl(lib.es5.d.ts, --, --))
}
foo();
>foo : Symbol(foo, Decl(unusedLocalsInMethod4.ts, 55, 20))
}
function f4() {
>f4 : Symbol(f4, Decl(unusedLocalsInMethod4.ts, 60, 1))
let x: number; // should error
>x : Symbol(x, Decl(unusedLocalsInMethod4.ts, 63, 7))
return {
foo() {
>foo : Symbol(foo, Decl(unusedLocalsInMethod4.ts, 64, 12))
return x.toString();
>x.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(unusedLocalsInMethod4.ts, 63, 7))
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
}
};
}
declare let x: number; // should not error
>x : Symbol(x, Decl(unusedLocalsInMethod4.ts, 71, 11))
function f5() {
>f5 : Symbol(f5, Decl(unusedLocalsInMethod4.ts, 71, 22))
x.toString();
>x.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(unusedLocalsInMethod4.ts, 71, 11))
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
}
export default {};
function f6() {
>f6 : Symbol(f6, Decl(unusedLocalsInMethod4.ts, 75, 18))
let key: string; // should not error
>key : Symbol(key, Decl(unusedLocalsInMethod4.ts, 78, 7))
for (key in {}) {
>key : Symbol(key, Decl(unusedLocalsInMethod4.ts, 78, 7))
console.log(key);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>key : Symbol(key, Decl(unusedLocalsInMethod4.ts, 78, 7))
}
}
function f7() {
>f7 : Symbol(f7, Decl(unusedLocalsInMethod4.ts, 82, 1))
let key: string; // should not error
>key : Symbol(key, Decl(unusedLocalsInMethod4.ts, 85, 7))
for (key of []) {
>key : Symbol(key, Decl(unusedLocalsInMethod4.ts, 85, 7))
console.log(key);
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>key : Symbol(key, Decl(unusedLocalsInMethod4.ts, 85, 7))
}
}
function f8() {
>f8 : Symbol(f8, Decl(unusedLocalsInMethod4.ts, 89, 1))
function ff() {
>ff : Symbol(ff, Decl(unusedLocalsInMethod4.ts, 91, 15))
let _;
>_ : Symbol(_, Decl(unusedLocalsInMethod4.ts, 93, 11))
let rest: {}; // should not error
>rest : Symbol(rest, Decl(unusedLocalsInMethod4.ts, 94, 11))
[_, ...rest] = bar();
>_ : Symbol(_, Decl(unusedLocalsInMethod4.ts, 93, 11))
>rest : Symbol(rest, Decl(unusedLocalsInMethod4.ts, 94, 11))
>bar : Symbol(bar, Decl(unusedLocalsInMethod4.ts, 98, 1))
}
}
declare function bar(): [number, ...string[]];
>bar : Symbol(bar, Decl(unusedLocalsInMethod4.ts, 98, 1))
function f9() {
>f9 : Symbol(f9, Decl(unusedLocalsInMethod4.ts, 99, 46))
const x: number; // should have only one error
>x : Symbol(x, Decl(unusedLocalsInMethod4.ts, 102, 9))
function bar() {
>bar : Symbol(bar, Decl(unusedLocalsInMethod4.ts, 102, 20))
let y = x;
>y : Symbol(y, Decl(unusedLocalsInMethod4.ts, 104, 11))
>x : Symbol(x, Decl(unusedLocalsInMethod4.ts, 102, 9))
}
}
function rw() {
>rw : Symbol(rw, Decl(unusedLocalsInMethod4.ts, 106, 1))
let i: number; // should error
>i : Symbol(i, Decl(unusedLocalsInMethod4.ts, 110, 7))
function inside() {
>inside : Symbol(inside, Decl(unusedLocalsInMethod4.ts, 110, 18))
i++;
>i : Symbol(i, Decl(unusedLocalsInMethod4.ts, 110, 7))
console.log(i); // NaN
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>i : Symbol(i, Decl(unusedLocalsInMethod4.ts, 110, 7))
}
inside();
>inside : Symbol(inside, Decl(unusedLocalsInMethod4.ts, 110, 18))
}
rw();
>rw : Symbol(rw, Decl(unusedLocalsInMethod4.ts, 106, 1))
function createBinder() {
>createBinder : Symbol(createBinder, Decl(unusedLocalsInMethod4.ts, 117, 5))
var file: string; // should not error
>file : Symbol(file, Decl(unusedLocalsInMethod4.ts, 120, 7))
function bindSourceFile(f: string) {
>bindSourceFile : Symbol(bindSourceFile, Decl(unusedLocalsInMethod4.ts, 120, 21))
>f : Symbol(f, Decl(unusedLocalsInMethod4.ts, 122, 28))
file = f;
>file : Symbol(file, Decl(unusedLocalsInMethod4.ts, 120, 7))
>f : Symbol(f, Decl(unusedLocalsInMethod4.ts, 122, 28))
file.toString();
>file.toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --))
>file : Symbol(file, Decl(unusedLocalsInMethod4.ts, 120, 7))
>toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --))
}
}
function transformClassFields() {
>transformClassFields : Symbol(transformClassFields, Decl(unusedLocalsInMethod4.ts, 127, 1))
enum ClassPropertySubstitutionFlags {
>ClassPropertySubstitutionFlags : Symbol(ClassPropertySubstitutionFlags, Decl(unusedLocalsInMethod4.ts, 129, 33))
ClassAliases = 1 << 0,
>ClassAliases : Symbol(ClassPropertySubstitutionFlags.ClassAliases, Decl(unusedLocalsInMethod4.ts, 130, 41))
ClassStaticThisOrSuperReference = 1 << 1,
>ClassStaticThisOrSuperReference : Symbol(ClassPropertySubstitutionFlags.ClassStaticThisOrSuperReference, Decl(unusedLocalsInMethod4.ts, 131, 30))
}
let enabledSubstitutions: ClassPropertySubstitutionFlags; // should error
>enabledSubstitutions : Symbol(enabledSubstitutions, Decl(unusedLocalsInMethod4.ts, 135, 7))
>ClassPropertySubstitutionFlags : Symbol(ClassPropertySubstitutionFlags, Decl(unusedLocalsInMethod4.ts, 129, 33))
function enableSubstitutionForClassAliases() {
>enableSubstitutionForClassAliases : Symbol(enableSubstitutionForClassAliases, Decl(unusedLocalsInMethod4.ts, 135, 61))
enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassAliases;
>enabledSubstitutions : Symbol(enabledSubstitutions, Decl(unusedLocalsInMethod4.ts, 135, 7))
>ClassPropertySubstitutionFlags.ClassAliases : Symbol(ClassPropertySubstitutionFlags.ClassAliases, Decl(unusedLocalsInMethod4.ts, 130, 41))
>ClassPropertySubstitutionFlags : Symbol(ClassPropertySubstitutionFlags, Decl(unusedLocalsInMethod4.ts, 129, 33))
>ClassAliases : Symbol(ClassPropertySubstitutionFlags.ClassAliases, Decl(unusedLocalsInMethod4.ts, 130, 41))
enabledSubstitutions.toString();
>enabledSubstitutions.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
>enabledSubstitutions : Symbol(enabledSubstitutions, Decl(unusedLocalsInMethod4.ts, 135, 7))
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
}
}

View File

@ -0,0 +1,687 @@
//// [tests/cases/compiler/unusedLocalsInMethod4.ts] ////
=== unusedLocalsInMethod4.ts ===
function f<T, NonNull extends {}>() {
>f : <T, NonNull extends {}>() => void
> : ^ ^^ ^^^^^^^^^ ^^^^^^^^^^^
let x1: number[]; // should error
>x1 : number[]
> : ^^^^^^^^
let x2: number[] | null; // should error
>x2 : number[] | null
> : ^^^^^^^^^^^^^^^
let x3: number[] | undefined; // should not error
>x3 : number[] | undefined
> : ^^^^^^^^^^^^^^^^^^^^
let x4: number[] | undefined | null; // should not error
>x4 : number[] | null | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^
let x5!: number[]; // should not error
>x5 : number[]
> : ^^^^^^^^
let x6: any; // should not error
>x6 : any
> : ^^^
let x7: unknown; // should not error
>x7 : unknown
> : ^^^^^^^
let x8: T; // should error
>x8 : T
> : ^
let x9: NonNull; // should error
>x9 : NonNull
> : ^^^^^^^
var x10: NonNull; // should not error
>x10 : NonNull
> : ^^^^^^^
let x11: NonNull; // should not error
>x11 : NonNull
> : ^^^^^^^
function foo() {
>foo : () => void
> : ^^^^^^^^^^
console.log(x1);
>console.log(x1) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x1 : number[]
> : ^^^^^^^^
console.log(x2);
>console.log(x2) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x2 : number[] | null
> : ^^^^^^^^^^^^^^^
console.log(x3);
>console.log(x3) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x3 : number[] | undefined
> : ^^^^^^^^^^^^^^^^^^^^
console.log(x4);
>console.log(x4) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x4 : number[] | null | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^
console.log(x5);
>console.log(x5) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x5 : number[]
> : ^^^^^^^^
console.log(x6);
>console.log(x6) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x6 : any
> : ^^^
console.log(x7);
>console.log(x7) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x7 : unknown
> : ^^^^^^^
console.log(x8);
>console.log(x8) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x8 : T
> : ^
console.log(x9);
>console.log(x9) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x9 : NonNull
> : ^^^^^^^
console.log(x10);
>console.log(x10) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x10 : NonNull
> : ^^^^^^^
console.log(x11);
>console.log(x11) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x11 : NonNull
> : ^^^^^^^
}
function bar() {
>bar : () => void
> : ^^^^^^^^^^
x11 = {} as any;
>x11 = {} as any : any
> : ^^^
>x11 : NonNull
> : ^^^^^^^
>{} as any : any
> : ^^^
>{} : {}
> : ^^
}
foo();
>foo() : void
> : ^^^^
>foo : () => void
> : ^^^^^^^^^^
}
function f2<T, NonNull extends {}>() {
>f2 : <T, NonNull extends {}>() => void
> : ^ ^^ ^^^^^^^^^ ^^^^^^^^^^^
let x1: number[]; // should error
>x1 : number[]
> : ^^^^^^^^
let x2: number[] | null; // should error
>x2 : number[] | null
> : ^^^^^^^^^^^^^^^
let x3: number[] | undefined; // should not error
>x3 : number[] | undefined
> : ^^^^^^^^^^^^^^^^^^^^
let x4: number[] | undefined | null; // should not error
>x4 : number[] | null | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^
let x5!: number[]; // should not error
>x5 : number[]
> : ^^^^^^^^
let x6: any; // should not error
>x6 : any
> : ^^^
let x7: unknown; // should not error
>x7 : unknown
> : ^^^^^^^
let x8: T; // should error
>x8 : T
> : ^
let x9: NonNull; // should error
>x9 : NonNull
> : ^^^^^^^
console.log(x1);
>console.log(x1) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x1 : number[]
> : ^^^^^^^^
console.log(x2);
>console.log(x2) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x2 : number[] | null
> : ^^^^^^^^^^^^^^^
console.log(x3);
>console.log(x3) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x3 : number[] | undefined
> : ^^^^^^^^^^^^^^^^^^^^
console.log(x4);
>console.log(x4) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x4 : number[] | null | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^
console.log(x5);
>console.log(x5) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x5 : number[]
> : ^^^^^^^^
console.log(x6);
>console.log(x6) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x6 : any
> : ^^^
console.log(x7);
>console.log(x7) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x7 : unknown
> : ^^^^^^^
console.log(x8);
>console.log(x8) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x8 : T
> : ^
console.log(x9);
>console.log(x9) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>x9 : NonNull
> : ^^^^^^^
}
function f3() {
>f3 : () => void
> : ^^^^^^^^^^
let x: number[]; // should error
>x : number[]
> : ^^^^^^^^
function foo() {
>foo : () => void
> : ^^^^^^^^^^
x.toString();
>x.toString() : string
> : ^^^^^^
>x.toString : () => string
> : ^^^^^^
>x : number[]
> : ^^^^^^^^
>toString : () => string
> : ^^^^^^
}
foo();
>foo() : void
> : ^^^^
>foo : () => void
> : ^^^^^^^^^^
}
function f4() {
>f4 : () => { foo(): string; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^
let x: number; // should error
>x : number
> : ^^^^^^
return {
>{ foo() { return x.toString(); } } : { foo(): string; }
> : ^^^^^^^^^^^^^^^^^^
foo() {
>foo : () => string
> : ^^^^^^^^^^^^
return x.toString();
>x.toString() : string
> : ^^^^^^
>x.toString : (radix?: number) => string
> : ^ ^^^ ^^^^^
>x : number
> : ^^^^^^
>toString : (radix?: number) => string
> : ^ ^^^ ^^^^^
}
};
}
declare let x: number; // should not error
>x : number
> : ^^^^^^
function f5() {
>f5 : () => void
> : ^^^^^^^^^^
x.toString();
>x.toString() : string
> : ^^^^^^
>x.toString : (radix?: number) => string
> : ^ ^^^ ^^^^^
>x : number
> : ^^^^^^
>toString : (radix?: number) => string
> : ^ ^^^ ^^^^^
}
export default {};
>{} : {}
> : ^^
function f6() {
>f6 : () => void
> : ^^^^^^^^^^
let key: string; // should not error
>key : string
> : ^^^^^^
for (key in {}) {
>key : string
> : ^^^^^^
>{} : {}
> : ^^
console.log(key);
>console.log(key) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>key : string
> : ^^^^^^
}
}
function f7() {
>f7 : () => void
> : ^^^^^^^^^^
let key: string; // should not error
>key : string
> : ^^^^^^
for (key of []) {
>key : string
> : ^^^^^^
>[] : never[]
> : ^^^^^^^
console.log(key);
>console.log(key) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>key : string
> : ^^^^^^
}
}
function f8() {
>f8 : () => void
> : ^^^^^^^^^^
function ff() {
>ff : () => void
> : ^^^^^^^^^^
let _;
>_ : any
> : ^^^
let rest: {}; // should not error
>rest : {}
> : ^^
[_, ...rest] = bar();
>[_, ...rest] = bar() : [number, ...string[]]
> : ^^^^^^^^^^^^^^^^^^^^^
>[_, ...rest] : [any, ...unknown[]]
> : ^^^^^^^^^^^^^^^^^^^
>_ : any
> : ^^^
>...rest : any
> : ^^^
>rest : {}
> : ^^
>bar() : [number, ...string[]]
> : ^^^^^^^^^^^^^^^^^^^^^
>bar : () => [number, ...string[]]
> : ^^^^^^
}
}
declare function bar(): [number, ...string[]];
>bar : () => [number, ...string[]]
> : ^^^^^^
function f9() {
>f9 : () => void
> : ^^^^^^^^^^
const x: number; // should have only one error
>x : number
> : ^^^^^^
function bar() {
>bar : () => void
> : ^^^^^^^^^^
let y = x;
>y : number
> : ^^^^^^
>x : number
> : ^^^^^^
}
}
function rw() {
>rw : () => void
> : ^^^^^^^^^^
let i: number; // should error
>i : number
> : ^^^^^^
function inside() {
>inside : () => void
> : ^^^^^^^^^^
i++;
>i++ : number
> : ^^^^^^
>i : number
> : ^^^^^^
console.log(i); // NaN
>console.log(i) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^
>i : number
> : ^^^^^^
}
inside();
>inside() : void
> : ^^^^
>inside : () => void
> : ^^^^^^^^^^
}
rw();
>rw() : void
> : ^^^^
>rw : () => void
> : ^^^^^^^^^^
function createBinder() {
>createBinder : () => void
> : ^^^^^^^^^^
var file: string; // should not error
>file : string
> : ^^^^^^
function bindSourceFile(f: string) {
>bindSourceFile : (f: string) => void
> : ^ ^^ ^^^^^^^^^
>f : string
> : ^^^^^^
file = f;
>file = f : string
> : ^^^^^^
>file : string
> : ^^^^^^
>f : string
> : ^^^^^^
file.toString();
>file.toString() : string
> : ^^^^^^
>file.toString : () => string
> : ^^^^^^
>file : string
> : ^^^^^^
>toString : () => string
> : ^^^^^^
}
}
function transformClassFields() {
>transformClassFields : () => void
> : ^^^^^^^^^^
enum ClassPropertySubstitutionFlags {
>ClassPropertySubstitutionFlags : ClassPropertySubstitutionFlags
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ClassAliases = 1 << 0,
>ClassAliases : ClassPropertySubstitutionFlags.ClassAliases
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>1 << 0 : number
> : ^^^^^^
>1 : 1
> : ^
>0 : 0
> : ^
ClassStaticThisOrSuperReference = 1 << 1,
>ClassStaticThisOrSuperReference : ClassPropertySubstitutionFlags.ClassStaticThisOrSuperReference
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>1 << 1 : number
> : ^^^^^^
>1 : 1
> : ^
>1 : 1
> : ^
}
let enabledSubstitutions: ClassPropertySubstitutionFlags; // should error
>enabledSubstitutions : ClassPropertySubstitutionFlags
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
function enableSubstitutionForClassAliases() {
>enableSubstitutionForClassAliases : () => void
> : ^^^^^^^^^^
enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassAliases;
>enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassAliases : number
> : ^^^^^^
>enabledSubstitutions : ClassPropertySubstitutionFlags
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>ClassPropertySubstitutionFlags.ClassAliases : ClassPropertySubstitutionFlags.ClassAliases
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>ClassPropertySubstitutionFlags : typeof ClassPropertySubstitutionFlags
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>ClassAliases : ClassPropertySubstitutionFlags.ClassAliases
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
enabledSubstitutions.toString();
>enabledSubstitutions.toString() : string
> : ^^^^^^
>enabledSubstitutions.toString : (radix?: number) => string
> : ^ ^^^ ^^^^^
>enabledSubstitutions : ClassPropertySubstitutionFlags
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>toString : (radix?: number) => string
> : ^ ^^^ ^^^^^
}
}

View File

@ -155,3 +155,13 @@ function f12() {
}
values.forEach(v => foo.push(v));
}
function f13() {
// Test for captured 'var' declaration (as opposed to parameters, let, const).
var foo: string | undefined;
foo = '';
return () => {
foo.toLocaleLowerCase();
}
}

View File

@ -0,0 +1,145 @@
// @strict: true
function f<T, NonNull extends {}>() {
let x1: number[]; // should error
let x2: number[] | null; // should error
let x3: number[] | undefined; // should not error
let x4: number[] | undefined | null; // should not error
let x5!: number[]; // should not error
let x6: any; // should not error
let x7: unknown; // should not error
let x8: T; // should error
let x9: NonNull; // should error
var x10: NonNull; // should not error
let x11: NonNull; // should not error
function foo() {
console.log(x1);
console.log(x2);
console.log(x3);
console.log(x4);
console.log(x5);
console.log(x6);
console.log(x7);
console.log(x8);
console.log(x9);
console.log(x10);
console.log(x11);
}
function bar() {
x11 = {} as any;
}
foo();
}
function f2<T, NonNull extends {}>() {
let x1: number[]; // should error
let x2: number[] | null; // should error
let x3: number[] | undefined; // should not error
let x4: number[] | undefined | null; // should not error
let x5!: number[]; // should not error
let x6: any; // should not error
let x7: unknown; // should not error
let x8: T; // should error
let x9: NonNull; // should error
console.log(x1);
console.log(x2);
console.log(x3);
console.log(x4);
console.log(x5);
console.log(x6);
console.log(x7);
console.log(x8);
console.log(x9);
}
function f3() {
let x: number[]; // should error
function foo() {
x.toString();
}
foo();
}
function f4() {
let x: number; // should error
return {
foo() {
return x.toString();
}
};
}
declare let x: number; // should not error
function f5() {
x.toString();
}
export default {};
function f6() {
let key: string; // should not error
for (key in {}) {
console.log(key);
}
}
function f7() {
let key: string; // should not error
for (key of []) {
console.log(key);
}
}
function f8() {
function ff() {
let _;
let rest: {}; // should not error
[_, ...rest] = bar();
}
}
declare function bar(): [number, ...string[]];
function f9() {
const x: number; // should have only one error
function bar() {
let y = x;
}
}
function rw() {
let i: number; // should error
function inside() {
i++;
console.log(i); // NaN
}
inside();
}
rw();
function createBinder() {
var file: string; // should not error
function bindSourceFile(f: string) {
file = f;
file.toString();
}
}
function transformClassFields() {
enum ClassPropertySubstitutionFlags {
ClassAliases = 1 << 0,
ClassStaticThisOrSuperReference = 1 << 1,
}
let enabledSubstitutions: ClassPropertySubstitutionFlags; // should error
function enableSubstitutionForClassAliases() {
enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassAliases;
enabledSubstitutions.toString();
}
}