Ivan Dugalic
04/24/2022, 4:20 PMeither
to Effect
. I like it BTW, it is a nice abstraction IMHO. But I have some issues. It is a multiplatform project and issue might not be related to Arrow, but it emerged once I switched to Effect
. It looks related to native
target(s) only. More in the thread …Ivan Dugalic
04/24/2022, 4:20 PMDetails: Internal error in body lowering: kotlin.NotImplementedError: An operation is not implemented: Unknown file
* Source files:
* Compiler version info: Konan: 1.6.21 / Kotlin: 1.6.21
* Output kind: PROGRAM
e: org.jetbrains.kotlin.backend.common.CompilationException: Back-end: Please report this problem <https://kotl.in/issue>
/home/runner/work/fmodel/fmodel/application-arrow/src/commonMain/kotlin/com/fraktalio/fmodel/application/MaterializedViewArrowExtension.kt:36:9
Problem with `suspend fun <S : Any?, E : Any?> MaterializedView<S, E>.handleEither(event: E): Effect<Error, S> {
local fun S?.eitherComputeNewStateOrFail(event: E): Effect<Error, S> {
return effect<Error, S>(f = local suspend fun EffectScope<Error>.<anonymous>(): S {
return try { // BLOCK
(<this>, <this>).computeNewState(event = event)
}
catch (t: Throwable){ // BLOCK
$this$effect.shift<S>(r = CalculatingNewViewStateFailed<S?, E>(state = <this>, event = event, throwable = t.nonFatalOrThrow()))
}
}
Ivan Dugalic
04/24/2022, 4:21 PMIvan Dugalic
04/24/2022, 4:22 PM<https://github.com/fraktalio/fmodel/pull/95/files>
simon.vergauwen
04/25/2022, 7:06 AMsimon.vergauwen
04/25/2022, 7:06 AMsimon.vergauwen
04/25/2022, 7:07 AMinline suspend
. There are a couple issues with that still, are you using that a lot in your code?raulraja
04/25/2022, 7:59 AMraulraja
04/25/2022, 8:01 AMval IrDeclaration.file: IrFile
get() = fileOrNull ?: TODO("Unknown file")
simon.vergauwen
04/25/2022, 8:02 AMSeems like is hitting one of these two, maybe if we can look at the actual declaration failing with the debugger we can workaround it and submit an issueThat'd be great! Inline suspension seems to be stabilizing in the compiler relatively fast, if we can support them with good issues that'd be awesome Nice find!
Ivan Dugalic
04/25/2022, 8:37 AMgood
issue 😞 TBH, I would need time to understand it at first.raulraja
04/25/2022, 8:39 AMsuspend fun <S : Any?, E : Any?> MaterializedView<S, E>.handleEither(event: E): Effect<Error, S>
have local function on its body?raulraja
04/25/2022, 8:40 AMraulraja
04/25/2022, 8:40 AMlocal fun S?.eitherComputeNewStateOrFail(event: E): Effect<Error, S>
raulraja
04/25/2022, 8:42 AMraulraja
04/25/2022, 8:42 AMIvan Dugalic
04/25/2022, 8:43 AMIvan Dugalic
04/25/2022, 8:44 AM<https://github.com/fraktalio/fmodel/pull/95/files>
) is not doing much. Only switching to efffect
It was working with either
. Everything else is the same.Ivan Dugalic
04/25/2022, 8:47 AMIvan Dugalic
04/25/2022, 8:48 AMe: org.jetbrains.kotlin.backend.common.CompilationException: Back-end: Please report this problem <https://kotl.in/issue>
/Users/idugalic/work/fraktalio/fmodel/application-arrow/src/commonMain/kotlin/com/fraktalio/fmodel/application/MaterializedViewArrowExtension.kt:36:9
Problem with `suspend fun <S : Any?, E : Any?> MaterializedView<S, E>.handleEither(event: E): Effect<Error, S> {
return effect<Error, S>(f = local suspend fun EffectScope<Error>.<anonymous>(): S {
return (<this>, (<this>, (<this>, event).fetchState()).computeNewState(event = event)).save()
}
)
}
`
Details: Internal error in body lowering: kotlin.NotImplementedError: An operation is not implemented: Unknown file
at org.jetbrains.kotlin.ir.util.IrUtilsKt.getFile(IrUtils.kt)
at org.jetbrains.kotlin.backend.common.lower.LocalDeclarationsLowering$LocalDeclarationsTransformer.collectLocalDeclarations(LocalDeclarationsLowering.kt:893)
...
Ivan Dugalic
04/25/2022, 8:55 AMnative
targets.Ivan Dugalic
04/25/2022, 8:55 AM// val hostOs = System.getProperty("os.name")
// val isMingwX64 = hostOs.startsWith("Windows")
// val nativeTarget = when {
// hostOs == "Mac OS X" -> macosX64()
// hostOs == "Linux" -> linuxX64()
// isMingwX64 -> mingwX64()
// else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
// }
// nativeTarget.compilations.all {
// kotlinOptions.verbose = true
// }
Ivan Dugalic
04/25/2022, 9:43 AMraulraja
04/25/2022, 9:50 AMlocal suspend fun EffectScope<Error>.<anonymous>()
raulraja
04/25/2022, 9:50 AMLocalDeclarationsLowering$LocalDeclarationsTransformer.collectLocalDeclarations(LocalDeclarationsLowering.kt:893)
Ivan Dugalic
04/25/2022, 11:33 AMlocal
is coming. I believe I removed all local/inner scope functions. I have further simplified the case (handlerEither function)Ivan Dugalic
04/25/2022, 11:33 AMfun <S, E> handleEither(event: E): Effect<Throwable, S> = effect {
shift(RuntimeException("OUPS"))
}
Ivan Dugalic
04/25/2022, 11:33 AMIvan Dugalic
04/25/2022, 11:34 AMclass MaterializedViewTest : FunSpec({
test("Materialized view - even number added") {
handleEither<EvenNumberState, NumberEvent.EvenNumberEvent>(
EvenNumberAdded(
Description("2"),
NumberValue(2)
)
)
}
})
Ivan Dugalic
04/25/2022, 11:34 AMIvan Dugalic
04/25/2022, 11:35 AMe: org.jetbrains.kotlin.backend.common.CompilationException: Back-end: Please report this problem <https://kotl.in/issue>
/Users/idugalic/work/fraktalio/fmodel/application-arrow/src/commonMain/kotlin/com/fraktalio/fmodel/application/MaterializedViewArrowExtension.kt:31:1
Problem with `fun <S : Any?, E : Any?> handleEither(event: E): Effect<Throwable, S> {
return effect<Throwable, S>(f = local suspend fun EffectScope<Throwable>.<anonymous>(): S {
return $this$effect.shift<S>(r = RuntimeException(message = "OUPS"))
}
)
}
`
Details: Internal error in body lowering: kotlin.NotImplementedError: An operation is not implemented: Unknown file
at org.jetbrains.kotlin.ir.util.IrUtilsKt.getFile(IrUtils.kt)
at org.jetbrains.kotlin.backend.common.lower.LocalDeclarationsLowering$LocalDeclarationsTransformer.collectLocalDeclarations(LocalDeclarationsLowering.kt:893)
at org.jetbrains.kotlin.backend.common.lower.LocalDeclarationsLowering$LocalDeclarationsTransformer.lowerLocalDeclarations(LocalDeclarationsLowering.kt:248)
at org.jetbrains.kotlin.backend.common.lower.LocalDeclarationsLowering.lower(LocalDeclarationsLowering.kt:102)
at org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineLambdasLowering$lower$1.visitCall(LocalClasses.kt:59)
at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitCall(IrElementTransformerVoid.kt:215)
at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitCall(IrElementTransformerVoid.kt:24)
at org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl.accept(IrCallImpl.kt:47)
at org.jetbrains.kotlin.ir.expressions.IrExpression.transform(IrExpression.kt:33)
Ivan Dugalic
04/25/2022, 11:42 AMsimon.vergauwen
04/25/2022, 12:05 PMlocal
come from the fact that the EffectScope
is an anonymous implementation?
https://github.com/arrow-kt/arrow/blob/eeac854dec3677fc8fd42871a7df136f3ba0d02f/ar[…]w-core/src/commonMain/kotlin/arrow/core/continuations/Effect.kt
Weird that it's only failing for native though, since it seems to be failing in common
code 🤔simon.vergauwen
04/25/2022, 12:05 PMIR
so more likely during code-gen phase.Ivan Dugalic
04/25/2022, 12:16 PMDoes the local come from the fact that the EffectScope is an anonymous implementation?
It could be you are on the right track.raulraja
04/25/2022, 12:28 PMf
raulraja
04/25/2022, 12:29 PMeffect
function that uses a class instead of the object to implement Effect
raulraja
04/25/2022, 12:32 PMf
. Also not sure inline here buys us much, it may be creating bigger binaries because of the inlined implIvan Dugalic
04/25/2022, 12:34 PMIvan Dugalic
04/25/2022, 1:59 PMIvan Dugalic
04/25/2022, 2:00 PMfun <R, A> myEffect(f: suspend EffectScope<R>.() -> A): Effect<R, A> = MyEffect(f)
class MyEffect<R, A>(val f: suspend EffectScope<R>.() -> A) : Effect<R, A> { // copy-pasted the implementation }
Ivan Dugalic
04/25/2022, 2:10 PMraulraja
04/25/2022, 2:14 PMraulraja
04/25/2022, 2:15 PMraulraja
04/25/2022, 2:16 PMIvan Dugalic
04/25/2022, 2:25 PMraulraja
04/25/2022, 2:26 PMIvan Dugalic
04/25/2022, 2:29 PMIvan Dugalic
04/25/2022, 2:56 PMinline fun <R, A> myEffect(crossinline f: suspend EffectScope<R>.() -> A): Effect<R, A> = object : Effect<R, A> { Copy pasting Arrow code here, overriding the methods. Implementing Token, Suspend and FoldContinuation internal classes }
Ivan Dugalic
04/25/2022, 2:57 PMsimon.vergauwen
04/25/2022, 3:20 PMIvan Dugalic
04/25/2022, 3:24 PMmyEffect
☝️Ivan Dugalic
04/25/2022, 3:25 PMIvan Dugalic
04/25/2022, 3:25 PMfun <S, E> handleEither(event: E): Effect<Throwable, S> = myEffect {
shift(RuntimeException("OUPS"))
}
This does not work:Ivan Dugalic
04/25/2022, 3:26 PMfun <S, E> handleEither(event: E): Effect<Throwable, S> = effect {
shift(RuntimeException("OUPS"))
}
simon.vergauwen
04/25/2022, 3:27 PMsimon.vergauwen
04/25/2022, 3:27 PMIvan Dugalic
04/25/2022, 3:27 PMraulraja
04/25/2022, 3:27 PMIvan Dugalic
04/25/2022, 3:30 PMEffect
is being placed in the same module under comonMain
source set/compilation.Ivan Dugalic
04/25/2022, 3:31 PM@PublishedApi
internal class Token {
override fun toString(): String = "Token(${hashCode().toString(16)})"
}
@PublishedApi
internal class Suspend(val token: Token, val shifted: Any?, val recover: suspend (Any?) -> Any?) : ShiftCancellationException() {
override fun toString(): String = "ShiftCancellationException($message)"
}
@PublishedApi
internal class FoldContinuation<B>(
private val token: Token,
override val context: CoroutineContext,
private val parent: Continuation<B>
) : Continuation<B> {
override fun resumeWith(result: Result<B>) {
result.fold(parent::resume) { throwable ->
if (throwable is Suspend && token == throwable.token) {
val f: suspend () -> B = { throwable.recover(throwable.shifted) as B }
when (val res = f.startCoroutineUninterceptedOrReturn(parent)) {
COROUTINE_SUSPENDED -> Unit
else -> parent.resume(res as B)
}
} else parent.resumeWith(result)
}
}
}
sealed class ShiftCancellationException : CancellationException("Shifted Continuation")
inline fun <R, A> myEffect(crossinline f: suspend EffectScope<R>.() -> A): Effect<R, A> = object : Effect<R, A> {
override suspend fun <B> fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B =
suspendCoroutineUninterceptedOrReturn { cont ->
val token = Token()
val effectScope =
object : EffectScope<R> {
override suspend fun <B> shift(r: R): B =
throw Suspend(token, r, recover as suspend (Any?) -> Any?)
}
try {
suspend { transform(f(effectScope)) }
.startCoroutineUninterceptedOrReturn(FoldContinuation(token, cont.context, cont))
} catch (e: Suspend) {
if (token == e.token) {
val f: suspend () -> B = { e.recover(e.shifted) as B }
f.startCoroutineUninterceptedOrReturn(cont)
} else throw e
}
}
}
fun <S, E> handleEither(event: E): Effect<Throwable, S> = myEffect {
shift(RuntimeException("OUPS"))
}
raulraja
04/25/2022, 3:32 PMIvan Dugalic
04/25/2022, 3:32 PMIvan Dugalic
04/25/2022, 3:32 PMIvan Dugalic
04/25/2022, 3:42 PMcommonMain
Ivan Dugalic
04/25/2022, 3:44 PMraulraja
04/25/2022, 3:45 PMsimon.vergauwen
04/25/2022, 3:46 PMIvan Dugalic
04/25/2022, 3:47 PMIvan Dugalic
04/25/2022, 3:50 PMIvan Dugalic
06/03/2022, 6:01 PMbuild
is green (https://github.com/fraktalio/fmodel/actions/runs/2436185398) and I am going to continue with adopting Effect
. You can find more here https://youtrack.jetbrains.com/issue/KT-52540/Internal-error-in-body-lowering-kotlinNotImplementedError (in case someone else runs into a similar issue).