change synthetic sender’s reply type to UnknownDoNotWriteMeDown
This commit is contained in:
parent
aec29618e3
commit
5e763bbb38
5 changed files with 19 additions and 8 deletions
|
|
@ -14,6 +14,14 @@ sealed trait TNil extends ChannelList
|
|||
sealed trait :+:[A <: (_, _), B <: ChannelList] extends ChannelList
|
||||
sealed trait ReplyChannels[T <: ChannelList] extends ChannelList
|
||||
|
||||
/**
|
||||
* This type is used to stand in for the unknown reply types of the fabricated
|
||||
* sender references; users don’t need to write it down, and if they do, they
|
||||
* know that they’re cheating (since these ref types must not escape their
|
||||
* defining actor context).
|
||||
*/
|
||||
sealed trait UnknownDoNotWriteMeDown
|
||||
|
||||
class ActorRefOps(val ref: ActorRef) extends AnyVal {
|
||||
import macros.Helpers._
|
||||
def narrow[C <: ChannelList](implicit timeout: Timeout, ec: ExecutionContext, tt: ru.TypeTag[C]): Future[ChannelRef[C]] = {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ object Ask {
|
|||
|
||||
Tell.verify(c)(null, unwrapped, typeOf[(Any, Nothing) :+: TNil], tpeChannel)
|
||||
|
||||
implicit val ttReturnChannels = c.TypeTag[ReturnChannels](toChannels(c.universe)(out))
|
||||
implicit val ttReturnChannels = c.TypeTag[ReturnChannels](toChannels(c.universe)(out, weakTypeOf[Nothing]))
|
||||
implicit val ttReturnLUB = c.TypeTag[ReturnLUB](c.universe.lub(out))
|
||||
reify(askOps[WrappedMessage[ReturnChannels, ReturnLUB]](
|
||||
c.prefix.splice.actorRef, toMsg(c)(msg, tpeMsg).splice)(imp[Timeout](c).splice))
|
||||
|
|
@ -54,7 +54,7 @@ object Ask {
|
|||
|
||||
Tell.verify(c)(null, unwrapped, typeOf[(Any, Nothing) :+: TNil], tpeChannel)
|
||||
|
||||
implicit val ttReturnChannels = c.TypeTag[ReturnChannels](toChannels(c.universe)(out))
|
||||
implicit val ttReturnChannels = c.TypeTag[ReturnChannels](toChannels(c.universe)(out, weakTypeOf[Nothing]))
|
||||
implicit val ttReturnLUB = c.TypeTag[ReturnLUB](c.universe.lub(out))
|
||||
val msg = reify(c.prefix.splice.value)
|
||||
reify(askOps[WrappedMessage[ReturnChannels, ReturnLUB]](
|
||||
|
|
@ -78,7 +78,7 @@ object Ask {
|
|||
|
||||
Tell.verify(c)(null, unwrapped, typeOf[(Any, Nothing) :+: TNil], tpeChannel)
|
||||
|
||||
implicit val ttReturnChannels = c.TypeTag[ReturnChannels](toChannels(c.universe)(out))
|
||||
implicit val ttReturnChannels = c.TypeTag[ReturnChannels](toChannels(c.universe)(out, weakTypeOf[Nothing]))
|
||||
implicit val ttReturnLUB = c.TypeTag[ReturnLUB](c.universe.lub(out))
|
||||
if (tpeMsg <:< typeOf[ChannelList])
|
||||
reify(askFutureWrapped[WrappedMessage[ReturnChannels, ReturnLUB]](
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ object Channel {
|
|||
checkUnique(c.universe)(tpeMsgT, tpeMyChannels) foreach (c.error(c.enclosingPosition, _))
|
||||
// need to calculate the intersection of the reply channel sets for all input channels
|
||||
val intersection = inputChannels(c.universe)(tpeMsgT) map (replyChannels(c.universe)(tpeMyChannels, _).toSet) reduce (_ intersect _)
|
||||
val channels = toChannels(c.universe)(intersection.toList)
|
||||
val channels = toChannels(c.universe)(intersection.toList, weakTypeOf[UnknownDoNotWriteMeDown])
|
||||
implicit val ttMyChannels = c.TypeTag[MyChannels](tpeMyChannels)
|
||||
implicit val ttReplyChannels = c.TypeTag[ReplyChannels](channels)
|
||||
implicit val ttMsgT = c.TypeTag[MsgT](tpeMsgT)
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ object Helpers {
|
|||
* convert a list of types List(<T1>, <T2>, ...) into a ChannelList
|
||||
* ( Channel[<T1>, Nothing] :=: Channel[<T2>, Nothing] :=: ... :=: TNil )
|
||||
*/
|
||||
final def toChannels(u: Universe)(list: List[u.Type]): u.Type = {
|
||||
final def toChannels(u: Universe)(list: List[u.Type], out: u.Type): u.Type = {
|
||||
import u._
|
||||
def rec(l: List[Type], acc: Type): Type = l match {
|
||||
case head :: (tail: List[Type]) ⇒
|
||||
|
|
@ -127,7 +127,7 @@ object Helpers {
|
|||
appliedType(weakTypeOf[:+:[_, _]].typeConstructor, List(
|
||||
appliedType(weakTypeOf[Tuple2[_, _]].typeConstructor, List(
|
||||
head,
|
||||
weakTypeOf[Nothing])),
|
||||
out)),
|
||||
acc)))
|
||||
case _ ⇒ acc
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,15 +70,18 @@ object Tell {
|
|||
}
|
||||
|
||||
def verify(c: Context)(sender: c.universe.Tree, msgT: c.universe.Type, sndT: c.universe.Type, chT: c.universe.Type)(): Unit = {
|
||||
val unknown = c.universe.weakTypeOf[UnknownDoNotWriteMeDown]
|
||||
val nothing = c.universe.weakTypeOf[Nothing]
|
||||
def ignoreUnknown(in: c.universe.Type): c.universe.Type = if (in =:= unknown) nothing else in
|
||||
def rec(msg: Set[c.universe.Type], checked: Set[c.universe.Type], depth: Int): Unit =
|
||||
if (msg.nonEmpty) {
|
||||
val u: c.universe.type = c.universe
|
||||
val replies = msg map (m ⇒ m -> replyChannels(u)(chT, m))
|
||||
val replies = msg map (m ⇒ m -> (replyChannels(u)(chT, m) map (t => ignoreUnknown(t))))
|
||||
val missing = replies collect { case (k, v) if v.size == 0 ⇒ k }
|
||||
if (missing.nonEmpty)
|
||||
error(c, s"target ChannelRef does not support messages of types ${missing mkString ", "} (at depth $depth)")
|
||||
else {
|
||||
val nextSend = replies.map(_._2).flatten map (m ⇒ m -> replyChannels(u)(sndT, m))
|
||||
val nextSend = replies.map(_._2).flatten map (m ⇒ m -> (replyChannels(u)(sndT, m) map (t => ignoreUnknown(t))))
|
||||
val nextMissing = nextSend collect { case (k, v) if v.size == 0 ⇒ k }
|
||||
if (nextMissing.nonEmpty)
|
||||
error(c, s"implicit sender `$sender` does not support messages of the reply types ${nextMissing mkString ", "} (at depth $depth)")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue