While cracking my head over another question, I came across different riddles which seem related. This is one of them:
trait Sys[S <: Sys[S]] {
type Peer <: Sys[Peer]
}
trait Fenced {
type Peer <: Sys[Peer]
}
def makeFence[S <: Sys[S]] = new Fenced { type Peer = S#Peer }
Where the error is as follows:
error: overriding type Peer in trait Fenced with bounds >: Nothing <: Sys[this.Peer];
type Peer has incompatible type
def makeFence[S <: Sys[S]] = new Fenced { type Peer = S#Peer }
^
Why? (also tried to add self-type _:S =>
to Sys
, didn't matter)
While Rex's answer makes it possible to construct the Fenced
object, it does not really solve the issues I have with the representation type character getting lost when using a type projection (S#Peer
). I have come up with another scenario which poses harder constraints; I think this is the core issue:
trait Test[S <: Sys[S]] {
def make[T <: Sys[T]](): Unit
make[S#Peer]()
}
error: type arguments [S#Peer] do not conform to method make's type
parameter bounds [T <: Sys[T]]
make[S#Peer]()
^
I still am not entirely certain what constraints you're looking for, but here is one possibility:
This gives you (and requires!) access to both
Peer
and the original outer type withinFenced
. I am not sure whetherFenced
may do this, or whether it must abstract across outer types.