Skip to content

Sort unions without using type IDs #61399

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
392 changes: 386 additions & 6 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions src/compiler/core.ts
Original file line number Diff line number Diff line change
@@ -1209,7 +1209,7 @@ export function binarySearchKey<T, U>(array: readonly T[], key: U, keySelector:
while (low <= high) {
const middle = low + ((high - low) >> 1);
const midKey = keySelector(array[middle], middle);
switch (keyComparer(midKey, key)) {
switch (Math.sign(keyComparer(midKey, key))) {
case Comparison.LessThan:
low = middle + 1;
break;
@@ -1967,9 +1967,11 @@ export function equateStringsCaseSensitive(a: string, b: string): boolean {
return equateValues(a, b);
}

function compareComparableValues(a: string | undefined, b: string | undefined): Comparison;
function compareComparableValues(a: number | undefined, b: number | undefined): Comparison;
function compareComparableValues(a: string | number | undefined, b: string | number | undefined) {
/** @internal */
export function compareComparableValues(a: string | undefined, b: string | undefined): Comparison;
/** @internal */
export function compareComparableValues(a: number | undefined, b: number | undefined): Comparison;
export function compareComparableValues(a: string | number | undefined, b: string | number | undefined) {
return a === b ? Comparison.EqualTo :
a === undefined ? Comparison.LessThan :
b === undefined ? Comparison.GreaterThan :
40 changes: 21 additions & 19 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
@@ -6269,21 +6269,21 @@ export interface SerializedTypeEntry {
export const enum TypeFlags {
Any = 1 << 0,
Unknown = 1 << 1,
String = 1 << 2,
Number = 1 << 3,
Boolean = 1 << 4,
Enum = 1 << 5, // Numeric computed enum member value
BigInt = 1 << 6,
StringLiteral = 1 << 7,
NumberLiteral = 1 << 8,
BooleanLiteral = 1 << 9,
EnumLiteral = 1 << 10, // Always combined with StringLiteral, NumberLiteral, or Union
BigIntLiteral = 1 << 11,
ESSymbol = 1 << 12, // Type of symbol primitive introduced in ES6
UniqueESSymbol = 1 << 13, // unique symbol
Void = 1 << 14,
Undefined = 1 << 15,
Null = 1 << 16,
Undefined = 1 << 2,
Null = 1 << 3,
Void = 1 << 4,
String = 1 << 5,
Number = 1 << 6,
BigInt = 1 << 7,
Boolean = 1 << 8,
ESSymbol = 1 << 9, // Type of symbol primitive introduced in ES6
StringLiteral = 1 << 10,
NumberLiteral = 1 << 11,
BooleanLiteral = 1 << 12,
BigIntLiteral = 1 << 13,
UniqueESSymbol = 1 << 14, // unique symbol
EnumLiteral = 1 << 15, // Always combined with StringLiteral, NumberLiteral, or Union
Enum = 1 << 16, // Numeric computed enum member value
Never = 1 << 17, // Never type
TypeParameter = 1 << 18, // Type parameter
Object = 1 << 19, // Object type
@@ -6484,15 +6484,17 @@ export const enum ObjectFlags {
PropagatingFlags = ContainsWideningType | ContainsObjectOrArrayLiteral | NonInferrableType,
/** @internal */
InstantiatedMapped = Mapped | Instantiated,
// Object flags that uniquely identify the kind of ObjectType
/** @internal */
ObjectTypeKindMask = ClassOrInterface | Reference | Tuple | Anonymous | Mapped | ReverseMapped | EvolvingArray,


// Flags that require TypeFlags.Object
ContainsSpread = 1 << 21, // Object literal contains spread operation
ObjectRestType = 1 << 22, // Originates in object rest declaration
InstantiationExpressionType = 1 << 23, // Originates in instantiation expression
SingleSignatureType = 1 << 27, // A single signature type extracted from a potentially broader type

// Object flags that uniquely identify the kind of ObjectType
/** @internal */
ObjectTypeKindMask = ClassOrInterface | Reference | Tuple | Anonymous | Mapped | ReverseMapped | EvolvingArray | InstantiationExpressionType | SingleSignatureType,

/** @internal */
IsClassInstanceClone = 1 << 24, // Type is a clone of a class instance type
// Flags that require TypeFlags.Object and ObjectFlags.Reference
4 changes: 2 additions & 2 deletions tests/baselines/reference/TypeGuardWithArrayUnion.types
Original file line number Diff line number Diff line change
@@ -13,13 +13,13 @@ class Message {
function saySize(message: Message | Message[]) {
>saySize : (message: Message | Message[]) => number
> : ^ ^^ ^^^^^^^^^^^
>message : Message | Message[]
>message : Message[] | Message
> : ^^^^^^^^^^^^^^^^^^^

if (message instanceof Array) {
>message instanceof Array : boolean
> : ^^^^^^^
>message : Message | Message[]
>message : Message[] | Message
> : ^^^^^^^^^^^^^^^^^^^
>Array : ArrayConstructor
> : ^^^^^^^^^^^^^^^^
22 changes: 11 additions & 11 deletions tests/baselines/reference/TypeGuardWithEnumUnion.types
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ function f1(x: Color | string) {
if (typeof x === "number") {
>typeof x === "number" : boolean
> : ^^^^^^^
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>typeof x : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>x : string | Color
> : ^^^^^^^^^^^^^^
@@ -53,15 +53,15 @@ function f1(x: Color | string) {
function f2(x: Color | string | string[]) {
>f2 : (x: Color | string | string[]) => void
> : ^ ^^ ^^^^^^^^^
>x : string | Color | string[]
>x : string | string[] | Color
> : ^^^^^^^^^^^^^^^^^^^^^^^^^

if (typeof x === "object") {
>typeof x === "object" : boolean
> : ^^^^^^^
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>typeof x : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>x : string | Color | string[]
>x : string | string[] | Color
> : ^^^^^^^^^^^^^^^^^^^^^^^^^
>"object" : "object"
> : ^^^^^^^^
@@ -79,9 +79,9 @@ function f2(x: Color | string | string[]) {
if (typeof x === "number") {
>typeof x === "number" : boolean
> : ^^^^^^^
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>typeof x : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>x : string | Color | string[]
>x : string | string[] | Color
> : ^^^^^^^^^^^^^^^^^^^^^^^^^
>"number" : "number"
> : ^^^^^^^^
@@ -110,9 +110,9 @@ function f2(x: Color | string | string[]) {
if (typeof x === "string") {
>typeof x === "string" : boolean
> : ^^^^^^^
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>typeof x : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>x : string | Color | string[]
>x : string | string[] | Color
> : ^^^^^^^^^^^^^^^^^^^^^^^^^
>"string" : "string"
> : ^^^^^^^^
@@ -129,13 +129,13 @@ function f2(x: Color | string | string[]) {
}
else {
var b = x;
>b : Color | string[]
>b : string[] | Color
> : ^^^^^^^^^^^^^^^^
>x : Color | string[]
>x : string[] | Color
> : ^^^^^^^^^^^^^^^^

var b: Color | string[];
>b : Color | string[]
>b : string[] | Color
> : ^^^^^^^^^^^^^^^^
}
}
4 changes: 2 additions & 2 deletions tests/baselines/reference/ambientExportDefaultErrors.types
Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@ declare module "indirect" {
> : ^^^^^^^^^^^^^^^^^^^^^^^^^

export default typeof Foo.default;
>typeof Foo.default : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>typeof Foo.default : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>Foo.default : number
> : ^^^^^^
@@ -58,7 +58,7 @@ declare module "indirect2" {
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^

export = typeof Foo2;
>typeof Foo2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>typeof Foo2 : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>Foo2 : number
> : ^^^^^^
2 changes: 1 addition & 1 deletion tests/baselines/reference/anonymousClassExpression1.types
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ function f() {
return typeof class {} === "function";
>typeof class {} === "function" : boolean
> : ^^^^^^^
>typeof class {} : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>typeof class {} : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>class {} : typeof (Anonymous class)
> : ^^^^^^^^^^^^^^^^^^^^^^^^
56 changes: 28 additions & 28 deletions tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
@@ -6570,21 +6570,21 @@ declare namespace ts {
enum TypeFlags {
Any = 1,
Unknown = 2,
String = 4,
Number = 8,
Boolean = 16,
Enum = 32,
BigInt = 64,
StringLiteral = 128,
NumberLiteral = 256,
BooleanLiteral = 512,
EnumLiteral = 1024,
BigIntLiteral = 2048,
ESSymbol = 4096,
UniqueESSymbol = 8192,
Void = 16384,
Undefined = 32768,
Null = 65536,
Undefined = 4,
Null = 8,
Void = 16,
String = 32,
Number = 64,
BigInt = 128,
Boolean = 256,
ESSymbol = 512,
StringLiteral = 1024,
NumberLiteral = 2048,
BooleanLiteral = 4096,
BigIntLiteral = 8192,
UniqueESSymbol = 16384,
EnumLiteral = 32768,
Enum = 65536,
Never = 131072,
TypeParameter = 262144,
Object = 524288,
@@ -6597,26 +6597,26 @@ declare namespace ts {
NonPrimitive = 67108864,
TemplateLiteral = 134217728,
StringMapping = 268435456,
Literal = 2944,
Unit = 109472,
Freshable = 2976,
StringOrNumberLiteral = 384,
PossiblyFalsy = 117724,
StringLike = 402653316,
NumberLike = 296,
BigIntLike = 2112,
BooleanLike = 528,
EnumLike = 1056,
ESSymbolLike = 12288,
VoidLike = 49152,
Literal = 15360,
Unit = 97292,
Freshable = 80896,
StringOrNumberLiteral = 3072,
PossiblyFalsy = 15868,
StringLike = 402654240,
NumberLike = 67648,
BigIntLike = 8320,
BooleanLike = 4352,
EnumLike = 98304,
ESSymbolLike = 16896,
VoidLike = 20,
UnionOrIntersection = 3145728,
StructuredType = 3670016,
TypeVariable = 8650752,
InstantiableNonPrimitive = 58982400,
InstantiablePrimitive = 406847488,
Instantiable = 465829888,
StructuredOrInstantiable = 469499904,
Narrowable = 536624127,
Narrowable = 536707043,
}
type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression;
interface Type {
32 changes: 16 additions & 16 deletions tests/baselines/reference/arrayBestCommonTypes.types
Original file line number Diff line number Diff line change
@@ -620,10 +620,10 @@ module EmptyTypes {
> : ^^^^^^^^^^^^

var b1 = [baseObj, base2Obj, ifaceObj];
>b1 : iface[]
> : ^^^^^^^
>[baseObj, base2Obj, ifaceObj] : iface[]
> : ^^^^^^^
>b1 : (base | base2)[]
> : ^^^^^^^^^^^^^^^^
>[baseObj, base2Obj, ifaceObj] : (base | base2)[]
> : ^^^^^^^^^^^^^^^^
>baseObj : base
> : ^^^^
>base2Obj : base2
@@ -632,10 +632,10 @@ module EmptyTypes {
> : ^^^^^

var b2 = [base2Obj, baseObj, ifaceObj];
>b2 : iface[]
> : ^^^^^^^
>[base2Obj, baseObj, ifaceObj] : iface[]
> : ^^^^^^^
>b2 : (base | base2)[]
> : ^^^^^^^^^^^^^^^^
>[base2Obj, baseObj, ifaceObj] : (base | base2)[]
> : ^^^^^^^^^^^^^^^^
>base2Obj : base2
> : ^^^^^
>baseObj : base
@@ -644,10 +644,10 @@ module EmptyTypes {
> : ^^^^^

var b3 = [baseObj, ifaceObj, base2Obj];
>b3 : iface[]
> : ^^^^^^^
>[baseObj, ifaceObj, base2Obj] : iface[]
> : ^^^^^^^
>b3 : (base | base2)[]
> : ^^^^^^^^^^^^^^^^
>[baseObj, ifaceObj, base2Obj] : (base | base2)[]
> : ^^^^^^^^^^^^^^^^
>baseObj : base
> : ^^^^
>ifaceObj : iface
@@ -656,10 +656,10 @@ module EmptyTypes {
> : ^^^^^

var b4 = [ifaceObj, baseObj, base2Obj];
>b4 : iface[]
> : ^^^^^^^
>[ifaceObj, baseObj, base2Obj] : iface[]
> : ^^^^^^^
>b4 : (base | base2)[]
> : ^^^^^^^^^^^^^^^^
>[ifaceObj, baseObj, base2Obj] : (base | base2)[]
> : ^^^^^^^^^^^^^^^^
>ifaceObj : iface
> : ^^^^^
>baseObj : base
4 changes: 2 additions & 2 deletions tests/baselines/reference/arrayConcat3.types
Original file line number Diff line number Diff line change
@@ -19,11 +19,11 @@ function doStuff<T extends object, T1 extends T>(a: Array<Fn<T>>, b: Array<Fn<T1
b.concat(a);
>b.concat(a) : Fn<T1>[]
> : ^^^^^^^^
>b.concat : { (...items: ConcatArray<Fn<T1>>[]): Fn<T1>[]; (...items: (Fn<T1> | ConcatArray<Fn<T1>>)[]): Fn<T1>[]; }
>b.concat : { (...items: ConcatArray<Fn<T1>>[]): Fn<T1>[]; (...items: (ConcatArray<Fn<T1>> | Fn<T1>)[]): Fn<T1>[]; }
> : ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>b : Fn<T1>[]
> : ^^^^^^^^
>concat : { (...items: ConcatArray<Fn<T1>>[]): Fn<T1>[]; (...items: (Fn<T1> | ConcatArray<Fn<T1>>)[]): Fn<T1>[]; }
>concat : { (...items: ConcatArray<Fn<T1>>[]): Fn<T1>[]; (...items: (ConcatArray<Fn<T1>> | Fn<T1>)[]): Fn<T1>[]; }
> : ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : Fn<T>[]
> : ^^^^^^^
Original file line number Diff line number Diff line change
@@ -97,7 +97,7 @@ export function evaluate(expression: Expression): boolean {
return expression === 'true';
>expression === 'true' : boolean
> : ^^^^^^^
>expression : "true" | "false"
>expression : "false" | "true"
> : ^^^^^^^^^^^^^^^^
>'true' : "true"
> : ^^^^^^
2 changes: 1 addition & 1 deletion tests/baselines/reference/arrayEvery.types
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ const isString = (x: unknown): x is string => typeof x === 'string';
> : ^^^^^^^
>typeof x === 'string' : boolean
> : ^^^^^^^
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>typeof x : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>x : unknown
> : ^^^^^^^
2 changes: 1 addition & 1 deletion tests/baselines/reference/arrayFind.types
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ function isNumber(x: any): x is number {
return typeof x === "number";
>typeof x === "number" : boolean
> : ^^^^^^^
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>typeof x : "bigint" | "boolean" | "function" | "number" | "object" | "string" | "symbol" | "undefined"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>x : any
>"number" : "number"
4 changes: 2 additions & 2 deletions tests/baselines/reference/arrayFlatNoCrashInference.types
Original file line number Diff line number Diff line change
@@ -2,15 +2,15 @@

=== arrayFlatNoCrashInference.ts ===
function foo<T>(arr: T[], depth: number) {
>foo : <T>(arr: T[], depth: number) => FlatArray<T, 0 | 1 | -1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20>[]
>foo : <T>(arr: T[], depth: number) => FlatArray<T, -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20>[]
> : ^ ^^ ^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>arr : T[]
> : ^^^
>depth : number
> : ^^^^^^

return arr.flat(depth);
>arr.flat(depth) : FlatArray<T, 0 | 1 | -1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20>[]
>arr.flat(depth) : FlatArray<T, -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20>[]
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>arr.flat : <A, D extends number = 1>(this: A, depth?: D | undefined) => FlatArray<A, D>[]
> : ^ ^^ ^^^^^^^^^ ^^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Original file line number Diff line number Diff line change
@@ -13,4 +13,4 @@ function foo(arr, depth) {


//// [arrayFlatNoCrashInferenceDeclarations.d.ts]
declare function foo<T>(arr: T[], depth: number): FlatArray<T, 0 | 1 | -1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20>[];
declare function foo<T>(arr: T[], depth: number): FlatArray<T, -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20>[];
Loading