Closed
Description
Minimized code
trait Rec[-K <: String] { self =>
protected val map: Map[String, Any]
type ValueOf[A <: K]
def get(k: K): ValueOf[k.type] = map(k).asInstanceOf
def +[K0 <: K, K1 <: String](that: Rec[K1]): Rec[K0 | K1] {
type ValueOf[A <: K0 | K1] = A match {
case K0 => self.ValueOf[A]
case K1 => that.ValueOf[A]
}
} = new Rec[K0 | K1] {
protected val map = self.map ++ that.map
type ValueOf[A <: K0 | K1] = A match {
case K0 => self.ValueOf[A]
case K1 => that.ValueOf[A]
}
}
}
object Rec {
def field[V](s: String & Singleton)(v: V): Rec[s.type] {
type ValueOf[K <: s.type] = K match {
case s.type => V
}
} = new Rec[s.type] {
protected val map = Map(s -> v)
type ValueOf[K <: s.type] = K match {
case s.type => V
}
}
}
def getZ(r: Rec["z"]): r.ValueOf["z"] = r.get("z")
@main def Test = {
val rec = Rec.field("k")("Str") + (Rec.field("v")(0)) + (Rec.field("z")(true))
// val rec = Rec.field("k")("Str").+["k", "v"](Rec.field("v")(0)).+["k" | "v", "z"](Rec.field("z")(true)) // this works
def res1: String = rec.get("k")
def res2: Int = rec.get("v")
def res3: Boolean = getZ(rec)
println((res1, res2, res3))
}
Output
Error:(129, 31) Found: ("k" : String/T)
Required: Nothing/T |/T ("z" : String/T)
def res1: String = rec.get("k")
Error:(130, 31) Found: ("v" : String/T)
Required: Nothing/T |/T ("z" : String/T)
def res2: Int = rec.get("v")
Expectation
Expected it to compile without explicit annotations. This may be related to the deliberate restrictions on inferrence of unions in Dotty.