Work around `java.lang.IllegalStateException: Recursive update` in //src/main/java/com/google/devtools/build/lib:gen_skylarklibrary caused by logical cycle in CallUtils#getCacheValue due to class loading order.
See code comments for details.
Before: (with debugging hacks)
After:
RELNOTES: None
@@ -19,6 +19,7 @@ import com.google.devtools.build.docgen.starlark.StarlarkBuiltinDoc;
import com.google.devtools.build.docgen.starlark.StarlarkConstructorMethodDoc;
import com.google.devtools.build.docgen.starlark.StarlarkJavaMethodDoc;
import com.google.devtools.build.lib.syntax.CallUtils;
+import com.google.devtools.build.lib.syntax.Starlark;
import com.google.devtools.build.lib.syntax.StarlarkSemantics;
import com.google.devtools.build.lib.syntax.StarlarkValue;
import java.lang.reflect.Method;
@@ -52,6 +53,15 @@ final class StarlarkDocumentationCollector {
* a map that maps Starlark module name to the module documentation.
*/
public static Map<String, StarlarkBuiltinDoc> collectModules(Iterable<Class<?>> classes) {
+ // Force class loading of com.google.devtools.build.lib.syntax.Starlark before we do any of our
+ // own processing. Otherwise, we're in trouble since com.google.devtools.build.lib.syntax.Dict
+ // happens to be the first class on our classpath that we proccess via #collectModuleMethods,
+ // but that entails a logical cycle in
+ // com.google.devtools.build.lib.syntax.CallUtils#getCacheValue.
+ // TODO(b/161479826): Address this in a less hacky manner.
+ @SuppressWarnings("unused")
+ Object forceClassLoading = Starlark.UNIVERSE;
+
Map<String, StarlarkBuiltinDoc> modules = new TreeMap<>();
// The top level module first.
// (This is a special case of {@link StarlarkBuiltinDoc} as it has no object name).
