retrofit icon indicating copy to clipboard operation
retrofit copied to clipboard

Add support for Kotlin's Result

Open Goooler opened this issue 2 years ago • 5 comments

  • Closes #3500.
  • Closes #3558.
  • Closes #3873.

Goooler avatar Dec 21 '23 14:12 Goooler

And if we should include this in default adapters?

Goooler avatar Dec 21 '23 14:12 Goooler

I tested this by including a build from this branch in Tusky. A release build crashes immediately with

java.lang.IllegalArgumentException: Unable to create call adapter for class F5.f
	for method d.W0
	at S7.i0.j(SourceFile:40)
	at S7.A.b(SourceFile:2844)
	at S7.c0.c(SourceFile:30)
	at S7.a0.invoke(SourceFile:36)
	at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
	at $Proxy3.W0(Unknown Source)
	at W3.P.t(SourceFile:40)
	at L5.a.i(SourceFile:6)
	at f6.a.c(SourceFile:140)
	at h2.f.R0(SourceFile:12)
	at a6.a.i0(SourceFile:76)
	at R4.l0.D0(SourceFile:30)
	at com.keylesspalace.tusky.MainActivity.onCreate(SourceFile:664)
	at android.app.Activity.performCreate(Activity.java:8051)
	at android.app.Activity.performCreate(Activity.java:8031)
	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1329)
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3608)
	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3792)
	at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2210)
	at android.os.Handler.dispatchMessage(Handler.java:106)
	at android.os.Looper.loopOnce(Looper.java:201)
	at android.os.Looper.loop(Looper.java:288)
	at android.app.ActivityThread.main(ActivityThread.java:7839)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
	Suppressed: f6.g: [s0{Cancelling}@4de4607, Dispatchers.Main.immediate]
Caused by: java.lang.IllegalStateException: Result must have a generic type (e.g., Result<T>)
	at S7.Z.a(SourceFile:40)
	at S7.c0.a(SourceFile:33)
	at S7.A.b(SourceFile:2686)
	... 27 more

Debug build seems fine.

connyduck avatar Mar 01 '24 09:03 connyduck

Ooops, need to keep kotlin.Result, fixed in 6e9b4b64414fa9239a035b885d4aea0f1a08dfd6.

Goooler avatar Mar 01 '24 10:03 Goooler

Now it does no longer crash at startup, but I can reproduce this bug that caused me to deprecate my calladapter.

Deobfuscated Stacktrace:

java.lang.ClassCastException: kotlin.Result cannot be cast to com.keylesspalace.tusky.entity.AppCredentials
	at com.keylesspalace.tusky.components.login.LoginActivity$onLoginClick$1.invokeSuspend(LoginActivity.kt:177)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:363)
	at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:26)
	at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:21)
	at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:88)
	at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:123)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:52)
	at kotlinx.coroutines.BuildersKt.launch(Builders.kt:1)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:43)
	at kotlinx.coroutines.BuildersKt.launch$default(Builders.kt:1)
	at com.keylesspalace.tusky.components.login.LoginActivity.onLoginClick(LoginActivity.kt:170)
	at com.keylesspalace.tusky.components.login.LoginActivity.onCreate$lambda$1(LoginActivity.kt:106)
	at android.view.View.performClick(View.java:7441)
	at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1218)
	at android.view.View.performClickInternal(View.java:7418)
	at android.view.View.access$3700(View.java:835)
	at android.view.View$PerformClick.run(View.java:28676)
	at android.os.Handler.handleCallback(Handler.java:938)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:201)
	at android.os.Looper.loop(Looper.java:288)
	at android.app.ActivityThread.main(ActivityThread.java:7839)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [s0{Cancelling}@b75f08b, Dispatchers.Main.immediate]

To reproduce, go offline and trigger some network calls (sometimes needs a few tries).

I think the main problem is that Result is a value class and as such is partially inlined at runtime.

connyduck avatar Mar 01 '24 13:03 connyduck

Reproduced! You are right, this is a bug of Kotlin, see:

  • https://github.com/Kotlin/kotlinx.coroutines/issues/3403
  • https://youtrack.jetbrains.com/issue/KT-27105
  • https://youtrack.jetbrains.com/issue/KT-27586
  • https://youtrack.jetbrains.com/issue/KT-53559
  • https://youtrack.jetbrains.com/issue/KT-68197

Goooler avatar Mar 01 '24 14:03 Goooler