I'd like to pass an object to a function that accepts an argument with a projected type, and get Scala to deduce that the object's type comes from the object that encloses it. Here's some simple code to illustrate the difficulty:
trait Cult { cult_ =>
case class CultLeader(personality: Personality) {
val cult = cult_
val follower = personality.attractFollower(this)
}
case class Follower(leader: CultLeader, name: String)
}
trait Personality {
def attractFollower(leader: Cult#CultLeader) =
leader.cult.Follower(leader, "Fred") // <-- THIS LINE FAILS TO COMPILE
}
In other words, a CultLeader’s Personality should attract a Follower to the same Cult as the CultLeader.
The Scala 2.11.2 compiler says:
TypeProjection.scala:11: error: type mismatch;
found : Cult#CultLeader
required: leader.cult.CultLeader
leader.cult.Follower(leader, "Fred")
^
It compiles and runs correctly if I add a cast, like this:
leader.cult.Follower(leader.asInstanceOf[leader.cult.CultLeader], "Fred")
That seems clumsy and it introduces run-time checking for something that ought to be deducible at compile-time. At least I have a workaround. How can I get the Scala compiler to deduce that leader
's type is in fact leader.cult.CultLeader
?
I'd prefer not to pass cult
as another argument to attractFollower
. In my actual code, that could result in a lot of ugly passing around of the cult
parameter—when it really shouldn't need to be passed at all.