4

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?

Shastick
  • 1,218
  • 1
  • 12
  • 29
  • 1
    List libraries, compiler flags and compiler plugins in both setups and compare them. Since it's 2.12 it might be something as silly as missing `-Ypartial-unification`. – Mateusz Kubuszok Sep 03 '20 at 15:21
  • After looking a few minutes at how I could list the scalac options passed by Bazel, I just tried to add `scalacoptions = "-Ypartial-unification"` to the rule and.... it worked. Thanks a lot. If you write this into an Answer I'll be more than happy to accept it. – Shastick Sep 03 '20 at 17:53

1 Answers1

4

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).

Mateusz Kubuszok
  • 24,995
  • 4
  • 42
  • 64
  • Thanks for this unexpected answer. The scala ecosystem on Bazel is unfortunately not entirely ready for 2.13 yet :(. – Shastick Sep 03 '20 at 17:59
  • If you haven't add this flag to sbt yourself I guess it was some sbt plugin like sbt-tpolecat. That is why I suggested looking at the flags - they can change the behavior, but they might not be added by you personally. And then things are confusing. – Mateusz Kubuszok Sep 03 '20 at 18:01