Add extra diagnostic information when no common supertypes are found
We're suspecting that the culprit of such errors is race condition on 'supertypes' in AbstractTypeConstructor, when it is created using 'LockBasedStorageManager.NO_LOCKS'
This commit is contained in:
@@ -142,15 +142,15 @@ public class CommonSupertypes {
|
|||||||
if (commonSupertypes.isEmpty()) {
|
if (commonSupertypes.isEmpty()) {
|
||||||
StringBuilder info = new StringBuilder();
|
StringBuilder info = new StringBuilder();
|
||||||
for (SimpleType type : types) {
|
for (SimpleType type : types) {
|
||||||
String superTypes = type.getConstructor().getSupertypes().stream()
|
String superTypes = TypeUtils.getAllSupertypes(type).stream()
|
||||||
.map(CommonSupertypes::renderTypeFully)
|
.map(t -> "-- " + renderTypeFully(t))
|
||||||
.collect(Collectors.joining(", "));
|
.collect(Collectors.joining("\n"));
|
||||||
|
|
||||||
info
|
info
|
||||||
.append("Info about ").append(renderTypeFully(type)).append(": ").append('\n')
|
.append("Info about ").append(renderTypeFully(type)).append(": ").append('\n')
|
||||||
.append("- Supertypes: ").append(superTypes).append('\n')
|
.append("- Supertypes: ").append('\n')
|
||||||
|
.append(superTypes).append('\n')
|
||||||
.append("- DeclarationDescriptor class: ").append(classOfDeclarationDescriptor(type)).append('\n')
|
.append("- DeclarationDescriptor class: ").append(classOfDeclarationDescriptor(type)).append('\n')
|
||||||
.append("- TypeConstructor class: ").append(type.getConstructor().getClass()).append('\n')
|
|
||||||
.append('\n');
|
.append('\n');
|
||||||
}
|
}
|
||||||
throw new IllegalStateException("There is no common supertype for: " + types + " \n" + info.toString());
|
throw new IllegalStateException("There is no common supertype for: " + types + " \n" + info.toString());
|
||||||
@@ -166,7 +166,18 @@ public class CommonSupertypes {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static String renderTypeFully(@NotNull KotlinType type) {
|
private static String renderTypeFully(@NotNull KotlinType type) {
|
||||||
return DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type);
|
return DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type) + ", typeConstructor debug: " +
|
||||||
|
renderTypeConstructorVerboseDebugInformation(type.getConstructor());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
private static String renderTypeConstructorVerboseDebugInformation(TypeConstructor typeConstructor) {
|
||||||
|
if (!(typeConstructor instanceof AbstractTypeConstructor)) {
|
||||||
|
return typeConstructor.toString() + "[" + typeConstructor.getClass().getName() + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractTypeConstructor abstractTypeConstructor = (AbstractTypeConstructor) typeConstructor;
|
||||||
|
return abstractTypeConstructor.renderAdditionalDebugInformation();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
@@ -76,4 +76,6 @@ abstract class AbstractTypeConstructor(storageManager: StorageManager) : TypeCon
|
|||||||
protected open fun getAdditionalNeighboursInSupertypeGraph(useCompanions: Boolean): Collection<KotlinType> = emptyList()
|
protected open fun getAdditionalNeighboursInSupertypeGraph(useCompanions: Boolean): Collection<KotlinType> = emptyList()
|
||||||
protected open fun defaultSupertypeIfEmpty(): KotlinType? = null
|
protected open fun defaultSupertypeIfEmpty(): KotlinType? = null
|
||||||
|
|
||||||
|
// Only for debugging
|
||||||
|
fun renderAdditionalDebugInformation(): String = "supertypes=${supertypes.renderDebugInformation()}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,6 +146,11 @@ public class LockBasedStorageManager implements StorageManager {
|
|||||||
protected RecursionDetectedResult<T> recursionDetected(boolean firstTime) {
|
protected RecursionDetectedResult<T> recursionDetected(boolean firstTime) {
|
||||||
return RecursionDetectedResult.value(onRecursiveCall);
|
return RecursionDetectedResult.value(onRecursiveCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String presentableName() {
|
||||||
|
return "RecursionTolerantLazyValue";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,6 +175,11 @@ public class LockBasedStorageManager implements StorageManager {
|
|||||||
protected void postCompute(@NotNull T value) {
|
protected void postCompute(@NotNull T value) {
|
||||||
postCompute.invoke(value);
|
postCompute.invoke(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String presentableName() {
|
||||||
|
return "LazyValueWithPostCompute";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,6 +198,11 @@ public class LockBasedStorageManager implements StorageManager {
|
|||||||
protected RecursionDetectedResult<T> recursionDetected(boolean firstTime) {
|
protected RecursionDetectedResult<T> recursionDetected(boolean firstTime) {
|
||||||
return RecursionDetectedResult.value(onRecursiveCall);
|
return RecursionDetectedResult.value(onRecursiveCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String presentableName() {
|
||||||
|
return "RecursionTolerantNullableLazyValue";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,6 +216,11 @@ public class LockBasedStorageManager implements StorageManager {
|
|||||||
protected void postCompute(@Nullable T value) {
|
protected void postCompute(@Nullable T value) {
|
||||||
postCompute.invoke(value);
|
postCompute.invoke(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String presentableName() {
|
||||||
|
return "NullableLazyValueWithPostCompute";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,6 +376,15 @@ public class LockBasedStorageManager implements StorageManager {
|
|||||||
protected void postCompute(T value) {
|
protected void postCompute(T value) {
|
||||||
// Doing something in post-compute helps prevent infinite recursion
|
// Doing something in post-compute helps prevent infinite recursion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public String renderDebugInformation() {
|
||||||
|
return presentableName() + ", storageManager=" + storageManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String presentableName() {
|
||||||
|
return this.getClass().getName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LockBasedNotNullLazyValue<T> extends LockBasedLazyValue<T> implements NotNullLazyValue<T> {
|
private static class LockBasedNotNullLazyValue<T> extends LockBasedLazyValue<T> implements NotNullLazyValue<T> {
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ interface MemoizedFunctionToNullable<in P, out R : Any> : Function1<P, R?> {
|
|||||||
interface NotNullLazyValue<out T : Any> : Function0<T> {
|
interface NotNullLazyValue<out T : Any> : Function0<T> {
|
||||||
fun isComputed(): Boolean
|
fun isComputed(): Boolean
|
||||||
fun isComputing(): Boolean
|
fun isComputing(): Boolean
|
||||||
|
|
||||||
|
// Only for debugging
|
||||||
|
fun renderDebugInformation(): String = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NullableLazyValue<out T : Any> : Function0<T?> {
|
interface NullableLazyValue<out T : Any> : Function0<T?> {
|
||||||
|
|||||||
Reference in New Issue
Block a user