mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-29 16:29:19 -05:00
Detect comparisons between large unions or intersections (#41574)
* Detect comparisons between large unions or intersections If their multiplied size is greater than 1E6 (chosen based on the repro in #41517), then we'll expend a large amount of time and memory comparing them, so record a trace event. Related to #41517 * Make an exception for primitive union comparisons * Address PR feedback * Pick up baseline change from master * Eliminate diagnostic and only trace * Don't check reportErrors
This commit is contained in:
@@ -16892,7 +16892,6 @@ namespace ts {
|
||||
return isIdenticalTo(source, target);
|
||||
}
|
||||
|
||||
|
||||
// We fastpath comparing a type parameter to exactly its constraint, as this is _super_ common,
|
||||
// and otherwise, for type parameters in large unions, causes us to need to compare the union to itself,
|
||||
// as we break down the _target_ union first, _then_ get the source constraint - so for every
|
||||
@@ -16953,6 +16952,8 @@ namespace ts {
|
||||
return Ternary.False;
|
||||
}
|
||||
|
||||
traceUnionsOrIntersectionsTooLarge(source, target);
|
||||
|
||||
let result = Ternary.False;
|
||||
const saveErrorInfo = captureErrorCalculationState();
|
||||
|
||||
@@ -17088,11 +17089,41 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function traceUnionsOrIntersectionsTooLarge(source: Type, target: Type): void {
|
||||
if (!tracing.isTracing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((source.flags & TypeFlags.UnionOrIntersection) && (target.flags & TypeFlags.UnionOrIntersection)) {
|
||||
const sourceUnionOrIntersection = source as UnionOrIntersectionType;
|
||||
const targetUnionOrIntersection = target as UnionOrIntersectionType;
|
||||
|
||||
if (sourceUnionOrIntersection.objectFlags & targetUnionOrIntersection.objectFlags & ObjectFlags.PrimitiveUnion) {
|
||||
// There's a fast path for comparing primitive unions
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceSize = sourceUnionOrIntersection.types.length;
|
||||
const targetSize = targetUnionOrIntersection.types.length;
|
||||
if (sourceSize * targetSize > 1E6) {
|
||||
tracing.instant(tracing.Phase.CheckTypes, "traceUnionsOrIntersectionsTooLarge_DepthLimit", {
|
||||
sourceId: source.id,
|
||||
sourceSize,
|
||||
targetId: target.id,
|
||||
targetSize,
|
||||
pos: errorNode?.pos,
|
||||
end: errorNode?.end
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isIdenticalTo(source: Type, target: Type): Ternary {
|
||||
const flags = source.flags & target.flags;
|
||||
if (!(flags & TypeFlags.Substructure)) {
|
||||
return Ternary.False;
|
||||
}
|
||||
traceUnionsOrIntersectionsTooLarge(source, target);
|
||||
if (flags & TypeFlags.UnionOrIntersection) {
|
||||
let result = eachTypeRelatedToSomeType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target);
|
||||
if (result) {
|
||||
|
||||
Reference in New Issue
Block a user