Reputation: 875
I have a scenario that is causing a type mismatch that I cannot seem to resolve. Here's a simplified version of the code:
abstract class Msg
trait Channel[M <: Msg] {
def receive(): M
def ack(envelope: M)
}
object ChannelSender {
private var channel : Channel[_ <: Msg] = _
def assignChannel(channel : Channel[_ <: Msg]) = this.channel = channel
def test() {
val msg = channel.receive()
channel.ack(msg) // Type mismatch here
}
}
The error from the compiler is:
type mismatch; found : msg.type (with underlying type com.msgtest.Envelope) required: _$1 where type _$1 <: com.msgtest.Envelope
What sort of changes could I make to get this working? Additionally, the changes require that the following concrete implementation compile:
class SomeMsg extends Msg
object SomeChannel extends Channel[SomeMsg] {
def receive(): SomeMsg = { null.asInstanceOf[SomeMsg] }
def ack(envelope: SomeMsg) {}
}
object Setup {
ChannelSender.assignChannel(SomeChannel)
}
Upvotes: 1
Views: 2387
Reputation: 21112
I could get it to compile under Scala 2.9 with two changes,
trait Channel[M <: Msg] {
type M2 = M // Introduce a type member that's externally visible
def receive(): M2
def ack(envelope: M2)
}
object ChannelSender {
private var channel : Channel[_ <: Msg] = _
def assignChannel(channel : Channel[_ <: Msg]) = this.channel = channel
def test() {
val c = channel // An immutable value, so that c.M2 is stable
val msg = c.receive()
c.ack(msg) // OK now
}
}
The first change is to use an immutable value val c = channel
, so that the path dependent type c.M2
always means the same thing. The second change is to introduce a type member type M2 = M
in trait Channel
. I'm not totally sure why this is necessary (could it be a bug?). One thing to note is that c.M2
is a valid type, whereas c.M
is undefined.
Upvotes: 4