From 67b3fe58fa9b0761da93d9ea6ab2e8019b6a4b22 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 7 Aug 2016 08:53:36 -0700 Subject: [PATCH] Add regression test --- .../reference/controlFlowInstanceof.js | 156 +++++++++++++ .../reference/controlFlowInstanceof.symbols | 194 ++++++++++++++++ .../reference/controlFlowInstanceof.types | 217 ++++++++++++++++++ tests/cases/compiler/controlFlowInstanceof.ts | 80 +++++++ 4 files changed, 647 insertions(+) create mode 100644 tests/baselines/reference/controlFlowInstanceof.js create mode 100644 tests/baselines/reference/controlFlowInstanceof.symbols create mode 100644 tests/baselines/reference/controlFlowInstanceof.types create mode 100644 tests/cases/compiler/controlFlowInstanceof.ts diff --git a/tests/baselines/reference/controlFlowInstanceof.js b/tests/baselines/reference/controlFlowInstanceof.js new file mode 100644 index 00000000000..7c7833927ca --- /dev/null +++ b/tests/baselines/reference/controlFlowInstanceof.js @@ -0,0 +1,156 @@ +//// [controlFlowInstanceof.ts] + +// Repros from #10167 + +function f1(s: Set | Set) { + s = new Set(); + s; // Set + if (s instanceof Set) { + s; // Set + } + s; // Set + s.add(42); +} + +function f2(s: Set | Set) { + s = new Set(); + s; // Set + if (s instanceof Promise) { + s; // Set & Promise + } + s; // Set + s.add(42); +} + +function f3(s: Set | Set) { + s; // Set | Set + if (s instanceof Set) { + s; // Set | Set + } + else { + s; // never + } +} + +function f4(s: Set | Set) { + s = new Set(); + s; // Set + if (s instanceof Set) { + s; // Set + } + else { + s; // never + } +} + +// More tests + +class A { a: string } +class B extends A { b: string } +class C extends A { c: string } + +function foo(x: A | undefined) { + x; // A | undefined + if (x instanceof B || x instanceof C) { + x; // B | C + } + x; // A | undefined + if (x instanceof B && x instanceof C) { + x; // B & C + } + x; // A | undefined + if (!x) { + return; + } + x; // A + if (x instanceof B) { + x; // B + if (x instanceof C) { + x; // B & C + } + else { + x; // B + } + x; // B + } + else { + x; // A + } + x; // A +} + +//// [controlFlowInstanceof.js] +// Repros from #10167 +function f1(s) { + s = new Set(); + s; // Set + if (s instanceof Set) { + s; // Set + } + s; // Set + s.add(42); +} +function f2(s) { + s = new Set(); + s; // Set + if (s instanceof Promise) { + s; // Set & Promise + } + s; // Set + s.add(42); +} +function f3(s) { + s; // Set | Set + if (s instanceof Set) { + s; // Set | Set + } + else { + s; // never + } +} +function f4(s) { + s = new Set(); + s; // Set + if (s instanceof Set) { + s; // Set + } + else { + s; // never + } +} +// More tests +class A { +} +class B extends A { +} +class C extends A { +} +function foo(x) { + x; // A | undefined + if (x instanceof B || x instanceof C) { + x; // B | C + } + x; // A | undefined + if (x instanceof B && x instanceof C) { + x; // B & C + } + x; // A | undefined + if (!x) { + return; + } + x; // A + if (x instanceof B) { + x; // B + if (x instanceof C) { + x; // B & C + } + else { + x; // B + } + x; // B + } + else { + x; // A + } + x; // A +} diff --git a/tests/baselines/reference/controlFlowInstanceof.symbols b/tests/baselines/reference/controlFlowInstanceof.symbols new file mode 100644 index 00000000000..64b567c1548 --- /dev/null +++ b/tests/baselines/reference/controlFlowInstanceof.symbols @@ -0,0 +1,194 @@ +=== tests/cases/compiler/controlFlowInstanceof.ts === + +// Repros from #10167 + +function f1(s: Set | Set) { +>f1 : Symbol(f1, Decl(controlFlowInstanceof.ts, 0, 0)) +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 3, 12)) +>Set : Symbol(Set, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --)) +>Set : Symbol(Set, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --)) + + s = new Set(); +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 3, 12)) +>Set : Symbol(Set, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --)) + + s; // Set +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 3, 12)) + + if (s instanceof Set) { +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 3, 12)) +>Set : Symbol(Set, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --)) + + s; // Set +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 3, 12)) + } + s; // Set +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 3, 12)) + + s.add(42); +>s.add : Symbol(Set.add, Decl(lib.es2015.collection.d.ts, --, --)) +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 3, 12)) +>add : Symbol(Set.add, Decl(lib.es2015.collection.d.ts, --, --)) +} + +function f2(s: Set | Set) { +>f2 : Symbol(f2, Decl(controlFlowInstanceof.ts, 11, 1)) +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 13, 12)) +>Set : Symbol(Set, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --)) +>Set : Symbol(Set, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --)) + + s = new Set(); +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 13, 12)) +>Set : Symbol(Set, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --)) + + s; // Set +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 13, 12)) + + if (s instanceof Promise) { +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 13, 12)) +>Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --)) + + s; // Set & Promise +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 13, 12)) + } + s; // Set +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 13, 12)) + + s.add(42); +>s.add : Symbol(Set.add, Decl(lib.es2015.collection.d.ts, --, --)) +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 13, 12)) +>add : Symbol(Set.add, Decl(lib.es2015.collection.d.ts, --, --)) +} + +function f3(s: Set | Set) { +>f3 : Symbol(f3, Decl(controlFlowInstanceof.ts, 21, 1)) +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 23, 12)) +>Set : Symbol(Set, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --)) +>Set : Symbol(Set, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --)) + + s; // Set | Set +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 23, 12)) + + if (s instanceof Set) { +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 23, 12)) +>Set : Symbol(Set, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --)) + + s; // Set | Set +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 23, 12)) + } + else { + s; // never +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 23, 12)) + } +} + +function f4(s: Set | Set) { +>f4 : Symbol(f4, Decl(controlFlowInstanceof.ts, 31, 1)) +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 33, 12)) +>Set : Symbol(Set, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --)) +>Set : Symbol(Set, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --)) + + s = new Set(); +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 33, 12)) +>Set : Symbol(Set, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --)) + + s; // Set +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 33, 12)) + + if (s instanceof Set) { +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 33, 12)) +>Set : Symbol(Set, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --)) + + s; // Set +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 33, 12)) + } + else { + s; // never +>s : Symbol(s, Decl(controlFlowInstanceof.ts, 33, 12)) + } +} + +// More tests + +class A { a: string } +>A : Symbol(A, Decl(controlFlowInstanceof.ts, 42, 1)) +>a : Symbol(A.a, Decl(controlFlowInstanceof.ts, 46, 9)) + +class B extends A { b: string } +>B : Symbol(B, Decl(controlFlowInstanceof.ts, 46, 21)) +>A : Symbol(A, Decl(controlFlowInstanceof.ts, 42, 1)) +>b : Symbol(B.b, Decl(controlFlowInstanceof.ts, 47, 19)) + +class C extends A { c: string } +>C : Symbol(C, Decl(controlFlowInstanceof.ts, 47, 31)) +>A : Symbol(A, Decl(controlFlowInstanceof.ts, 42, 1)) +>c : Symbol(C.c, Decl(controlFlowInstanceof.ts, 48, 19)) + +function foo(x: A | undefined) { +>foo : Symbol(foo, Decl(controlFlowInstanceof.ts, 48, 31)) +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) +>A : Symbol(A, Decl(controlFlowInstanceof.ts, 42, 1)) + + x; // A | undefined +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) + + if (x instanceof B || x instanceof C) { +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) +>B : Symbol(B, Decl(controlFlowInstanceof.ts, 46, 21)) +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) +>C : Symbol(C, Decl(controlFlowInstanceof.ts, 47, 31)) + + x; // B | C +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) + } + x; // A | undefined +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) + + if (x instanceof B && x instanceof C) { +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) +>B : Symbol(B, Decl(controlFlowInstanceof.ts, 46, 21)) +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) +>C : Symbol(C, Decl(controlFlowInstanceof.ts, 47, 31)) + + x; // B & C +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) + } + x; // A | undefined +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) + + if (!x) { +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) + + return; + } + x; // A +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) + + if (x instanceof B) { +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) +>B : Symbol(B, Decl(controlFlowInstanceof.ts, 46, 21)) + + x; // B +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) + + if (x instanceof C) { +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) +>C : Symbol(C, Decl(controlFlowInstanceof.ts, 47, 31)) + + x; // B & C +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) + } + else { + x; // B +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) + } + x; // B +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) + } + else { + x; // A +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) + } + x; // A +>x : Symbol(x, Decl(controlFlowInstanceof.ts, 50, 13)) +} diff --git a/tests/baselines/reference/controlFlowInstanceof.types b/tests/baselines/reference/controlFlowInstanceof.types new file mode 100644 index 00000000000..362715914f9 --- /dev/null +++ b/tests/baselines/reference/controlFlowInstanceof.types @@ -0,0 +1,217 @@ +=== tests/cases/compiler/controlFlowInstanceof.ts === + +// Repros from #10167 + +function f1(s: Set | Set) { +>f1 : (s: Set | Set) => void +>s : Set | Set +>Set : Set +>Set : Set + + s = new Set(); +>s = new Set() : Set +>s : Set | Set +>new Set() : Set +>Set : SetConstructor + + s; // Set +>s : Set + + if (s instanceof Set) { +>s instanceof Set : boolean +>s : Set +>Set : SetConstructor + + s; // Set +>s : Set + } + s; // Set +>s : Set + + s.add(42); +>s.add(42) : Set +>s.add : (value: number) => Set +>s : Set +>add : (value: number) => Set +>42 : number +} + +function f2(s: Set | Set) { +>f2 : (s: Set | Set) => void +>s : Set | Set +>Set : Set +>Set : Set + + s = new Set(); +>s = new Set() : Set +>s : Set | Set +>new Set() : Set +>Set : SetConstructor + + s; // Set +>s : Set + + if (s instanceof Promise) { +>s instanceof Promise : boolean +>s : Set +>Promise : PromiseConstructor + + s; // Set & Promise +>s : Set & Promise + } + s; // Set +>s : Set + + s.add(42); +>s.add(42) : Set +>s.add : (value: number) => Set +>s : Set +>add : (value: number) => Set +>42 : number +} + +function f3(s: Set | Set) { +>f3 : (s: Set | Set) => void +>s : Set | Set +>Set : Set +>Set : Set + + s; // Set | Set +>s : Set | Set + + if (s instanceof Set) { +>s instanceof Set : boolean +>s : Set | Set +>Set : SetConstructor + + s; // Set | Set +>s : Set | Set + } + else { + s; // never +>s : never + } +} + +function f4(s: Set | Set) { +>f4 : (s: Set | Set) => void +>s : Set | Set +>Set : Set +>Set : Set + + s = new Set(); +>s = new Set() : Set +>s : Set | Set +>new Set() : Set +>Set : SetConstructor + + s; // Set +>s : Set + + if (s instanceof Set) { +>s instanceof Set : boolean +>s : Set +>Set : SetConstructor + + s; // Set +>s : Set + } + else { + s; // never +>s : never + } +} + +// More tests + +class A { a: string } +>A : A +>a : string + +class B extends A { b: string } +>B : B +>A : A +>b : string + +class C extends A { c: string } +>C : C +>A : A +>c : string + +function foo(x: A | undefined) { +>foo : (x: A) => void +>x : A +>A : A + + x; // A | undefined +>x : A + + if (x instanceof B || x instanceof C) { +>x instanceof B || x instanceof C : boolean +>x instanceof B : boolean +>x : A +>B : typeof B +>x instanceof C : boolean +>x : A +>C : typeof C + + x; // B | C +>x : B | C + } + x; // A | undefined +>x : A + + if (x instanceof B && x instanceof C) { +>x instanceof B && x instanceof C : boolean +>x instanceof B : boolean +>x : A +>B : typeof B +>x instanceof C : boolean +>x : B +>C : typeof C + + x; // B & C +>x : B & C + } + x; // A | undefined +>x : A + + if (!x) { +>!x : boolean +>x : A + + return; + } + x; // A +>x : A + + if (x instanceof B) { +>x instanceof B : boolean +>x : A +>B : typeof B + + x; // B +>x : B + + if (x instanceof C) { +>x instanceof C : boolean +>x : B +>C : typeof C + + x; // B & C +>x : B & C + } + else { + x; // B +>x : B + } + x; // B +>x : B + } + else { + x; // A +>x : A + } + x; // A +>x : A +} diff --git a/tests/cases/compiler/controlFlowInstanceof.ts b/tests/cases/compiler/controlFlowInstanceof.ts new file mode 100644 index 00000000000..229a00236ba --- /dev/null +++ b/tests/cases/compiler/controlFlowInstanceof.ts @@ -0,0 +1,80 @@ +// @target: es6 + +// Repros from #10167 + +function f1(s: Set | Set) { + s = new Set(); + s; // Set + if (s instanceof Set) { + s; // Set + } + s; // Set + s.add(42); +} + +function f2(s: Set | Set) { + s = new Set(); + s; // Set + if (s instanceof Promise) { + s; // Set & Promise + } + s; // Set + s.add(42); +} + +function f3(s: Set | Set) { + s; // Set | Set + if (s instanceof Set) { + s; // Set | Set + } + else { + s; // never + } +} + +function f4(s: Set | Set) { + s = new Set(); + s; // Set + if (s instanceof Set) { + s; // Set + } + else { + s; // never + } +} + +// More tests + +class A { a: string } +class B extends A { b: string } +class C extends A { c: string } + +function foo(x: A | undefined) { + x; // A | undefined + if (x instanceof B || x instanceof C) { + x; // B | C + } + x; // A | undefined + if (x instanceof B && x instanceof C) { + x; // B & C + } + x; // A | undefined + if (!x) { + return; + } + x; // A + if (x instanceof B) { + x; // B + if (x instanceof C) { + x; // B & C + } + else { + x; // B + } + x; // B + } + else { + x; // A + } + x; // A +} \ No newline at end of file