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 :+:[A <: (_, _), B <: ChannelList] extends ChannelList
|
||||||
sealed trait ReplyChannels[T <: 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 {
|
class ActorRefOps(val ref: ActorRef) extends AnyVal {
|
||||||
import macros.Helpers._
|
import macros.Helpers._
|
||||||
def narrow[C <: ChannelList](implicit timeout: Timeout, ec: ExecutionContext, tt: ru.TypeTag[C]): Future[ChannelRef[C]] = {
|
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)
|
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))
|
implicit val ttReturnLUB = c.TypeTag[ReturnLUB](c.universe.lub(out))
|
||||||
reify(askOps[WrappedMessage[ReturnChannels, ReturnLUB]](
|
reify(askOps[WrappedMessage[ReturnChannels, ReturnLUB]](
|
||||||
c.prefix.splice.actorRef, toMsg(c)(msg, tpeMsg).splice)(imp[Timeout](c).splice))
|
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)
|
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))
|
implicit val ttReturnLUB = c.TypeTag[ReturnLUB](c.universe.lub(out))
|
||||||
val msg = reify(c.prefix.splice.value)
|
val msg = reify(c.prefix.splice.value)
|
||||||
reify(askOps[WrappedMessage[ReturnChannels, ReturnLUB]](
|
reify(askOps[WrappedMessage[ReturnChannels, ReturnLUB]](
|
||||||
|
|
@ -78,7 +78,7 @@ object Ask {
|
||||||
|
|
||||||
Tell.verify(c)(null, unwrapped, typeOf[(Any, Nothing) :+: TNil], tpeChannel)
|
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))
|
implicit val ttReturnLUB = c.TypeTag[ReturnLUB](c.universe.lub(out))
|
||||||
if (tpeMsg <:< typeOf[ChannelList])
|
if (tpeMsg <:< typeOf[ChannelList])
|
||||||
reify(askFutureWrapped[WrappedMessage[ReturnChannels, ReturnLUB]](
|
reify(askFutureWrapped[WrappedMessage[ReturnChannels, ReturnLUB]](
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ object Channel {
|
||||||
checkUnique(c.universe)(tpeMsgT, tpeMyChannels) foreach (c.error(c.enclosingPosition, _))
|
checkUnique(c.universe)(tpeMsgT, tpeMyChannels) foreach (c.error(c.enclosingPosition, _))
|
||||||
// need to calculate the intersection of the reply channel sets for all input channels
|
// 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 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 ttMyChannels = c.TypeTag[MyChannels](tpeMyChannels)
|
||||||
implicit val ttReplyChannels = c.TypeTag[ReplyChannels](channels)
|
implicit val ttReplyChannels = c.TypeTag[ReplyChannels](channels)
|
||||||
implicit val ttMsgT = c.TypeTag[MsgT](tpeMsgT)
|
implicit val ttMsgT = c.TypeTag[MsgT](tpeMsgT)
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ object Helpers {
|
||||||
* convert a list of types List(<T1>, <T2>, ...) into a ChannelList
|
* convert a list of types List(<T1>, <T2>, ...) into a ChannelList
|
||||||
* ( Channel[<T1>, Nothing] :=: Channel[<T2>, Nothing] :=: ... :=: TNil )
|
* ( 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._
|
import u._
|
||||||
def rec(l: List[Type], acc: Type): Type = l match {
|
def rec(l: List[Type], acc: Type): Type = l match {
|
||||||
case head :: (tail: List[Type]) ⇒
|
case head :: (tail: List[Type]) ⇒
|
||||||
|
|
@ -127,7 +127,7 @@ object Helpers {
|
||||||
appliedType(weakTypeOf[:+:[_, _]].typeConstructor, List(
|
appliedType(weakTypeOf[:+:[_, _]].typeConstructor, List(
|
||||||
appliedType(weakTypeOf[Tuple2[_, _]].typeConstructor, List(
|
appliedType(weakTypeOf[Tuple2[_, _]].typeConstructor, List(
|
||||||
head,
|
head,
|
||||||
weakTypeOf[Nothing])),
|
out)),
|
||||||
acc)))
|
acc)))
|
||||||
case _ ⇒ 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 = {
|
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 =
|
def rec(msg: Set[c.universe.Type], checked: Set[c.universe.Type], depth: Int): Unit =
|
||||||
if (msg.nonEmpty) {
|
if (msg.nonEmpty) {
|
||||||
val u: c.universe.type = c.universe
|
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 }
|
val missing = replies collect { case (k, v) if v.size == 0 ⇒ k }
|
||||||
if (missing.nonEmpty)
|
if (missing.nonEmpty)
|
||||||
error(c, s"target ChannelRef does not support messages of types ${missing mkString ", "} (at depth $depth)")
|
error(c, s"target ChannelRef does not support messages of types ${missing mkString ", "} (at depth $depth)")
|
||||||
else {
|
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 }
|
val nextMissing = nextSend collect { case (k, v) if v.size == 0 ⇒ k }
|
||||||
if (nextMissing.nonEmpty)
|
if (nextMissing.nonEmpty)
|
||||||
error(c, s"implicit sender `$sender` does not support messages of the reply types ${nextMissing mkString ", "} (at depth $depth)")
|
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