From bf0b786d31d36387266f7c53bf450eb42c89c574 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Sat, 29 Jun 2024 22:51:12 -0700 Subject: [PATCH 1/2] hacking on short circuit literal relation --- src/compiler/checker.ts | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a965c51d2286b..3ade36c27201b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20530,6 +20530,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // TYPE CHECKING function isTypeIdenticalTo(source: Type, target: Type): boolean { + // const potentiallyRelated = isTypePotentiallyRelated(source, target); + // if (potentiallyRelated !== Ternary.Maybe) return !!potentiallyRelated; return isTypeRelatedTo(source, target, identityRelation); } @@ -20557,6 +20559,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return isTypeRelatedTo(source, target, assignableRelation); } + // function isTypePotentiallyRelated(source: Type, target: Type): Ternary { + // if (source === target) return Ternary.True; + + // if ( + // source.flags & TypeFlags.Literal + // && (source.flags & TypeFlags.Literal) === (target.flags & TypeFlags.Literal) + // && !(source.flags & TypeFlags.EnumLiteral && target.flags & TypeFlags.EnumLiteral) + // ) { + // if (source.flags & TypeFlags.BooleanLiteral) { + // const sourceIsTrue = source === trueType || source === regularTrueType; + // const targetIsTrue = target === trueType || target === regularTrueType; + // return sourceIsTrue === targetIsTrue ? Ternary.True : Ternary.False; + // } + // return (source as LiteralType).value === (target as LiteralType).value ? Ternary.True : Ternary.False; + // } + + // return Ternary.Maybe; + // } + // An object type S is considered to be derived from an object type T if // S is a union type and every constituent of S is derived from T, // T is a union type and S is derived from at least one constituent of T, or @@ -21554,6 +21575,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (source === target) { return true; } + if ( + source.flags & TypeFlags.Literal + && (source.flags & TypeFlags.Literal) === (target.flags & TypeFlags.Literal) + && !(source.flags & TypeFlags.EnumLiteral && target.flags & TypeFlags.EnumLiteral) + ) { + if (source.flags & TypeFlags.BooleanLiteral) { + const sourceIsTrue = source === regularTrueType; + const targetIsTrue = target === regularTrueType; + return sourceIsTrue === targetIsTrue; + } + return (source as LiteralType).value === (target as LiteralType).value; + } if (relation !== identityRelation) { if (relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) || isSimpleTypeRelatedTo(source, target, relation)) { return true; From 17d02d9ed9da704eaebd8c3371caf208fcbc1f69 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Sun, 30 Jun 2024 17:05:58 -0700 Subject: [PATCH 2/2] isTriviallyRelated --- src/compiler/checker.ts | 56 ++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3ade36c27201b..abe163f3813c0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20589,6 +20589,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Note that this check ignores type parameters and only considers the // inheritance hierarchy. function isTypeDerivedFrom(source: Type, target: Type): boolean { + const triviallyRelated = isTriviallyRelated(source, target); + if (triviallyRelated !== Ternary.Maybe) { + return triviallyRelated === Ternary.True; + } return source.flags & TypeFlags.Union ? every((source as UnionType).types, t => isTypeDerivedFrom(t, target)) : target.flags & TypeFlags.Union ? some((target as UnionType).types, t => isTypeDerivedFrom(source, t)) : source.flags & TypeFlags.Intersection ? some((source as IntersectionType).types, t => isTypeDerivedFrom(t, target)) : @@ -21565,15 +21569,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - function isTypeRelatedTo(source: Type, target: Type, relation: Map) { - if (isFreshLiteralType(source)) { - source = (source as FreshableType).regularType; - } - if (isFreshLiteralType(target)) { - target = (target as FreshableType).regularType; - } + function isTriviallyRelated(source: Type, target: Type): Ternary { if (source === target) { - return true; + return Ternary.True; } if ( source.flags & TypeFlags.Literal @@ -21581,11 +21579,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { && !(source.flags & TypeFlags.EnumLiteral && target.flags & TypeFlags.EnumLiteral) ) { if (source.flags & TypeFlags.BooleanLiteral) { - const sourceIsTrue = source === regularTrueType; - const targetIsTrue = target === regularTrueType; - return sourceIsTrue === targetIsTrue; + const sourceIsTrue = source === trueType || source === regularTrueType; + const targetIsTrue = target === trueType || target === regularTrueType; + return sourceIsTrue === targetIsTrue ? Ternary.True : Ternary.False; } - return (source as LiteralType).value === (target as LiteralType).value; + return (source as LiteralType).value === (target as LiteralType).value ? Ternary.True : Ternary.False; + } + return Ternary.Maybe; + } + + function isTypeRelatedTo(source: Type, target: Type, relation: Map) { + const triviallyRelated = isTriviallyRelated(source, target); + if (triviallyRelated !== Ternary.Maybe) { + return triviallyRelated === Ternary.True; + } + + if (isFreshLiteralType(source)) { + source = (source as FreshableType).regularType; + } + if (isFreshLiteralType(target)) { + target = (target as FreshableType).regularType; + } + if (source === target) { + return true; } if (relation !== identityRelation) { if (relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) || isSimpleTypeRelatedTo(source, target, relation)) { @@ -29296,8 +29312,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const directlyRelated = mapType( matching || type, checkDerived ? - t => isTypeDerivedFrom(t, c) ? t : isTypeDerivedFrom(c, t) ? c : neverType : - t => isTypeStrictSubtypeOf(t, c) ? t : isTypeStrictSubtypeOf(c, t) ? c : isTypeSubtypeOf(t, c) ? t : isTypeSubtypeOf(c, t) ? c : neverType, + t => { + const triviallyRelated = isTriviallyRelated(t, c); + if (triviallyRelated !== Ternary.Maybe) { + return triviallyRelated === Ternary.True ? t : neverType; + } + return isTypeDerivedFrom(t, c) ? t : isTypeDerivedFrom(c, t) ? c : neverType; + } : + t => { + const triviallyRelated = isTriviallyRelated(t, c); + if (triviallyRelated !== Ternary.Maybe) { + return triviallyRelated === Ternary.True ? t : neverType; + } + return isTypeStrictSubtypeOf(t, c) ? t : isTypeStrictSubtypeOf(c, t) ? c : isTypeSubtypeOf(t, c) ? t : isTypeSubtypeOf(c, t) ? c : neverType; + }, ); // If no constituents are directly related, create intersections for any generic constituents that // are related by constraint.