From b3ca80fb0f2fc4f5afd4a820d0b9b09cf648724b Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Sat, 30 Nov 2024 11:02:41 +0100 Subject: [PATCH] Ensure ZLayer macros use the trace from implicit scope --- .../test/scala/zio/autowire/AutoWireSpec.scala | 17 +++++++++++++++++ .../zio/internal/macros/LayerMacroUtils.scala | 18 ++++++++++-------- .../zio/internal/macros/LayerMacroUtils.scala | 16 +++++++++------- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/core-tests/shared/src/test/scala/zio/autowire/AutoWireSpec.scala b/core-tests/shared/src/test/scala/zio/autowire/AutoWireSpec.scala index af85f86f1d54..0141cd3b0ac5 100644 --- a/core-tests/shared/src/test/scala/zio/autowire/AutoWireSpec.scala +++ b/core-tests/shared/src/test/scala/zio/autowire/AutoWireSpec.scala @@ -4,6 +4,7 @@ import zio._ import zio.internal.macros.StringUtils.StringOps import zio.test.Assertion.{anything, equalTo, isLeft} import zio.test._ + import scala.annotation.nowarn object AutoWireSpec extends ZIOBaseSpec { @@ -212,6 +213,22 @@ object AutoWireSpec extends ZIOBaseSpec { s1 <- ZIO.service[String].provideLayer(tree) s2 <- ZIO.service[String].provideLayer(mermaid) } yield assertTrue(s1 == "Hello 1!", s2 == "Hello 2!") + }, + test("takes trace from the implicit scope") { + var numTraces: Int = 0 + val layer = { + implicit def trace: Trace = { + numTraces += 1 + Trace.empty + } + + ZLayer.make[String]( + ZLayer.succeed(42), + ZLayer.fromFunction((_: Int).toString) + ) + } + + assertZIO(layer.build.as(numTraces))(equalTo(3)) } ), suite("`ZLayer.makeSome`")( diff --git a/core/shared/src/main/scala-2/zio/internal/macros/LayerMacroUtils.scala b/core/shared/src/main/scala-2/zio/internal/macros/LayerMacroUtils.scala index eeb7fd9fb54f..bc027fbad24b 100644 --- a/core/shared/src/main/scala-2/zio/internal/macros/LayerMacroUtils.scala +++ b/core/shared/src/main/scala-2/zio/internal/macros/LayerMacroUtils.scala @@ -4,7 +4,6 @@ import zio._ import zio.internal.TerminalRendering import scala.reflect.macros.blackbox -import zio.internal.stacktracer.Tracer private[zio] trait LayerMacroUtils { val c: blackbox.Context @@ -49,16 +48,17 @@ private[zio] trait LayerMacroUtils { case Expr(q"$prefix.mermaid") if prefix.symbol == debug => ZLayer.Debug.Mermaid } + val trace = c.freshName(TermName("trace")) + val compose = c.freshName(TermName("compose")) var usesEnvironment = false var usesCompose = false def typeToNode(tpe: Type): Node[Type, LayerExpr] = { usesEnvironment = true - Node(Nil, List(tpe), c.Expr(q"${reify(ZLayer)}.environment[$tpe]")) + Node(Nil, List(tpe), c.Expr(q"${reify(ZLayer)}.environment[$tpe]($trace)")) } def buildFinalTree(tree: LayerTree[LayerExpr]): LayerExpr = { - val compose = c.freshName(TermName("compose")) val memoList: List[(LayerExpr, LayerExpr)] = tree.toList.map(_ -> c.Expr[ZLayer[_, _, _]](q"${c.freshName(TermName("layer"))}")) val definitions = memoList.map { case (expr, memoizedNode) => @@ -79,10 +79,7 @@ private[zio] trait LayerMacroUtils { ) val traceVal = if (usesEnvironment || usesCompose) { - val trace = c.freshName(TermName("trace")) - val suppress = typeOf[SuppressWarnings] - val wartRemover = q"""${reify(Array)}("org.wartremover.warts.ExplicitImplicitTypes")""" - List(q"@$suppress($wartRemover) implicit val $trace: ${typeOf[Trace]} = ${reify(Tracer)}.newTrace") + List(q"val $trace = ${reify(Predef)}.implicitly[${typeOf[Trace]}]") } else { Nil } @@ -93,7 +90,12 @@ private[zio] trait LayerMacroUtils { val E = c.freshName(TypeName("E")) val O1 = c.freshName(TypeName("O1")) val O2 = c.freshName(TypeName("O2")) - List(q"def $compose[$R, $E, $O1, $O2](lhs: $ZLayer[$R, $E, $O1], rhs: $ZLayer[$O1, $E, $O2]) = lhs >>> rhs") + List(q""" + def $compose[$R, $E, $O1, $O2]( + lhs: $ZLayer[$R, $E, $O1], + rhs: $ZLayer[$O1, $E, $O2] + ) = lhs.>>>(rhs)($trace) + """) } else { Nil } diff --git a/core/shared/src/main/scala-3/zio/internal/macros/LayerMacroUtils.scala b/core/shared/src/main/scala-3/zio/internal/macros/LayerMacroUtils.scala index 92af358887a6..dbcc7237080b 100644 --- a/core/shared/src/main/scala-3/zio/internal/macros/LayerMacroUtils.scala +++ b/core/shared/src/main/scala-3/zio/internal/macros/LayerMacroUtils.scala @@ -10,8 +10,11 @@ import zio.internal.stacktracer.Tracer private[zio] object LayerMacroUtils { type LayerExpr[E] = Expr[ZLayer[_, E, _]] - def composeLayer[R1, E, O1, O2](lhs: ZLayer[R1, E, O1], rhs: ZLayer[O1, E, O2])(using Trace): ZLayer[R1, E, O2] = - lhs.to(rhs) + def composeLayer[R1, E, O1, O2]( + lhs: ZLayer[R1, E, O1], + rhs: ZLayer[O1, E, O2] + )(using Trace): ZLayer[R1, E, O2] = + lhs >>> rhs def constructLayer[R0: Type, R: Type, E: Type](using Quotes)( layers: Seq[LayerExpr[E]], @@ -48,12 +51,11 @@ private[zio] object LayerMacroUtils { } '{ - val trace = Tracer.newTrace - given Trace = trace + val trace = summonInline[Trace] ${ def typeToNode(tpe: TypeRepr): Node[TypeRepr, LayerExpr[E]] = - Node(Nil, List(tpe), tpe.asType match { case '[t] => '{ ZLayer.environment[t] } }) + Node(Nil, List(tpe), tpe.asType match { case '[t] => '{ ZLayer.environment[t](trace) } }) def composeH(lhs: LayerExpr[E], rhs: LayerExpr[E]): LayerExpr[E] = lhs match { @@ -61,7 +63,7 @@ private[zio] object LayerMacroUtils { rhs match { case '{ $rhs: ZLayer[i2, E, o2] } => rhs.asTerm match { - case _: Ident => '{ $lhs.and($rhs)(summonInline) } + case _: Ident => '{ $lhs.++($rhs)(summonInline) } case _ => '{ $lhs +!+ $rhs } } } @@ -72,7 +74,7 @@ private[zio] object LayerMacroUtils { case '{ $lhs: ZLayer[i, E, o] } => rhs match { case '{ $rhs: ZLayer[`o`, E, o2] } => - '{ composeLayer($lhs, $rhs) } + '{ composeLayer($lhs, $rhs)(using trace) } } }