Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AssertionError: Recursion detected in a lazy value under LockBasedStorageManager in multiplatform project #3565

Open
illarionov opened this issue Apr 14, 2024 · 2 comments
Assignees
Labels

Comments

@illarionov
Copy link

Describe the bug

./gradle dokkaGfm fails on a multiplatform project with the following exception: java.lang.AssertionError: Recursion detected in a lazy value under LockBasedStorageManager@61bed5ef (Dokka).

Repository with an example project: https://github.com/illarionov/playground-android-composite-build/tree/dokka-typealias-recursion (dokka-typealias-recursion branch).
This project has a shared Jvm + Android source set and some typealias defined.

To Reproduce
Clone the above example repository, or create a new multiplatform project with about the following submodule configuration (build.gradle.kts):

plugins {
    id("org.jetbrains.kotlin.multiplatform")
    id("com.android.library")
}

kotlin {
    androidTarget()
    jvm()

    applyDefaultHierarchyTemplate()

    sourceSets {
        val jvmAndAndroid by creating {
            dependsOn(commonMain.get())
        }
        androidMain.get().dependsOn(jvmAndAndroid)
        jvmMain.get().dependsOn(jvmAndAndroid)
    }
}

Create a Kotlin source code file in the shared source set (composeApp/src/jvmAndAndroid/kotlin/org/example/dokka/Types.jvmAndAndroid.kt):

package org.example.dokka

import java.io.File

typealias File = File

Run ./gradlew dokkaGfm --stacktrace. It will fail with the following stacktrace:

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':composeApp:dokkaGfm'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:130)
        at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:282)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:128)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:116)
        at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:74)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:200)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:195)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
        at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:42)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:331)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:318)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.lambda$execute$0(DefaultTaskExecutionGraph.java:314)
        at org.gradle.internal.operations.CurrentBuildOperationRef.with(CurrentBuildOperationRef.java:80)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:314)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:303)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:463)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:380)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
        at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
