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
in
andlayer
toin >>> layer
,in
eliminatesString
from what is required bylayer
, but the rest (Int
andDouble
) is still required by the resulting layer. However, the type annotation onout
in yourbad
example states that it only requiresInt
, which is not correct.Note that there are different ways to fix the error in
bad
:Double
to what's required byout
Double
from what's required bylayer
Double
to what's provided byin
Seems that the compiler considers the type of
out
fix, and suggests the second solution, which is exactly what you did ingood
.