google / dagger

A fast dependency injector for Android and Java.
https://dagger.dev
Apache License 2.0
17.45k stars 2.02k forks source link

[KSP2] Simple map multi-bindings fail with NoSuchElementException: List is empty #4492

Closed mcumings closed 2 weeks ago

mcumings commented 2 weeks ago

When building with Dagger 2.52, the following scenario fails with an exception:

An interface to be implemented:

interface ProviderInterface

An implementation of the interface:

class ProviderImpl @Inject constructor(): ProviderInterface

Multi-binding the implementation as the interface into a map:

@Module
interface ReproModule {
    @[Binds StringKey("foo") IntoMap]
    fun bind(instance: ProviderImpl): ProviderInterface
}

This results in the following exception:

Caused by: java.util.NoSuchElementException: List is empty.
    at kotlin.collections.CollectionsKt___CollectionsKt.first(_Collections.kt:221)
    at com.google.devtools.ksp.impl.symbol.kotlin.UtilKt.fillInDeepSubstitutor(util.kt:650)
    at com.google.devtools.ksp.impl.ResolverAAImpl.computeAsMemberOf$kotlin_analysis_api(ResolverAAImpl.kt:910)
    at com.google.devtools.ksp.impl.symbol.kotlin.KSFunctionDeclarationImpl.asMemberOf(KSFunctionDeclarationImpl.kt:133)
    at dagger.spi.internal.shaded.androidx.room.compiler.processing.ksp.KSAsMemberOfKt.typeAsMemberOf(KSAsMemberOf.kt:63)
    at dagger.spi.internal.shaded.androidx.room.compiler.processing.ksp.KspExecutableParameterElement.createAsMemberOf(KspExecutableParameterElement.kt:82)
    at dagger.spi.internal.shaded.androidx.room.compiler.processing.ksp.KspExecutableParameterElement.asMemberOf(KspExecutableParameterElement.kt:71)
    at dagger.spi.internal.shaded.androidx.room.compiler.processing.ksp.KspExecutableParameterElement.asMemberOf(KspExecutableParameterElement.kt:32)
    at dagger.spi.internal.shaded.androidx.room.compiler.processing.ksp.KspExecutableType$parameterTypes$2.invoke(KspExecutableType.kt:31)
    at dagger.spi.internal.shaded.androidx.room.compiler.processing.ksp.KspExecutableType$parameterTypes$2.invoke(KspExecutableType.kt:27)
    at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
    at dagger.spi.internal.shaded.androidx.room.compiler.processing.ksp.KspExecutableType.getParameterTypes(KspExecutableType.kt:27)
    at dagger.internal.codegen.binding.BindsTypeChecker.methodParameterTypes(BindsTypeChecker.java:95)
    at dagger.internal.codegen.binding.BindsTypeChecker.desiredAssignableType(BindsTypeChecker.java:84)
    at dagger.internal.codegen.binding.BindsTypeChecker.isAssignable(BindsTypeChecker.java:66)
    at dagger.internal.codegen.validation.BindsMethodValidator$Validator.checkParameter(BindsMethodValidator.java:100)
    at dagger.internal.codegen.validation.BindingMethodValidator$MethodValidator.checkParameters(BindingMethodValidator.java:224)
    at dagger.internal.codegen.validation.BindsMethodValidator$Validator.checkParameters(BindsMethodValidator.java:85)
    at dagger.internal.codegen.validation.BindingMethodValidator$MethodValidator.checkAdditionalProperties(BindingMethodValidator.java:149)
    at dagger.internal.codegen.validation.BindingElementValidator$ElementValidator.validate(BindingElementValidator.java:149)
    at dagger.internal.codegen.validation.BindingElementValidator$ElementValidator.access$000(BindingElementValidator.java:131)
    at dagger.internal.codegen.validation.BindingElementValidator.validateUncached(BindingElementValidator.java:80)
    at dagger.internal.codegen.base.Util.reentrantComputeIfAbsent(Util.java:33)
    at dagger.internal.codegen.validation.BindingElementValidator.validate(BindingElementValidator.java:76)
    at dagger.internal.codegen.validation.AnyBindingMethodValidator.validateUncached(AnyBindingMethodValidator.java:102)
    at dagger.internal.codegen.base.Util.reentrantComputeIfAbsent(Util.java:33)
    at dagger.internal.codegen.validation.AnyBindingMethodValidator.validate(AnyBindingMethodValidator.java:80)
    at dagger.internal.codegen.validation.ModuleValidator.validateUncached(ModuleValidator.java:174)
    at dagger.internal.codegen.validation.ModuleValidator.lambda$validate$0(ModuleValidator.java:162)
    at dagger.internal.codegen.base.Util.reentrantComputeIfAbsent(Util.java:33)
    at dagger.internal.codegen.validation.ModuleValidator.validate(ModuleValidator.java:162)
    at dagger.internal.codegen.validation.ModuleValidator.validate(ModuleValidator.java:157)
    at dagger.internal.codegen.processingstep.ModuleProcessingStep.process(ModuleProcessingStep.java:110)
    at dagger.internal.codegen.processingstep.ModuleProcessingStep.process(ModuleProcessingStep.java:49)
    at dagger.internal.codegen.processingstep.TypeCheckingProcessingStep.lambda$process$0(TypeCheckingProcessingStep.java:94)
    at com.google.common.collect.SingletonImmutableBiMap.forEach(SingletonImmutableBiMap.java:70)
    at dagger.internal.codegen.processingstep.TypeCheckingProcessingStep.process(TypeCheckingProcessingStep.java:72)
    at dagger.internal.codegen.processingstep.ModuleProcessingStep.process(ModuleProcessingStep.java:94)
    at dagger.internal.codegen.processingstep.ModuleProcessingStep.process(ModuleProcessingStep.java:49)
    at dagger.spi.internal.shaded.androidx.room.compiler.processing.XProcessingStep.process(XProcessingStep.kt:57)
    at dagger.spi.internal.shaded.androidx.room.compiler.processing.CommonProcessorDelegate.processRound(XBasicAnnotationProcessor.kt:134)
    at dagger.spi.internal.shaded.androidx.room.compiler.processing.ksp.KspBasicAnnotationProcessor.process(KspBasicAnnotationProcessor.kt:62)
    at com.google.devtools.ksp.impl.KotlinSymbolProcessing.execute(KotlinSymbolProcessing.kt:538)
    at com.google.devtools.ksp.impl.KSPLoader$Companion.loadAndRunKSP(KSPLoader.kt:36)
    at com.google.devtools.ksp.impl.KSPLoader.loadAndRunKSP(KSPLoader.kt)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
    at com.google.devtools.ksp.gradle.KspAAWorkerAction.execute(KspAATask.kt:510)
    at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63)
    at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:66)
    at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:62)
    at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:100)
    at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:62)
    at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
    at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
    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:166)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
    at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
    at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:59)
    at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:174)
    at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:194)
    at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:127)
    at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:169)
    at org.gradle.internal.Factories$1.create(Factories.java:31)
    at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:263)
    at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:127)
    at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:132)
    at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:164)
    at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:133)
    ... 2 more
kuanyingchou commented 2 weeks ago

Hi, @mcumings , there are some fixes on asMemberOf in KSP recently. Could you try again with the latest release (https://github.com/google/ksp/releases/tag/2.0.21-1.0.26)?

mcumings commented 2 weeks ago

Ah, looks like those fixes did the trick, thanks!