Building a ZIO and http4s app, works with sbt, fails with Bazel: missing an implicit

446 Views Asked by At

I'm attempting to build a service that integrates ZIO and http4s.

The starting point is this example (it uses zio 1.0.1, http4s 0.21.3, scala 2.12.11)

I was able to build the code below without any problems using sbt, but am running into trouble when attempting to build with Bazel:

import org.http4s.HttpRoutes
import org.http4s.dsl.Http4sDsl
import org.http4s.implicits._
import org.http4s.server.blaze._
import zio._
import zio.interop.catz._
import zio.interop.catz.implicits._

object Hello1 extends App {

  val server: ZIO[ZEnv, Throwable, Unit] = ZIO.runtime[ZEnv]
    .flatMap {
      implicit rts =>
        BlazeServerBuilder[Task]
          .bindHttp(8080, "localhost")
          .withHttpApp(Hello1Service.service)
          .serve
          .compile
          .drain
    }

  def run(args: List[String]) =
    server.exitCode
}

Sbt is happy, but when I build this with Bazel:

[Error] analytics/test-endpoint/Hello1.scala:20 could not find implicit value for parameter compiler: fs2.Stream.Compiler[[x]zio.ZIO[Any,Throwable,x],G]

About the bazel setup: I'm using the rules_scala from higherkindness with a BUILD file looking like:

scala_binary(
    name = "endpoint-bin",
    srcs = ["Hello1.scala", "Hello1Service.scala"],
    deps = [
        "//3rdparty/jvm/default/org/http4s:http4s_dsl",
        "//3rdparty/jvm/default/org/http4s:http4s_blaze_server",
        "//3rdparty/jvm/default/dev/zio:zio",
        "//3rdparty/jvm/default/dev/zio:zio_interop_cats",
        "//3rdparty/jvm/default/org/typelevel:cats_effect",
    ],
)

I'm not overly knowledgeable when it comes to implicits, and I was wondering what part of the "magic sauce" is missing to get this to work in Bazel. So far I have two hypotheses:

  • I missed a dependency that I need to explicitely specify somewhere, and it's on the classpath when built with sbt while missing in Bazel
  • this whole thing depends on macros, which I know may be problematic in my setup

Hence, the fundamental question I have: could anyone shine some light about the magic that goes on that lets the compiler find the correct implicit to be passed to compile in the sample code above?

1

There are 1 best solutions below

2
On BEST ANSWER

Add -Ypartial-unification to scalacOptions. Lack of this flag is the main offender in Cats, Scalaz, ZIO and type-level-heavy code in general. Or, if you can, migrate to 2.13 where behavior of this flag was changed to be always on (and the flag itself removed).