Hi! We have just introduced Arrow Optics version 2...
# arrow
d
Hi! We have just introduced Arrow Optics version 2.0.1 with ksp to our project and it compiles and runs just fine, except that it crashes with a RuntimeException when opening a screen from a SDK that we use, with the following exception:
Copy code
FATAL EXCEPTION: DefaultDispatcher-worker-2
Process: no.norsktipping.android.maestro.debug, PID: 21534
java.lang.NoSuchMethodError: No virtual method milliseconds-UwyO8pc(J)J in class Lkotlin/time/Duration$Companion; or its super classes (declaration of 'kotlin.time.Duration$Companion' appears in /data/app/~~OmkWAYIviJY1rc00zUAm8A==/no.norsktipping.android.maestro.debug-mJDZvG7ZQHYio7dbAEFP4Q==/base.apk!classes40.dex)
	at dk.shape.danskespil.foundation.repository.GamesCachingKt.refreshJob(Unknown Source:6)
	at dk.shape.danskespil.foundation.repository.GamesCachingKt.access$refreshJob(Unknown Source:0)
I suspect that it might have something to do with some of our dependencies using another version of kotlin, that is binary incompatible with ours. We use kotlin 2.0.21. Anyone knows if I'm on the right track? Is this a known issue? Is there anything I can do? When removing Arrow from the project the crash disappears.
a
this is really strange... the only problem I could think of is Arrow bringing some unexpected version bump. Could you look at the output of Gradle dependencies and see if there's some change in
kotlin-stdlib
between both?
d
I'm not very familiar with inspecting gradle dependencies, but as far as I can tell Arrow uses kotlin 2.1.0
Copy code
|    |    \--- io.arrow-kt:arrow-optics:2.0.1
|    |         \--- io.arrow-kt:arrow-optics-android:2.0.1
|    |              +--- io.arrow-kt:arrow-core:2.0.1
|    |              |    \--- io.arrow-kt:arrow-core-android:2.0.1
|    |              |         +--- io.arrow-kt:arrow-atomic:2.0.1
|    |              |         |    \--- io.arrow-kt:arrow-atomic-android:2.0.1
|    |              |         |         +--- org.jetbrains.kotlin:kotlin-stdlib -> 2.1.0 (*)
|    |              |         |         +--- org.codehaus.mojo:animal-sniffer-annotations:1.24
|    |              |         |         \--- org.jetbrains.kotlin:kotlin-stdlib:2.1.0 (c)
|    |              |         +--- io.arrow-kt:arrow-annotations:2.0.1
|    |              |         |    \--- io.arrow-kt:arrow-annotations-android:2.0.1
|    |              |         |         +--- org.codehaus.mojo:animal-sniffer-annotations:1.24
|    |              |         |         +--- org.jetbrains.kotlin:kotlin-stdlib -> 2.1.0 (*)
|    |              |         |         \--- org.jetbrains.kotlin:kotlin-stdlib:2.1.0 (c)
|    |              |         +--- org.jetbrains.kotlin:kotlin-stdlib -> 2.1.0 (*)
|    |              |         +--- org.codehaus.mojo:animal-sniffer-annotations:1.24
|    |              |         \--- org.jetbrains.kotlin:kotlin-stdlib:2.1.0 (c)
|    |              +--- org.jetbrains.kotlin:kotlin-stdlib -> 2.1.0 (*)
|    |              +--- org.codehaus.mojo:animal-sniffer-annotations:1.24
|    |              \--- org.jetbrains.kotlin:kotlin-stdlib:2.1.0 (c)
and the sdk that crashes uses 1.9.0
Copy code
|    |    +--- dk.shape.games.norsk-tipping-oddsen:norsk-tipping-oddsen-android-fataar:2.0.0
|    |    |    +--- org.jetbrains.kotlin:kotlin-parcelize-runtime:1.9.0 -> 2.0.21 (*)
|    |    |    +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.0 -> 2.1.0 (*)
|    |    |    +--- org.jetbrains.kotlin:kotlin-reflect:1.9.0 -> 2.0.21 (*)
|    |    |    +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2 -> 1.9.0 (*)
|    |    |    +--- org.jetbrains.kotlinx:kotlinx-coroutines-reactive:1.5.2 -> 1.9.0
|    |    |    |    +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0 (*)
|    |    |    |    +--- org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.9.0 (*)
|    |    |    |    +--- org.reactivestreams:reactive-streams:1.0.3
|    |    |    |    \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 -> 2.1.0 (*)
|    |    |    +--- org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.5.2 -> 1.9.0
|    |    |    |    +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0 (*)
|    |    |    |    +--- org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.9.0 (*)
|    |    |    |    \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 -> 2.1.0 (*)
|    |    |    +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0 -> 1.9.20 (*)
|    |    |    +--- org.jetbrains:annotations:20.1.0 -> 23.0.0
|    |    |    +--- org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.0 -> 1.7.3 (*)
...but I'm not sure 🙂 Please guide me if this is not what we are looking for 🙂
a
yep, that seems exactly what may be causing the problem, since
milliseconds-UwyO8pc(J)J
is a public name for their value classes unboxed functions, and these may have changed
you may want to force
1.9.0
to be used instead of
2.1.0
, maybe this would not break anything in Arrow (although it would be better if the SDK was updated to compile against 2.1.0, I understand this might be difficult)
d
Can you help me with that? I guess what I should be googling is "force version of transitive dependency" or something, but this is not my field of expertise 🫠
(And yes, we will create an issue for our sdk provider to upgrade to newer kotlin versions, but this will probably take some time..)
d
I didn't get it working.. 🥲 Tried to do something like this in relevant modules:
Copy code
configurations.all {
    resolutionStrategy.force("org.jetbrains.kotlin:kotlin-stdlib:1.9.0")
}
But, since it crashes when calling code from the sdk (which uses kotlin 1.9.0), how does forcing Arrow (which is not called anywhere near that sdk) to kotlin 1.9.0 mitigate that crash? How can Arrow break code in another module? Will all dependencies in all modules end up using the same kotlin binary when compiled or something? 🤔
a
the problem is not that Arrow breaks code... it's that by depending on Arrow you transitively depend on stdlib 2.1.0 (the default resolution strategy is to use the latest version). Unfortunately the stdlib 2.x is not compatible with 1.9, so the SDK you are using breaks because it's trying to call a method it knew from stdlib 1.9 which is no longet present in 2.x
you should be able to reproduce this without Arrow if you explicitly depend on stdlib 2.1 in some of your build
d
Thank you for the explanation! I can indeed confirm that the problem is still there if removing Arrow but upgrading the rest of the project to 2.1.x. Even more reason to push our sdk provider to upgrade their kotlin version. Thank you for your time! 🙏
Aaand, I actually got it working now by excluding arrow's kotlin transitive dependency:
Copy code
implementation(libs.arrow.optics) {
    exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib")
}
(which I guess was what you tried to make me do yesterday which I didn't catch 🥲)
a
I'm glad you made it work! 💪