Skip to content

Commit c9d3a04

Browse files
authored
Revert "Fix unlawful instances (#595)" (#615)
1 parent 274fad3 commit c9d3a04

File tree

12 files changed

+239
-975
lines changed

12 files changed

+239
-975
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package zio.interop
22

3-
import cats.effect.{ Async, IO as CIO, LiftIO, Outcome }
3+
import cats.effect.{ IO as CIO, LiftIO }
44
import cats.effect.kernel.{ Concurrent, Resource }
55
import zio.interop.catz.*
66
import zio.test.*
7-
import zio.*
7+
import zio.{ Promise, Task, ZIO }
88

99
object CatsInteropSpec extends CatsRunnableSpec {
1010
def spec = suite("Cats interop")(
@@ -25,184 +25,6 @@ object CatsInteropSpec extends CatsRunnableSpec {
2525
_ <- lift.liftIO(promise1.get)
2626
_ <- fiber.interrupt
2727
} yield assertCompletes
28-
},
29-
test("ZIO respects Async#async cancel finalizer") {
30-
def test[F[_]](implicit F: Async[F]) = {
31-
import cats.syntax.all.*
32-
import cats.effect.syntax.all.*
33-
for {
34-
counter <- F.ref(0)
35-
latch <- F.deferred[Unit]
36-
fiber <- F.start(
37-
F.async[Unit] { _ =>
38-
for {
39-
_ <- latch.complete(())
40-
_ <- counter.update(_ + 1)
41-
} yield Some(counter.update(_ + 1))
42-
}.forceR(counter.update(_ + 9000))
43-
)
44-
_ <- latch.get
45-
_ <- fiber.cancel
46-
res <- counter.get
47-
} yield assertTrue(res == 2)
48-
}
49-
50-
for {
51-
sanityCheckCIO <- fromEffect(test[CIO])
52-
zioResult <- test[Task]
53-
} yield zioResult && sanityCheckCIO
54-
},
55-
test("onCancel is not triggered by ZIO.parTraverse + ZIO.fail https://github.com/zio/zio/issues/6911") {
56-
val F = Concurrent[Task]
57-
58-
for {
59-
counter <- F.ref("")
60-
_ <- F.guaranteeCase(
61-
F.onError(
62-
F.onCancel(
63-
ZIO.collectAllPar(
64-
List(
65-
ZIO.unit.forever,
66-
counter.update(_ + "A") *> ZIO.fail(new RuntimeException("x")).unit
67-
)
68-
),
69-
counter.update(_ + "1")
70-
)
71-
) { case _ => counter.update(_ + "B") }
72-
) {
73-
case Outcome.Errored(_) => counter.update(_ + "C")
74-
case Outcome.Canceled() => counter.update(_ + "2")
75-
case Outcome.Succeeded(_) => counter.update(_ + "3")
76-
}.exit
77-
res <- counter.get
78-
} yield assertTrue(!res.contains("1")) && assertTrue(res == "ABC")
79-
},
80-
test("onCancel is not triggered by ZIO.parTraverse + ZIO.die https://github.com/zio/zio/issues/6911") {
81-
val F = Concurrent[Task]
82-
83-
for {
84-
counter <- F.ref("")
85-
_ <- F.guaranteeCase(
86-
F.onError(
87-
F.onCancel(
88-
ZIO.collectAllPar(
89-
List(
90-
ZIO.unit.forever,
91-
counter.update(_ + "A") *> ZIO.die(new RuntimeException("x")).unit
92-
)
93-
),
94-
counter.update(_ + "1")
95-
)
96-
) { case _ => counter.update(_ + "B") }
97-
) {
98-
case Outcome.Errored(_) => counter.update(_ + "C")
99-
case Outcome.Canceled() => counter.update(_ + "2")
100-
case Outcome.Succeeded(_) => counter.update(_ + "3")
101-
}.exit
102-
res <- counter.get
103-
} yield assertTrue(!res.contains("1")) && assertTrue(res == "AC")
104-
},
105-
test("onCancel is not triggered by ZIO.parTraverse + ZIO.interrupt https://github.com/zio/zio/issues/6911") {
106-
val F = Concurrent[Task]
107-
108-
for {
109-
counter <- F.ref("")
110-
_ <- F.guaranteeCase(
111-
F.onError(
112-
F.onCancel(
113-
ZIO.collectAllPar(
114-
List(
115-
ZIO.unit.forever,
116-
counter.update(_ + "A") *> ZIO.interrupt.unit
117-
)
118-
),
119-
counter.update(_ + "1")
120-
)
121-
) { case _ => counter.update(_ + "B") }
122-
) {
123-
case Outcome.Errored(_) => counter.update(_ + "C")
124-
case Outcome.Canceled() => counter.update(_ + "2")
125-
case Outcome.Succeeded(_) => counter.update(_ + "3")
126-
}.exit
127-
res <- counter.get
128-
} yield assertTrue(!res.contains("1")) && assertTrue(res == "AC")
129-
},
130-
test(
131-
"onCancel is triggered when a fiber executing ZIO.parTraverse + ZIO.fail is interrupted and the inner typed" +
132-
" error is, unlike ZIO 1, preserved in final Cause (in ZIO 1 Fail & Interrupt nodes CAN both exist in Cause after external interruption)"
133-
) {
134-
val F = Concurrent[Task]
135-
136-
def println(s: String): Unit = {
137-
val _ = s
138-
}
139-
140-
for {
141-
latch1 <- F.deferred[Unit]
142-
latch2 <- F.deferred[Unit]
143-
latch3 <- F.deferred[Unit]
144-
counter <- F.ref("")
145-
cause <- F.ref(Option.empty[Cause[Throwable]])
146-
fiberId <- ZIO.fiberId
147-
fiber <- F.guaranteeCase(
148-
F.onError(
149-
F.onCancel(
150-
ZIO
151-
.collectAllPar(
152-
List(
153-
F.onCancel(
154-
ZIO.never,
155-
ZIO.succeed(println("A")) *> latch2.complete(()).unit
156-
).onExit(_ => ZIO.succeed(println("XA"))),
157-
(latch1.complete(()) *> latch3.get *> ZIO.succeed(println("C"))).uninterruptible,
158-
counter.update(_ + "A") *>
159-
latch1.get *>
160-
ZIO.succeed(println("B")) *> ZIO.fail(new RuntimeException("The_Error")).unit
161-
)
162-
)
163-
.onExit {
164-
case Exit.Success(_) => ZIO.unit
165-
case Exit.Failure(c) => cause.set(Some(c)).orDie
166-
},
167-
counter.update(_ + "B")
168-
)
169-
) { case _ => counter.update(_ + "1") }
170-
) {
171-
case Outcome.Errored(_) => counter.update(_ + "2")
172-
case Outcome.Canceled() => counter.update(_ + "C")
173-
case Outcome.Succeeded(_) => counter.update(_ + "3")
174-
}.fork
175-
_ = println("x1")
176-
_ <- latch2.get
177-
_ = println("x2")
178-
_ <- fiber.interruptFork
179-
_ = println("x3")
180-
_ <- latch3.complete(())
181-
_ <- fiber.interrupt
182-
_ = println("x4")
183-
res <- counter.get
184-
cause <- cause.get
185-
} yield assertTrue(!res.contains("1")) &&
186-
assertTrue(res == "ABC") &&
187-
assertTrue(cause.isDefined) &&
188-
assertTrue(cause.get.prettyPrint.contains("The_Error")) &&
189-
assertTrue(cause.get.interruptors.contains(fiberId))
190-
},
191-
test("F.canceled.toEffect results in CancellationException, not BoxedException") {
192-
val F = Concurrent[Task]
193-
194-
val exception: Option[Throwable] =
195-
try {
196-
F.canceled.toEffect[cats.effect.IO].unsafeRunSync()
197-
None
198-
} catch {
199-
case t: Throwable => Some(t)
200-
}
201-
202-
assertTrue(
203-
!exception.get.getMessage.contains("Boxed Exception") &&
204-
exception.get.getMessage.contains("The fiber was canceled")
205-
)
20628
}
20729
)
20830
}

