diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 05d42573b66..3d4917c2389 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -23348,6 +23348,15 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n") const key = getFlowCacheKey((node as AccessExpression).expression, declaredType, initialType, flowContainer); return key && key + "." + propName; } + break; + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.MethodDeclaration: + // Handle pseudo-references originating in getNarrowedTypeOfSymbol. + return `${getNodeId(node)}#${getTypeId(declaredType)}`; } return undefined; } diff --git a/tests/baselines/reference/dependentDestructuredVariables.errors.txt b/tests/baselines/reference/dependentDestructuredVariables.errors.txt index fbddf80744c..e3704b567ac 100644 --- a/tests/baselines/reference/dependentDestructuredVariables.errors.txt +++ b/tests/baselines/reference/dependentDestructuredVariables.errors.txt @@ -331,4 +331,47 @@ tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts(314,5): er test8 = value1.test8, test9 = value1.test9 }) {} + + // Repro from #49772 + + function fa1(x: [true, number] | [false, string]) { + const [guard, value] = x; + if (guard) { + for (;;) { + value; // number + } + } + else { + while (!!true) { + value; // string + } + } + } + + function fa2(x: { guard: true, value: number } | { guard: false, value: string }) { + const { guard, value } = x; + if (guard) { + for (;;) { + value; // number + } + } + else { + while (!!true) { + value; // string + } + } + } + + const fa3: (...args: [true, number] | [false, string]) => void = (guard, value) => { + if (guard) { + for (;;) { + value; // number + } + } + else { + while (!!true) { + value; // string + } + } + } \ No newline at end of file diff --git a/tests/baselines/reference/dependentDestructuredVariables.js b/tests/baselines/reference/dependentDestructuredVariables.js index eab12767faf..6971c1ad1d2 100644 --- a/tests/baselines/reference/dependentDestructuredVariables.js +++ b/tests/baselines/reference/dependentDestructuredVariables.js @@ -323,6 +323,49 @@ function foo({ test8 = value1.test8, test9 = value1.test9 }) {} + +// Repro from #49772 + +function fa1(x: [true, number] | [false, string]) { + const [guard, value] = x; + if (guard) { + for (;;) { + value; // number + } + } + else { + while (!!true) { + value; // string + } + } +} + +function fa2(x: { guard: true, value: number } | { guard: false, value: string }) { + const { guard, value } = x; + if (guard) { + for (;;) { + value; // number + } + } + else { + while (!!true) { + value; // string + } + } +} + +const fa3: (...args: [true, number] | [false, string]) => void = (guard, value) => { + if (guard) { + for (;;) { + value; // number + } + } + else { + while (!!true) { + value; // string + } + } +} //// [dependentDestructuredVariables.js] @@ -567,6 +610,45 @@ const f60 = (kind, payload) => { }; // Repro from #48902 function foo({ value1, test1 = value1.test1, test2 = value1.test2, test3 = value1.test3, test4 = value1.test4, test5 = value1.test5, test6 = value1.test6, test7 = value1.test7, test8 = value1.test8, test9 = value1.test9 }) { } +// Repro from #49772 +function fa1(x) { + const [guard, value] = x; + if (guard) { + for (;;) { + value; // number + } + } + else { + while (!!true) { + value; // string + } + } +} +function fa2(x) { + const { guard, value } = x; + if (guard) { + for (;;) { + value; // number + } + } + else { + while (!!true) { + value; // string + } + } +} +const fa3 = (guard, value) => { + if (guard) { + for (;;) { + value; // number + } + } + else { + while (!!true) { + value; // string + } + } +}; //// [dependentDestructuredVariables.d.ts] @@ -696,3 +778,12 @@ declare function foo({ value1, test1, test2, test3, test4, test5, test6, test7, test8?: any; test9?: any; }): void; +declare function fa1(x: [true, number] | [false, string]): void; +declare function fa2(x: { + guard: true; + value: number; +} | { + guard: false; + value: string; +}): void; +declare const fa3: (...args: [true, number] | [false, string]) => void; diff --git a/tests/baselines/reference/dependentDestructuredVariables.symbols b/tests/baselines/reference/dependentDestructuredVariables.symbols index ccaaaa72fe9..6fed5c24708 100644 --- a/tests/baselines/reference/dependentDestructuredVariables.symbols +++ b/tests/baselines/reference/dependentDestructuredVariables.symbols @@ -830,3 +830,81 @@ function foo({ }) {} +// Repro from #49772 + +function fa1(x: [true, number] | [false, string]) { +>fa1 : Symbol(fa1, Decl(dependentDestructuredVariables.ts, 323, 5)) +>x : Symbol(x, Decl(dependentDestructuredVariables.ts, 327, 13)) + + const [guard, value] = x; +>guard : Symbol(guard, Decl(dependentDestructuredVariables.ts, 328, 11)) +>value : Symbol(value, Decl(dependentDestructuredVariables.ts, 328, 17)) +>x : Symbol(x, Decl(dependentDestructuredVariables.ts, 327, 13)) + + if (guard) { +>guard : Symbol(guard, Decl(dependentDestructuredVariables.ts, 328, 11)) + + for (;;) { + value; // number +>value : Symbol(value, Decl(dependentDestructuredVariables.ts, 328, 17)) + } + } + else { + while (!!true) { + value; // string +>value : Symbol(value, Decl(dependentDestructuredVariables.ts, 328, 17)) + } + } +} + +function fa2(x: { guard: true, value: number } | { guard: false, value: string }) { +>fa2 : Symbol(fa2, Decl(dependentDestructuredVariables.ts, 339, 1)) +>x : Symbol(x, Decl(dependentDestructuredVariables.ts, 341, 13)) +>guard : Symbol(guard, Decl(dependentDestructuredVariables.ts, 341, 17)) +>value : Symbol(value, Decl(dependentDestructuredVariables.ts, 341, 30)) +>guard : Symbol(guard, Decl(dependentDestructuredVariables.ts, 341, 50)) +>value : Symbol(value, Decl(dependentDestructuredVariables.ts, 341, 64)) + + const { guard, value } = x; +>guard : Symbol(guard, Decl(dependentDestructuredVariables.ts, 342, 11)) +>value : Symbol(value, Decl(dependentDestructuredVariables.ts, 342, 18)) +>x : Symbol(x, Decl(dependentDestructuredVariables.ts, 341, 13)) + + if (guard) { +>guard : Symbol(guard, Decl(dependentDestructuredVariables.ts, 342, 11)) + + for (;;) { + value; // number +>value : Symbol(value, Decl(dependentDestructuredVariables.ts, 342, 18)) + } + } + else { + while (!!true) { + value; // string +>value : Symbol(value, Decl(dependentDestructuredVariables.ts, 342, 18)) + } + } +} + +const fa3: (...args: [true, number] | [false, string]) => void = (guard, value) => { +>fa3 : Symbol(fa3, Decl(dependentDestructuredVariables.ts, 355, 5)) +>args : Symbol(args, Decl(dependentDestructuredVariables.ts, 355, 12)) +>guard : Symbol(guard, Decl(dependentDestructuredVariables.ts, 355, 66)) +>value : Symbol(value, Decl(dependentDestructuredVariables.ts, 355, 72)) + + if (guard) { +>guard : Symbol(guard, Decl(dependentDestructuredVariables.ts, 355, 66)) + + for (;;) { + value; // number +>value : Symbol(value, Decl(dependentDestructuredVariables.ts, 355, 72)) + } + } + else { + while (!!true) { + value; // string +>value : Symbol(value, Decl(dependentDestructuredVariables.ts, 355, 72)) + } + } +} + diff --git a/tests/baselines/reference/dependentDestructuredVariables.types b/tests/baselines/reference/dependentDestructuredVariables.types index f3f90242313..01de281b3d9 100644 --- a/tests/baselines/reference/dependentDestructuredVariables.types +++ b/tests/baselines/reference/dependentDestructuredVariables.types @@ -955,3 +955,100 @@ function foo({ }) {} +// Repro from #49772 + +function fa1(x: [true, number] | [false, string]) { +>fa1 : (x: [true, number] | [false, string]) => void +>x : [true, number] | [false, string] +>true : true +>false : false + + const [guard, value] = x; +>guard : boolean +>value : string | number +>x : [true, number] | [false, string] + + if (guard) { +>guard : boolean + + for (;;) { + value; // number +>value : number + } + } + else { + while (!!true) { +>!!true : true +>!true : false +>true : true + + value; // string +>value : string + } + } +} + +function fa2(x: { guard: true, value: number } | { guard: false, value: string }) { +>fa2 : (x: { guard: true; value: number;} | { guard: false; value: string;}) => void +>x : { guard: true; value: number; } | { guard: false; value: string; } +>guard : true +>true : true +>value : number +>guard : false +>false : false +>value : string + + const { guard, value } = x; +>guard : boolean +>value : string | number +>x : { guard: true; value: number; } | { guard: false; value: string; } + + if (guard) { +>guard : boolean + + for (;;) { + value; // number +>value : number + } + } + else { + while (!!true) { +>!!true : true +>!true : false +>true : true + + value; // string +>value : string + } + } +} + +const fa3: (...args: [true, number] | [false, string]) => void = (guard, value) => { +>fa3 : (...args: [true, number] | [false, string]) => void +>args : [true, number] | [false, string] +>true : true +>false : false +>(guard, value) => { if (guard) { for (;;) { value; // number } } else { while (!!true) { value; // string } }} : (guard: boolean, value: string | number) => void +>guard : boolean +>value : string | number + + if (guard) { +>guard : boolean + + for (;;) { + value; // number +>value : number + } + } + else { + while (!!true) { +>!!true : true +>!true : false +>true : true + + value; // string +>value : string + } + } +} + diff --git a/tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts b/tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts index ae11c010fad..c25f3adf08b 100644 --- a/tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts +++ b/tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts @@ -327,3 +327,46 @@ function foo({ test8 = value1.test8, test9 = value1.test9 }) {} + +// Repro from #49772 + +function fa1(x: [true, number] | [false, string]) { + const [guard, value] = x; + if (guard) { + for (;;) { + value; // number + } + } + else { + while (!!true) { + value; // string + } + } +} + +function fa2(x: { guard: true, value: number } | { guard: false, value: string }) { + const { guard, value } = x; + if (guard) { + for (;;) { + value; // number + } + } + else { + while (!!true) { + value; // string + } + } +} + +const fa3: (...args: [true, number] | [false, string]) => void = (guard, value) => { + if (guard) { + for (;;) { + value; // number + } + } + else { + while (!!true) { + value; // string + } + } +}