From d8b7de4f0e43c73f157435f92443891c8b94160e Mon Sep 17 00:00:00 2001 From: Dmitry Savvinov Date: Mon, 9 Apr 2018 13:13:27 +0300 Subject: [PATCH] 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' --- .../kotlin/types/CommonSupertypes.java | 23 +++++++++++---- .../kotlin/types/AbstractTypeConstructor.kt | 2 ++ .../storage/LockBasedStorageManager.java | 29 +++++++++++++++++++ .../org/jetbrains/kotlin/storage/storage.kt | 3 ++ 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/CommonSupertypes.java b/compiler/frontend/src/org/jetbrains/kotlin/types/CommonSupertypes.java index bc0dd354a57..e976b169711 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/CommonSupertypes.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/CommonSupertypes.java @@ -142,15 +142,15 @@ public class CommonSupertypes { if (commonSupertypes.isEmpty()) { StringBuilder info = new StringBuilder(); for (SimpleType type : types) { - String superTypes = type.getConstructor().getSupertypes().stream() - .map(CommonSupertypes::renderTypeFully) - .collect(Collectors.joining(", ")); + String superTypes = TypeUtils.getAllSupertypes(type).stream() + .map(t -> "-- " + renderTypeFully(t)) + .collect(Collectors.joining("\n")); info .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("- TypeConstructor class: ").append(type.getConstructor().getClass()).append('\n') .append('\n'); } throw new IllegalStateException("There is no common supertype for: " + types + " \n" + info.toString()); @@ -166,7 +166,18 @@ public class CommonSupertypes { @NotNull 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 diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/AbstractTypeConstructor.kt b/core/descriptors/src/org/jetbrains/kotlin/types/AbstractTypeConstructor.kt index b442480c271..1a37d4f799e 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/AbstractTypeConstructor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/AbstractTypeConstructor.kt @@ -76,4 +76,6 @@ abstract class AbstractTypeConstructor(storageManager: StorageManager) : TypeCon protected open fun getAdditionalNeighboursInSupertypeGraph(useCompanions: Boolean): Collection = emptyList() protected open fun defaultSupertypeIfEmpty(): KotlinType? = null + // Only for debugging + fun renderAdditionalDebugInformation(): String = "supertypes=${supertypes.renderDebugInformation()}" } diff --git a/core/util.runtime/src/org/jetbrains/kotlin/storage/LockBasedStorageManager.java b/core/util.runtime/src/org/jetbrains/kotlin/storage/LockBasedStorageManager.java index fe8af81541e..8b504c97393 100644 --- a/core/util.runtime/src/org/jetbrains/kotlin/storage/LockBasedStorageManager.java +++ b/core/util.runtime/src/org/jetbrains/kotlin/storage/LockBasedStorageManager.java @@ -146,6 +146,11 @@ public class LockBasedStorageManager implements StorageManager { protected RecursionDetectedResult recursionDetected(boolean firstTime) { 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) { postCompute.invoke(value); } + + @Override + protected String presentableName() { + return "LazyValueWithPostCompute"; + } }; } @@ -188,6 +198,11 @@ public class LockBasedStorageManager implements StorageManager { protected RecursionDetectedResult recursionDetected(boolean firstTime) { 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) { postCompute.invoke(value); } + + @Override + protected String presentableName() { + return "NullableLazyValueWithPostCompute"; + } }; } @@ -356,6 +376,15 @@ public class LockBasedStorageManager implements StorageManager { protected void postCompute(T value) { // 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 extends LockBasedLazyValue implements NotNullLazyValue { diff --git a/core/util.runtime/src/org/jetbrains/kotlin/storage/storage.kt b/core/util.runtime/src/org/jetbrains/kotlin/storage/storage.kt index a7762896037..02fba7c8f43 100644 --- a/core/util.runtime/src/org/jetbrains/kotlin/storage/storage.kt +++ b/core/util.runtime/src/org/jetbrains/kotlin/storage/storage.kt @@ -29,6 +29,9 @@ interface MemoizedFunctionToNullable : Function1 { interface NotNullLazyValue : Function0 { fun isComputed(): Boolean fun isComputing(): Boolean + + // Only for debugging + fun renderDebugInformation(): String = "" } interface NullableLazyValue : Function0 {