Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Pass Trace transparently through withError #3358

Draft
wants to merge 25 commits into
base: arrow-2
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
af2aedd
Pass Trace transparently through withError.
kyay10 Jan 23, 2024
30040fd
Merge branch 'arrow-2' into kyay10/with-error-traced
kyay10 Jan 23, 2024
90c27f9
Branch was auto-updated.
github-actions[bot] Jan 30, 2024
d699c88
Add Raise.underlyingRaise with default implementation
kyay10 Feb 1, 2024
3c100b8
Branch was auto-updated.
github-actions[bot] Feb 6, 2024
1c533d7
Branch was auto-updated.
github-actions[bot] Feb 6, 2024
9d8dbb9
Branch was auto-updated.
github-actions[bot] Feb 6, 2024
158242e
Branch was auto-updated.
github-actions[bot] Feb 6, 2024
4886dde
Branch was auto-updated.
github-actions[bot] Feb 6, 2024
d028021
Branch was auto-updated.
github-actions[bot] Feb 8, 2024
341931e
Branch was auto-updated.
github-actions[bot] Feb 8, 2024
a63eeaf
Branch was auto-updated.
github-actions[bot] Feb 18, 2024
cef9426
Branch was auto-updated.
github-actions[bot] Feb 19, 2024
9317bb7
Branch was auto-updated.
github-actions[bot] Apr 13, 2024
75db109
Branch was auto-updated.
github-actions[bot] Apr 14, 2024
6247698
Branch was auto-updated.
github-actions[bot] Apr 14, 2024
c962527
Branch was auto-updated.
github-actions[bot] Apr 16, 2024
4999684
Branch was auto-updated.
github-actions[bot] Apr 17, 2024
9980d54
Branch was auto-updated.
github-actions[bot] Apr 17, 2024
1e61243
Branch was auto-updated.
github-actions[bot] Apr 17, 2024
29d8c07
Branch was auto-updated.
github-actions[bot] Apr 17, 2024
5a48eb4
Branch was auto-updated.
github-actions[bot] Apr 17, 2024
f49df4f
Branch was auto-updated.
github-actions[bot] Apr 17, 2024
47cb3e6
Branch was auto-updated.
github-actions[bot] May 13, 2024
9ed9b46
Branch was auto-updated.
github-actions[bot] May 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 41 additions & 53 deletions arrow-libs/core/arrow-core/api/arrow-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -901,25 +901,15 @@ public abstract interface annotation class arrow/core/raise/DelicateRaiseApi : j
public abstract interface annotation class arrow/core/raise/ExperimentalTraceApi : java/lang/annotation/Annotation {
}

public final class arrow/core/raise/IorRaise : arrow/core/raise/Raise {
public final class arrow/core/raise/IorRaise : arrow/core/raise/RaiseWrapper {
public fun <init> (Lkotlin/jvm/functions/Function2;Ljava/util/concurrent/atomic/AtomicReference;Larrow/core/raise/Raise;)V
public fun bind (Larrow/core/Either;)Ljava/lang/Object;
public final fun bind (Larrow/core/Ior;)Ljava/lang/Object;
public fun bind (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun bindAll (Ljava/lang/Iterable;)Ljava/util/List;
public fun bindAll (Ljava/util/Map;)Ljava/util/Map;
public fun bindAll-1TN0_VU (Ljava/util/Set;)Ljava/util/Set;
public fun bindAll-vcjLgH4 (Ljava/util/List;)Ljava/util/List;
public final fun bindAllIor (Ljava/lang/Iterable;)Ljava/util/List;
public final fun bindAllIor (Ljava/util/List;)Ljava/util/List;
public final fun bindAllIor (Ljava/util/Map;)Ljava/util/Map;
public final fun bindAllIor (Ljava/util/Set;)Ljava/util/Set;
public final fun combine (Ljava/lang/Object;)Ljava/lang/Object;
public final fun getCombineError ()Lkotlin/jvm/functions/Function2;
public fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun raise (Ljava/lang/Object;)Ljava/lang/Void;
public final fun recover (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
}

Expand Down Expand Up @@ -948,26 +938,21 @@ public final class arrow/core/raise/Raise$DefaultImpls {
public static fun invoke (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public class arrow/core/raise/RaiseAccumulate : arrow/core/raise/Raise {
public class arrow/core/raise/RaiseAccumulate : arrow/core/raise/TransformingRaise {
public fun <init> (Larrow/core/raise/Raise;)V
public final fun _mapOrAccumulate (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)Ljava/util/List;
public final fun _mapOrAccumulate (Ljava/util/List;Lkotlin/jvm/functions/Function2;)Ljava/util/List;
public final fun _mapOrAccumulate (Ljava/util/Set;Lkotlin/jvm/functions/Function2;)Ljava/util/Set;
public fun bind (Larrow/core/Either;)Ljava/lang/Object;
public fun bind (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun bindAll (Ljava/lang/Iterable;)Ljava/util/List;
public fun bindAll (Ljava/util/Map;)Ljava/util/Map;
public fun bindAll-1TN0_VU (Ljava/util/Set;)Ljava/util/Set;
public fun bindAll-vcjLgH4 (Ljava/util/List;)Ljava/util/List;
public final fun bindNel (Larrow/core/Either;)Ljava/lang/Object;
public final fun getRaise ()Larrow/core/raise/Raise;
public fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun mapOrAccumulate (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)Ljava/util/List;
public final fun mapOrAccumulate-FrVv2gs (Ljava/util/List;Lkotlin/jvm/functions/Function2;)Ljava/util/List;
public final fun mapOrAccumulate-nfMsDo0 (Ljava/util/Set;Lkotlin/jvm/functions/Function2;)Ljava/util/Set;
public fun raise (Ljava/lang/Object;)Ljava/lang/Void;
public synthetic fun transform (Ljava/lang/Object;)Ljava/lang/Object;
protected fun transform-0-xjo5U (Ljava/lang/Object;)Ljava/util/List;
public final fun withNel (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
}

Expand Down Expand Up @@ -1016,11 +1001,14 @@ public final class arrow/core/raise/RaiseKt {
public static final fun merge (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static final fun nullable (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public static final fun option (Lkotlin/jvm/functions/Function1;)Larrow/core/Option;
public static final fun raiseWithTrace-LzgXH30 (Larrow/core/raise/Raise;Larrow/core/raise/Traced;Ljava/lang/Object;)Ljava/lang/Void;
public static final fun raisedOrRethrow (Ljava/util/concurrent/CancellationException;Larrow/core/raise/DefaultRaise;)Ljava/lang/Object;
public static final fun realUnderlying (Larrow/core/raise/Raise;)Larrow/core/raise/DefaultRaise;
public static final fun recover (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public static final fun recover (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public static final fun recover (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function1;
public static final fun recover (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function2;
public static final fun recoverTraced (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
public static final fun result (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public static final fun singleton (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public static final fun toEither (Lkotlin/jvm/functions/Function1;)Larrow/core/Either;
Expand All @@ -1034,7 +1022,6 @@ public final class arrow/core/raise/RaiseKt {
public static final fun toResult (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static final fun toResult (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static final fun traced (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
public static final fun withCause (Larrow/core/raise/Traced;Larrow/core/raise/Traced;)Larrow/core/raise/Traced;
public static final fun withError (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function9;)Ljava/lang/Object;
public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function8;)Ljava/lang/Object;
Expand All @@ -1054,38 +1041,25 @@ public final class arrow/core/raise/RaiseKt {
public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
}

public final class arrow/core/raise/ResultRaise : arrow/core/raise/Raise {
public abstract class arrow/core/raise/RaiseWrapper : arrow/core/raise/TransformingRaise {
public fun <init> (Larrow/core/raise/Raise;)V
protected final fun transform (Ljava/lang/Object;)Ljava/lang/Object;
}

public final class arrow/core/raise/ResultRaise : arrow/core/raise/RaiseWrapper {
public fun <init> (Larrow/core/raise/Raise;)V
public fun bind (Larrow/core/Either;)Ljava/lang/Object;
public final fun bind (Ljava/lang/Object;)Ljava/lang/Object;
public fun bind (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun bindAll (Ljava/lang/Iterable;)Ljava/util/List;
public fun bindAll (Ljava/util/Map;)Ljava/util/Map;
public fun bindAll-1TN0_VU (Ljava/util/Set;)Ljava/util/Set;
public fun bindAll-vcjLgH4 (Ljava/util/List;)Ljava/util/List;
public final fun bindAllResult (Ljava/lang/Iterable;)Ljava/util/List;
public final fun bindAllResult (Ljava/util/List;)Ljava/util/List;
public final fun bindAllResult (Ljava/util/Map;)Ljava/util/Map;
public final fun bindAllResult (Ljava/util/Set;)Ljava/util/Set;
public fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public synthetic fun raise (Ljava/lang/Object;)Ljava/lang/Void;
public fun raise (Ljava/lang/Throwable;)Ljava/lang/Void;
public final fun recover (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
}

public final class arrow/core/raise/SingletonRaise : arrow/core/raise/Raise {
public final class arrow/core/raise/SingletonRaise : arrow/core/raise/TransformingRaise {
public fun <init> (Larrow/core/raise/Raise;)V
public fun bind (Larrow/core/Either;)Ljava/lang/Object;
public final fun bind (Larrow/core/Option;)Ljava/lang/Object;
public final fun bind (Ljava/lang/Object;)Ljava/lang/Object;
public fun bind (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun bindAll (Ljava/lang/Iterable;)Ljava/util/List;
public fun bindAll (Ljava/util/Map;)Ljava/util/Map;
public fun bindAll-1TN0_VU (Ljava/util/Set;)Ljava/util/Set;
public fun bindAll-vcjLgH4 (Ljava/util/List;)Ljava/util/List;
public final fun bindAllNullable (Ljava/lang/Iterable;)Ljava/util/List;
public final fun bindAllNullable (Ljava/util/List;)Ljava/util/List;
public final fun bindAllNullable (Ljava/util/Map;)Ljava/util/Map;
Expand All @@ -1097,26 +1071,40 @@ public final class arrow/core/raise/SingletonRaise : arrow/core/raise/Raise {
public final fun ensure (Z)V
public final fun ensureNotNull (Ljava/lang/Object;)Ljava/lang/Object;
public final fun ignoreErrors (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun raise ()Ljava/lang/Void;
public fun raise (Ljava/lang/Object;)Ljava/lang/Void;
public final fun recover (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;
public synthetic fun transform (Ljava/lang/Object;)Ljava/lang/Object;
}

public final class arrow/core/raise/Trace {
public static final synthetic fun box-impl (Ljava/util/concurrent/CancellationException;)Larrow/core/raise/Trace;
public static fun constructor-impl (Ljava/util/concurrent/CancellationException;)Ljava/util/concurrent/CancellationException;
public static final synthetic fun box-impl (Larrow/core/raise/Traced;)Larrow/core/raise/Trace;
public static fun constructor-impl (Larrow/core/raise/Traced;)Larrow/core/raise/Traced;
public fun equals (Ljava/lang/Object;)Z
public static fun equals-impl (Ljava/util/concurrent/CancellationException;Ljava/lang/Object;)Z
public static final fun equals-impl0 (Ljava/util/concurrent/CancellationException;Ljava/util/concurrent/CancellationException;)Z
public static fun equals-impl (Larrow/core/raise/Traced;Ljava/lang/Object;)Z
public static final fun equals-impl0 (Larrow/core/raise/Traced;Larrow/core/raise/Traced;)Z
public fun hashCode ()I
public static fun hashCode-impl (Ljava/util/concurrent/CancellationException;)I
public static final fun printStackTrace-impl (Ljava/util/concurrent/CancellationException;)V
public static final fun stackTraceToString-impl (Ljava/util/concurrent/CancellationException;)Ljava/lang/String;
public static final fun suppressedExceptions-impl (Ljava/util/concurrent/CancellationException;)Ljava/util/List;
public static fun hashCode-impl (Larrow/core/raise/Traced;)I
public static final fun printStackTrace-impl (Larrow/core/raise/Traced;)V
public static final fun stackTraceToString-impl (Larrow/core/raise/Traced;)Ljava/lang/String;
public static final fun suppressedExceptions-impl (Larrow/core/raise/Traced;)Ljava/util/List;
public fun toString ()Ljava/lang/String;
public static fun toString-impl (Ljava/util/concurrent/CancellationException;)Ljava/lang/String;
public final synthetic fun unbox-impl ()Ljava/util/concurrent/CancellationException;
public static fun toString-impl (Larrow/core/raise/Traced;)Ljava/lang/String;
public final synthetic fun unbox-impl ()Larrow/core/raise/Traced;
}

public abstract class arrow/core/raise/TransformingRaise : arrow/core/raise/Raise {
public fun <init> (Larrow/core/raise/Raise;)V
public fun bind (Larrow/core/Either;)Ljava/lang/Object;
public fun bind (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun bindAll (Ljava/lang/Iterable;)Ljava/util/List;
public fun bindAll (Ljava/util/Map;)Ljava/util/Map;
public fun bindAll-1TN0_VU (Ljava/util/Set;)Ljava/util/Set;
public fun bindAll-vcjLgH4 (Ljava/util/List;)Ljava/util/List;
public final fun getRaise ()Larrow/core/raise/Raise;
public fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun raise (Ljava/lang/Object;)Ljava/lang/Void;
protected abstract fun transform (Ljava/lang/Object;)Ljava/lang/Object;
}

Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.experimental.ExperimentalTypeInference
import kotlin.js.JsName
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName

Expand Down Expand Up @@ -156,12 +157,12 @@ public inline fun impure(block: SingletonRaise<Unit>.() -> Unit) {
return singleton({ }, block)
}

public class SingletonRaise<in E>(private val raise: Raise<Unit>): Raise<E> {
@RaiseDSL
public fun raise(): Nothing = raise.raise(Unit)
public class SingletonRaise<in E>(raise: Raise<Unit>): TransformingRaise<E, Unit>(raise) {
override fun transform(r: E) { }

@RaiseDSL
override fun raise(r: E): Nothing = raise()
@JsName("raiseUnit")
public fun raise(): Nothing = raise.raise(Unit)

@RaiseDSL
public fun ensure(condition: Boolean) {
Expand Down Expand Up @@ -258,7 +259,7 @@ public class SingletonRaise<in E>(private val raise: Raise<Unit>): Raise<E> {
* Implementation of [Raise] used by [result].
* You should never use this directly.
*/
public class ResultRaise(private val raise: Raise<Throwable>) : Raise<Throwable> by raise {
public class ResultRaise(raise: Raise<Throwable>) : RaiseWrapper<Throwable>(raise) {
@RaiseDSL
public fun <A> Result<A>.bind(): A = fold(::identity) { raise(it) }

Expand Down Expand Up @@ -298,8 +299,8 @@ public class ResultRaise(private val raise: Raise<Throwable>) : Raise<Throwable>
public class IorRaise<Error> @PublishedApi internal constructor(
@PublishedApi internal val combineError: (Error, Error) -> Error,
private val state: Atomic<Any?>,
private val raise: Raise<Error>,
) : Raise<Error> by raise {
raise: Raise<Error>,
) : RaiseWrapper<Error>(raise) {
@Suppress("UNCHECKED_CAST")
@PublishedApi
internal fun combine(e: Error): Error = state.updateAndGet { EmptyValue.combine(it, e, combineError) } as Error
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,27 @@ public inline fun <Error, A, B> foldUnsafe(
}
}

@OptIn(DelicateRaiseApi::class)
@ExperimentalTraceApi
@RaiseDSL
public inline fun <Error, A> recoverTraced(
@BuilderInference block: Raise<Error>.() -> A,
recover: (trace: Trace, error: Error) -> A
): A {
contract {
callsInPlace(block, AT_MOST_ONCE)
callsInPlace(recover, AT_MOST_ONCE)
}
val nested = DefaultRaise(true)
return try {
block(nested).also { nested.complete() }
} catch (e: Traced) {
nested.complete()
val r: Error = e.raisedOrRethrow(nested)
recover(Trace(e), r)
}
}

/**
* Inspect a [Trace] value of [Error].
*
Expand Down Expand Up @@ -232,27 +253,21 @@ public inline fun <Error, A> Raise<Error>.traced(
callsInPlace(block, AT_MOST_ONCE)
callsInPlace(trace, AT_MOST_ONCE)
}
val nested = DefaultRaise(true)
return try {
block(nested).also { nested.complete() }
} catch (e: Traced) {
nested.complete()
val r: Error = e.raisedOrRethrow(nested)
trace(Trace(e), r)
// If our outer Raise happens to be traced
// Then we want the stack trace to match the inner one
try {
raise(r)
} catch (rethrown: Traced) {
throw rethrown.withCause(e)
}
return recoverTraced(block) { t, r ->
trace(t, r)
raiseWithTrace(t, r)
}
}

@PublishedApi
@DelicateRaiseApi
internal fun Traced.withCause(cause: Traced): Traced =
Traced(raised, raise, cause)
@ExperimentalTraceApi
@RaiseDSL
public fun <Error> Raise<Error>.raiseWithTrace(trace: Trace, r: Error): Nothing =
try {
raise(r)
} catch (rethrown: Traced) {
throw Traced(rethrown.raised, rethrown.raise, trace)
}

/** Returns the raised value, rethrows the CancellationException if not our scope */
@PublishedApi
Expand All @@ -271,13 +286,21 @@ internal class DefaultRaise(@PublishedApi internal val isTraced: Boolean) : Rais

@PublishedApi
internal fun complete(): Boolean = isActive.getAndSet(false)
@OptIn(DelicateRaiseApi::class)
@OptIn(DelicateRaiseApi::class, ExperimentalTraceApi::class)
override fun raise(r: Any?): Nothing = when {
isActive.value -> throw if (isTraced) Traced(r, this) else NoTrace(r, this)
else -> throw RaiseLeakedException()
}
}

@DelicateRaiseApi
@PublishedApi
internal tailrec fun Raise<*>.realUnderlying(): DefaultRaise =
when (this) {
is TransformingRaise<*, *> -> raise.realUnderlying()
is DefaultRaise -> this
}

@MustBeDocumented
@Retention(AnnotationRetention.BINARY)
@RequiresOptIn(RaiseCancellationExceptionCaptured, RequiresOptIn.Level.WARNING)
Expand All @@ -298,7 +321,8 @@ public sealed class RaiseCancellationException(
internal expect class NoTrace(raised: Any?, raise: Raise<Any?>) : RaiseCancellationException

@DelicateRaiseApi
internal class Traced(raised: Any?, raise: Raise<Any?>, override val cause: Traced? = null): RaiseCancellationException(raised, raise)
@ExperimentalTraceApi
internal class Traced(raised: Any?, raise: Raise<Any?>, val originalTrace: Trace? = null): RaiseCancellationException(raised, raise)

private class RaiseLeakedException : IllegalStateException(
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public annotation class RaiseDSL
* <!--- KNIT example-raise-dsl-04.kt -->
* <!--- TEST lines.isEmpty() -->
*/
public interface Raise<in Error> {
public sealed interface Raise<in Error> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly, for me this is a no-go, we really want to keep this one open for extension (we even talk about that in the docs).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that I'm keeping it open by instead providing RaiseWrapper and TransformingRaise. Those 2 are the only use cases that I can observe. Most people will use RaiseWrapper if they're just defining an intersection type (and we can deprecate it when contexts are stable). TransformingRaise is another pattern where one wants to change the error type right then and there (used in RaiseAccumulate and SingletonRaise), and it's slightly more performance than withError.

Instead of this change, would you prefer we force implementors to provide a val underlyingRaise: Raise<*> or something along those lines? I didn't want to go through that approach because one can do val underlyingRaise get() = this which I heavily dislike

Copy link
Member

@nomisRev nomisRev Jan 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @serras. I understand it's still open for extension, but not in a straightforward way.

Did not yet have the time to properly dive into this, but perhaps we can find a different solution. Perhaps going the other-way around might be better. Something like CoroutineStackFrame which you can optionally implement, if you need behavior like this one.

We can dynamically check if a Raise interface implements RaiseFrame, or similar and then we'd get access to additional properties. That would probably even be possible to add in 1.x

No idea if any of this would work, just spitting some ideas ☺️ Will make some time asap to look into this issue.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've head of teams using CoroutineContext to pass this information, but unfortunately we don't have suspend in our raise function.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about introducing some form of interface RaiseWrapper<Error>: Raise<Error> { val underlyingRaise: Raise<*> } and encouraging users to gradually use it? We can support this feature then for those implementors. Alternatively, we can add an val underlyingRaise into Raise directly, with a default impl of returning this, although this would be a 2.0 feature.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I'm also getting distracted by thinking too far into the future. With contexts, we don't want "delegating" implementors of Raise, because they can always be replaced by composing Raise and the class in question. Instead, we want "transforming" implementors that actually do something interesting with the error value. Maybe that, as a plan, is unnecessarily ambitious. I'll experiment here with simplifying this, focusing on requiring as little migration as possible.


/**
* Raises a _logical failure_ of type [Error].
Expand Down Expand Up @@ -653,6 +653,7 @@ public inline fun <Error, B : Any> Raise<Error>.ensureNotNull(value: B?, raise:
* <!--- KNIT example-raise-dsl-11.kt -->
* <!--- TEST lines.isEmpty() -->
*/
@OptIn(DelicateRaiseApi::class, ExperimentalTraceApi::class)
@RaiseDSL
public inline fun <Error, OtherError, A> Raise<Error>.withError(
transform: (OtherError) -> Error,
Expand All @@ -661,7 +662,9 @@ public inline fun <Error, OtherError, A> Raise<Error>.withError(
contract {
callsInPlace(transform, AT_MOST_ONCE)
}
return recover(block) { raise(transform(it)) }
val outer = realUnderlying()
return if (outer.isTraced) recoverTraced(block) { t, r -> raiseWithTrace(t, transform(r)) }
else recover(block) { raise(transform(it)) }
}

/**
Expand Down
Loading
Loading