Skip to content

Commit

Permalink
Faster exit from isTypeRelatedTo with identityRelation (#36590)
Browse files Browse the repository at this point in the history
* Faster exit from isTypeRelatedTo with identityRelation

* Reorganize a bit
  • Loading branch information
ahejlsberg authored Feb 6, 2020
1 parent 77b81ed commit 0a16032
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 20 deletions.
45 changes: 25 additions & 20 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14706,11 +14706,17 @@ namespace ts {
if (isFreshLiteralType(target)) {
target = (<FreshableType>target).regularType;
}
if (source === target ||
relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) ||
relation !== identityRelation && isSimpleTypeRelatedTo(source, target, relation)) {
if (source === target) {
return true;
}
if (relation !== identityRelation) {
if (relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) || isSimpleTypeRelatedTo(source, target, relation)) {
return true;
}
}
else {
if (!(source.flags === target.flags && source.flags & TypeFlags.Substructure)) return false;
}
if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) {
const related = relation.get(getRelationKey(source, target, IntersectionState.None, relation));
if (related !== undefined) {
Expand Down Expand Up @@ -15048,6 +15054,12 @@ namespace ts {
let source = getNormalizedType(originalSource, /*writing*/ false);
let target = getNormalizedType(originalTarget, /*writing*/ true);

if (source === target) return Ternary.True;

if (relation === identityRelation) {
return isIdenticalTo(source, target);
}

// Try to see if we're relating something like `Foo` -> `Bar | null | undefined`.
// If so, reporting the `null` and `undefined` in the type is hardly useful.
// First, see if we're even relating an object type to a union.
Expand All @@ -15061,17 +15073,11 @@ namespace ts {
(target as UnionType).types.length <= 3 && maybeTypeOfKind(target, TypeFlags.Nullable)) {
const nullStrippedTarget = extractTypesOfKind(target, ~TypeFlags.Nullable);
if (!(nullStrippedTarget.flags & (TypeFlags.Union | TypeFlags.Never))) {
if (source === nullStrippedTarget) return Ternary.True;
target = nullStrippedTarget;
}
}

// both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases
if (source === target) return Ternary.True;

if (relation === identityRelation) {
return isIdenticalTo(source, target);
}

if (relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) ||
isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True;

Expand Down Expand Up @@ -15217,19 +15223,18 @@ namespace ts {
}

function isIdenticalTo(source: Type, target: Type): Ternary {
let result: Ternary;
const flags = source.flags & target.flags;
if (flags & TypeFlags.Object || flags & TypeFlags.IndexedAccess || flags & TypeFlags.Conditional || flags & TypeFlags.Index || flags & TypeFlags.Substitution) {
return recursiveTypeRelatedTo(source, target, /*reportErrors*/ false, IntersectionState.None);
if (!(flags & TypeFlags.Substructure)) {
return Ternary.False;
}
if (flags & (TypeFlags.Union | TypeFlags.Intersection)) {
if (result = eachTypeRelatedToSomeType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target)) {
if (result &= eachTypeRelatedToSomeType(<UnionOrIntersectionType>target, <UnionOrIntersectionType>source)) {
return result;
}
if (flags & TypeFlags.UnionOrIntersection) {
let result = eachTypeRelatedToSomeType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target);
if (result) {
result &= eachTypeRelatedToSomeType(<UnionOrIntersectionType>target, <UnionOrIntersectionType>source);
}
return result;
}
return Ternary.False;
return recursiveTypeRelatedTo(source, target, /*reportErrors*/ false, IntersectionState.None);
}

function getTypeOfPropertyInTypes(types: Type[], name: __String) {
Expand Down Expand Up @@ -18390,7 +18395,7 @@ namespace ts {
}

function isTypeOrBaseIdenticalTo(s: Type, t: Type) {
return isTypeIdenticalTo(s, t) || !!(s.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) && isTypeIdenticalTo(getBaseTypeOfLiteralType(s), t);
return isTypeIdenticalTo(s, t) || !!(t.flags & TypeFlags.String && s.flags & TypeFlags.StringLiteral || t.flags & TypeFlags.Number && s.flags & TypeFlags.NumberLiteral);
}

function isTypeCloselyMatchedBy(s: Type, t: Type) {
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4328,6 +4328,8 @@ namespace ts {
ObjectFlagsType = Any | Nullable | Never | Object | Union | Intersection,
/* @internal */
Simplifiable = IndexedAccess | Conditional,
/* @internal */
Substructure = Object | Union | Intersection | Index | IndexedAccess | Conditional | Substitution,
// 'Narrowable' types are types where narrowing actually narrows.
// This *should* be every type other than null, undefined, void, and never
Narrowable = Any | Unknown | StructuredOrInstantiable | StringLike | NumberLike | BigIntLike | BooleanLike | ESSymbol | UniqueESSymbol | NonPrimitive,
Expand Down

0 comments on commit 0a16032

Please sign in to comment.