I’m currently in a process of migration to Kotlin ...
# squarelibraries
i
I’m currently in a process of migration to Kotlin 2.0 in my project. I’ve followed the
Anvil
part of @Zac Sweers post (interface merging part as well): https://www.zacsweers.dev/preparing-for-k2/ However, I’m getting a compilation error suggesting that interface merging was not in fact done:
Copy code
Type mismatch: inferred type is ScreenComponent but UserDocumentsDependencies was expected
Type mismatch: inferred type is ScreenComponent but CatalogDependencies was expected
... etc
What is a proper way to debug this situation?
z
This is pretty limited information and it’s hard to advise without more details
i
@Zac Sweers I’m sorry. I’m using Anvil 2.5.0-beta09 Gradle 8.7 Kotlin 2.0.0 Here’s all my build configuration (several convention plugins as well as build configuration for library module which contains
ScreenComponent
), example of how
ScreenComponent
and (for instance) contributed
UserDocumentDependencies
looks like. https://gist.github.com/IlyaGulya/2b53e49ccc856a135dea065cdf179bd8 I’ve tried to attach a debugger to Gradle.
IrContributionMerger
seems to be registered:
Copy code
IrGenerationExtension.registerExtension(
  project,
  IrContributionMerger(scanner, moduleDescriptorFactory),
)
But
IrContributionMerger.generate
method never being called for some reason.
Above error happens when I’m trying to assign
ScreenComponent
to contributed interface’s
lateinit var instance
inside its companion object
z
🤔 that’s surprising that the merger isn’t called. In the stub gen task or the compilation task? The latter is what would affect your runtime cast
i
It’s not called nor in the stub gen task, neither in compilation task 😅 My breakpoint in the
AnvilComponentRegistrar
stops only in the compilation task, btw.
@Zac Sweers
The latter is what would affect your runtime cast
- that’s not runtime issue, but compile-time one.
z
can you paste a full stacktrace?
i
Untitled
Here’s a stacktrace from gradle as a snippet above, if it helps. That’s a regular compilation error, not an exception:
Copy code
> Task :apps:base:store:compileInternalDebugKotlin FAILED
e: file:///Users/ilyagulya/Projects/Qantor/qa-android-apps/apps/base/store/src/main/java/ru/qantor/customer/presentation/CustomerApp.kt:155:54 Type mismatch: inferred type is ScreenComponent but UserDocumentsDependencies was expected
e: file:///Users/ilyagulya/Projects/Qantor/qa-android-apps/apps/base/store/src/main/java/ru/qantor/customer/presentation/CustomerApp.kt:156:48 Type mismatch: inferred type is ScreenComponent but CatalogDependencies was expected
e: file:///Users/ilyagulya/Projects/Qantor/qa-android-apps/apps/base/store/src/main/java/ru/qantor/customer/presentation/CustomerApp.kt:157:50 Type mismatch: inferred type is ScreenComponent but FavoritesDependencies was expected
e: file:///Users/ilyagulya/Projects/Qantor/qa-android-apps/apps/base/store/src/main/java/ru/qantor/customer/presentation/CustomerApp.kt:158:57 Type mismatch: inferred type is ScreenComponent but PersonalManagersDependencies was expected
e: file:///Users/ilyagulya/Projects/Qantor/qa-android-apps/apps/base/store/src/main/java/ru/qantor/customer/presentation/CustomerApp.kt:159:49 Type mismatch: inferred type is ScreenComponent but MarkdownDependencies was expected
e: file:///Users/ilyagulya/Projects/Qantor/qa-android-apps/apps/base/store/src/main/java/ru/qantor/customer/presentation/CustomerApp.kt:160:47 Type mismatch: inferred type is ScreenComponent but EventsDependencies was expected
IrContributionMerger.generate
seems to be called in the modules with such configuration:
Copy code
anvil {
    useKsp(contributesAndFactoryGeneration = true)
    generateDaggerFactories = true
}
But not in ones where I fallback Kapt and KotlinCompile tasks
languageVersion
to
1.9
z
that seems surprising, contribution merging should never run at the same time as dagger factory generation as you’d end up with duplicate classes
are you able to put together a minimal repro?
i
I will try tomorrow 🙂
👍 1
@Zac Sweers ok, I couldn’t wait and made a reproducer 🙂 https://github.com/IlyaGulya/AnvilInterfaceMerginIssueSample You can try to run
MainKt
in
:entrypoint
module and see the error:
Type mismatch: inferred type is SomeComponent! but Dependencies was expected
👍 1
@Zac Sweers hi! I’ve made some research regarding this issue. Apparently interface merging does not work in k1 because there’s no previously present
SyntheticResolveExtension
which were deleted in these commit. https://github.com/square/anvil/commit/c35bef587974c432371fffebb610122ccb96d89b This happens because IR generation is running after analysis, and analysis fails because of absense of
SyntheticResolveException
. I’ve just checked that returning
SyntheticResolveExtension
back fixes the issue. I’m not sure what is the correct way to provide analyzer information about the supertypes which will be merged in the IR generation phase. I’ve just checked the Parcelize plugin and it seems to use
SyntheticResolveExtension
as well for this purpose. Are you sure that it’s no longer required? Seems that it should be preserved for K1 (I’m assuming this according to this message https://kotlinlang.slack.com/archives/C7L3JB43G/p1709191343204389?thread_ts=1709191090.501719&cid=C7L3JB43G)
z
We reimplemented it in IR instead, that’s why it’s deleted there
It works on K1 but not K2
i
But IR implementation is not enough to provide the analyzer all required info. I suppose that this is also the case for K2 and there will be required a FirDeclarationGenerationExtension as well
z
the sad news is that IR isn’t viable long term anyway
I’ve already talked with compiler folks about this, and the TL;DR is that we cannot rely on modifying supertypes during IR generation
🫠 1
so we will need to do something different, likely generating a new merged component class and making the root one extend it
I have started this work in Anvil, but I’m limited by reviews
that new one is implemented in KSP
i
I see. Just checked the ksp implementation and I'm not quite sure how are you going to implement the interface merging without FIR or IR transformations? What do you mean by "making the root one extend it"? I hope I'm not wasting your time by this questions 😅
z
we can’t modify sources
so the KSP implementation will generate a new class
and the original source impl will just need to manually extend it
or users will need to reference the generated component
more likely going to be the latter in the end
where we generate an API that looks like dagger’s, but it will call through an internal intermediary merged component we generated
i
Oh, I see
Thanks for explanation! Do you need any help?
z
No I just need reviews from the square side
👌 1
126 Views