zio-interop-cats-tests/jvm/src/test/scala/zio/interop/CatsZManagedSyntaxSpec.scala

+7-79
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package zio.interop
22

3-
import cats.effect.kernel.{ Concurrent, Resource }
3+
import cats.effect.kernel.Resource
44
import cats.effect.IO as CIO
55
import zio.*
66
import zio.interop.catz.*
@@ -15,39 +15,13 @@ object CatsZManagedSyntaxSpec extends CatsRunnableSpec {
1515
def spec =
1616
suite("CatsZManagedSyntaxSpec")(
1717
suite("toManaged")(
18-
test("calls finalizers correctly when use is externally interrupted") {
18+
test("calls finalizers correctly when use is interrupted") {
1919
val effects = new mutable.ListBuffer[Int]
2020
def res(x: Int): Resource[CIO, Unit] =
2121
Resource.makeCase(CIO.delay(effects += x).void) {
2222
case (_, Resource.ExitCase.Canceled) =>
2323
CIO.delay(effects += x + 1).void
24-
case (_, _) =>
25-
CIO.unit
26-
}
27-
28-
val testCase = {
29-
val managed: ZManaged[Any, Throwable, Unit] = res(1).toManaged
30-
Promise.make[Nothing, Unit].flatMap { latch =>
31-
managed
32-
.use(_ => latch.succeed(()) *> ZIO.never)
33-
.forkDaemon
34-
.flatMap(latch.await *> _.interrupt)
35-
}
36-
}
37-
38-
for {
39-
_ <- testCase
40-
effects <- ZIO.succeed(effects.toList)
41-
} yield assert(effects)(equalTo(List(1, 2)))
42-
},
43-
test("calls finalizers correctly when use is internally interrupted") {
44-
val effects = new mutable.ListBuffer[Int]
45-
def res(x: Int): Resource[CIO, Unit] =
46-
Resource.makeCase(CIO.delay(effects += x).void) {
47-
case (_, Resource.ExitCase.Errored(_)) =>
48-
CIO.delay(effects += x + 1).void
49-
case (_, _) =>
50-
CIO.unit
24+
case _ => CIO.unit
5125
}
5226

5327
val testCase = {
@@ -154,7 +128,7 @@ object CatsZManagedSyntaxSpec extends CatsRunnableSpec {
154128
}
155129
),
156130
suite("toManagedZIO")(
157-
test("calls finalizers correctly when use is externally interrupted") {
131+
test("calls finalizers correctly when use is interrupted") {
158132
val effects = new mutable.ListBuffer[Int]
159133
def res(x: Int): Resource[Task, Unit] =
160134
Resource.makeCase(ZIO.attempt(effects += x).unit) {
@@ -163,30 +137,6 @@ object CatsZManagedSyntaxSpec extends CatsRunnableSpec {
163137
case _ => ZIO.unit
164138
}
165139

166-
val testCase = {
167-
val managed: ZManaged[Any, Throwable, Unit] = res(1).toManagedZIO
168-
Promise.make[Nothing, Unit].flatMap { latch =>
169-
managed
170-
.use(_ => latch.succeed(()) *> ZIO.never)
171-
.forkDaemon
172-
.flatMap(latch.await *> _.interrupt)
173-
}
174-
}
175-
176-
for {
177-
_ <- testCase
178-
effects <- ZIO.succeed(effects.toList)
179-
} yield assert(effects)(equalTo(List(1, 2)))
180-
},
181-
test("calls finalizers correctly when use is internally interrupted") {
182-
val effects = new mutable.ListBuffer[Int]
183-
def res(x: Int): Resource[Task, Unit] =
184-
Resource.makeCase(ZIO.attempt(effects += x).unit) {
185-
case (_, Resource.ExitCase.Errored(_)) =>
186-
ZIO.attempt(effects += x + 1).unit
187-
case _ => ZIO.unit
188-
}
189-
190140
val testCase = {
191141
val managed: ZManaged[Any, Throwable, Unit] = res(1).toManagedZIO
192142
managed.use(_ => ZIO.interrupt.unit)
@@ -318,13 +268,13 @@ object CatsZManagedSyntaxSpec extends CatsRunnableSpec {
318268
effects <- ZIO.succeed(effects.toList)
319269
} yield assert(effects)(equalTo(List(1, 2)))
320270
},
321-
test("calls finalizers when using resource is internally interrupted") {
271+
test("calls finalizers when using resource is canceled") {
322272
val effects = new mutable.ListBuffer[Int]
323273
def man(x: Int): ZManaged[Any, Throwable, Unit] =
324274
ZManaged.acquireReleaseExitWith(ZIO.succeed(effects += x).unit) {
325-
case (_, Exit.Failure(c)) if !c.isInterrupted && c.failureOption.nonEmpty =>
275+
case (_, e) if e.isInterrupted =>
326276
ZIO.succeed(effects += x + 1)
327-
case _ =>
277+
case _ =>
328278
ZIO.unit
329279
}
330280

@@ -334,28 +284,6 @@ object CatsZManagedSyntaxSpec extends CatsRunnableSpec {
334284
effects <- ZIO.succeed(effects.toList)
335285
} yield assert(effects)(equalTo(List(1, 2)))
336286
},
337-
test("calls finalizers when using resource is externally interrupted") {
338-
val effects = new mutable.ListBuffer[Int]
339-
def man(x: Int): ZManaged[Any, Throwable, Unit] =
340-
ZManaged.acquireReleaseExitWith(ZIO.succeed(effects += x).unit) {
341-
case (_, e) if e.isInterrupted =>
342-
ZIO.succeed(effects += x + 1)
343-
case _ =>
344-
ZIO.unit
345-
}
346-
347-
val exception: Option[Throwable] =
348-
try {
349-
man(1).toResource[Task].use(_ => Concurrent[Task].canceled).toEffect[cats.effect.IO].unsafeRunSync()
350-
None
351-
} catch {
352-
case t: Throwable => Some(t)
353-
}
354-
355-
assert(effects.toList)(equalTo(List(1, 2))) && assertTrue(
356-
exception.get.getMessage.contains("The fiber was canceled")
357-
)
358-
},
359287
test("acquisition of Reservation preserves cancellability in new F") {
360288
for {
361289
startLatch <- Promise.make[Nothing, Unit]

zio-interop-cats-tests/shared/src/test/scala/zio/interop/CatsSpec.scala

+5-34
Original file line numberDiff line numberDiff line change
@@ -21,30 +21,8 @@ class CatsSpec extends ZioSpecBase {
2121
"Temporal[Task]",
2222
implicit tc => GenTemporalTests[Task, Throwable].temporal[Int, Int, Int](100.millis)
2323
)
24-
25-
locally {
26-
checkAllAsync(
27-
"GenTemporal[IO[Int, _], Cause[Int]]",
28-
{ implicit tc =>
29-
import zio.interop.catz.generic.*
30-
GenTemporalTests[IO[Int, _], Cause[Int]].temporal[Int, Int, Int](100.millis)
31-
}
32-
)
33-
checkAllAsync(
34-
"GenSpawn[IO[Int, _], Cause[Int]]",
35-
{ implicit tc =>
36-
import zio.interop.catz.generic.*
37-
GenSpawnTests[IO[Int, _], Cause[Int]].spawn[Int, Int, Int]
38-
}
39-
)
40-
checkAllAsync(
41-
"MonadCancel[IO[In t, _], Cause[Int]]",
42-
{ implicit tc =>
43-
import zio.interop.catz.generic.*
44-
MonadCancelTests[IO[Int, _], Cause[Int]].monadCancel[Int, Int, Int]
45-
}
46-
)
47-
}
24+
checkAllAsync("GenSpawn[IO[Int, _], Int]", implicit tc => GenSpawnTests[IO[Int, _], Int].spawn[Int, Int, Int])
25+
checkAllAsync("MonadError[IO[In t, _]]", implicit tc => MonadErrorTests[IO[Int, _], Int].monadError[Int, Int, Int])
4826
checkAllAsync("MonoidK[IO[Int, _]]", implicit tc => MonoidKTests[IO[Int, _]].monoidK[Int])
4927
checkAllAsync("SemigroupK[IO[Option[Unit], _]]", implicit tc => SemigroupKTests[IO[Option[Unit], _]].semigroupK[Int])
5028
checkAllAsync("SemigroupK[Task]", implicit tc => SemigroupKTests[Task].semigroupK[Int])
@@ -68,13 +46,9 @@ class CatsSpec extends ZioSpecBase {
6846

6947
Async[RIO[ZClock, _]]
7048
Sync[RIO[ZClock, _]]
71-
locally {
72-
import zio.interop.catz.generic.*
73-
74-
GenTemporal[ZIO[ZClock, Int, _], Cause[Int]]
75-
GenConcurrent[ZIO[String, Int, _], Cause[Int]]
76-
}
49+
GenTemporal[ZIO[ZClock, Int, _], Int]
7750
Temporal[RIO[ZClock, _]]
51+
GenConcurrent[ZIO[String, Int, _], Int]
7852
Concurrent[RIO[String, _]]
7953
MonadError[RIO[String, _], Throwable]
8054
Monad[RIO[String, _]]
@@ -92,10 +66,7 @@ class CatsSpec extends ZioSpecBase {
9266

9367
def liftRIO(implicit runtime: IORuntime) = LiftIO[RIO[String, _]]
9468
def liftZManaged(implicit runtime: IORuntime) = LiftIO[ZManaged[String, Throwable, _]]
95-
def runtimeGenTemporal(implicit runtime: Runtime[ZClock]) = {
96-
import zio.interop.catz.generic.*
97-
GenTemporal[ZIO[Any, Int, _], Cause[Int]]
98-
}
69+
def runtimeGenTemporal(implicit runtime: Runtime[ZClock]) = GenTemporal[ZIO[Any, Int, _], Int]
9970
def runtimeTemporal(implicit runtime: Runtime[ZClock]) = Temporal[Task]
10071
}
10172

0 commit comments

Comments
 (0)