Fix an issue when resolving non-trivial unions with complex types, where the check for existence of template types would be n^2 and cause timeouts.
@@ -80,8 +80,9 @@ public abstract class JSType {
private boolean hashCodeInProgress = false;
private boolean inTemplatedCheckVisit = false;
- private static final CanCastToVisitor CAN_CAST_TO_VISITOR =
- new CanCastToVisitor();
+ // Use "Boolean" as a 3-state value where not set is `null`.
+ private Boolean templateCheckResult = null;
+ private static final CanCastToVisitor CAN_CAST_TO_VISITOR = new CanCastToVisitor();
final JSTypeRegistry registry;
@@ -507,15 +508,25 @@ public abstract class JSType {
}
public boolean hasAnyTemplateTypes() {
- if (!this.inTemplatedCheckVisit) {
+ // If the result has been cached use that.
+ if (this.templateCheckResult != null) {
+ return templateCheckResult;
+ }
+
+ if (this.inTemplatedCheckVisit) {
+ // prevent infinite recursion, this is "not yet".
+ return false;
+ }
+
this.inTemplatedCheckVisit = true;
boolean result = hasAnyTemplateTypesInternal();
this.inTemplatedCheckVisit = false;
- return result;
- } else {
- // prevent infinite recursion, this is "not yet".
- return false;
+
+ // Cache the result if the type has been resolved.
+ if (this.isResolved()) {
+ templateCheckResult = result;
}
+ return result;
}
boolean hasAnyTemplateTypesInternal() {
@@ -1456,7 +1467,6 @@ public abstract class JSType {
.check();
}
-
public final boolean isSubtypeOf(JSType supertype, SubtypingMode mode) {
return new SubtypeChecker(this.registry)
.setSubtype(this)
