@@ -13439,6 +13439,7 @@ namespace ts {
13439
13439
let visited: Map<boolean>;
13440
13440
let contravariant = false;
13441
13441
let propagationType: Type;
13442
+ let allowComplexConstraintInference = true;
13442
13443
inferFromTypes(originalSource, originalTarget);
13443
13444
13444
13445
function inferFromTypes(source: Type, target: Type): void {
@@ -13616,7 +13617,15 @@ namespace ts {
13616
13617
// getApparentType can return _any_ type, since an indexed access or conditional may simplify to any other type.
13617
13618
// If that occurs and it doesn't simplify to an object or intersection, we'll need to restart `inferFromTypes`
13618
13619
// with the simplified source.
13619
- if (apparentSource !== source && !(apparentSource.flags & (TypeFlags.Object | TypeFlags.Intersection))) {
13620
+ if (apparentSource !== source && allowComplexConstraintInference && !(apparentSource.flags & (TypeFlags.Object | TypeFlags.Intersection))) {
13621
+ // TODO: The `allowComplexConstraintInference` flag is a hack! This forbids inference from complex constraints within constraints!
13622
+ // This isn't required algorithmically, but rather is used to lower the memory burden caused by performing inference
13623
+ // that is _too good_ in projects with complicated constraints (eg, fp-ts). In such cases, if we did not limit ourselves
13624
+ // here, we might produce more valid inferences for types, causing us to do more checks and perform more instantiations
13625
+ // (in addition to the extra stack depth here) which, in turn, can push the already close process over its limit.
13626
+ // TL;DR: If we ever become generally more memory efficienct (or our resource budget ever increases), we should just
13627
+ // remove this `allowComplexConstraintInference` flag.
13628
+ allowComplexConstraintInference = false;
13620
13629
return inferFromTypes(apparentSource, target);
13621
13630
}
13622
13631
source = apparentSource;
0 commit comments