From 65b4c26ca4ada9ec13d680862a5acf777cdc6685 Mon Sep 17 00:00:00 2001 From: Kyri Petrou Date: Mon, 3 Feb 2025 07:23:25 +0200 Subject: [PATCH 1/2] `ZIO.fromEither` should produce a stacktrace on failure --- .../shared/src/test/scala/zio/ZIOSpec.scala | 16 ++++++++++++++++ core/shared/src/main/scala/zio/ZIO.scala | 14 ++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/core-tests/shared/src/test/scala/zio/ZIOSpec.scala b/core-tests/shared/src/test/scala/zio/ZIOSpec.scala index 8ad0a10fcb9c..93e4c9d7f7f4 100644 --- a/core-tests/shared/src/test/scala/zio/ZIOSpec.scala +++ b/core-tests/shared/src/test/scala/zio/ZIOSpec.scala @@ -1308,6 +1308,22 @@ object ZIOSpec extends ZIOBaseSpec { assertCompletes } ), + suite("fromEither") { + test("produces a stack trace on failure") { + ZIO + .fromEither(Left("foo")) + .catchAllCause(cause => ZIO.succeed(cause.trace.stackTrace)) + .map(t => assertTrue(t.nonEmpty)) + } + }, + suite("fromEitherCause") { + test("produces a stack trace on failure") { + ZIO + .fromEitherCause(Left(Cause.fail("foo"))) + .catchAllCause(cause => ZIO.succeed(cause.trace.stackTrace)) + .map(t => assertTrue(t.nonEmpty)) + } + }, suite("fromFutureInterrupt")( test("running Future can be interrupted") { import java.util.concurrent.atomic.AtomicInteger diff --git a/core/shared/src/main/scala/zio/ZIO.scala b/core/shared/src/main/scala/zio/ZIO.scala index 6666c8cfe325..5bf30f5e575b 100644 --- a/core/shared/src/main/scala/zio/ZIO.scala +++ b/core/shared/src/main/scala/zio/ZIO.scala @@ -3708,13 +3708,23 @@ object ZIO extends ZIOCompanionPlatformSpecific with ZIOCompanionVersionSpecific * Lifts an `Either` into a `ZIO` value. */ def fromEither[E, A](v: => Either[E, A])(implicit trace: Trace): IO[E, A] = - succeed(v).flatMap(_.fold(ZIO.failFn, ZIO.successFn)) + ZIO.suspendSucceed { + v match { + case Right(v) => Exit.succeed(v) + case Left(c) => ZIO.fail(c) + } + } /** * Lifts an `Either` into a `ZIO` value. */ def fromEitherCause[E, A](v: => Either[Cause[E], A])(implicit trace: Trace): IO[E, A] = - succeed(v).flatMap(_.fold(Exit.failCause, ZIO.successFn)) + ZIO.suspendSucceed { + v match { + case Right(v) => Exit.succeed(v) + case Left(c) => ZIO.failCause(c) + } + } /** * Creates a `ZIO` value that represents the exit value of the specified From 6f04ba2629f9e7ea6394f58592e4244b412a8ab6 Mon Sep 17 00:00:00 2001 From: Kyri Petrou Date: Mon, 3 Feb 2025 07:24:47 +0200 Subject: [PATCH 2/2] Rename local val --- core/shared/src/main/scala/zio/ZIO.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/shared/src/main/scala/zio/ZIO.scala b/core/shared/src/main/scala/zio/ZIO.scala index 5bf30f5e575b..bcadb5c7fe30 100644 --- a/core/shared/src/main/scala/zio/ZIO.scala +++ b/core/shared/src/main/scala/zio/ZIO.scala @@ -3710,8 +3710,8 @@ object ZIO extends ZIOCompanionPlatformSpecific with ZIOCompanionVersionSpecific def fromEither[E, A](v: => Either[E, A])(implicit trace: Trace): IO[E, A] = ZIO.suspendSucceed { v match { - case Right(v) => Exit.succeed(v) - case Left(c) => ZIO.fail(c) + case Right(s) => Exit.succeed(s) + case Left(e) => ZIO.fail(e) } } @@ -3721,7 +3721,7 @@ object ZIO extends ZIOCompanionPlatformSpecific with ZIOCompanionVersionSpecific def fromEitherCause[E, A](v: => Either[Cause[E], A])(implicit trace: Trace): IO[E, A] = ZIO.suspendSucceed { v match { - case Right(v) => Exit.succeed(v) + case Right(s) => Exit.succeed(s) case Left(c) => ZIO.failCause(c) } }