Why does this ZIO layer composition not compile?

103 views Asked by At

Obviously, this wasn't exactly my use case, but here is the MCVE, demonstrating the problem:

  def bad = {
    val in: ZLayer[Any, Any, String] = null
    val layer: ZLayer[String with Int with Double, Any, Double] = null
    val out: ZLayer[Any & Int, Any, Double] = in >>> layer
  }

This should work, right? Intellij agrees, and says everything is right ... until you hit compile. The compiler says:

 found   : zio.ZLayer[String with Int with Double,Any,Double]
 required: zio.ZLayer[String with Any with Int,Any,Double]

What??? Why?

Interestingly, if you change the first Double to a String (or to anything else for that matter if you adjust the out type), it works fine:

  def good = {
    val in: ZLayer[Any, Any, String] = null
    val layer: ZLayer[String with Int with String, Any, Double] = null
    val out: ZLayer[Any & Int, Any, Double] = in >>> layer
  }

Any ideas? I am starting to think, this is a compiler bug?

1

There are 1 answers

2
zagyi On BEST ANSWER

Some type tetris :) Let's visualize, what's going on here:

layer requires provides
in - String
layer String, Int, Double Double
in >>> layer Int, Double Double
out Int Double

When you compose in and layer to in >>> layer, in eliminates String from what is required by layer, but the rest (Int and Double) is still required by the resulting layer. However, the type annotation on out in your bad example states that it only requires Int, which is not correct.

Note that there are different ways to fix the error in bad:

  1. Add Double to what's required by out
  2. Remove Double from what's required by layer
  3. Add Double to what's provided by in

Seems that the compiler considers the type of out fix, and suggests the second solution, which is exactly what you did in good.