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.