From 26902dfcea6e46d61d907375aa225a0e8b0840ce Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 5 Jan 2023 16:54:30 -0800 Subject: [PATCH] Add tests --- .../coAndContraVariantInferences2.js | 140 +++++++ .../coAndContraVariantInferences2.symbols | 367 ++++++++++++++++++ .../coAndContraVariantInferences2.types | 263 +++++++++++++ .../compiler/coAndContraVariantInferences2.ts | 109 ++++++ 4 files changed, 879 insertions(+) create mode 100644 tests/baselines/reference/coAndContraVariantInferences2.js create mode 100644 tests/baselines/reference/coAndContraVariantInferences2.symbols create mode 100644 tests/baselines/reference/coAndContraVariantInferences2.types create mode 100644 tests/cases/compiler/coAndContraVariantInferences2.ts diff --git a/tests/baselines/reference/coAndContraVariantInferences2.js b/tests/baselines/reference/coAndContraVariantInferences2.js new file mode 100644 index 0000000000000..f2bb2a4374e23 --- /dev/null +++ b/tests/baselines/reference/coAndContraVariantInferences2.js @@ -0,0 +1,140 @@ +//// [coAndContraVariantInferences2.ts] +interface A { a: string } +interface B extends A { b: string } +interface C extends A { c: string } + +declare function cast(x: T, test: (x: T) => x is U): U; + +declare function isC(x: A): x is C; + +function f1(a: A, b: B) { + const x1 = cast(a, isC); // cast + const x2 = cast(b, isC); // cast +} + +declare function useA(a: A): void; + +declare function consume(t: T, u: U, f: (x: T) => void): void; + +function f2(b: B, c: C) { + consume(b, c, useA); // consume + consume(c, b, useA); // consume + consume(b, b, useA); // consume + consume(c, c, useA); // consume +} + +// Repro from #52111 + +enum SyntaxKind { + Block, + Identifier, + CaseClause, + FunctionExpression, + FunctionDeclaration, +} + +interface Node { kind: SyntaxKind; } +interface Expression extends Node { _expressionBrand: any; } +interface Declaration extends Node { _declarationBrand: any; } +interface Block extends Node { kind: SyntaxKind.Block; } +interface Identifier extends Expression, Declaration { kind: SyntaxKind.Identifier; } +interface CaseClause extends Node { kind: SyntaxKind.CaseClause; } +interface FunctionDeclaration extends Declaration { kind: SyntaxKind.FunctionDeclaration; } + +type HasLocals = Block | FunctionDeclaration; +declare function canHaveLocals(node: Node): node is HasLocals; + +declare function assertNode(node: T | undefined, test: (node: T) => node is U): asserts node is U; +declare function assertNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined): void; + +function foo(node: FunctionDeclaration | CaseClause) { + assertNode(node, canHaveLocals); // assertNode + node; // FunctionDeclaration +} + +declare function isExpression(node: Node): node is Expression; + +declare function tryCast(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut; + +function bar(node: Identifier | FunctionDeclaration) { + const a = tryCast(node, isExpression); // tryCast +} + +// Repro from #49924 + +const enum SyntaxKind1 { + ClassExpression, + ClassStatement, +} + +interface Node1 { + kind: SyntaxKind1; +} + +interface Statement1 extends Node1 { + _statementBrand: any; +} + +interface ClassExpression1 extends Node1 { + kind: SyntaxKind1.ClassExpression; +} + +interface ClassStatement1 extends Statement1 { + kind: SyntaxKind1.ClassStatement; +} + +type ClassLike1 = ClassExpression1 | ClassStatement1; + +declare function isClassLike(node: Node1): node is ClassLike1; + +declare const statement: Statement1 | undefined; + +const maybeClassStatement = tryCast(statement, isClassLike); // ClassLike1 + +// Repro from #49924 + +interface TypeNode extends Node { + typeInfo: string; +} + +interface NodeArray extends Array { + someProp: string; +} + +declare function isNodeArray(array: readonly T[]): array is NodeArray; + +declare const types: readonly TypeNode[]; + +const x = tryCast(types, isNodeArray); // NodeAray + + +//// [coAndContraVariantInferences2.js] +"use strict"; +function f1(a, b) { + var x1 = cast(a, isC); // cast + var x2 = cast(b, isC); // cast +} +function f2(b, c) { + consume(b, c, useA); // consume + consume(c, b, useA); // consume + consume(b, b, useA); // consume + consume(c, c, useA); // consume +} +// Repro from #52111 +var SyntaxKind; +(function (SyntaxKind) { + SyntaxKind[SyntaxKind["Block"] = 0] = "Block"; + SyntaxKind[SyntaxKind["Identifier"] = 1] = "Identifier"; + SyntaxKind[SyntaxKind["CaseClause"] = 2] = "CaseClause"; + SyntaxKind[SyntaxKind["FunctionExpression"] = 3] = "FunctionExpression"; + SyntaxKind[SyntaxKind["FunctionDeclaration"] = 4] = "FunctionDeclaration"; +})(SyntaxKind || (SyntaxKind = {})); +function foo(node) { + assertNode(node, canHaveLocals); // assertNode + node; // FunctionDeclaration +} +function bar(node) { + var a = tryCast(node, isExpression); // tryCast +} +var maybeClassStatement = tryCast(statement, isClassLike); // ClassLike1 +var x = tryCast(types, isNodeArray); // NodeAray diff --git a/tests/baselines/reference/coAndContraVariantInferences2.symbols b/tests/baselines/reference/coAndContraVariantInferences2.symbols new file mode 100644 index 0000000000000..b91904fca99ba --- /dev/null +++ b/tests/baselines/reference/coAndContraVariantInferences2.symbols @@ -0,0 +1,367 @@ +=== tests/cases/compiler/coAndContraVariantInferences2.ts === +interface A { a: string } +>A : Symbol(A, Decl(coAndContraVariantInferences2.ts, 0, 0)) +>a : Symbol(A.a, Decl(coAndContraVariantInferences2.ts, 0, 13)) + +interface B extends A { b: string } +>B : Symbol(B, Decl(coAndContraVariantInferences2.ts, 0, 25)) +>A : Symbol(A, Decl(coAndContraVariantInferences2.ts, 0, 0)) +>b : Symbol(B.b, Decl(coAndContraVariantInferences2.ts, 1, 23)) + +interface C extends A { c: string } +>C : Symbol(C, Decl(coAndContraVariantInferences2.ts, 1, 35)) +>A : Symbol(A, Decl(coAndContraVariantInferences2.ts, 0, 0)) +>c : Symbol(C.c, Decl(coAndContraVariantInferences2.ts, 2, 23)) + +declare function cast(x: T, test: (x: T) => x is U): U; +>cast : Symbol(cast, Decl(coAndContraVariantInferences2.ts, 2, 35)) +>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 4, 22)) +>U : Symbol(U, Decl(coAndContraVariantInferences2.ts, 4, 24)) +>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 4, 22)) +>x : Symbol(x, Decl(coAndContraVariantInferences2.ts, 4, 38)) +>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 4, 22)) +>test : Symbol(test, Decl(coAndContraVariantInferences2.ts, 4, 43)) +>x : Symbol(x, Decl(coAndContraVariantInferences2.ts, 4, 51)) +>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 4, 22)) +>x : Symbol(x, Decl(coAndContraVariantInferences2.ts, 4, 51)) +>U : Symbol(U, Decl(coAndContraVariantInferences2.ts, 4, 24)) +>U : Symbol(U, Decl(coAndContraVariantInferences2.ts, 4, 24)) + +declare function isC(x: A): x is C; +>isC : Symbol(isC, Decl(coAndContraVariantInferences2.ts, 4, 71)) +>x : Symbol(x, Decl(coAndContraVariantInferences2.ts, 6, 21)) +>A : Symbol(A, Decl(coAndContraVariantInferences2.ts, 0, 0)) +>x : Symbol(x, Decl(coAndContraVariantInferences2.ts, 6, 21)) +>C : Symbol(C, Decl(coAndContraVariantInferences2.ts, 1, 35)) + +function f1(a: A, b: B) { +>f1 : Symbol(f1, Decl(coAndContraVariantInferences2.ts, 6, 35)) +>a : Symbol(a, Decl(coAndContraVariantInferences2.ts, 8, 12)) +>A : Symbol(A, Decl(coAndContraVariantInferences2.ts, 0, 0)) +>b : Symbol(b, Decl(coAndContraVariantInferences2.ts, 8, 17)) +>B : Symbol(B, Decl(coAndContraVariantInferences2.ts, 0, 25)) + + const x1 = cast(a, isC); // cast +>x1 : Symbol(x1, Decl(coAndContraVariantInferences2.ts, 9, 9)) +>cast : Symbol(cast, Decl(coAndContraVariantInferences2.ts, 2, 35)) +>a : Symbol(a, Decl(coAndContraVariantInferences2.ts, 8, 12)) +>isC : Symbol(isC, Decl(coAndContraVariantInferences2.ts, 4, 71)) + + const x2 = cast(b, isC); // cast +>x2 : Symbol(x2, Decl(coAndContraVariantInferences2.ts, 10, 9)) +>cast : Symbol(cast, Decl(coAndContraVariantInferences2.ts, 2, 35)) +>b : Symbol(b, Decl(coAndContraVariantInferences2.ts, 8, 17)) +>isC : Symbol(isC, Decl(coAndContraVariantInferences2.ts, 4, 71)) +} + +declare function useA(a: A): void; +>useA : Symbol(useA, Decl(coAndContraVariantInferences2.ts, 11, 1)) +>a : Symbol(a, Decl(coAndContraVariantInferences2.ts, 13, 22)) +>A : Symbol(A, Decl(coAndContraVariantInferences2.ts, 0, 0)) + +declare function consume(t: T, u: U, f: (x: T) => void): void; +>consume : Symbol(consume, Decl(coAndContraVariantInferences2.ts, 13, 34)) +>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 15, 25)) +>U : Symbol(U, Decl(coAndContraVariantInferences2.ts, 15, 27)) +>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 15, 25)) +>t : Symbol(t, Decl(coAndContraVariantInferences2.ts, 15, 41)) +>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 15, 25)) +>u : Symbol(u, Decl(coAndContraVariantInferences2.ts, 15, 46)) +>U : Symbol(U, Decl(coAndContraVariantInferences2.ts, 15, 27)) +>f : Symbol(f, Decl(coAndContraVariantInferences2.ts, 15, 52)) +>x : Symbol(x, Decl(coAndContraVariantInferences2.ts, 15, 57)) +>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 15, 25)) + +function f2(b: B, c: C) { +>f2 : Symbol(f2, Decl(coAndContraVariantInferences2.ts, 15, 78)) +>b : Symbol(b, Decl(coAndContraVariantInferences2.ts, 17, 12)) +>B : Symbol(B, Decl(coAndContraVariantInferences2.ts, 0, 25)) +>c : Symbol(c, Decl(coAndContraVariantInferences2.ts, 17, 17)) +>C : Symbol(C, Decl(coAndContraVariantInferences2.ts, 1, 35)) + + consume(b, c, useA); // consume +>consume : Symbol(consume, Decl(coAndContraVariantInferences2.ts, 13, 34)) +>b : Symbol(b, Decl(coAndContraVariantInferences2.ts, 17, 12)) +>c : Symbol(c, Decl(coAndContraVariantInferences2.ts, 17, 17)) +>useA : Symbol(useA, Decl(coAndContraVariantInferences2.ts, 11, 1)) + + consume(c, b, useA); // consume +>consume : Symbol(consume, Decl(coAndContraVariantInferences2.ts, 13, 34)) +>c : Symbol(c, Decl(coAndContraVariantInferences2.ts, 17, 17)) +>b : Symbol(b, Decl(coAndContraVariantInferences2.ts, 17, 12)) +>useA : Symbol(useA, Decl(coAndContraVariantInferences2.ts, 11, 1)) + + consume(b, b, useA); // consume +>consume : Symbol(consume, Decl(coAndContraVariantInferences2.ts, 13, 34)) +>b : Symbol(b, Decl(coAndContraVariantInferences2.ts, 17, 12)) +>b : Symbol(b, Decl(coAndContraVariantInferences2.ts, 17, 12)) +>useA : Symbol(useA, Decl(coAndContraVariantInferences2.ts, 11, 1)) + + consume(c, c, useA); // consume +>consume : Symbol(consume, Decl(coAndContraVariantInferences2.ts, 13, 34)) +>c : Symbol(c, Decl(coAndContraVariantInferences2.ts, 17, 17)) +>c : Symbol(c, Decl(coAndContraVariantInferences2.ts, 17, 17)) +>useA : Symbol(useA, Decl(coAndContraVariantInferences2.ts, 11, 1)) +} + +// Repro from #52111 + +enum SyntaxKind { +>SyntaxKind : Symbol(SyntaxKind, Decl(coAndContraVariantInferences2.ts, 22, 1)) + + Block, +>Block : Symbol(SyntaxKind.Block, Decl(coAndContraVariantInferences2.ts, 26, 17)) + + Identifier, +>Identifier : Symbol(SyntaxKind.Identifier, Decl(coAndContraVariantInferences2.ts, 27, 10)) + + CaseClause, +>CaseClause : Symbol(SyntaxKind.CaseClause, Decl(coAndContraVariantInferences2.ts, 28, 15)) + + FunctionExpression, +>FunctionExpression : Symbol(SyntaxKind.FunctionExpression, Decl(coAndContraVariantInferences2.ts, 29, 15)) + + FunctionDeclaration, +>FunctionDeclaration : Symbol(SyntaxKind.FunctionDeclaration, Decl(coAndContraVariantInferences2.ts, 30, 23)) +} + +interface Node { kind: SyntaxKind; } +>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1)) +>kind : Symbol(Node.kind, Decl(coAndContraVariantInferences2.ts, 34, 16)) +>SyntaxKind : Symbol(SyntaxKind, Decl(coAndContraVariantInferences2.ts, 22, 1)) + +interface Expression extends Node { _expressionBrand: any; } +>Expression : Symbol(Expression, Decl(coAndContraVariantInferences2.ts, 34, 36)) +>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1)) +>_expressionBrand : Symbol(Expression._expressionBrand, Decl(coAndContraVariantInferences2.ts, 35, 35)) + +interface Declaration extends Node { _declarationBrand: any; } +>Declaration : Symbol(Declaration, Decl(coAndContraVariantInferences2.ts, 35, 60)) +>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1)) +>_declarationBrand : Symbol(Declaration._declarationBrand, Decl(coAndContraVariantInferences2.ts, 36, 36)) + +interface Block extends Node { kind: SyntaxKind.Block; } +>Block : Symbol(Block, Decl(coAndContraVariantInferences2.ts, 36, 62)) +>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1)) +>kind : Symbol(Block.kind, Decl(coAndContraVariantInferences2.ts, 37, 30)) +>SyntaxKind : Symbol(SyntaxKind, Decl(coAndContraVariantInferences2.ts, 22, 1)) +>Block : Symbol(SyntaxKind.Block, Decl(coAndContraVariantInferences2.ts, 26, 17)) + +interface Identifier extends Expression, Declaration { kind: SyntaxKind.Identifier; } +>Identifier : Symbol(Identifier, Decl(coAndContraVariantInferences2.ts, 37, 56)) +>Expression : Symbol(Expression, Decl(coAndContraVariantInferences2.ts, 34, 36)) +>Declaration : Symbol(Declaration, Decl(coAndContraVariantInferences2.ts, 35, 60)) +>kind : Symbol(Identifier.kind, Decl(coAndContraVariantInferences2.ts, 38, 54)) +>SyntaxKind : Symbol(SyntaxKind, Decl(coAndContraVariantInferences2.ts, 22, 1)) +>Identifier : Symbol(SyntaxKind.Identifier, Decl(coAndContraVariantInferences2.ts, 27, 10)) + +interface CaseClause extends Node { kind: SyntaxKind.CaseClause; } +>CaseClause : Symbol(CaseClause, Decl(coAndContraVariantInferences2.ts, 38, 85)) +>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1)) +>kind : Symbol(CaseClause.kind, Decl(coAndContraVariantInferences2.ts, 39, 35)) +>SyntaxKind : Symbol(SyntaxKind, Decl(coAndContraVariantInferences2.ts, 22, 1)) +>CaseClause : Symbol(SyntaxKind.CaseClause, Decl(coAndContraVariantInferences2.ts, 28, 15)) + +interface FunctionDeclaration extends Declaration { kind: SyntaxKind.FunctionDeclaration; } +>FunctionDeclaration : Symbol(FunctionDeclaration, Decl(coAndContraVariantInferences2.ts, 39, 66)) +>Declaration : Symbol(Declaration, Decl(coAndContraVariantInferences2.ts, 35, 60)) +>kind : Symbol(FunctionDeclaration.kind, Decl(coAndContraVariantInferences2.ts, 40, 51)) +>SyntaxKind : Symbol(SyntaxKind, Decl(coAndContraVariantInferences2.ts, 22, 1)) +>FunctionDeclaration : Symbol(SyntaxKind.FunctionDeclaration, Decl(coAndContraVariantInferences2.ts, 30, 23)) + +type HasLocals = Block | FunctionDeclaration; +>HasLocals : Symbol(HasLocals, Decl(coAndContraVariantInferences2.ts, 40, 91)) +>Block : Symbol(Block, Decl(coAndContraVariantInferences2.ts, 36, 62)) +>FunctionDeclaration : Symbol(FunctionDeclaration, Decl(coAndContraVariantInferences2.ts, 39, 66)) + +declare function canHaveLocals(node: Node): node is HasLocals; +>canHaveLocals : Symbol(canHaveLocals, Decl(coAndContraVariantInferences2.ts, 42, 45)) +>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 43, 31)) +>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1)) +>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 43, 31)) +>HasLocals : Symbol(HasLocals, Decl(coAndContraVariantInferences2.ts, 40, 91)) + +declare function assertNode(node: T | undefined, test: (node: T) => node is U): asserts node is U; +>assertNode : Symbol(assertNode, Decl(coAndContraVariantInferences2.ts, 43, 62), Decl(coAndContraVariantInferences2.ts, 45, 127)) +>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 45, 28)) +>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1)) +>U : Symbol(U, Decl(coAndContraVariantInferences2.ts, 45, 43)) +>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 45, 28)) +>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 45, 57)) +>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 45, 28)) +>test : Symbol(test, Decl(coAndContraVariantInferences2.ts, 45, 77)) +>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 45, 85)) +>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 45, 28)) +>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 45, 85)) +>U : Symbol(U, Decl(coAndContraVariantInferences2.ts, 45, 43)) +>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 45, 57)) +>U : Symbol(U, Decl(coAndContraVariantInferences2.ts, 45, 43)) + +declare function assertNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined): void; +>assertNode : Symbol(assertNode, Decl(coAndContraVariantInferences2.ts, 43, 62), Decl(coAndContraVariantInferences2.ts, 45, 127)) +>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 46, 28)) +>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1)) +>test : Symbol(test, Decl(coAndContraVariantInferences2.ts, 46, 51)) +>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 46, 60)) +>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1)) + +function foo(node: FunctionDeclaration | CaseClause) { +>foo : Symbol(foo, Decl(coAndContraVariantInferences2.ts, 46, 103)) +>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 48, 13)) +>FunctionDeclaration : Symbol(FunctionDeclaration, Decl(coAndContraVariantInferences2.ts, 39, 66)) +>CaseClause : Symbol(CaseClause, Decl(coAndContraVariantInferences2.ts, 38, 85)) + + assertNode(node, canHaveLocals); // assertNode +>assertNode : Symbol(assertNode, Decl(coAndContraVariantInferences2.ts, 43, 62), Decl(coAndContraVariantInferences2.ts, 45, 127)) +>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 48, 13)) +>canHaveLocals : Symbol(canHaveLocals, Decl(coAndContraVariantInferences2.ts, 42, 45)) + + node; // FunctionDeclaration +>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 48, 13)) +} + +declare function isExpression(node: Node): node is Expression; +>isExpression : Symbol(isExpression, Decl(coAndContraVariantInferences2.ts, 51, 1)) +>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 53, 30)) +>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1)) +>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 53, 30)) +>Expression : Symbol(Expression, Decl(coAndContraVariantInferences2.ts, 34, 36)) + +declare function tryCast(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut; +>tryCast : Symbol(tryCast, Decl(coAndContraVariantInferences2.ts, 53, 62)) +>TOut : Symbol(TOut, Decl(coAndContraVariantInferences2.ts, 55, 25)) +>TIn : Symbol(TIn, Decl(coAndContraVariantInferences2.ts, 55, 42)) +>TIn : Symbol(TIn, Decl(coAndContraVariantInferences2.ts, 55, 42)) +>value : Symbol(value, Decl(coAndContraVariantInferences2.ts, 55, 54)) +>TIn : Symbol(TIn, Decl(coAndContraVariantInferences2.ts, 55, 42)) +>test : Symbol(test, Decl(coAndContraVariantInferences2.ts, 55, 77)) +>value : Symbol(value, Decl(coAndContraVariantInferences2.ts, 55, 85)) +>TIn : Symbol(TIn, Decl(coAndContraVariantInferences2.ts, 55, 42)) +>value : Symbol(value, Decl(coAndContraVariantInferences2.ts, 55, 85)) +>TOut : Symbol(TOut, Decl(coAndContraVariantInferences2.ts, 55, 25)) +>TOut : Symbol(TOut, Decl(coAndContraVariantInferences2.ts, 55, 25)) + +function bar(node: Identifier | FunctionDeclaration) { +>bar : Symbol(bar, Decl(coAndContraVariantInferences2.ts, 55, 121)) +>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 57, 13)) +>Identifier : Symbol(Identifier, Decl(coAndContraVariantInferences2.ts, 37, 56)) +>FunctionDeclaration : Symbol(FunctionDeclaration, Decl(coAndContraVariantInferences2.ts, 39, 66)) + + const a = tryCast(node, isExpression); // tryCast +>a : Symbol(a, Decl(coAndContraVariantInferences2.ts, 58, 9)) +>tryCast : Symbol(tryCast, Decl(coAndContraVariantInferences2.ts, 53, 62)) +>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 57, 13)) +>isExpression : Symbol(isExpression, Decl(coAndContraVariantInferences2.ts, 51, 1)) +} + +// Repro from #49924 + +const enum SyntaxKind1 { +>SyntaxKind1 : Symbol(SyntaxKind1, Decl(coAndContraVariantInferences2.ts, 59, 1)) + + ClassExpression, +>ClassExpression : Symbol(SyntaxKind1.ClassExpression, Decl(coAndContraVariantInferences2.ts, 63, 24)) + + ClassStatement, +>ClassStatement : Symbol(SyntaxKind1.ClassStatement, Decl(coAndContraVariantInferences2.ts, 64, 20)) +} + +interface Node1 { +>Node1 : Symbol(Node1, Decl(coAndContraVariantInferences2.ts, 66, 1)) + + kind: SyntaxKind1; +>kind : Symbol(Node1.kind, Decl(coAndContraVariantInferences2.ts, 68, 17)) +>SyntaxKind1 : Symbol(SyntaxKind1, Decl(coAndContraVariantInferences2.ts, 59, 1)) +} + +interface Statement1 extends Node1 { +>Statement1 : Symbol(Statement1, Decl(coAndContraVariantInferences2.ts, 70, 1)) +>Node1 : Symbol(Node1, Decl(coAndContraVariantInferences2.ts, 66, 1)) + + _statementBrand: any; +>_statementBrand : Symbol(Statement1._statementBrand, Decl(coAndContraVariantInferences2.ts, 72, 36)) +} + +interface ClassExpression1 extends Node1 { +>ClassExpression1 : Symbol(ClassExpression1, Decl(coAndContraVariantInferences2.ts, 74, 1)) +>Node1 : Symbol(Node1, Decl(coAndContraVariantInferences2.ts, 66, 1)) + + kind: SyntaxKind1.ClassExpression; +>kind : Symbol(ClassExpression1.kind, Decl(coAndContraVariantInferences2.ts, 76, 42)) +>SyntaxKind1 : Symbol(SyntaxKind1, Decl(coAndContraVariantInferences2.ts, 59, 1)) +>ClassExpression : Symbol(SyntaxKind1.ClassExpression, Decl(coAndContraVariantInferences2.ts, 63, 24)) +} + +interface ClassStatement1 extends Statement1 { +>ClassStatement1 : Symbol(ClassStatement1, Decl(coAndContraVariantInferences2.ts, 78, 1)) +>Statement1 : Symbol(Statement1, Decl(coAndContraVariantInferences2.ts, 70, 1)) + + kind: SyntaxKind1.ClassStatement; +>kind : Symbol(ClassStatement1.kind, Decl(coAndContraVariantInferences2.ts, 80, 46)) +>SyntaxKind1 : Symbol(SyntaxKind1, Decl(coAndContraVariantInferences2.ts, 59, 1)) +>ClassStatement : Symbol(SyntaxKind1.ClassStatement, Decl(coAndContraVariantInferences2.ts, 64, 20)) +} + +type ClassLike1 = ClassExpression1 | ClassStatement1; +>ClassLike1 : Symbol(ClassLike1, Decl(coAndContraVariantInferences2.ts, 82, 1)) +>ClassExpression1 : Symbol(ClassExpression1, Decl(coAndContraVariantInferences2.ts, 74, 1)) +>ClassStatement1 : Symbol(ClassStatement1, Decl(coAndContraVariantInferences2.ts, 78, 1)) + +declare function isClassLike(node: Node1): node is ClassLike1; +>isClassLike : Symbol(isClassLike, Decl(coAndContraVariantInferences2.ts, 84, 53)) +>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 86, 29)) +>Node1 : Symbol(Node1, Decl(coAndContraVariantInferences2.ts, 66, 1)) +>node : Symbol(node, Decl(coAndContraVariantInferences2.ts, 86, 29)) +>ClassLike1 : Symbol(ClassLike1, Decl(coAndContraVariantInferences2.ts, 82, 1)) + +declare const statement: Statement1 | undefined; +>statement : Symbol(statement, Decl(coAndContraVariantInferences2.ts, 88, 13)) +>Statement1 : Symbol(Statement1, Decl(coAndContraVariantInferences2.ts, 70, 1)) + +const maybeClassStatement = tryCast(statement, isClassLike); // ClassLike1 +>maybeClassStatement : Symbol(maybeClassStatement, Decl(coAndContraVariantInferences2.ts, 90, 5)) +>tryCast : Symbol(tryCast, Decl(coAndContraVariantInferences2.ts, 53, 62)) +>statement : Symbol(statement, Decl(coAndContraVariantInferences2.ts, 88, 13)) +>isClassLike : Symbol(isClassLike, Decl(coAndContraVariantInferences2.ts, 84, 53)) + +// Repro from #49924 + +interface TypeNode extends Node { +>TypeNode : Symbol(TypeNode, Decl(coAndContraVariantInferences2.ts, 90, 60)) +>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1)) + + typeInfo: string; +>typeInfo : Symbol(TypeNode.typeInfo, Decl(coAndContraVariantInferences2.ts, 94, 33)) +} + +interface NodeArray extends Array { +>NodeArray : Symbol(NodeArray, Decl(coAndContraVariantInferences2.ts, 96, 1)) +>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 98, 20)) +>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 98, 20)) + + someProp: string; +>someProp : Symbol(NodeArray.someProp, Decl(coAndContraVariantInferences2.ts, 98, 54)) +} + +declare function isNodeArray(array: readonly T[]): array is NodeArray; +>isNodeArray : Symbol(isNodeArray, Decl(coAndContraVariantInferences2.ts, 100, 1)) +>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 102, 29)) +>Node : Symbol(Node, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(coAndContraVariantInferences2.ts, 32, 1)) +>array : Symbol(array, Decl(coAndContraVariantInferences2.ts, 102, 45)) +>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 102, 29)) +>array : Symbol(array, Decl(coAndContraVariantInferences2.ts, 102, 45)) +>NodeArray : Symbol(NodeArray, Decl(coAndContraVariantInferences2.ts, 96, 1)) +>T : Symbol(T, Decl(coAndContraVariantInferences2.ts, 102, 29)) + +declare const types: readonly TypeNode[]; +>types : Symbol(types, Decl(coAndContraVariantInferences2.ts, 104, 13)) +>TypeNode : Symbol(TypeNode, Decl(coAndContraVariantInferences2.ts, 90, 60)) + +const x = tryCast(types, isNodeArray); // NodeAray +>x : Symbol(x, Decl(coAndContraVariantInferences2.ts, 106, 5)) +>tryCast : Symbol(tryCast, Decl(coAndContraVariantInferences2.ts, 53, 62)) +>types : Symbol(types, Decl(coAndContraVariantInferences2.ts, 104, 13)) +>isNodeArray : Symbol(isNodeArray, Decl(coAndContraVariantInferences2.ts, 100, 1)) + diff --git a/tests/baselines/reference/coAndContraVariantInferences2.types b/tests/baselines/reference/coAndContraVariantInferences2.types new file mode 100644 index 0000000000000..1e332d285b412 --- /dev/null +++ b/tests/baselines/reference/coAndContraVariantInferences2.types @@ -0,0 +1,263 @@ +=== tests/cases/compiler/coAndContraVariantInferences2.ts === +interface A { a: string } +>a : string + +interface B extends A { b: string } +>b : string + +interface C extends A { c: string } +>c : string + +declare function cast(x: T, test: (x: T) => x is U): U; +>cast : (x: T, test: (x: T) => x is U) => U +>x : T +>test : (x: T) => x is U +>x : T + +declare function isC(x: A): x is C; +>isC : (x: A) => x is C +>x : A + +function f1(a: A, b: B) { +>f1 : (a: A, b: B) => void +>a : A +>b : B + + const x1 = cast(a, isC); // cast +>x1 : C +>cast(a, isC) : C +>cast : (x: T, test: (x: T) => x is U) => U +>a : A +>isC : (x: A) => x is C + + const x2 = cast(b, isC); // cast +>x2 : C +>cast(b, isC) : C +>cast : (x: T, test: (x: T) => x is U) => U +>b : B +>isC : (x: A) => x is C +} + +declare function useA(a: A): void; +>useA : (a: A) => void +>a : A + +declare function consume(t: T, u: U, f: (x: T) => void): void; +>consume : (t: T, u: U, f: (x: T) => void) => void +>t : T +>u : U +>f : (x: T) => void +>x : T + +function f2(b: B, c: C) { +>f2 : (b: B, c: C) => void +>b : B +>c : C + + consume(b, c, useA); // consume +>consume(b, c, useA) : void +>consume : (t: T, u: U, f: (x: T) => void) => void +>b : B +>c : C +>useA : (a: A) => void + + consume(c, b, useA); // consume +>consume(c, b, useA) : void +>consume : (t: T, u: U, f: (x: T) => void) => void +>c : C +>b : B +>useA : (a: A) => void + + consume(b, b, useA); // consume +>consume(b, b, useA) : void +>consume : (t: T, u: U, f: (x: T) => void) => void +>b : B +>b : B +>useA : (a: A) => void + + consume(c, c, useA); // consume +>consume(c, c, useA) : void +>consume : (t: T, u: U, f: (x: T) => void) => void +>c : C +>c : C +>useA : (a: A) => void +} + +// Repro from #52111 + +enum SyntaxKind { +>SyntaxKind : SyntaxKind + + Block, +>Block : SyntaxKind.Block + + Identifier, +>Identifier : SyntaxKind.Identifier + + CaseClause, +>CaseClause : SyntaxKind.CaseClause + + FunctionExpression, +>FunctionExpression : SyntaxKind.FunctionExpression + + FunctionDeclaration, +>FunctionDeclaration : SyntaxKind.FunctionDeclaration +} + +interface Node { kind: SyntaxKind; } +>kind : SyntaxKind + +interface Expression extends Node { _expressionBrand: any; } +>_expressionBrand : any + +interface Declaration extends Node { _declarationBrand: any; } +>_declarationBrand : any + +interface Block extends Node { kind: SyntaxKind.Block; } +>kind : SyntaxKind.Block +>SyntaxKind : any + +interface Identifier extends Expression, Declaration { kind: SyntaxKind.Identifier; } +>kind : SyntaxKind.Identifier +>SyntaxKind : any + +interface CaseClause extends Node { kind: SyntaxKind.CaseClause; } +>kind : SyntaxKind.CaseClause +>SyntaxKind : any + +interface FunctionDeclaration extends Declaration { kind: SyntaxKind.FunctionDeclaration; } +>kind : SyntaxKind.FunctionDeclaration +>SyntaxKind : any + +type HasLocals = Block | FunctionDeclaration; +>HasLocals : Block | FunctionDeclaration + +declare function canHaveLocals(node: Node): node is HasLocals; +>canHaveLocals : (node: Node) => node is HasLocals +>node : Node + +declare function assertNode(node: T | undefined, test: (node: T) => node is U): asserts node is U; +>assertNode : { (node: T | undefined, test: (node: T) => node is U): asserts node is U; (node: Node | undefined, test: ((node: Node) => boolean) | undefined): void; } +>node : T | undefined +>test : (node: T) => node is U +>node : T + +declare function assertNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined): void; +>assertNode : { (node: T | undefined, test: (node: T) => node is U): asserts node is U; (node: Node | undefined, test: ((node: Node) => boolean) | undefined): void; } +>node : Node | undefined +>test : ((node: Node) => boolean) | undefined +>node : Node + +function foo(node: FunctionDeclaration | CaseClause) { +>foo : (node: FunctionDeclaration | CaseClause) => void +>node : CaseClause | FunctionDeclaration + + assertNode(node, canHaveLocals); // assertNode +>assertNode(node, canHaveLocals) : void +>assertNode : { (node: T | undefined, test: (node: T) => node is U): asserts node is U; (node: Node | undefined, test: ((node: Node) => boolean) | undefined): void; } +>node : CaseClause | FunctionDeclaration +>canHaveLocals : (node: Node) => node is HasLocals + + node; // FunctionDeclaration +>node : FunctionDeclaration +} + +declare function isExpression(node: Node): node is Expression; +>isExpression : (node: Node) => node is Expression +>node : Node + +declare function tryCast(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut; +>tryCast : (value: TIn | undefined, test: (value: TIn) => value is TOut) => TOut +>value : TIn | undefined +>test : (value: TIn) => value is TOut +>value : TIn + +function bar(node: Identifier | FunctionDeclaration) { +>bar : (node: Identifier | FunctionDeclaration) => void +>node : Identifier | FunctionDeclaration + + const a = tryCast(node, isExpression); // tryCast +>a : Expression +>tryCast(node, isExpression) : Expression +>tryCast : (value: TIn | undefined, test: (value: TIn) => value is TOut) => TOut +>node : Identifier | FunctionDeclaration +>isExpression : (node: Node) => node is Expression +} + +// Repro from #49924 + +const enum SyntaxKind1 { +>SyntaxKind1 : SyntaxKind1 + + ClassExpression, +>ClassExpression : SyntaxKind1.ClassExpression + + ClassStatement, +>ClassStatement : SyntaxKind1.ClassStatement +} + +interface Node1 { + kind: SyntaxKind1; +>kind : SyntaxKind1 +} + +interface Statement1 extends Node1 { + _statementBrand: any; +>_statementBrand : any +} + +interface ClassExpression1 extends Node1 { + kind: SyntaxKind1.ClassExpression; +>kind : SyntaxKind1.ClassExpression +>SyntaxKind1 : any +} + +interface ClassStatement1 extends Statement1 { + kind: SyntaxKind1.ClassStatement; +>kind : SyntaxKind1.ClassStatement +>SyntaxKind1 : any +} + +type ClassLike1 = ClassExpression1 | ClassStatement1; +>ClassLike1 : ClassExpression1 | ClassStatement1 + +declare function isClassLike(node: Node1): node is ClassLike1; +>isClassLike : (node: Node1) => node is ClassLike1 +>node : Node1 + +declare const statement: Statement1 | undefined; +>statement : Statement1 | undefined + +const maybeClassStatement = tryCast(statement, isClassLike); // ClassLike1 +>maybeClassStatement : ClassLike1 +>tryCast(statement, isClassLike) : ClassLike1 +>tryCast : (value: TIn | undefined, test: (value: TIn) => value is TOut) => TOut +>statement : Statement1 | undefined +>isClassLike : (node: Node1) => node is ClassLike1 + +// Repro from #49924 + +interface TypeNode extends Node { + typeInfo: string; +>typeInfo : string +} + +interface NodeArray extends Array { + someProp: string; +>someProp : string +} + +declare function isNodeArray(array: readonly T[]): array is NodeArray; +>isNodeArray : (array: readonly T[]) => array is NodeArray +>array : readonly T[] + +declare const types: readonly TypeNode[]; +>types : readonly TypeNode[] + +const x = tryCast(types, isNodeArray); // NodeAray +>x : NodeArray +>tryCast(types, isNodeArray) : NodeArray +>tryCast : (value: TIn | undefined, test: (value: TIn) => value is TOut) => TOut +>types : readonly TypeNode[] +>isNodeArray : (array: readonly T[]) => array is NodeArray + diff --git a/tests/cases/compiler/coAndContraVariantInferences2.ts b/tests/cases/compiler/coAndContraVariantInferences2.ts new file mode 100644 index 0000000000000..d7d486442cbc1 --- /dev/null +++ b/tests/cases/compiler/coAndContraVariantInferences2.ts @@ -0,0 +1,109 @@ +// @strict: true + +interface A { a: string } +interface B extends A { b: string } +interface C extends A { c: string } + +declare function cast(x: T, test: (x: T) => x is U): U; + +declare function isC(x: A): x is C; + +function f1(a: A, b: B) { + const x1 = cast(a, isC); // cast + const x2 = cast(b, isC); // cast +} + +declare function useA(a: A): void; + +declare function consume(t: T, u: U, f: (x: T) => void): void; + +function f2(b: B, c: C) { + consume(b, c, useA); // consume + consume(c, b, useA); // consume + consume(b, b, useA); // consume + consume(c, c, useA); // consume +} + +// Repro from #52111 + +enum SyntaxKind { + Block, + Identifier, + CaseClause, + FunctionExpression, + FunctionDeclaration, +} + +interface Node { kind: SyntaxKind; } +interface Expression extends Node { _expressionBrand: any; } +interface Declaration extends Node { _declarationBrand: any; } +interface Block extends Node { kind: SyntaxKind.Block; } +interface Identifier extends Expression, Declaration { kind: SyntaxKind.Identifier; } +interface CaseClause extends Node { kind: SyntaxKind.CaseClause; } +interface FunctionDeclaration extends Declaration { kind: SyntaxKind.FunctionDeclaration; } + +type HasLocals = Block | FunctionDeclaration; +declare function canHaveLocals(node: Node): node is HasLocals; + +declare function assertNode(node: T | undefined, test: (node: T) => node is U): asserts node is U; +declare function assertNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined): void; + +function foo(node: FunctionDeclaration | CaseClause) { + assertNode(node, canHaveLocals); // assertNode + node; // FunctionDeclaration +} + +declare function isExpression(node: Node): node is Expression; + +declare function tryCast(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut; + +function bar(node: Identifier | FunctionDeclaration) { + const a = tryCast(node, isExpression); // tryCast +} + +// Repro from #49924 + +const enum SyntaxKind1 { + ClassExpression, + ClassStatement, +} + +interface Node1 { + kind: SyntaxKind1; +} + +interface Statement1 extends Node1 { + _statementBrand: any; +} + +interface ClassExpression1 extends Node1 { + kind: SyntaxKind1.ClassExpression; +} + +interface ClassStatement1 extends Statement1 { + kind: SyntaxKind1.ClassStatement; +} + +type ClassLike1 = ClassExpression1 | ClassStatement1; + +declare function isClassLike(node: Node1): node is ClassLike1; + +declare const statement: Statement1 | undefined; + +const maybeClassStatement = tryCast(statement, isClassLike); // ClassLike1 + +// Repro from #49924 + +interface TypeNode extends Node { + typeInfo: string; +} + +interface NodeArray extends Array { + someProp: string; +} + +declare function isNodeArray(array: readonly T[]): array is NodeArray; + +declare const types: readonly TypeNode[]; + +const x = tryCast(types, isNodeArray); // NodeAray