Skip to content

Commit 4165980

Browse files
committed
Simplify constraint depth limiter logic
1 parent db1820b commit 4165980

File tree

1 file changed

+8
-22
lines changed

1 file changed

+8
-22
lines changed

src/compiler/checker.ts

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,6 @@ namespace ts {
336336
let totalInstantiationCount = 0;
337337
let instantiationCount = 0;
338338
let instantiationDepth = 0;
339-
let constraintDepth = 0;
340339
let currentNode: Node | undefined;
341340

342341
const typeCatalog: Type[] = []; // NB: id is index + 1
@@ -11033,7 +11032,6 @@ namespace ts {
1103311032
if (type.resolvedBaseConstraint) {
1103411033
return type.resolvedBaseConstraint;
1103511034
}
11036-
let nonTerminating = false;
1103711035
const stack: Type[] = [];
1103811036
return type.resolvedBaseConstraint = getTypeWithThisArgument(getImmediateBaseConstraint(type), type);
1103911037

@@ -11042,22 +11040,16 @@ namespace ts {
1104211040
if (!pushTypeResolution(t, TypeSystemPropertyName.ImmediateBaseConstraint)) {
1104311041
return circularConstraintType;
1104411042
}
11045-
if (constraintDepth >= 50) {
11046-
// We have reached 50 recursive invocations of getImmediateBaseConstraint and there is a
11047-
// very high likelihood we're dealing with an infinite generic type that perpetually generates
11048-
// new type identities as we descend into it. We stop the recursion here and mark this type
11049-
// and the outer types as having circular constraints.
11050-
tracing.instant(tracing.Phase.CheckTypes, "getImmediateBaseConstraint_DepthLimit", { typeId: t.id, originalTypeId: type.id, depth: constraintDepth });
11051-
error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite);
11052-
nonTerminating = true;
11053-
return t.immediateBaseConstraint = noConstraintType;
11054-
}
1105511043
let result;
11056-
if (stack.length < 10 || !isDeeplyNestedType(t, stack, stack.length)) {
11044+
// We always explore at least 10 levels of nested constraints. Thereafter, we continue to explore
11045+
// up to 50 levels of nested constraints provided there are no "deeply nested" types on the stack
11046+
// (i.e. no types for which five instantiations have been recorded on the stack). If we reach 50
11047+
// levels of nesting, we are presumably exploring a repeating pattern with a long cycle that hasn't
11048+
// yet triggered the deeply nested limiter. We have no test cases that actually get to 50 levels of
11049+
// nesting, so it is effectively just a safety stop.
11050+
if (stack.length < 10 || stack.length < 50 && !isDeeplyNestedType(t, stack, stack.length)) {
1105711051
stack.push(t);
11058-
constraintDepth++;
1105911052
result = computeBaseConstraint(getSimplifiedType(t, /*writing*/ false));
11060-
constraintDepth--;
1106111053
stack.pop();
1106211054
}
1106311055
if (!popTypeResolution()) {
@@ -11072,9 +11064,6 @@ namespace ts {
1107211064
}
1107311065
result = circularConstraintType;
1107411066
}
11075-
if (nonTerminating) {
11076-
result = circularConstraintType;
11077-
}
1107811067
t.immediateBaseConstraint = result || noConstraintType;
1107911068
}
1108011069
return t.immediateBaseConstraint;
@@ -11125,10 +11114,7 @@ namespace ts {
1112511114
}
1112611115
if (t.flags & TypeFlags.Conditional) {
1112711116
const constraint = getConstraintFromConditionalType(<ConditionalType>t);
11128-
constraintDepth++; // Penalize repeating conditional types (this captures the recursion within getConstraintFromConditionalType and carries it forward)
11129-
const result = constraint && getBaseConstraint(constraint);
11130-
constraintDepth--;
11131-
return result;
11117+
return constraint && getBaseConstraint(constraint);
1113211118
}
1113311119
if (t.flags & TypeFlags.Substitution) {
1113411120
return getBaseConstraint((<SubstitutionType>t).substitute);

0 commit comments

Comments
 (0)