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

IO.suspend -> IO.defer #2169

Merged
merged 5 commits into from
Jul 27, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
31 changes: 21 additions & 10 deletions core/shared/src/main/scala/cats/effect/IO.scala
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,7 @@ abstract private[effect] class IOParallelNewtype extends internals.IOTimerRef wi
final override def unit: IO.Par[Unit] =
par(IO.unit)
override def map2Eval[A, B, Z](fa: IO.Par[A], fb: Eval[IO.Par[B]])(f: (A, B) => Z): Eval[IO.Par[Z]] =
Eval.now(map2(fa, par(IO.suspend(unwrap(fb.value))))(f))
Eval.now(map2(fa, par(IO.defer(unwrap(fb.value))))(f))
}
}

Expand Down Expand Up @@ -918,7 +918,7 @@ abstract private[effect] class IOLowPriorityInstances extends IOParallelNewtype
final override def delay[A](thunk: => A): IO[A] =
IO.delay(thunk)
final override def suspend[A](thunk: => IO[A]): IO[A] =
IO.suspend(thunk)
IO.defer(thunk)
final override def async[A](k: (Either[Throwable, A] => Unit) => Unit): IO[A] =
IO.async(k)
final override def asyncF[A](k: (Either[Throwable, A] => Unit) => IO[Unit]): IO[A] =
Expand Down Expand Up @@ -1143,6 +1143,23 @@ object IO extends IOInstances {
def apply[A](body: => A): IO[A] =
delay(body)

/**
* Suspends a synchronous side effect which produces an `IO` in `IO`.
*
* This is useful for trampolining (i.e. when the side effect is
* conceptually the allocation of a stack frame). Any exceptions
* thrown by the side effect will be caught and sequenced into the
* `IO`.
*/
def defer[A](thunk: => IO[A]): IO[A] = {
val nextIo = Suspend(() => thunk)
if (isFullStackTracing) {
IOTracing.decorated(nextIo)
} else {
nextIo
}
}

/**
* Suspends a synchronous side effect in `IO`.
*
Expand All @@ -1166,14 +1183,8 @@ object IO extends IOInstances {
* thrown by the side effect will be caught and sequenced into the
* `IO`.
*/
def suspend[A](thunk: => IO[A]): IO[A] = {
val nextIo = Suspend(() => thunk)
if (isFullStackTracing) {
IOTracing.decorated(nextIo)
} else {
nextIo
}
}
@deprecated("use defer", "2.5.2")
def suspend[A](thunk: => IO[A]): IO[A] = defer(thunk)

/**
* Suspends a pure value in `IO`.
Expand Down
15 changes: 13 additions & 2 deletions core/shared/src/main/scala/cats/effect/SyncIO.scala
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,18 @@ object SyncIO extends SyncIOInstances {
* thrown by the side effect will be caught and sequenced into the
* `SyncIO`.
*/
def suspend[A](thunk: => SyncIO[A]): SyncIO[A] = new SyncIO(IO.suspend(thunk.toIO))
def defer[A](thunk: => SyncIO[A]): SyncIO[A] = new SyncIO(IO.defer(thunk.toIO))

/**
* Suspends a synchronous side effect which produces a `SyncIO` in `SyncIO`.
*
* This is useful for trampolining (i.e. when the side effect is
* conceptually the allocation of a stack frame). Any exceptions
* thrown by the side effect will be caught and sequenced into the
* `SyncIO`.
*/
@deprecated("use defer", "2.5.2")
def suspend[A](thunk: => SyncIO[A]): SyncIO[A] = defer(thunk)

/**
* Suspends a pure value in `SyncIO`.
Expand Down Expand Up @@ -463,5 +474,5 @@ abstract private[effect] class SyncIOSync extends Sync[SyncIO] with StackSafeMon
final override def delay[A](thunk: => A): SyncIO[A] =
SyncIO(thunk)
final override def suspend[A](thunk: => SyncIO[A]): SyncIO[A] =
SyncIO.suspend(thunk)
SyncIO.defer(thunk)
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ private[effect] object CancelUtils {
if (cancelables.isEmpty) {
IO.unit
} else {
IO.suspend {
IO.defer {
cancelAll(cancelables.iterator)
}
}
Expand All @@ -41,7 +41,7 @@ private[effect] object CancelUtils {
if (cursor.isEmpty) {
IO.unit
} else {
IO.suspend {
IO.defer {
val frame = new CancelAllFrame(cursor)
frame.loop()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ private[effect] object IOBracket {
def release(c: ExitCase[Throwable]): CancelToken[IO]

private def applyRelease(e: ExitCase[Throwable]): IO[Unit] =
IO.suspend {
IO.defer {
if (waitsForResult.compareAndSet(true, false))
release(e)
.redeemWith[Unit](ex => IO(p.success(())).flatMap(_ => IO.raiseError(ex)), _ => IO { p.success(()); () })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ private[effect] object IOConnection {
private[this] val state = new AtomicReference(List.empty[CancelToken[IO]])
private[this] val p: Promise[Unit] = Promise()

val cancel = IO.suspend {
val cancel = IO.defer {
state.getAndSet(null) match {
case Nil => IO { p.success(()); () }
case null => IOFromFuture(p.future)
Expand Down
2 changes: 1 addition & 1 deletion laws/jvm/src/test/scala/cats/effect/IOJVMTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class IOJVMTests extends CatsEffectSuite {

try {
val latch = new java.util.concurrent.CountDownLatch(1)
def loop(): IO[Int] = IO.suspend(loop())
def loop(): IO[Int] = IO.defer(loop())

implicit val ctx: ContextShift[IO] = IO.contextShift(ec)
val task = IO.shift *> IO(latch.countDown()) *> loop()
Expand Down
2 changes: 1 addition & 1 deletion laws/shared/src/test/scala/cats/effect/IOTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ class IOTests extends BaseTestsSuite {
}

test("suspend with unsafeRunSync") {
val io = IO.suspend(IO(1)).map(_ + 1)
val io = IO.defer(IO(1)).map(_ + 1)
assertEquals(io.unsafeRunSync(), 2)
}

Expand Down
2 changes: 1 addition & 1 deletion laws/shared/src/test/scala/cats/effect/SyncIOTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ class SyncIOTests extends BaseTestsSuite {
}

test("suspend with unsafeRunSync") {
val io = SyncIO.suspend(SyncIO(1)).map(_ + 1)
val io = SyncIO.defer(SyncIO(1)).map(_ + 1)
assertEquals(io.unsafeRunSync(), 2)
}

Expand Down
1 change: 1 addition & 0 deletions scalafix/.bsp/sbt.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"name":"sbt","version":"1.5.5","bspVersion":"2.0.0-M5","languages":["scala"],"argv":["/Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home/bin/java","-Xms100m","-Xmx100m","-classpath","/Users/vasil/Software/sbt/bin/sbt-launch.jar","xsbt.boot.Boot","-bsp","--sbt-launch-jar=/Users/vasil/Software/sbt/bin/sbt-launch.jar"]}
34 changes: 33 additions & 1 deletion scalafix/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ lazy val v2_4_0_output = project
lazy val v2_4_0_tests = project
.in(file("v2_4_0/tests"))
.settings(
libraryDependencies += "ch.epfl.scala" % "scalafix-testkit" % V.scalafixVersion % Test cross CrossVersion.full,
libraryDependencies += ("ch.epfl.scala" % "scalafix-testkit" % V.scalafixVersion % Test).cross(CrossVersion.full),
(Compile / compile) :=
(Compile / compile).dependsOn(v2_4_0_input / Compile / compile).value,
scalafixTestkitOutputSourceDirectories :=
Expand All @@ -44,3 +44,35 @@ lazy val v2_4_0_tests = project
)
.dependsOn(v2_4_0_input, rules)
.enablePlugins(ScalafixTestkitPlugin)

lazy val v2_5_2_input = project
.in(file("v2_5_2/input"))
.settings(
libraryDependencies ++= Seq(
"org.typelevel" %% "cats-effect" % "2.5.1"
)
)

lazy val v2_5_2_output = project
.in(file("v2_5_2/output"))
.settings(
libraryDependencies ++= Seq(
"org.typelevel" %% "cats-effect" % "2.5.2"
)
)

lazy val v2_5_2_tests = project
.in(file("v2_5_2/tests"))
.settings(
libraryDependencies += ("ch.epfl.scala" % "scalafix-testkit" % V.scalafixVersion % Test).cross(CrossVersion.full),
(Compile / compile) :=
(Compile / compile).dependsOn(v2_5_2_input / Compile / compile).value,
scalafixTestkitOutputSourceDirectories :=
(v2_5_2_output / Compile / sourceDirectories).value,
scalafixTestkitInputSourceDirectories :=
(v2_5_2_input / Compile / sourceDirectories).value,
scalafixTestkitInputClasspath :=
(v2_5_2_input / Compile / fullClasspath).value
)
.dependsOn(v2_5_2_input, rules)
.enablePlugins(ScalafixTestkitPlugin)
11 changes: 11 additions & 0 deletions scalafix/rules/src/main/scala/fix/v2_5_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package fix

import scalafix.v1._

class v2_5_2 extends SemanticRule("v2_5_2") {
override def fix(implicit doc: SemanticDocument): Patch =
Patch.replaceSymbols(
"cats/effect/IO.suspend()." -> "defer",
"cats/effect/SyncIO.suspend()." -> "defer"
)
}
11 changes: 11 additions & 0 deletions scalafix/v2_5_2/input/src/main/scala/fix/IORewrites.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
rule = "scala:fix.v2_5_2"
*/
package fix

import cats.effect.IO

object IORewrites {
IO.suspend(IO.unit)
cats.effect.IO.suspend(IO.unit)
}
11 changes: 11 additions & 0 deletions scalafix/v2_5_2/input/src/main/scala/fix/SyncIORewrites.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
rule = "scala:fix.v2_5_2"
*/
package fix

import cats.effect.SyncIO

object SyncIORewrites {
SyncIO.suspend(SyncIO.unit)
cats.effect.SyncIO.suspend(SyncIO.unit)
}
8 changes: 8 additions & 0 deletions scalafix/v2_5_2/output/src/main/scala/fix/IORewrites.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package fix

import cats.effect.IO

object IORewrites {
IO.defer(IO.unit)
cats.effect.IO.defer(IO.unit)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package fix

import cats.effect.SyncIO

object SyncIORewrites {
SyncIO.defer(SyncIO.unit)
cats.effect.SyncIO.defer(SyncIO.unit)
}
8 changes: 8 additions & 0 deletions scalafix/v2_5_2/tests/src/test/scala/fix/V252Tests.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package fix

import org.scalatest.FunSuiteLike
import scalafix.testkit.AbstractSemanticRuleSuite

class V252Tests extends AbstractSemanticRuleSuite with FunSuiteLike {
runAllTests()
}