Skip to content

Commit

Permalink
Update to ZIO 2 (#1963)
Browse files Browse the repository at this point in the history
* Update fundamentals-bio to ZIO 2 (no tracing yet, no trifunctor)

* Tests pass on 2.13 JVM sans trifunctor BIO

* Fix JS build

* Use InteropTracer in BIO. Update zio-interop-cats to 23.0.0.7

* merge fix

* Fix Scala 3 build

* Rename HasConstructor to ZEnvConstructor, rename fromHas to fromZEnv, restore LogZIO, fix microsite

* Fix 2.12 build

* Fix 2.12 build. Move ZIOHasInjectionTest to JVM-only
  • Loading branch information
neko-kai authored Jun 19, 2023
1 parent 3f58c26 commit 32c25cc
Show file tree
Hide file tree
Showing 94 changed files with 2,188 additions and 1,688 deletions.
11 changes: 11 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ lazy val `fundamentals-orphans` = crossProject(JVMPlatform, JSPlatform).crossTyp
"org.typelevel" %%% "cats-core" % V.cats % Optional,
"org.typelevel" %%% "cats-effect" % V.cats_effect % Optional,
"dev.zio" %%% "zio" % V.zio % Optional excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %%% "zio-managed" % V.zio % Optional excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %%% "izumi-reflect" % V.izumi_reflect % Optional,
"dev.zio" %%% "zio-interop-cats" % V.zio_interop_cats % Optional excludeAll("dev.zio" %% "izumi-reflect")
),
Expand Down Expand Up @@ -1411,7 +1412,9 @@ lazy val `fundamentals-bio` = crossProject(JVMPlatform, JSPlatform).crossType(Cr
"org.typelevel" %%% "cats-core" % V.cats % Optional,
"org.typelevel" %%% "cats-effect" % V.cats_effect % Optional,
"dev.zio" %%% "zio" % V.zio % Optional excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %%% "zio-managed" % V.zio % Optional excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %%% "izumi-reflect" % V.izumi_reflect % Optional,
"dev.zio" %%% "zio-interop-tracer" % V.zio_interop_cats,
"org.typelevel" %%% "cats-effect-laws" % V.cats_effect % Test,
"org.typelevel" %%% "cats-effect-testkit" % V.cats_effect % Test,
"org.scalatest" %%% "scalatest" % V.scalatest % Test,
Expand Down Expand Up @@ -1597,10 +1600,12 @@ lazy val `distage-core-api` = crossProject(JVMPlatform, JSPlatform).crossType(Cr
"org.typelevel" %%% "cats-core" % V.cats % Optional,
"org.typelevel" %%% "cats-effect" % V.cats_effect % Optional,
"dev.zio" %%% "zio" % V.zio % Optional excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %%% "zio-managed" % V.zio % Optional excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %%% "izumi-reflect" % V.izumi_reflect % Optional,
"org.typelevel" %%% "cats-core" % V.cats % Test,
"org.typelevel" %%% "cats-effect" % V.cats_effect % Test,
"dev.zio" %%% "zio" % V.zio % Test excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %%% "zio-managed" % V.zio % Test excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %%% "izumi-reflect" % V.izumi_reflect % Test
),
libraryDependencies ++= { if (scalaVersion.value.startsWith("2.")) Seq(
Expand Down Expand Up @@ -2100,6 +2105,7 @@ lazy val `distage-core` = crossProject(JVMPlatform, JSPlatform).crossType(CrossT
"org.typelevel" %%% "cats-core" % V.cats % Optional,
"org.typelevel" %%% "cats-effect" % V.cats_effect % Optional,
"dev.zio" %%% "zio" % V.zio % Optional excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %%% "zio-managed" % V.zio % Optional excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %%% "izumi-reflect" % V.izumi_reflect % Optional,
"dev.zio" %%% "zio-interop-cats" % V.zio_interop_cats % Optional excludeAll("dev.zio" %% "izumi-reflect"),
"javax.inject" % "javax.inject" % "1" % Test
Expand Down Expand Up @@ -2822,6 +2828,7 @@ lazy val `distage-framework` = crossProject(JVMPlatform, JSPlatform).crossType(C
"org.typelevel" %%% "cats-core" % V.cats % Test,
"org.typelevel" %%% "cats-effect" % V.cats_effect % Test,
"dev.zio" %%% "zio" % V.zio % Test excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %%% "zio-managed" % V.zio % Test excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %%% "izumi-reflect" % V.izumi_reflect % Test
),
libraryDependencies ++= { if (scalaVersion.value.startsWith("2.")) Seq(
Expand Down Expand Up @@ -3008,6 +3015,7 @@ lazy val `distage-framework-docker` = project.in(file("distage/distage-framework
"org.typelevel" %% "cats-core" % V.cats % Test,
"org.typelevel" %% "cats-effect" % V.cats_effect % Test,
"dev.zio" %% "zio" % V.zio % Test excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %% "zio-managed" % V.zio % Test excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %% "izumi-reflect" % V.izumi_reflect % Test,
"com.github.docker-java" % "docker-java-core" % V.docker_java,
"com.github.docker-java" % "docker-java-transport-zerodep" % V.docker_java
Expand Down Expand Up @@ -3325,6 +3333,7 @@ lazy val `distage-testkit-scalatest` = project.in(file("distage/distage-testkit-
"org.typelevel" %% "cats-core" % V.cats % Optional,
"org.typelevel" %% "cats-effect" % V.cats_effect % Optional,
"dev.zio" %% "zio" % V.zio % Optional excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %% "zio-managed" % V.zio % Optional excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %% "izumi-reflect" % V.izumi_reflect % Optional,
"org.scalatest" %% "scalatest" % V.scalatest
),
Expand Down Expand Up @@ -3487,6 +3496,7 @@ lazy val `logstage-core` = crossProject(JVMPlatform, JSPlatform).crossType(Cross
"org.typelevel" %%% "cats-core" % V.cats % Optional,
"org.typelevel" %%% "cats-effect" % V.cats_effect % Optional,
"dev.zio" %%% "zio" % V.zio % Optional excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %%% "zio-managed" % V.zio % Optional excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %%% "izumi-reflect" % V.izumi_reflect % Optional
),
libraryDependencies ++= { if (scalaVersion.value.startsWith("2.")) Seq(
Expand Down Expand Up @@ -4178,6 +4188,7 @@ lazy val `microsite` = project.in(file("doc/microsite"))
"org.typelevel" %% "cats-core" % V.cats,
"org.typelevel" %% "cats-effect" % V.cats_effect,
"dev.zio" %% "zio" % V.zio excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %% "zio-managed" % V.zio excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %% "zio-interop-cats" % V.zio_interop_cats excludeAll("dev.zio" %% "izumi-reflect"),
"dev.zio" %% "izumi-reflect" % V.izumi_reflect,
"org.tpolecat" %% "doobie-core" % V.doobie,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import izumi.distage.model.providers.Functoid
import izumi.distage.model.reflection.SafeType
import izumi.fundamentals.platform.strings.IzString.toRichIterable
import izumi.reflect.WeakTag
import zio.ZEnvironment

import scala.language.experimental.macros as enableMacros

Expand All @@ -18,7 +19,7 @@ import scala.language.experimental.macros as enableMacros
*
* Since version `1.1.0`, does not generate constructors "factory-like" traits and abstract classes, instead use [[FactoryConstructor]].
*
* Use [[HasConstructor]] to generate constructors for `zio.Has` values.
* Use [[ZEnvConstructor]] to generate constructors for `zio.ZEnvironment` values.
*
* @example
* {{{
Expand All @@ -45,13 +46,25 @@ sealed trait AnyConstructor[T] extends Any with AnyConstructorOptionalMakeDSL[T]
def provider: Functoid[T]
}

object AnyConstructor {
def apply[T](implicit ctor: AnyConstructor[T]): Functoid[T] = ctor.provider

implicit def materialize[T]: AnyConstructor[T] = macro AnyConstructorMacro.mkAnyConstructor[T]
}

/**
* An implicitly summonable constructor for a concrete class `T`
*
* @see [[AnyConstructor]]
*/
final class ClassConstructor[T](val provider: Functoid[T]) extends AnyVal with AnyConstructor[T]

object ClassConstructor {
def apply[T](implicit ctor: ClassConstructor[T]): Functoid[T] = ctor.provider

implicit def materialize[T]: ClassConstructor[T] = macro ClassConstructorMacro.mkClassConstructor[T]
}

/**
* An implicitly summonable constructor for a traits or abstract class `T`
*
Expand All @@ -61,37 +74,6 @@ final class ClassConstructor[T](val provider: Functoid[T]) extends AnyVal with A
*/
final class TraitConstructor[T](val provider: Functoid[T]) extends AnyVal with AnyConstructor[T]

/**
* An implicitly summonable constructor for a "factory-like" trait or abstract class `T`
*
* @see [[https://izumi.7mind.io/distage/basics.html#auto-factories Auto-Factories feature]]
* @see [[izumi.distage.model.definition.impl]] recommended documenting annotation for use with [[FactoryConstructor]]
* @see [[AnyConstructor]]
*/
final class FactoryConstructor[T](val provider: Functoid[T]) extends AnyVal with AnyConstructor[T]

/**
* An implicitly summonable constructor for a `T <: zio.Has[A] with zio.Has[B] with zio.Has[C]`
*
* `zio.Has` heterogeneous map values may be used by ZIO or other Reader-like effects
*
* @see [[https://izumi.7mind.io/distage/basics.html#zio-has-bindings ZIO Has bindings]]
* @see [[AnyConstructor]]
*/
final class HasConstructor[T](val provider: Functoid[T]) extends AnyVal with AnyConstructor[T]

object AnyConstructor {
def apply[T](implicit ctor: AnyConstructor[T]): Functoid[T] = ctor.provider

implicit def materialize[T]: AnyConstructor[T] = macro AnyConstructorMacro.mkAnyConstructor[T]
}

object ClassConstructor {
def apply[T](implicit ctor: ClassConstructor[T]): Functoid[T] = ctor.provider

implicit def materialize[T]: ClassConstructor[T] = macro ClassConstructorMacro.mkClassConstructor[T]
}

object TraitConstructor {
def apply[T](implicit ctor: TraitConstructor[T]): Functoid[T] = ctor.provider

Expand All @@ -107,18 +89,37 @@ object TraitConstructor {
}
}

/**
* An implicitly summonable constructor for a "factory-like" trait or abstract class `T`
*
* @see [[https://izumi.7mind.io/distage/basics.html#auto-factories Auto-Factories feature]]
* @see [[izumi.distage.model.definition.impl]] recommended documenting annotation for use with [[FactoryConstructor]]
* @see [[AnyConstructor]]
*/
final class FactoryConstructor[T](val provider: Functoid[T]) extends AnyVal with AnyConstructor[T]

object FactoryConstructor {
def apply[T](implicit ctor: FactoryConstructor[T]): Functoid[T] = ctor.provider

implicit def materialize[T]: FactoryConstructor[T] = macro FactoryConstructorMacro.mkFactoryConstructor[T]
}

object HasConstructor {
def apply[T](implicit ctor: HasConstructor[T]): Functoid[T] = ctor.provider
/**
* An implicitly summonable constructor for a `ZEnvironment[A & B & C]`
*
* `zio.ZEnvironment` heterogeneous map values may be used by ZIO or other Reader-like effects
*
* @see [[https://izumi.7mind.io/distage/basics.html#zio-environment-bindings ZIO Environment bindings]]
* @see [[AnyConstructor]]
*/
final class ZEnvConstructor[T](val provider: Functoid[ZEnvironment[T]]) extends AnyVal with AnyConstructor[ZEnvironment[T]]

object ZEnvConstructor {
def apply[T](implicit ctor: ZEnvConstructor[T]): Functoid[ZEnvironment[T]] = ctor.provider

val empty: HasConstructor[Any] = new HasConstructor(Functoid.unit)
def empty: ZEnvConstructor[Any] = new ZEnvConstructor(Functoid.pure(ZEnvironment.empty))

implicit def materialize[T]: HasConstructor[T] = macro HasConstructorMacro.mkHasConstructor[T]
implicit def materialize[T]: ZEnvConstructor[T] = macro ZEnvConstructorMacro.mkZEnvConstructor[T]
}

private[constructors] sealed trait AnyConstructorOptionalMakeDSL[T] extends Any {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,11 @@ object ClassConstructorMacros {
}
}

abstract class HasConstructorMacros extends ConstructorMacrosBase {
import c.universe._

def ziohasConstructorAssertion(targetType: Type, deepIntersection: List[Type]): Unit = {
val (good, bad) = deepIntersection.partition(tpe => tpe.typeConstructor.typeSymbol.fullName == "zio.Has")
if (bad.nonEmpty) {
c.abort(
c.enclosingPosition,
s"Cannot construct an implementation for ZIO Has type `$targetType`: intersection contains type constructors that aren't `zio.Has` or `Any`: $bad (${bad.map(_.typeSymbol)})",
)
}
if (good.isEmpty) {
c.abort(
c.enclosingPosition,
s"Cannot construct an implementation for ZIO Has type `$targetType`: the intersection type is empty, it contains no `zio.Has` or `Any` type constructors in it, type was $targetType (${targetType.typeSymbol}",
)
}
}

}
object HasConstructorMacros {
type Aux[C <: blackbox.Context, U <: StaticDIUniverse] = HasConstructorMacros { val c: C; val u: U }
def apply(c0: blackbox.Context)(u0: StaticDIUniverse.Aux[c0.universe.type]): HasConstructorMacros.Aux[c0.type, u0.type] = {
new HasConstructorMacros {
abstract class ZEnvConstructorMacros extends ConstructorMacrosBase
object ZEnvConstructorMacros {
type Aux[C <: blackbox.Context, U <: StaticDIUniverse] = ZEnvConstructorMacros { val c: C; val u: U }
def apply(c0: blackbox.Context)(u0: StaticDIUniverse.Aux[c0.universe.type]): ZEnvConstructorMacros.Aux[c0.type, u0.type] = {
new ZEnvConstructorMacros {
val c: c0.type = c0
val u: u0.type = u0
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,51 +1,51 @@
package izumi.distage.constructors.macros

import izumi.distage.constructors.{DebugProperties, HasConstructor}
import izumi.distage.constructors.{DebugProperties, ZEnvConstructor}
import izumi.distage.model.providers.Functoid
import izumi.distage.model.reflection.Provider.ProviderType
import izumi.distage.model.reflection.universe.StaticDIUniverse
import izumi.distage.reflection.ReflectionProviderDefaultImpl
import izumi.fundamentals.reflection.{ReflectionUtil, TrivialMacroLogger}
import zio.ZEnvironment

import scala.reflect.macros.blackbox

object HasConstructorMacro {
object ZEnvConstructorMacro {

def mkHasConstructor[T: c.WeakTypeTag](c: blackbox.Context): c.Expr[HasConstructor[T]] = {
def mkZEnvConstructor[T: c.WeakTypeTag](c: blackbox.Context): c.Expr[ZEnvConstructor[T]] = {
val macroUniverse = StaticDIUniverse(c)
val impls = HasConstructorMacros(c)(macroUniverse)
val impls = ZEnvConstructorMacros(c)(macroUniverse)
import c.universe._
import impls.{c => _, u => _, _}

val targetType = ReflectionUtil.norm(c.universe: c.universe.type)(weakTypeOf[T].dealias)
requireConcreteTypeConstructor(c)("HasConstructor", targetType)
val targetType = weakTypeOf[T].dealias
requireConcreteTypeConstructor(c)("ZEnvConstructor", targetType)

targetType match {
case definitions.AnyTpe =>
c.Expr[HasConstructor[T]](q"_root_.izumi.distage.constructors.HasConstructor.empty")
c.Expr[ZEnvConstructor[T]](q"_root_.izumi.distage.constructors.ZEnvConstructor.empty")

case _ =>
val deepIntersection = ReflectionUtil
.deepIntersectionTypeMembers[c.universe.type](targetType)
.deepIntersectionTypeMembersNoNorm[c.universe.type](targetType)
.filter(_ ne definitions.AnyTpe)
ziohasConstructorAssertion(targetType, deepIntersection)

val reflectionProvider = ReflectionProviderDefaultImpl(macroUniverse)
val logger = TrivialMacroLogger.make[this.type](c, DebugProperties.`izumi.debug.macro.distage.constructors`.name)

val params = reflectionProvider.zioHasParameters(c.freshName)(deepIntersection)
val provider: c.Expr[Functoid[T]] = {
generateProvider[T, ProviderType.ZIOHas.type](params :: Nil) {
val provider: c.Expr[Functoid[ZEnvironment[T]]] = {
generateProvider[ZEnvironment[T], ProviderType.ZIOEnvironment.type](params :: Nil) {
case (headParam :: params) :: Nil =>
params.foldLeft(q"_root_.zio.Has.apply($headParam)") {
params.foldLeft(q"_root_.zio.ZEnvironment.apply($headParam)") {
(expr, arg) => q"$expr.add($arg)"
}
case _ => c.abort(c.enclosingPosition, s"Impossible happened, empty Has intersection or malformed type $targetType in HasConstructorMacro")
case _ => c.abort(c.enclosingPosition, s"Impossible happened, empty Has intersection or malformed type $targetType in ZEnvConstructorMacro")
}
}

val res = c.Expr[HasConstructor[T]](q"{ new ${weakTypeOf[HasConstructor[T]]}($provider) }")
logger.log(s"Final syntax tree of HasConstructor for $targetType:\n$res")
val res = c.Expr[ZEnvConstructor[T]](q"{ new ${weakTypeOf[ZEnvConstructor[T]]}($provider) }")
logger.log(s"Final syntax tree of ZEnvConstructor for $targetType:\n$res")

res
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ trait ReflectionProviderDefaultImpl extends ReflectionProvider {
override def zioHasParameters(transformName: String => String)(deepIntersection: List[u.TypeNative]): List[u.Association.Parameter] = {
deepIntersection.map {
hasTpe =>
val tpe = ReflectionUtil.norm(u.u)(hasTpe.dealias).typeArgs.head
val tpe = hasTpe.dealias
val syntheticSymbolInfo = SymbolInfo.Static.syntheticFromType(transformName)(tpe)
Association.Parameter(syntheticSymbolInfo, keyFromSymbolResultType(syntheticSymbolInfo))
}
Expand Down Expand Up @@ -119,7 +119,7 @@ trait ReflectionProviderDefaultImpl extends ReflectionProvider {
| * Type `$tpe` has been considered a factory because it's an abstract type and contains unimplemented abstract methods with parameters
| * Did you forget a `distage.With` annotation on the factory method to specify a non-abstract implementation type?
| * This may happen in case you unintentionally bind an abstract type (trait, etc) as implementation type.
|
|
| * $mms
|""".stripMargin,
SafeType.create(tpe),
Expand Down
Loading

0 comments on commit 32c25cc

Please sign in to comment.