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?
Some type tetris :) Let's visualize, what's going on here:
When you compose
inandlayertoin >>> layer,ineliminatesStringfrom what is required bylayer, but the rest (IntandDouble) is still required by the resulting layer. However, the type annotation onoutin yourbadexample states that it only requiresInt, which is not correct.Note that there are different ways to fix the error in
bad:Doubleto what's required byoutDoublefrom what's required bylayerDoubleto what's provided byinSeems that the compiler considers the type of
outfix, and suggests the second solution, which is exactly what you did ingood.