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:
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
:
Double
to what's required by out
Double
from what's required by layer
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
.