Caused by: java.lang.AssertionError: Recursion detected in a lazy value under LockBasedStorageManager@61bed5ef (Dokka)
        at org.jetbrains.kotlin.resolve.lazy.descriptors.LazyTypeAliasDescriptor.getDefaultType(LazyTypeAliasDescriptor.kt:57)
        at org.jetbrains.kotlin.types.KotlinTypeFactory.simpleType(KotlinTypeFactory.kt:85)
        at org.jetbrains.kotlin.types.KotlinTypeFactory.simpleType$default(KotlinTypeFactory.kt:77)
        at org.jetbrains.kotlin.resolve.TypeResolver.resolveTypeForTypeAlias(TypeResolver.kt:727)
        at org.jetbrains.kotlin.resolve.TypeResolver.resolveTypeForClassifier(TypeResolver.kt:583)
        at org.jetbrains.kotlin.resolve.TypeResolver$resolveTypeElement$1.visitUserType(TypeResolver.kt:278)
        at org.jetbrains.kotlin.psi.KtVisitorVoid.visitUserType(KtVisitorVoid.java:937)
        at org.jetbrains.kotlin.psi.KtVisitorVoid.visitUserType(KtVisitorVoid.java:21)
        at org.jetbrains.kotlin.psi.KtUserType.accept(KtUserType.java:42)
        at org.jetbrains.kotlin.psi.KtElementImplStub.accept(KtElementImplStub.java:49)
        at org.jetbrains.kotlin.resolve.TypeResolver.resolveTypeElement(TypeResolver.kt:257)
        at org.jetbrains.kotlin.resolve.TypeResolver.resolvePossiblyBareType(TypeResolver.kt:136)
        at org.jetbrains.kotlin.resolve.TypeResolver.resolveType(TypeResolver.kt:126)
        at org.jetbrains.kotlin.resolve.TypeResolver.resolveAbbreviatedType(TypeResolver.kt:104)
        at org.jetbrains.kotlin.resolve.DescriptorResolver.lambda$resolveTypeAliasDescriptor$2(DescriptorResolver.java:788)
        at org.jetbrains.kotlin.storage.LockBasedStorageManager$LockBasedLazyValue.invoke(LockBasedStorageManager.java:408)
        at org.jetbrains.kotlin.storage.LockBasedStorageManager$LockBasedNotNullLazyValue.invoke(LockBasedStorageManager.java:527)
        at org.jetbrains.kotlin.resolve.lazy.descriptors.LazyTypeAliasDescriptor.getUnderlyingType(LazyTypeAliasDescriptor.kt:54)
        at org.jetbrains.kotlin.resolve.lazy.descriptors.LazyTypeAliasDescriptor.computeClassDescriptor(LazyTypeAliasDescriptor.kt:74)
        at org.jetbrains.kotlin.resolve.lazy.descriptors.LazyTypeAliasDescriptor.access$computeClassDescriptor(LazyTypeAliasDescriptor.kt:34)
        at org.jetbrains.kotlin.resolve.lazy.descriptors.LazyTypeAliasDescriptor$initialize$2.invoke(LazyTypeAliasDescriptor.kt:70)
        at org.jetbrains.kotlin.resolve.lazy.descriptors.LazyTypeAliasDescriptor$initialize$2.invoke(LazyTypeAliasDescriptor.kt:70)
        at org.jetbrains.kotlin.storage.LockBasedStorageManager$LockBasedLazyValue.invoke(LockBasedStorageManager.java:408)
        at org.jetbrains.kotlin.resolve.lazy.descriptors.LazyTypeAliasDescriptor.getClassDescriptor(LazyTypeAliasDescriptor.kt:56)
        at org.jetbrains.kotlin.descriptors.impl.AbstractTypeAliasDescriptor.computeDefaultType(AbstractTypeAliasDescriptor.kt:98)
        at org.jetbrains.kotlin.resolve.lazy.descriptors.LazyTypeAliasDescriptor.access$computeDefaultType(LazyTypeAliasDescriptor.kt:34)
        at org.jetbrains.kotlin.resolve.lazy.descriptors.LazyTypeAliasDescriptor$initialize$1.invoke(LazyTypeAliasDescriptor.kt:69)
        at org.jetbrains.kotlin.resolve.lazy.descriptors.LazyTypeAliasDescriptor$initialize$1.invoke(LazyTypeAliasDescriptor.kt:69)
        at org.jetbrains.kotlin.storage.LockBasedStorageManager$LockBasedLazyValue.invoke(LockBasedStorageManager.java:408)
        at org.jetbrains.kotlin.storage.LockBasedStorageManager$LockBasedNotNullLazyValue.invoke(LockBasedStorageManager.java:527)
        at org.jetbrains.kotlin.resolve.lazy.descriptors.LazyTypeAliasDescriptor.getDefaultType(LazyTypeAliasDescriptor.kt:57)
        at org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.translator.DokkaDescriptorVisitor$visitTypeAliasDescriptor$2$1.invokeSuspend(DefaultDescriptorToDocumentableTranslator.kt:844)
        at org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.translator.DokkaDescriptorVisitor$visitTypeAliasDescriptor$2$1.invoke(DefaultDescriptorToDocumentableTranslator.kt)
        at org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.translator.DokkaDescriptorVisitor$visitTypeAliasDescriptor$2$1.invoke(DefaultDescriptorToDocumentableTranslator.kt)
        at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:78)
        at kotlinx.coroutines.CoroutineScopeKt.coroutineScope(CoroutineScope.kt:264)
        at org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.translator.DokkaDescriptorVisitor.visitTypeAliasDescriptor(DefaultDescriptorToDocumentableTranslator.kt:842)
        at org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.translator.DokkaDescriptorVisitor.access$visitTypeAliasDescriptor(DefaultDescriptorToDocumentableTranslator.kt:161)
        at org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.translator.DokkaDescriptorVisitor$visitTypealiases$2$invokeSuspend$$inlined$parallelMap$1$1.invokeSuspend(parallelCollectionOperations.kt:28)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)

Workaround: if we replace the typealias line to typealias File = java.io.File, then the build will succeed.

Installation

  • Operating system: Linux
  • Build tool: Gradle v8.7
  • Dokka version: 1.9.20
  • Kotlin version: 1.9.23
@vmishenev
Copy link
Member

vmishenev commented Apr 18, 2024

Related issues: #3317
#3513

Thank you for the reproducer.


The problem is that the Dokka Gradle Plugin wrongly(?) defines jvmAndAndroid as a common platform here.
That means that:

import java.io.File
typealias File = File

java.io.File is unresolved since JDK is only available for a JVM platform.
In K1, it causes a recursion (AssertionError that fails a Dokka run).
In K2, it just leads to an unresolved type.

@IgnatBeresnev
Copy link
Member

IgnatBeresnev commented Apr 22, 2024

An intermediate solution: do not fail the build to at least let the users build documentation, even if the reference is lost.

Overall, to address the issue properly, we need to investigate how this case should be handled, what the expected behaviour is from Kotlin's perspective, whether such setups are even allowed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants