From af2aedd329ce59df1396965055480ac11e5bf16a Mon Sep 17 00:00:00 2001 From: Youssef Shoaib Date: Tue, 23 Jan 2024 18:27:03 +0000 Subject: [PATCH 1/2] Pass Trace transparently through withError. This is achieved by sealing Raise to check DefaultRaise.isTraced. --- arrow-libs/core/arrow-core/api/arrow-core.api | 119 +++++++----------- .../kotlin/arrow/core/raise/Builders.kt | 18 ++- .../kotlin/arrow/core/raise/Fold.kt | 62 ++++++--- .../kotlin/arrow/core/raise/Raise.kt | 8 +- .../arrow/core/raise/RaiseAccumulate.kt | 9 +- .../kotlin/arrow/core/raise/Trace.kt | 10 +- .../arrow/core/raise/TransformingRaise.kt | 12 ++ .../kotlin/arrow/core/raise/TraceSpec.kt | 20 ++- 8 files changed, 138 insertions(+), 120 deletions(-) create mode 100644 arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/TransformingRaise.kt diff --git a/arrow-libs/core/arrow-core/api/arrow-core.api b/arrow-libs/core/arrow-core/api/arrow-core.api index 4b177726463..3337d5b23ee 100644 --- a/arrow-libs/core/arrow-core/api/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/arrow-core.api @@ -901,79 +901,41 @@ 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/IgnoreErrorsRaise : arrow/core/raise/Raise { +public final class arrow/core/raise/IgnoreErrorsRaise : arrow/core/raise/TransformingRaise { public fun (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function0;)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 ensure (Z)V public final fun ensureNotNull (Ljava/lang/Object;)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 fun raise (Ljava/lang/Object;)Ljava/lang/Void; } -public final class arrow/core/raise/IorRaise : arrow/core/raise/Raise { +public final class arrow/core/raise/IorRaise : arrow/core/raise/RaiseWrapper { public fun (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; } -public final class arrow/core/raise/NullableRaise : arrow/core/raise/Raise { +public final class arrow/core/raise/NullableRaise : arrow/core/raise/RaiseWrapper { public fun (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/Map;)Ljava/util/Map; 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 synthetic fun raise (Ljava/lang/Object;)Ljava/lang/Void; - public fun raise (Ljava/lang/Void;)Ljava/lang/Void; public final fun recover (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object; } -public final class arrow/core/raise/OptionRaise : arrow/core/raise/Raise { +public final class arrow/core/raise/OptionRaise : arrow/core/raise/RaiseWrapper { public fun (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 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 bindAllOption (Ljava/lang/Iterable;)Ljava/util/List; public final fun bindAllOption (Ljava/util/List;)Ljava/util/List; public final fun bindAllOption (Ljava/util/Map;)Ljava/util/Map; @@ -981,10 +943,6 @@ public final class arrow/core/raise/OptionRaise : 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 fun raise (Larrow/core/None;)Ljava/lang/Void; - public synthetic fun raise (Ljava/lang/Object;)Ljava/lang/Void; public final fun recover (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object; } @@ -1013,26 +971,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 (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; } @@ -1080,11 +1033,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 toEither (Lkotlin/jvm/functions/Function1;)Larrow/core/Either; public static final fun toEither (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; @@ -1097,7 +1053,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; @@ -1117,40 +1072,50 @@ 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 (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 (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/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 (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; } diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Builders.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Builders.kt index 7b7aba6a051..d0e1087ff0a 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Builders.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Builders.kt @@ -134,12 +134,10 @@ public inline fun iorNel(noinline combineError: (NonEmptyList, * You should never use this directly. */ public class IgnoreErrorsRaise( - private val raise: Raise, + raise: Raise, private val error: () -> N -) : Raise { - @RaiseDSL - override fun raise(r: Any?): Nothing = - raise.raise(error()) +) : TransformingRaise(raise) { + override fun transform(r: Any?): N = error() @RaiseDSL public fun ensure(value: Boolean): Unit = ensure(value) { null } @@ -166,7 +164,7 @@ public typealias Null = Nothing? * Implementation of [Raise] used by [nullable]. * You should never use this directly. */ -public class NullableRaise(private val raise: Raise) : Raise by raise { +public class NullableRaise(raise: Raise) : RaiseWrapper(raise) { @RaiseDSL public fun ensure(value: Boolean): Unit = ensure(value) { null } @@ -226,7 +224,7 @@ public class NullableRaise(private val raise: Raise) : Raise by rais * Implementation of [Raise] used by [result]. * You should never use this directly. */ -public class ResultRaise(private val raise: Raise) : Raise by raise { +public class ResultRaise(raise: Raise) : RaiseWrapper(raise){ @RaiseDSL public fun Result.bind(): A = fold(::identity) { raise(it) } @@ -263,7 +261,7 @@ public class ResultRaise(private val raise: Raise) : Raise * Implementation of [Raise] used by [option]. * You should never use this directly. */ -public class OptionRaise(private val raise: Raise) : Raise by raise { +public class OptionRaise(raise: Raise) : RaiseWrapper(raise) { @RaiseDSL public fun Option.bind(): A = getOrElse { raise(None) } @@ -332,8 +330,8 @@ public class OptionRaise(private val raise: Raise) : Raise by raise public class IorRaise @PublishedApi internal constructor( @PublishedApi internal val combineError: (Error, Error) -> Error, private val state: Atomic, - private val raise: Raise, -) : Raise by raise { + raise: Raise, +) : RaiseWrapper(raise) { @Suppress("UNCHECKED_CAST") @PublishedApi internal fun combine(e: Error): Error = state.updateAndGet { EmptyValue.combine(it, e, combineError) } as Error diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Fold.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Fold.kt index 9dc81d29b6a..4a3b1607a3a 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Fold.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Fold.kt @@ -183,6 +183,27 @@ public inline fun foldUnsafe( } } +@OptIn(DelicateRaiseApi::class) +@ExperimentalTraceApi +@RaiseDSL +public inline fun recoverTraced( + @BuilderInference block: Raise.() -> 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]. * @@ -232,27 +253,21 @@ public inline fun Raise.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 Raise.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 @@ -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) @@ -298,7 +321,8 @@ public sealed class RaiseCancellationException( internal expect class NoTrace(raised: Any?, raise: Raise) : RaiseCancellationException @DelicateRaiseApi -internal class Traced(raised: Any?, raise: Raise, override val cause: Traced? = null): RaiseCancellationException(raised, raise) +@ExperimentalTraceApi +internal class Traced(raised: Any?, raise: Raise, val originalTrace: Trace? = null): RaiseCancellationException(raised, raise) private class RaiseLeakedException : IllegalStateException( """ diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Raise.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Raise.kt index aa01e7663d8..d7d400b7b1c 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Raise.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Raise.kt @@ -14,7 +14,6 @@ import arrow.core.recover import kotlin.coroutines.cancellation.CancellationException import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind.AT_MOST_ONCE -import kotlin.contracts.InvocationKind.EXACTLY_ONCE import kotlin.contracts.contract import kotlin.experimental.ExperimentalTypeInference import kotlin.jvm.JvmMultifileClass @@ -144,7 +143,7 @@ public annotation class RaiseDSL * * */ -public interface Raise { +public sealed interface Raise { /** * Raises a _logical failure_ of type [Error]. @@ -654,6 +653,7 @@ public inline fun Raise.ensureNotNull(value: B?, raise: * * */ +@OptIn(DelicateRaiseApi::class, ExperimentalTraceApi::class) @RaiseDSL public inline fun Raise.withError( transform: (OtherError) -> Error, @@ -662,7 +662,9 @@ public inline fun Raise.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)) } } /** diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/RaiseAccumulate.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/RaiseAccumulate.kt index 6e7fae7c370..9992df055a4 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/RaiseAccumulate.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/RaiseAccumulate.kt @@ -592,12 +592,9 @@ public inline fun Raise>.mapOrAccumulate( * It extends [Raise] of [Error], and allows working over [Raise] of [NonEmptyList] of [Error] as well. */ public open class RaiseAccumulate( - public val raise: Raise> -) : Raise { - - @RaiseDSL - public override fun raise(r: Error): Nothing = - raise.raise(nonEmptyListOf(r)) + raise: Raise> +) : TransformingRaise>(raise) { + override fun transform(r: Error): NonEmptyList = nonEmptyListOf(r) public override fun Map>.bindAll(): Map = mapOrAccumulate { (_, a) -> a.bind() }.bindNel() diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Trace.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Trace.kt index d5a93439536..5af2f95b87c 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Trace.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Trace.kt @@ -14,15 +14,17 @@ public annotation class ExperimentalTraceApi /** Tracing result. Allows to inspect the traces from where raise was called. */ @ExperimentalTraceApi +@OptIn(DelicateRaiseApi::class) @JvmInline -public value class Trace(private val exception: CancellationException) { +public value class Trace +@PublishedApi internal constructor(private val exception: Traced) { /** * Returns the stacktrace as a [String] * * Note, the first line in the stacktrace will be the `RaiseCancellationException`. * The users call to `raise` can found in the_second line of the stacktrace. */ - public fun stackTraceToString(): String = (exception.cause ?: exception).stackTraceToString() + public fun stackTraceToString(): String = exception.originalTrace?.stackTraceToString() ?: exception.stackTraceToString() /** * Prints the stacktrace. @@ -31,7 +33,7 @@ public value class Trace(private val exception: CancellationException) { * The users call to `raise` can found in the_second line of the stacktrace. */ public fun printStackTrace(): Unit = - (exception.cause ?: exception).printStackTrace() + exception.originalTrace?.printStackTrace() ?: exception.printStackTrace() /** * Returns the suppressed exceptions that occurred during cancellation of the surrounding coroutines, @@ -41,5 +43,5 @@ public value class Trace(private val exception: CancellationException) { * if the finalizer then results in a `Throwable` it will be added as a `suppressedException` to the [CancellationException]. */ public fun suppressedExceptions(): List = - exception.cause?.suppressedExceptions.orEmpty() + exception.suppressedExceptions + exception.originalTrace?.suppressedExceptions().orEmpty() + exception.suppressedExceptions } diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/TransformingRaise.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/TransformingRaise.kt new file mode 100644 index 00000000000..fc3ac38b3df --- /dev/null +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/TransformingRaise.kt @@ -0,0 +1,12 @@ +package arrow.core.raise + +public abstract class TransformingRaise(@PublishedApi internal val raise: Raise) : Raise { + final override fun raise(r: Error): Nothing = + raise.raise(transform(r)) + + protected abstract fun transform(r: Error): @UnsafeVariance OuterError +} + +public abstract class RaiseWrapper(raise: Raise) : TransformingRaise(raise) { + final override fun transform(r: Error): @UnsafeVariance Error = r +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/TraceSpec.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/TraceSpec.kt index 85ca6c969bf..8da36f1f4e3 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/TraceSpec.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/TraceSpec.kt @@ -11,7 +11,7 @@ import kotlin.test.Test import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.test.runTest -@OptIn(ExperimentalTraceApi::class) +@OptIn(ExperimentalTraceApi::class, DelicateRaiseApi::class) class TraceSpec { @Test fun traceIsEmptyWhenNoErrors() = runTest { checkAll(Arb.int()) { i -> @@ -54,4 +54,22 @@ class TraceSpec { }) { _, unit -> unit shouldBe Unit } } } + + @Test + fun withErrorMaintainsTrace() = runTest { + val inner = CompletableDeferred() + merge { + traced({ + withError({ str: String -> str.length }) { + val e = shouldThrow { + raise("") + } + inner.complete(e.stackTraceToString()) + throw e + } + }) { traced, _ -> + inner.await() shouldBe traced.stackTraceToString() + } + } shouldBe 0 + } } From d699c88bc374870bacb5ed40ceaf5e926d50da79 Mon Sep 17 00:00:00 2001 From: Youssef Shoaib Date: Thu, 1 Feb 2024 16:34:47 +0000 Subject: [PATCH 2/2] Add Raise.underlyingRaise with default implementation --- arrow-libs/core/arrow-core/api/arrow-core.api | 77 ++++++++++++------- .../kotlin/arrow/core/raise/Builders.kt | 15 ++-- .../kotlin/arrow/core/raise/Fold.kt | 9 ++- .../kotlin/arrow/core/raise/Raise.kt | 5 +- .../arrow/core/raise/RaiseAccumulate.kt | 9 ++- .../arrow/core/raise/TransformingRaise.kt | 12 --- 6 files changed, 70 insertions(+), 57 deletions(-) delete mode 100644 arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/TransformingRaise.kt diff --git a/arrow-libs/core/arrow-core/api/arrow-core.api b/arrow-libs/core/arrow-core/api/arrow-core.api index c59a4a5d6ee..f4ed503ee3a 100644 --- a/arrow-libs/core/arrow-core/api/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/arrow-core.api @@ -889,6 +889,7 @@ public final class arrow/core/raise/DefaultRaise : arrow/core/raise/Raise { public fun bindAll-1TN0_VU (Ljava/util/Set;)Ljava/util/Set; public fun bindAll-vcjLgH4 (Ljava/util/List;)Ljava/util/List; public final fun complete ()Z + public fun getUnderlyingRaise ()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 isTraced ()Z @@ -901,15 +902,26 @@ 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/RaiseWrapper { +public final class arrow/core/raise/IorRaise : arrow/core/raise/Raise { public fun (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 getUnderlyingRaise ()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 fun raise (Ljava/lang/Object;)Ljava/lang/Void; public final fun recover (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } @@ -921,6 +933,7 @@ public abstract interface class arrow/core/raise/Raise { public abstract fun bindAll (Ljava/util/Map;)Ljava/util/Map; public abstract fun bindAll-1TN0_VU (Ljava/util/Set;)Ljava/util/Set; public abstract fun bindAll-vcjLgH4 (Ljava/util/List;)Ljava/util/List; + public abstract fun getUnderlyingRaise ()Larrow/core/raise/Raise; public abstract fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public abstract fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun raise (Ljava/lang/Object;)Ljava/lang/Void; @@ -934,25 +947,32 @@ public final class arrow/core/raise/Raise$DefaultImpls { public static fun bindAll (Larrow/core/raise/Raise;Ljava/util/Map;)Ljava/util/Map; public static fun bindAll-1TN0_VU (Larrow/core/raise/Raise;Ljava/util/Set;)Ljava/util/Set; public static fun bindAll-vcjLgH4 (Larrow/core/raise/Raise;Ljava/util/List;)Ljava/util/List; + public static fun getUnderlyingRaise (Larrow/core/raise/Raise;)Larrow/core/raise/Raise; public static fun invoke (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; 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/TransformingRaise { +public class arrow/core/raise/RaiseAccumulate : arrow/core/raise/Raise { public fun (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 getUnderlyingRaise ()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 synthetic fun transform (Ljava/lang/Object;)Ljava/lang/Object; - protected fun transform-0-xjo5U (Ljava/lang/Object;)Ljava/util/List; + public fun raise (Ljava/lang/Object;)Ljava/lang/Void; public final fun withNel (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } @@ -1041,25 +1061,39 @@ 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 abstract class arrow/core/raise/RaiseWrapper : arrow/core/raise/TransformingRaise { - public fun (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 final class arrow/core/raise/ResultRaise : arrow/core/raise/Raise { public fun (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 getUnderlyingRaise ()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 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/TransformingRaise { +public final class arrow/core/raise/SingletonRaise : arrow/core/raise/Raise { public fun (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; @@ -1070,10 +1104,13 @@ public final class arrow/core/raise/SingletonRaise : arrow/core/raise/Transformi public final fun bindAllOption (Ljava/util/Set;)Ljava/util/Set; public final fun ensure (Z)V public final fun ensureNotNull (Ljava/lang/Object;)Ljava/lang/Object; + public fun getUnderlyingRaise ()Larrow/core/raise/Raise; 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 { @@ -1092,19 +1129,3 @@ public final class arrow/core/raise/Trace { public final synthetic fun unbox-impl ()Larrow/core/raise/Traced; } -public abstract class arrow/core/raise/TransformingRaise : arrow/core/raise/Raise { - public fun (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; -} - diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Builders.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Builders.kt index 1e99237d72c..1cac6b4d3cd 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Builders.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Builders.kt @@ -23,7 +23,6 @@ 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 @@ -157,13 +156,13 @@ public inline fun impure(block: SingletonRaise.() -> Unit) { return singleton({ }, block) } -public class SingletonRaise(raise: Raise): TransformingRaise(raise) { - override fun transform(r: E) { } - +public class SingletonRaise(private val raise: Raise): Raise { @RaiseDSL - @JsName("raiseUnit") public fun raise(): Nothing = raise.raise(Unit) + @RaiseDSL + override fun raise(r: E): Nothing = raise() + @RaiseDSL public fun ensure(condition: Boolean) { contract { returns() implies condition } @@ -259,7 +258,7 @@ public class SingletonRaise(raise: Raise): TransformingRaise) : RaiseWrapper(raise) { +public class ResultRaise(private val raise: Raise) : Raise by raise { @RaiseDSL public fun Result.bind(): A = fold(::identity) { raise(it) } @@ -299,8 +298,8 @@ public class ResultRaise(raise: Raise) : RaiseWrapper(rais public class IorRaise @PublishedApi internal constructor( @PublishedApi internal val combineError: (Error, Error) -> Error, private val state: Atomic, - raise: Raise, -) : RaiseWrapper(raise) { + private val raise: Raise, +) : Raise by raise { @Suppress("UNCHECKED_CAST") @PublishedApi internal fun combine(e: Error): Error = state.updateAndGet { EmptyValue.combine(it, e, combineError) } as Error diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Fold.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Fold.kt index 4a3b1607a3a..7579d8d2497 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Fold.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Fold.kt @@ -295,10 +295,11 @@ internal class DefaultRaise(@PublishedApi internal val isTraced: Boolean) : Rais @DelicateRaiseApi @PublishedApi -internal tailrec fun Raise<*>.realUnderlying(): DefaultRaise = - when (this) { - is TransformingRaise<*, *> -> raise.realUnderlying() - is DefaultRaise -> this +internal tailrec fun Raise<*>.realUnderlying(): DefaultRaise? = + when (val underlying = underlyingRaise) { + is DefaultRaise -> underlying + this -> null + else -> underlying.realUnderlying() } @MustBeDocumented diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Raise.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Raise.kt index d7d400b7b1c..7e6d347fd44 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Raise.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Raise.kt @@ -143,7 +143,8 @@ public annotation class RaiseDSL * * */ -public sealed interface Raise { +public interface Raise { + public val underlyingRaise: Raise<*> get() = this /** * Raises a _logical failure_ of type [Error]. @@ -663,7 +664,7 @@ public inline fun Raise.withError( callsInPlace(transform, AT_MOST_ONCE) } val outer = realUnderlying() - return if (outer.isTraced) recoverTraced(block) { t, r -> raiseWithTrace(t, transform(r)) } + return if (outer?.isTraced == true) recoverTraced(block) { t, r -> raiseWithTrace(t, transform(r)) } else recover(block) { raise(transform(it)) } } diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/RaiseAccumulate.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/RaiseAccumulate.kt index 9992df055a4..6e7fae7c370 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/RaiseAccumulate.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/RaiseAccumulate.kt @@ -592,9 +592,12 @@ public inline fun Raise>.mapOrAccumulate( * It extends [Raise] of [Error], and allows working over [Raise] of [NonEmptyList] of [Error] as well. */ public open class RaiseAccumulate( - raise: Raise> -) : TransformingRaise>(raise) { - override fun transform(r: Error): NonEmptyList = nonEmptyListOf(r) + public val raise: Raise> +) : Raise { + + @RaiseDSL + public override fun raise(r: Error): Nothing = + raise.raise(nonEmptyListOf(r)) public override fun Map>.bindAll(): Map = mapOrAccumulate { (_, a) -> a.bind() }.bindNel() diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/TransformingRaise.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/TransformingRaise.kt deleted file mode 100644 index fc3ac38b3df..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/TransformingRaise.kt +++ /dev/null @@ -1,12 +0,0 @@ -package arrow.core.raise - -public abstract class TransformingRaise(@PublishedApi internal val raise: Raise) : Raise { - final override fun raise(r: Error): Nothing = - raise.raise(transform(r)) - - protected abstract fun transform(r: Error): @UnsafeVariance OuterError -} - -public abstract class RaiseWrapper(raise: Raise) : TransformingRaise(raise) { - final override fun transform(r: Error): @UnsafeVariance Error = r -}