diff --git a/build.sbt b/build.sbt index 50c64a1..599f2fd 100644 --- a/build.sbt +++ b/build.sbt @@ -19,6 +19,7 @@ fork := true libraryDependencies ++= List( scalaOrganization.value % "scala-compiler" % scalaVersion.value % "provided", "com.chuusai" %% "shapeless" % "2.3.3" % "test", + "dev.zio" %% "zio" % "1.0.4" % "test" ) libraryDependencies += "org.specs2" %% "specs2-core" % "4.5.1" % Test diff --git a/src/main/scala/splain/format/Formatters.scala b/src/main/scala/splain/format/Formatters.scala index 99801b7..50c9826 100644 --- a/src/main/scala/splain/format/Formatters.scala +++ b/src/main/scala/splain/format/Formatters.scala @@ -5,18 +5,6 @@ trait Formatters { self: Analyzer => def formatType(tpe: Type, top: Boolean): Formatted - object Refined { - def unapply(tpe: Type): Option[(List[Type], Scope)] = - tpe match { - case RefinedType(parents, decls) => - Some((parents, decls)) - case t @ SingleType(_, _) => - unapply(t.underlying) - case _ => - None - } - } - trait SpecialFormatter { def apply[A]( tpe: Type, @@ -169,6 +157,34 @@ trait Formatters { self: Analyzer => tpes.filterNot(t => ignoredTypes.exists(_ =:= t)) } + object Refined { + def unapply(tpe: Type): Option[(List[Type], Scope)] = + tpe match { + case TypeRef(pre, sym, List(RefinedType(parents, decls))) + if decls.isEmpty && pre.typeSymbol.fullName == "zio" && sym.fullName == "zio.Has" => + val sanitized = sanitizeParents(parents) + if (sanitized.length == 1) { + Some((List(TypeRef(pre, sym, sanitized.headOption.toList)), decls)) + } else { + None + } + case RefinedType(types, scope) => + if (scope.isEmpty) { + val subtypes = types.map(_.dealias).flatMap { + case Refined(types, _) => types + case tpe => List(tpe) + } + Some((subtypes, scope)) + } else { + Some((types, scope)) + } + case t @ SingleType(_, _) => + unapply(t.underlying) + case _ => + None + } + } + def formatDecl: Symbol => Formatted = { case DeclSymbol(n, t) => Decl(n, t) diff --git a/src/test/scala/splain/ErrorsSpec.scala b/src/test/scala/splain/ErrorsSpec.scala index d9bd39d..a35841d 100644 --- a/src/test/scala/splain/ErrorsSpec.scala +++ b/src/test/scala/splain/ErrorsSpec.scala @@ -115,6 +115,7 @@ class ErrorsSpec extends SpecBase { single types in function ${checkError("single-fn")} single types with free symbol ${checkError("single-free")} witness value types ${checkError("witness-value")} + zio test ${checkError("zlayer")} """ // def is = s2""" diff --git a/tests/zlayer/code.scala b/tests/zlayer/code.scala new file mode 100644 index 0000000..e86cf35 --- /dev/null +++ b/tests/zlayer/code.scala @@ -0,0 +1,20 @@ +import zio._ + +object layers { + + trait Service1 + trait Service2 + trait Service3 + trait Service4 + + val service1 = ZLayer.succeed(new Service1 {}) + + val service2 = ZLayer.succeed(new Service2 {}) + + val service3 = ZLayer.fromService { (_: Service1) => new Service3 {} } + + val service4 = ZLayer.succeed(new Service4 {}) + + val services: ULayer[Has[Service1] with Has[Service2] with Has[Service3] with Has[Service4]] = + service1 ++ service2 >+> service3// ++ service4 +} diff --git a/tests/zlayer/error b/tests/zlayer/error new file mode 100644 index 0000000..b40e0b2 --- /dev/null +++ b/tests/zlayer/error @@ -0,0 +1,2 @@ +type mismatch; + ZLayer[, Nothing, |Has[Service4] with Has[Service1] with Has[Service2] with Has[Service3]]