diff --git a/build.sbt b/build.sbt index 68243979d9..d5023377bf 100644 --- a/build.sbt +++ b/build.sbt @@ -379,7 +379,7 @@ lazy val kernel = crossProject(JSPlatform, JVMPlatform, NativePlatform) libraryDependencies += "org.scala-js" %%% "scala-js-macrotask-executor" % MacrotaskExecutorVersion % Test ) .nativeSettings( - libraryDependencies += "io.github.cquiroz" %%% "scala-java-time" % "2.4.0" + libraryDependencies += "io.github.cquiroz" %%% "scala-java-time" % "2.5.0" ) /** diff --git a/core/shared/src/main/scala/cats/effect/IO.scala b/core/shared/src/main/scala/cats/effect/IO.scala index 0b726b491b..43a9b3915d 100644 --- a/core/shared/src/main/scala/cats/effect/IO.scala +++ b/core/shared/src/main/scala/cats/effect/IO.scala @@ -1188,7 +1188,7 @@ object IO extends IOCompanionPlatform with IOLowPriorityImplicits { G.uncancelable { poll => lift(k(resume)) flatMap { case Some(fin) => G.onCancel(poll(get), lift(fin)) - case None => poll(get) + case None => get } } } @@ -1238,7 +1238,7 @@ object IO extends IOCompanionPlatform with IOLowPriorityImplicits { def async_[A](k: (Either[Throwable, A] => Unit) => Unit): IO[A] = { val body = new Cont[IO, A, A] { def apply[G[_]](implicit G: MonadCancel[G, Throwable]) = { (resume, get, lift) => - G.uncancelable { poll => lift(IO.delay(k(resume))).flatMap(_ => poll(get)) } + G.uncancelable(_ => lift(IO.delay(k(resume))).flatMap(_ => get)) } } diff --git a/core/shared/src/main/scala/cats/effect/IOFiber.scala b/core/shared/src/main/scala/cats/effect/IOFiber.scala index 93996e4e2e..d5cbdbe159 100644 --- a/core/shared/src/main/scala/cats/effect/IOFiber.scala +++ b/core/shared/src/main/scala/cats/effect/IOFiber.scala @@ -172,7 +172,7 @@ private final class IOFiber[A]( val handle = registerListener(oc => cb(Right(oc))) if (handle == null) - None /* we were already invoked, so no `CallbackStack` needs to be managed */ + Some(IO.unit) /* we were already invoked, so no `CallbackStack` needs to be managed */ else Some(IO(handle.clearCurrent())) } diff --git a/kernel/shared/src/main/scala/cats/effect/kernel/Async.scala b/kernel/shared/src/main/scala/cats/effect/kernel/Async.scala index fab8e244aa..c042060bdb 100644 --- a/kernel/shared/src/main/scala/cats/effect/kernel/Async.scala +++ b/kernel/shared/src/main/scala/cats/effect/kernel/Async.scala @@ -94,7 +94,7 @@ trait Async[F[_]] extends AsyncPlatform[F] with Sync[F] with Temporal[F] { lift(k(resume)) flatMap { case Right(a) => G.pure(a) case Left(Some(fin)) => G.onCancel(poll(get), lift(fin)) - case Left(None) => poll(get) + case Left(None) => get } } } @@ -156,7 +156,7 @@ trait Async[F[_]] extends AsyncPlatform[F] with Sync[F] with Temporal[F] { * Polymorphic so it can be used in situations where an arbitrary effect is expected eg * [[Fiber.joinWithNever]] */ - def never[A]: F[A] = async(_ => pure(none[F[Unit]])) + def never[A]: F[A] = async(_ => pure(Some(unit))) /** * Shift execution of the effect `fa` to the execution context `ec`. Execution is shifted back diff --git a/kernel/shared/src/main/scala/cats/effect/kernel/Ref.scala b/kernel/shared/src/main/scala/cats/effect/kernel/Ref.scala index 2b820b5f9c..8f2f9211f1 100644 --- a/kernel/shared/src/main/scala/cats/effect/kernel/Ref.scala +++ b/kernel/shared/src/main/scala/cats/effect/kernel/Ref.scala @@ -104,6 +104,11 @@ abstract class Ref[F[_], A] extends RefSource[F, A] with RefSink[F, A] { */ def modify[B](f: A => (A, B)): F[B] + /** + * Like `modify` but the evaluation of the return value is wrapped in the effect type `F`. + */ + def flatModify[B](f: A => (A, F[B]))(implicit F: FlatMap[F]): F[B] = F.flatten(modify(f)) + /** * Update the value of this ref with a state computation. * diff --git a/kernel/shared/src/main/scala/cats/effect/kernel/Resource.scala b/kernel/shared/src/main/scala/cats/effect/kernel/Resource.scala index 209b6a8e18..a0ec36a46f 100644 --- a/kernel/shared/src/main/scala/cats/effect/kernel/Resource.scala +++ b/kernel/shared/src/main/scala/cats/effect/kernel/Resource.scala @@ -996,23 +996,22 @@ object Resource extends ResourceFOInstances0 with ResourceHOInstances0 with Reso val nt2 = new (Resource[F, *] ~> D) { def apply[A](rfa: Resource[F, A]) = Kleisli { r => - nt(rfa.allocatedCase) flatMap { - case (a, fin) => - r.update(f => (ec: ExitCase) => f(ec) !> (F.unit >> fin(ec))).as(a) + G uncancelable { poll => + poll(nt(rfa.allocatedCase)) flatMap { + case (a, fin) => + r.update(f => (ec: ExitCase) => f(ec) !> (F.unit >> fin(ec))).as(a) + } } } } - for { - r <- nt(F.ref((_: ExitCase) => F.unit).map(_.mapK(nt))) - - a <- G.guaranteeCase(body[D].apply(cb, Kleisli.liftF(ga), nt2).run(r)) { + nt(F.ref((_: ExitCase) => F.unit).map(_.mapK(nt))) flatMap { r => + G.guaranteeCase( + (body[D].apply(cb, Kleisli.liftF(ga), nt2).run(r), r.get).tupled) { case Outcome.Succeeded(_) => G.unit case oc => r.get.flatMap(fin => nt(fin(ExitCase.fromOutcome(oc)))) } - - fin <- r.get - } yield (a, fin) + } } } } diff --git a/laws/shared/src/main/scala/cats/effect/laws/AsyncLaws.scala b/laws/shared/src/main/scala/cats/effect/laws/AsyncLaws.scala index cfddeba102..2aff62f13f 100644 --- a/laws/shared/src/main/scala/cats/effect/laws/AsyncLaws.scala +++ b/laws/shared/src/main/scala/cats/effect/laws/AsyncLaws.scala @@ -61,7 +61,7 @@ trait AsyncLaws[F[_]] extends GenTemporalLaws[F, Throwable] with SyncLaws[F] { F.async[A](k => F.delay(k(Left(e))) >> F.pure(Some(fu))) <-> F.raiseError(e) def neverIsDerivedFromAsync[A] = - F.never[A] <-> F.async[A](_ => F.pure(None)) + F.never[A] <-> F.async[A](_ => F.pure(Some(F.unit))) def executionContextCommutativity[A](fa: F[A]) = (fa *> F.executionContext) <-> (F.executionContext <* fa) diff --git a/project/plugins.sbt b/project/plugins.sbt index 95a6d5eb8f..6bfb4a02c6 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -4,7 +4,7 @@ addSbtPlugin("org.typelevel" % "sbt-typelevel" % "0.5.0-M6") addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.11.0") addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.2.0") -addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.7") +addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.9") addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.2.0") addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.3") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6") diff --git a/tests/shared/src/test/scala/cats/effect/ResourceSpec.scala b/tests/shared/src/test/scala/cats/effect/ResourceSpec.scala index af9f0b1619..9a769dd211 100644 --- a/tests/shared/src/test/scala/cats/effect/ResourceSpec.scala +++ b/tests/shared/src/test/scala/cats/effect/ResourceSpec.scala @@ -1074,7 +1074,7 @@ class ResourceSpec extends BaseSpec with ScalaCheck with Discipline { "Resource[IO, *]", AsyncTests[Resource[IO, *]].async[Int, Int, Int](10.millis) ) /*(Parameters(seed = - Some(Seed.fromBase64("75d9nzLIEobZ3mfn0DvzUkMv-Jt7o7IyQyIvjqwkeVJ=").get)))*/ + Some(Seed.fromBase64("0FaZxJyh_xN_NL3i_y7bNaLpaWuhO9qUPXmfxxgLIIN=").get)))*/ } {