Repository: slawlor/ractor
Pull request #13 (2023-01-08 19:11:48)

Adding a strongly-typed actor reference
`ActorRef` serves as a strongly-typed wrapper on top of `ActorCell` to automate a lot of the type mapping that needs to go one regarding getting the appropriate message and state types.

It also exposes a suite of functions related to rpcs, timers, and the registry which utilize the `TActor` that is encoded into the struct, removing the need to explicitly state it in the call.

This change also adds the `std::any::TypeId` to the `ActorProperties` upon creation, such that the type id is recorded for all future access. Attempts to send a message to an actor with a type id mismatch will return error and additionally attempts to load an actor from the named registry with the wrong handler type will return None. This gives us a lot of type safety when working with the actors, without having to remember all the type implementations and provide them in the calls.

Blocked on #10 and a rebase

Resolves: #11, #12 


Patch:
diff --git a/Cargo.toml b/Cargo.toml
index f1ab7f4..edeb161 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,5 +2,5 @@
 
 members = [
     "ractor",
-    "ractor-repl"
+    "ractor-playground"
 ]
diff --git a/ractor-repl/Cargo.toml b/ractor-playground/Cargo.toml
similarity index 76%
rename from ractor-repl/Cargo.toml
rename to ractor-playground/Cargo.toml
index dbaf9f8..a561c61 100644
--- a/ractor-repl/Cargo.toml
+++ b/ractor-playground/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
-name = "ractor-repl"
-default-run = "ractor-repl"
+name = "ractor-playground"
+default-run = "ractor-playground"
 version = "0.0.0"
 authors = ["Sean Lawlor <seanlawlor@fb.com>"]
 description = "A actor framework for Rust - REPL"
diff --git a/ractor-repl/src/main.rs b/ractor-playground/src/main.rs
similarity index 100%
rename from ractor-repl/src/main.rs
rename to ractor-playground/src/main.rs
diff --git a/ractor-repl/src/ping_pong.rs b/ractor-playground/src/ping_pong.rs
similarity index 79%
rename from ractor-repl/src/ping_pong.rs
rename to ractor-playground/src/ping_pong.rs
index a970bc9..94ed3c6 100644
--- a/ractor-repl/src/ping_pong.rs
+++ b/ractor-playground/src/ping_pong.rs
@@ -5,7 +5,7 @@
 
 //! A ping-pong actor implementation
 
-use ractor::{ActorCell, ActorHandler};
+use ractor::{ActorHandler, ActorRef};
 
 pub struct PingPong;
 
@@ -37,17 +37,17 @@ impl ActorHandler for PingPong {
 
     type State = u8;
 
-    async fn pre_start(&self, myself: ActorCell) -> Self::State {
+    async fn pre_start(&self, myself: ActorRef<Self>) -> Self::State {
         println!("pre_start called");
         // startup the event processing
-        self.send_message(myself, Message::Ping).unwrap();
+        myself.send_message(Message::Ping).unwrap();
         // create the initial state
         0u8
     }
 
     async fn post_start(
         &self,
-        _this_actor: ActorCell,
+        _this_actor: ActorRef<Self>,
         _state: &Self::State,
     ) -> Option<Self::State> {
         println!("post_start called");
@@ -55,20 +55,20 @@ impl ActorHandler for PingPong {
     }
 
     /// Invoked after an actor has been stopped.
-    async fn post_stop(&self, _this_actor: ActorCell, _state: Self::State) -> Self::State {
+    async fn post_stop(&self, _this_actor: ActorRef<Self>, _state: Self::State) -> Self::State {
         println!("post_stop called");
         _state
     }
 
     async fn handle(
         &self,
-        myself: ActorCell,
+        myself: ActorRef<Self>,
         message: Self::Msg,
         state: &Self::State,
     ) -> Option<Self::State> {
         if *state < 10u8 {
             message.print();
-            self.send_message(myself, message.next()).unwrap();
+            myself.send_message(message.next()).unwrap();
             Some(*state + 1)
         } else {
             println!();
diff --git a/ractor/Cargo.toml b/ractor/Cargo.toml
index ea3be38..a231e25 100644
--- a/ractor/Cargo.toml
+++ b/ractor/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "ractor"
-version = "0.1.2"
+version = "0.2.0"
 authors = ["Sean Lawlor <seanlawlor@fb.com>"]
 description = "A actor framework for Rust"
 license = "MIT"
diff --git a/ractor/examples/counter.rs b/ractor/examples/counter.rs
index cb5630a..d213014 100644
--- a/ractor/examples/counter.rs
+++ b/ractor/examples/counter.rs
@@ -14,7 +14,7 @@
 
 extern crate ractor;
 
-use ractor::{rpc, Actor, ActorCell, ActorHandler, RpcReplyPort};
+use ractor::{Actor, ActorHandler, ActorRef, RpcReplyPort};
 use tokio::time::Duration;
 
 struct Counter;
@@ -36,14 +36,14 @@ impl ActorHandler for Counter {
 
     type State = CounterState;
 
-    async fn pre_start(&self, _myself: ActorCell) -> Self::State {
+    async fn pre_start(&self, _myself: ActorRef<Self>) -> Self::State {
         // create the initial state
         CounterState { count: 0 }
     }
 
     async fn handle(
         &self,
-        _myself: ActorCell,
+        _myself: ActorRef<Self>,
         message: Self::Msg,
         state: &Self::State,
     ) -> Option<Self::State> {
@@ -73,22 +73,19 @@ async fn main() {
     // +5 +10 -5 a few times, printing the value via RPC
     for _i in 0..4 {
         actor
-            .send_message::<Counter>(CounterMessage::Increment(5))
+            .send_message(CounterMessage::Increment(5))
             .expect("Failed to send message");
         actor
-            .send_message::<Counter>(CounterMessage::Increment(10))
+            .send_message(CounterMessage::Increment(10))
             .expect("Failed to send message");
         actor
-            .send_message::<Counter>(CounterMessage::Decrement(5))
+            .send_message(CounterMessage::Decrement(5))
             .expect("Failed to send message");
 
-        let rpc_result = rpc::call::<Counter, _, _>(
-            &actor,
-            CounterMessage::Retrieve,
-            Some(Duration::from_millis(10)),
-        )
-        .await
-        .expect("Failed to send RPC");
+        let rpc_result = actor
+            .call(CounterMessage::Retrieve, Some(Duration::from_millis(10)))
+            .await
+            .expect("Failed to send RPC");
 
         println!(
             "Count is: {}",
diff --git a/ractor/examples/ping_pong.rs b/ractor/examples/ping_pong.rs
index d4d5825..2b71a05 100644
--- a/ractor/examples/ping_pong.rs
+++ b/ractor/examples/ping_pong.rs
@@ -14,7 +14,7 @@
 
 extern crate ractor;
 
-use ractor::{Actor, ActorCell, ActorHandler};
+use ractor::{Actor, ActorHandler, ActorRef};
 
 pub struct PingPong;
 
@@ -46,22 +46,22 @@ impl ActorHandler for PingPong {
 
     type State = u8;
 
-    async fn pre_start(&self, myself: ActorCell) -> Self::State {
+    async fn pre_start(&self, myself: ActorRef<Self>) -> Self::State {
         // startup the event processing
-        self.send_message(myself, Message::Ping).unwrap();
+        myself.send_message(Message::Ping).unwrap();
         // create the initial state
         0u8
     }
 
     async fn handle(
         &self,
-        myself: ActorCell,
+        myself: ActorRef<Self>,
         message: Self::Msg,
         state: &Self::State,
     ) -> Option<Self::State> {
         if *state < 10u8 {
             message.print();
-            self.send_message(myself, message.next()).unwrap();
+            myself.send_message(message.next()).unwrap();
             Some(*state + 1)
         } else {
             println!();
diff --git a/ractor/examples/supervisor.rs b/ractor/examples/supervisor.rs
index c478b56..1e2d8ac 100644
--- a/ractor/examples/supervisor.rs
+++ b/ractor/examples/supervisor.rs
@@ -11,7 +11,7 @@
 //! cargo run --example supervisor
 //! ```
 
-use ractor::{rpc, Actor, ActorCell, ActorHandler, RpcReplyPort, SupervisionEvent};
+use ractor::{Actor, ActorHandler, ActorRef, RpcReplyPort, SupervisionEvent};
 
 use tokio::time::Duration;
 
@@ -22,33 +22,33 @@ async fn main() {
     let (root, handle) = Actor::spawn(Some("root"), RootActor)
         .await
         .expect("Failed to start root actor");
-    let mid_level = rpc::call::<RootActor, _, _>(
-        &root,
-        RootActorMessage::GetMidLevel,
-        Some(Duration::from_millis(100)),
-    )
-    .await
-    .expect("Failed to send message to root actor")
-    .expect("Failed to get mid level actor");
-
-    let leaf = rpc::call::<MidLevelActor, _, _>(
-        &mid_level,
-        MidLevelActorMessage::GetLeaf,
-        Some(Duration::from_millis(100)),
-    )
-    .await
-    .expect("Failed to send message to mid-level actor")
-    .expect("Failed to get leaf actor");
+    let mid_level = root
+        .call(
+            RootActorMessage::GetMidLevel,
+            Some(Duration::from_millis(100)),
+        )
+        .await
+        .expect("Failed to send message to root actor")
+        .expect("Failed to get mid level actor");
+
+    let leaf = mid_level
+        .call(
+            MidLevelActorMessage::GetLeaf,
+            Some(Duration::from_millis(100)),
+        )
+        .await
+        .expect("Failed to send message to mid-level actor")
+        .expect("Failed to get leaf actor");
 
     // send some no-op's to the leaf
     for _ in 1..10 {
-        rpc::cast::<LeafActor>(&leaf, LeafActorMessage::NoOp)
+        leaf.cast(LeafActorMessage::NoOp)
             .expect("Failed to send message to leaf actor");
         tokio::time::sleep(Duration::from_millis(500)).await;
     }
 
     // send the "Boom" message and follow the supervision flow
-    rpc::cast::<LeafActor>(&leaf, LeafActorMessage::Boom)
+    leaf.cast(LeafActorMessage::Boom)
         .expect("Failed to send message to leaf actor");
 
     handle.await.expect("Failed waiting for root actor to die");
@@ -69,7 +69,7 @@ enum LeafActorMessage {
 impl ActorHandler for LeafActor {
     type Msg = LeafActorMessage;
     type State = LeafActorState;
-    async fn pre_start(&self, _myself: ActorCell) -> Self::State {
+    async fn pre_start(&self, _myself: ActorRef<Self>) -> Self::State {
         LeafActorState {}
     }
 
@@ -83,7 +83,7 @@ impl ActorHandler for LeafActor {
 
     async fn handle(
         &self,
-        _myself: ActorCell,
+        _myself: ActorRef<Self>,
         message: Self::Msg,
         _state: &Self::State,
     ) -> Option<Self::State> {
@@ -113,11 +113,11 @@ impl ActorHandler for LeafActor {
 struct MidLevelActor;
 
 struct MidLevelActorState {
-    leaf_actor: ActorCell,
+    leaf_actor: ActorRef<LeafActor>,
 }
 
 enum MidLevelActorMessage {
-    GetLeaf(RpcReplyPort<ActorCell>),
+    GetLeaf(RpcReplyPort<ActorRef<LeafActor>>),
 }
 
 #[async_trait::async_trait]
@@ -125,8 +125,8 @@ impl ActorHandler for MidLevelActor {
     type Msg = MidLevelActorMessage;
     type State = MidLevelActorState;
 
-    async fn pre_start(&self, myself: ActorCell) -> Self::State {
-        let (leaf_actor, _) = Actor::spawn_linked(Some("leaf"), LeafActor, myself)
+    async fn pre_start(&self, myself: ActorRef<Self>) -> Self::State {
+        let (leaf_actor, _) = Actor::spawn_linked(Some("leaf"), LeafActor, myself.into())
             .await
             .expect("Failed to start leaf actor");
         MidLevelActorState { leaf_actor }
@@ -142,7 +142,7 @@ impl ActorHandler for MidLevelActor {
 
     async fn handle(
         &self,
-        _myself: ActorCell,
+        _myself: ActorRef<Self>,
         message: Self::Msg,
         state: &Self::State,
     ) -> Option<Self::State> {
@@ -160,7 +160,7 @@ impl ActorHandler for MidLevelActor {
 
     async fn handle_supervisor_evt(
         &self,
-        _myself: ActorCell,
+        _myself: ActorRef<Self>,
         message: SupervisionEvent,
         state: &Self::State,
     ) -> Option<Self::State> {
@@ -191,11 +191,11 @@ impl ActorHandler for MidLevelActor {
 struct RootActor;
 
 struct RootActorState {
-    mid_level_actor: ActorCell,
+    mid_level_actor: ActorRef<MidLevelActor>,
 }
 
 enum RootActorMessage {
-    GetMidLevel(RpcReplyPort<ActorCell>),
+    GetMidLevel(RpcReplyPort<ActorRef<MidLevelActor>>),
 }
 
 #[async_trait::async_trait]
@@ -203,11 +203,12 @@ impl ActorHandler for RootActor {
     type Msg = RootActorMessage;
     type State = RootActorState;
 
-    async fn pre_start(&self, myself: ActorCell) -> Self::State {
+    async fn pre_start(&self, myself: ActorRef<Self>) -> Self::State {
         println!("RootActor: Started {:?}", myself);
-        let (mid_level_actor, _) = Actor::spawn_linked(Some("mid-level"), MidLevelActor, myself)
-            .await
-            .expect("Failed to spawn mid-level actor");
+        let (mid_level_actor, _) =
+            Actor::spawn_linked(Some("mid-level"), MidLevelActor, myself.into())
+                .await
+                .expect("Failed to spawn mid-level actor");
         RootActorState { mid_level_actor }
     }
 
@@ -221,7 +222,7 @@ impl ActorHandler for RootActor {
 
     async fn handle(
         &self,
-        _myself: ActorCell,
+        _myself: ActorRef<Self>,
         message: Self::Msg,
         state: &Self::State,
     ) -> Option<Self::State> {
@@ -239,7 +240,7 @@ impl ActorHandler for RootActor {
 
     async fn handle_supervisor_evt(
         &self,
-        myself: ActorCell,
+        myself: ActorRef<Self>,
         message: SupervisionEvent,
         state: &Self::State,
     ) -> Option<Self::State> {
diff --git a/ractor/src/actor/actor_cell/actor_properties.rs b/ractor/src/actor/actor_cell/actor_properties.rs
new file mode 100644
index 0000000..3d80f76
--- /dev/null
+++ b/ractor/src/actor/actor_cell/actor_properties.rs
@@ -0,0 +1,106 @@
+// Copyright (c) Sean Lawlor
+//
+// This source code is licensed under both the MIT license found in the
+// LICENSE-MIT file in the root directory of this source tree.
+
+use std::sync::atomic::{AtomicU8, Ordering};
+use std::sync::Arc;
+
+use tokio::sync::mpsc;
+
+use crate::actor::messages::{BoxedMessage, StopMessage};
+use crate::actor::supervision::SupervisionTree;
+use crate::port::{BoundedInputPort, BoundedInputPortReceiver, InputPort, InputPortReceiver};
+use crate::{
+    ActorHandler, ActorId, ActorName, ActorStatus, MessagingErr, Signal, SupervisionEvent,
+};
+
+// The inner-properties of an Actor
+pub(crate) struct ActorProperties {
+    pub(crate) id: ActorId,
+    pub(crate) name: Option<ActorName>,
+    status: Arc<AtomicU8>,
+    pub(crate) signal: BoundedInputPort<Signal>,
+    pub(crate) stop: BoundedInputPort<StopMessage>,
+    pub(crate) supervision: InputPort<SupervisionEvent>,
+    pub(crate) message: InputPort<BoxedMessage>,
+    pub(crate) tree: SupervisionTree,
+    pub(crate) type_id: std::any::TypeId,
+}
+
+impl ActorProperties {
+    pub fn new<TActor>(
+        name: Option<ActorName>,
+    ) -> (
+        Self,
+        BoundedInputPortReceiver<Signal>,
+        BoundedInputPortReceiver<StopMessage>,
+        InputPortReceiver<SupervisionEvent>,
+        InputPortReceiver<BoxedMessage>,
+    )
+    where
+        TActor: ActorHandler,
+    {
+        let (tx_signal, rx_signal) = mpsc::channel(2);
+        let (tx_stop, rx_stop) = mpsc::channel(2);
+        let (tx_supervision, rx_supervision) = mpsc::unbounded_channel();
+        let (tx_message, rx_message) = mpsc::unbounded_channel();
+        (
+            Self {
+                id: crate::ACTOR_ID_ALLOCATOR.fetch_add(1u64, Ordering::Relaxed),
+                name,
+                status: Arc::new(AtomicU8::new(ActorStatus::Unstarted as u8)),
+                signal: tx_signal,
+                stop: tx_stop,
+                supervision: tx_supervision,
+                message: tx_message,
+                tree: SupervisionTree::default(),
+                type_id: std::any::TypeId::of::<TActor>(),
+            },
+            rx_signal,
+            rx_stop,
+            rx_supervision,
+            rx_message,
+        )
+    }
+
+    pub fn get_status(&self) -> ActorStatus {
+        match self.status.load(Ordering::Relaxed) {
+            0u8 => ActorStatus::Unstarted,
+            1u8 => ActorStatus::Starting,
+            2u8 => ActorStatus::Running,
+            3u8 => ActorStatus::Upgrading,
+            4u8 => ActorStatus::Stopping,
+            _ => ActorStatus::Stopped,
+        }
+    }
+
+    pub fn set_status(&self, status: ActorStatus) {
+        self.status.store(status as u8, Ordering::Relaxed);
+    }
+
+    pub fn send_signal(&self, signal: Signal) -> Result<(), MessagingErr> {
+        self.signal.try_send(signal).map_err(|e| e.into())
+    }
+
+    pub fn send_supervisor_evt(&self, message: SupervisionEvent) -> Result<(), MessagingErr> {
+        self.supervision.send(message).map_err(|e| e.into())
+    }
+
+    pub fn send_message<TActor>(&self, message: TActor::Msg) -> Result<(), MessagingErr>
+    where
+        TActor: ActorHandler,
+    {
+        if self.type_id != std::any::TypeId::of::<TActor>() {
+            return Err(MessagingErr::InvalidActorType);
+        }
+
+        let boxed = BoxedMessage::new(message);
+        self.message.send(boxed).map_err(|e| e.into())
+    }
+
+    pub fn send_stop(&self, reason: Option<String>) -> Result<(), MessagingErr> {
+        let msg = reason.map(StopMessage::Reason).unwrap_or(StopMessage::Stop);
+        self.stop.try_send(msg).map_err(|e| e.into())
+    }
+}
diff --git a/ractor/src/actor/actor_cell/actor_ref.rs b/ractor/src/actor/actor_cell/actor_ref.rs
new file mode 100644
index 0000000..d8185fc
--- /dev/null
+++ b/ractor/src/actor/actor_cell/actor_ref.rs
@@ -0,0 +1,191 @@
+// Copyright (c) Sean Lawlor
+//
+// This source code is licensed under both the MIT license found in the
+// LICENSE-MIT file in the root directory of this source tree.
+
+//! [ActorRef] is a strongly-typed wrapper over an [ActorCell]
+
+use std::any::TypeId;
+use std::marker::PhantomData;
+
+use crate::{ActorHandler, ActorId, ActorName, ActorStatus, MessagingErr, SupervisionEvent};
+
+use super::ActorCell;
+
+/// An [ActorRef] is a strongly-typed wrapper over an [ActorCell]
+/// to provide some syntactic wrapping on the requirement to pass
+/// the actor type everywhere
+pub struct ActorRef<TActor>
+where
+    TActor: ActorHandler,
+{
+    pub(crate) inner: ActorCell,
+    _tactor: PhantomData<TActor>,
+}
+
+impl<TActor> Clone for ActorRef<TActor>
+where
+    TActor: ActorHandler,
+{
+    fn clone(&self) -> Self {
+        ActorRef {
+            inner: self.inner.clone(),
+            _tactor: PhantomData::<TActor>,
+        }
+    }
+}
+
+impl<TActor> std::ops::Deref for ActorRef<TActor>
+where
+    TActor: ActorHandler,
+{
+    type Target = ActorCell;
+
+    fn deref(&self) -> &Self::Target {
+        &self.inner
+    }
+}
+
+impl<TActor> From<ActorCell> for ActorRef<TActor>
+where
+    TActor: ActorHandler,
+{
+    fn from(value: ActorCell) -> Self {
+        Self {
+            inner: value,
+            _tactor: PhantomData::<TActor>,
+        }
+    }
+}
+
+impl<TActor> From<ActorRef<TActor>> for ActorCell
+where
+    TActor: ActorHandler,
+{
+    fn from(value: ActorRef<TActor>) -> Self {
+        value.inner
+    }
+}
+
+impl<TActor> std::fmt::Debug for ActorRef<TActor>
+where
+    TActor: ActorHandler,
+{
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{:?}", self.inner)
+    }
+}
+
+impl<TActor> ActorRef<TActor>
+where
+    TActor: ActorHandler,
+{
+    /// Retrieve a cloned [ActorCell] representing this [ActorRef]
+    pub fn get_cell(&self) -> ActorCell {
+        self.inner.clone()
+    }
+
+    /// Retrieve the [crate::Actor]'s unique identifier [ActorId]
+    pub fn get_id(&self) -> ActorId {
+        self.inner.get_id()
+    }
+
+    /// Retrieve the [crate::Actor]'s name
+    pub fn get_name(&self) -> Option<ActorName> {
+        self.inner.get_name()
+    }
+
+    /// Retrieve the current status of an [crate::Actor]
+    ///
+    /// Returns the [crate::Actor]'s current [ActorStatus]
+    pub fn get_status(&self) -> ActorStatus {
+        self.inner.get_status()
+    }
+
+    /// Set the status of the [crate::Actor]
+    ///
+    /// * `status` - The [ActorStatus] to set
+    pub(crate) fn set_status(&self, status: ActorStatus) {
+        self.inner.set_status(status)
+    }
+
+    /// Terminate this [crate::Actor] and all it's children
+    pub(crate) fn terminate(&self) {
+        self.inner.terminate();
+    }
+
+    /// Link this [crate::Actor] to the supervisor
+    ///
+    /// * `supervisor` - The supervisor to link this [crate::Actor] to
+    pub fn link(&self, supervisor: ActorCell) {
+        self.inner.link(supervisor);
+    }
+
+    /// Unlink this [crate::Actor] from the supervisor
+    ///
+    /// * `supervisor` - The supervisor to unlink this [crate::Actor] from
+    pub fn unlink(&self, supervisor: ActorCell) {
+        self.inner.unlink(supervisor)
+    }
+
+    /// Kill this [crate::Actor] forcefully (terminates async work)
+    pub fn kill(&self) {
+        self.inner.kill();
+    }
+
+    /// Stop this [crate::Actor] gracefully (stopping message processing)
+    ///
+    /// * `reason` - An optional static string reason why the stop is occurring
+    pub fn stop(&self, reason: Option<String>) {
+        self.inner.stop(reason);
+    }
+
+    /// Send a strongly-typed message, constructing the boxed message on the fly
+    ///
+    /// * `message` - The message to send
+    ///
+    /// Returns [Ok(())] on successful message send, [Err(MessagingErr)] otherwise
+    pub fn send_message(&self, message: TActor::Msg) -> Result<(), MessagingErr> {
+        self.inner.send_message::<TActor>(message)
+    }
+
+    /// Send a supervisor event to the supervisory port
+    ///
+    /// * `message` - The [SupervisionEvent] to send to the supervisory port
+    ///
+    /// Returns [Ok(())] on successful message send, [Err(MessagingErr)] otherwise
+    #[cfg(test)]
+    pub(crate) fn send_supervisor_evt(
+        &self,
+        message: SupervisionEvent,
+    ) -> Result<(), MessagingErr> {
+        self.inner.send_supervisor_evt(message)
+    }
+
+    /// Notify the supervisors that a supervision event occurred
+    ///
+    /// * `evt` - The event to send to this [crate::Actor]'s supervisors
+    pub fn notify_supervisors(&self, evt: SupervisionEvent) {
+        self.inner.notify_supervisors::<TActor>(evt)
+    }
+
+    // ========================== General Actor Operation Aliases ========================== //
+
+    // -------------------------- ActorRegistry -------------------------- //
+
+    /// Try and retrieve a strongly-typed actor from the registry.
+    ///
+    /// Alias of [crate::registry::try_get]
+    pub fn try_get_from_registry(name: ActorName) -> Option<ActorRef<TActor>> {
+        if let Some(actor) = crate::registry::try_get(name) {
+            // check the type id when pulling from the registry
+            if actor.inner.type_id == TypeId::of::<TActor>() {
+                Some(actor.into())
+            } else {
+                None
+            }
+        } else {
+            None
+        }
+    }
+}
diff --git a/ractor/src/actor/actor_cell.rs b/ractor/src/actor/actor_cell/mod.rs
similarity index 67%
rename from ractor/src/actor/actor_cell.rs
rename to ractor/src/actor/actor_cell/mod.rs
index f3a1c16..ecceb89 100644
--- a/ractor/src/actor/actor_cell.rs
+++ b/ractor/src/actor/actor_cell/mod.rs
@@ -9,21 +9,20 @@
 //! the internal properties, ports, states, etc. [ActorCell] is the basic primitive
 //! for references to a given actor and its communication channels
 
-use std::sync::atomic::{AtomicU8, Ordering};
 use std::sync::Arc;
 
-use tokio::sync::mpsc;
-use tokio::time::Duration;
-
 use super::errors::MessagingErr;
 use super::messages::{BoxedMessage, Signal, StopMessage};
-use super::supervision::SupervisionTree;
+
 use super::SupervisionEvent;
-use crate::port::{
-    BoundedInputPort, BoundedInputPortReceiver, InputPort, InputPortReceiver, RpcReplyPort,
-};
-use crate::rpc::{self, CallResult};
-use crate::{ActorHandler, ActorId, ActorName, Message, SpawnErr};
+use crate::port::{BoundedInputPortReceiver, InputPortReceiver};
+use crate::{ActorHandler, ActorId, ActorName, SpawnErr};
+
+pub mod actor_ref;
+pub use actor_ref::ActorRef;
+
+mod actor_properties;
+use actor_properties::ActorProperties;
 
 /// [ActorStatus] represents the status of an actor
 #[derive(Debug, Clone, Eq, PartialEq, Copy)]
@@ -132,83 +131,6 @@ impl ActorPortSet {
     }
 }
 
-/// The inner-properties of an Actor
-struct ActorProperties {
-    id: ActorId,
-    name: Option<ActorName>,
-    status: Arc<AtomicU8>,
-    signal: BoundedInputPort<Signal>,
-    stop: BoundedInputPort<StopMessage>,
-    supervision: InputPort<SupervisionEvent>,
-    message: InputPort<BoxedMessage>,
-    tree: SupervisionTree,
-}
-
-impl ActorProperties {
-    pub fn new(
-        name: Option<ActorName>,
-    ) -> (
-        Self,
-        BoundedInputPortReceiver<Signal>,
-        BoundedInputPortReceiver<StopMessage>,
-        InputPortReceiver<SupervisionEvent>,
-        InputPortReceiver<BoxedMessage>,
-    ) {
-        let (tx_signal, rx_signal) = mpsc::channel(2);
-        let (tx_stop, rx_stop) = mpsc::channel(2);
-        let (tx_supervision, rx_supervision) = mpsc::unbounded_channel();
-        let (tx_message, rx_message) = mpsc::unbounded_channel();
-        (
-            Self {
-                id: crate::ACTOR_ID_ALLOCATOR.fetch_add(1u64, Ordering::Relaxed),
-                name,
-                status: Arc::new(AtomicU8::new(ActorStatus::Unstarted as u8)),
-                signal: tx_signal,
-                stop: tx_stop,
-                supervision: tx_supervision,
-                message: tx_message,
-                tree: SupervisionTree::default(),
-            },
-            rx_signal,
-            rx_stop,
-            rx_supervision,
-            rx_message,
-        )
-    }
-
-    pub fn get_status(&self) -> ActorStatus {
-        match self.status.load(Ordering::Relaxed) {
-            0u8 => ActorStatus::Unstarted,
-            1u8 => ActorStatus::Starting,
-            2u8 => ActorStatus::Running,
-            3u8 => ActorStatus::Upgrading,
-            4u8 => ActorStatus::Stopping,
-            _ => ActorStatus::Stopped,
-        }
-    }
-
-    pub fn set_status(&self, status: ActorStatus) {
-        self.status.store(status as u8, Ordering::Relaxed);
-    }
-
-    pub fn send_signal(&self, signal: Signal) -> Result<(), MessagingErr> {
-        self.signal.try_send(signal).map_err(|e| e.into())
-    }
-
-    pub fn send_supervisor_evt(&self, message: SupervisionEvent) -> Result<(), MessagingErr> {
-        self.supervision.send(message).map_err(|e| e.into())
-    }
-
-    pub fn send_message(&self, message: BoxedMessage) -> Result<(), MessagingErr> {
-        self.message.send(message).map_err(|e| e.into())
-    }
-
-    pub fn send_stop(&self, reason: Option<String>) -> Result<(), MessagingErr> {
-        let msg = reason.map(StopMessage::Reason).unwrap_or(StopMessage::Stop);
-        self.stop.try_send(msg).map_err(|e| e.into())
-    }
-}
-
 /// A handy-dandy reference to and actor and their inner properties
 /// which can be cloned and passed around
 #[derive(Clone)]
@@ -246,8 +168,11 @@ impl ActorCell {
     /// * `name` - Optional name for the actor
     ///
     /// Returns a tuple [(ActorCell, ActorPortSet)] to bootstrap the [Actor]
-    pub(crate) fn new(name: Option<ActorName>) -> Result<(Self, ActorPortSet), SpawnErr> {
-        let (props, rx1, rx2, rx3, rx4) = ActorProperties::new(name);
+    pub(crate) fn new<TActor>(name: Option<ActorName>) -> Result<(Self, ActorPortSet), SpawnErr>
+    where
+        TActor: ActorHandler,
+    {
+        let (props, rx1, rx2, rx3, rx4) = ActorProperties::new::<TActor>(name);
         let cell = Self {
             inner: Arc::new(props),
         };
@@ -358,7 +283,7 @@ impl ActorCell {
     where
         TActor: ActorHandler,
     {
-        self.inner.send_message(BoxedMessage::new(message))
+        self.inner.send_message::<TActor>(message)
     }
 
     /// Notify the supervisors that a supervision event occurred
@@ -371,65 +296,9 @@ impl ActorCell {
         self.inner.tree.notify_supervisors::<TActor>(evt)
     }
 
-    /// Alias of [rpc::cast]
-    pub fn cast<TActor>(&self, msg: TActor::Msg) -> Result<(), MessagingErr>
-    where
-        TActor: ActorHandler,
-    {
-        rpc::cast::<TActor>(self, msg)
-    }
-
-    /// Alias of [rpc::call]
-    pub async fn call<TActor, TMsg, TReply, TMsgBuilder>(
-        &self,
-        msg_builder: TMsgBuilder,
-        timeout_option: Option<Duration>,
-    ) -> Result<CallResult<TReply>, MessagingErr>
-    where
-        TActor: ActorHandler<Msg = TMsg>,
-        TMsg: Message,
-        TMsgBuilder: FnOnce(RpcReplyPort<TReply>) -> TMsg,
-    {
-        rpc::call::<TActor, TReply, TMsgBuilder>(self, msg_builder, timeout_option).await
-    }
-
-    /// Alias of [rpc::call_and_forward]
-    pub fn call_and_forward<
-        TActor,
-        TForwardActor,
-        TMsg,
-        TReply,
-        TMsgBuilder,
-        FwdMapFn,
-        TForwardMessage,
-    >(
-        &self,
-        msg_builder: TMsgBuilder,
-        response_forward: ActorCell,
-        forward_mapping: FwdMapFn,
-        timeout_option: Option<Duration>,
-    ) -> Result<tokio::task::JoinHandle<CallResult<Result<(), MessagingErr>>>, MessagingErr>
-    where
-        TActor: ActorHandler<Msg = TMsg>,
-        TMsg: Message,
-        TReply: Message,
-        TMsgBuilder: FnOnce(RpcReplyPort<TReply>) -> TMsg,
-        TForwardActor: ActorHandler<Msg = TForwardMessage>,
-        FwdMapFn: FnOnce(TReply) -> TForwardMessage + Send + 'static,
-        TForwardMessage: Message,
-    {
-        rpc::call_and_forward::<TActor, TForwardActor, TReply, TMsgBuilder, FwdMapFn>(
-            self,
-            msg_builder,
-            response_forward,
-            forward_mapping,
-            timeout_option,
-        )
-    }
-
     /// Test utility to retrieve a clone of the underlying supervision tree
     #[cfg(test)]
-    pub(crate) fn get_tree(&self) -> SupervisionTree {
+    pub(crate) fn get_tree(&self) -> super::supervision::SupervisionTree {
         self.inner.tree.clone()
     }
 }
diff --git a/ractor/src/actor/errors.rs b/ractor/src/actor/errors.rs
index edf4be2..56724bf 100644
--- a/ractor/src/actor/errors.rs
+++ b/ractor/src/actor/errors.rs
@@ -87,6 +87,11 @@ pub enum MessagingErr {
     /// If you're sending to an [crate::ActorCell] then that means the actor has died
     /// (failure or not).
     ChannelClosed,
+
+    /// Tried to send a message to an actor with an invalid actor type defined.
+    /// This happens if you have an [crate::ActorCell] which has the type id of its
+    /// handler and you try to use an alternate handler to send a message
+    InvalidActorType,
 }
 
 impl<T> From<tokio::sync::mpsc::error::SendError<T>> for MessagingErr {
@@ -119,6 +124,9 @@ impl Display for MessagingErr {
             Self::ChannelClosed => {
                 write!(f, "Messaging failed because channel is closed")
             }
+            Self::InvalidActorType => {
+                write!(f, "Messaging failed due to the provided actor type not matching the actor's properties")
+            }
         }
     }
 }
diff --git a/ractor/src/actor/mod.rs b/ractor/src/actor/mod.rs
index d6cad37..abbff7f 100644
--- a/ractor/src/actor/mod.rs
+++ b/ractor/src/actor/mod.rs
@@ -24,7 +24,7 @@ pub mod supervision;
 mod tests;
 
 use crate::{ActorName, Message, State};
-use actor_cell::{ActorCell, ActorPortSet, ActorStatus};
+use actor_cell::{ActorCell, ActorPortSet, ActorRef, ActorStatus};
 use errors::{ActorErr, MessagingErr, SpawnErr};
 
 pub(crate) fn get_panic_string(e: Box<dyn std::any::Any + Send>) -> String {
@@ -81,7 +81,7 @@ pub trait ActorHandler: Sized + Sync + Send + 'static {
     /// * `myself` - A handle to the [ActorCell] representing this actor
     ///
     /// Returns an initial [ActorHandler::State] to bootstrap the actor
-    async fn pre_start(&self, myself: ActorCell) -> Self::State;
+    async fn pre_start(&self, myself: ActorRef<Self>) -> Self::State;
 
     /// Invoked after an actor has started.
     ///
@@ -95,7 +95,7 @@ pub trait ActorHandler: Sized + Sync + Send + 'static {
     ///
     /// Returns [Some(ActorHandler::State)] if the state should be updated with a new value, [None] otherwise
     #[allow(unused_variables)]
-    async fn post_start(&self, myself: ActorCell, state: &Self::State) -> Option<Self::State> {
+    async fn post_start(&self, myself: ActorRef<Self>, state: &Self::State) -> Option<Self::State> {
         None
     }
 
@@ -106,7 +106,7 @@ pub trait ActorHandler: Sized + Sync + Send + 'static {
     ///
     /// Returns: The last [ActorHandler::State] (after doing any teardown) which might be necessary to re-create the actor
     #[allow(unused_variables)]
-    async fn post_stop(&self, myself: ActorCell, state: Self::State) -> Self::State {
+    async fn post_stop(&self, myself: ActorRef<Self>, state: Self::State) -> Self::State {
         state
     }
 
@@ -121,7 +121,7 @@ pub trait ActorHandler: Sized + Sync + Send + 'static {
     #[allow(unused_variables)]
     async fn handle(
         &self,
-        myself: ActorCell,
+        myself: ActorRef<Self>,
         message: Self::Msg,
         state: &Self::State,
     ) -> Option<Self::State> {
@@ -139,22 +139,12 @@ pub trait ActorHandler: Sized + Sync + Send + 'static {
     #[allow(unused_variables)]
     async fn handle_supervisor_evt(
         &self,
-        myself: ActorCell,
+        myself: ActorRef<Self>,
         message: SupervisionEvent,
         state: &Self::State,
     ) -> Option<Self::State> {
         None
     }
-
-    /// Send a message to the specified actor, which is strong-typed to the message handler's type
-    ///
-    /// * `myself` - A handle to the [ActorCell] representing this actor
-    /// * `msg` - The message to send to this actor
-    ///
-    /// Returns [Ok(())] on successful send, [Err(MessagingError)] in the event sending failed
-    fn send_message(&self, myself: ActorCell, msg: Self::Msg) -> Result<(), MessagingErr> {
-        myself.send_message::<Self>(msg)
-    }
 }
 
 /// [Actor] is a struct which represents the actor. This struct is consumed by the
@@ -165,7 +155,7 @@ where
     TState: State,
     THandler: ActorHandler<Msg = TMsg, State = TState>,
 {
-    base: ActorCell,
+    base: ActorRef<THandler>,
     handler: Arc<THandler>,
 }
 
@@ -186,7 +176,7 @@ where
     pub async fn spawn(
         name: Option<ActorName>,
         handler: THandler,
-    ) -> Result<(ActorCell, JoinHandle<()>), SpawnErr> {
+    ) -> Result<(ActorRef<THandler>, JoinHandle<()>), SpawnErr> {
         let (actor, ports) = Self::new(name, handler)?;
         actor.start(ports, None).await
     }
@@ -204,7 +194,7 @@ where
         name: Option<ActorName>,
         handler: THandler,
         supervisor: ActorCell,
-    ) -> Result<(ActorCell, JoinHandle<()>), SpawnErr> {
+    ) -> Result<(ActorRef<THandler>, JoinHandle<()>), SpawnErr> {
         let (actor, ports) = Self::new(name, handler)?;
         actor.start(ports, Some(supervisor)).await
     }
@@ -216,10 +206,10 @@ where
     ///
     /// Returns A tuple [(Actor, ActorPortSet)] to be passed to the `start` function of [Actor]
     fn new(name: Option<ActorName>, handler: THandler) -> Result<(Self, ActorPortSet), SpawnErr> {
-        let (actor_cell, ports) = ActorCell::new(name)?;
+        let (actor_cell, ports) = actor_cell::ActorCell::new::<THandler>(name)?;
         Ok((
             Self {
-                base: actor_cell,
+                base: actor_cell.into(),
                 handler: Arc::new(handler),
             },
             ports,
@@ -242,7 +232,7 @@ where
         self,
         ports: ActorPortSet,
         supervisor: Option<ActorCell>,
-    ) -> Result<(ActorCell, JoinHandle<()>), SpawnErr> {
+    ) -> Result<(ActorRef<THandler>, JoinHandle<()>), SpawnErr> {
         // cannot start an actor more than once
         if self.base.get_status() != ActorStatus::Unstarted {
             return Err(SpawnErr::ActorAlreadyStarted);
@@ -255,7 +245,7 @@ where
 
         // setup supervision
         if let Some(sup) = &supervisor {
-            sup.link(self.base.clone());
+            sup.link(self.base.clone().into());
         }
 
         // run the processing loop, capturing panic's
@@ -267,18 +257,18 @@ where
                     .await
                 {
                     Ok((last_state, exit_reason)) => SupervisionEvent::ActorTerminated(
-                        myself.clone(),
+                        myself.clone().into(),
                         Some(BoxedState::new(last_state)),
                         exit_reason,
                     ),
                     Err(actor_err) => match actor_err {
                         ActorErr::Cancelled => SupervisionEvent::ActorTerminated(
-                            myself.clone(),
+                            myself.clone().into(),
                             None,
                             Some("killed".to_string()),
                         ),
                         ActorErr::Panic(msg) => {
-                            SupervisionEvent::ActorPanicked(myself.clone(), msg)
+                            SupervisionEvent::ActorPanicked(myself.clone().into(), msg)
                         }
                     },
                 };
@@ -287,12 +277,12 @@ where
             myself.terminate();
 
             // notify supervisors of the actor's death
-            myself.notify_supervisors::<THandler>(evt);
+            myself.notify_supervisors(evt);
 
             myself.set_status(ActorStatus::Stopped);
             // signal received or process exited cleanly, we should already have "handled" the signal, so we can just terminate
             if let Some(sup) = supervisor {
-                sup.unlink(myself.clone());
+                sup.unlink(myself.clone().into());
             }
         });
 
@@ -303,13 +293,13 @@ where
         ports: ActorPortSet,
         state: TState,
         handler: Arc<THandler>,
-        myself: ActorCell,
+        myself: ActorRef<THandler>,
     ) -> Result<(TState, Option<String>), ActorErr> {
         // perform the post-start, with supervision enabled
         let state = Self::do_post_start(myself.clone(), handler.clone(), state).await?;
 
         myself.set_status(ActorStatus::Running);
-        myself.notify_supervisors::<THandler>(SupervisionEvent::ActorStarted(myself.clone()));
+        myself.notify_supervisors(SupervisionEvent::ActorStarted(myself.clone().into()));
 
         // let mut last_state = state.clone();
         let myself_clone = myself.clone();
@@ -364,7 +354,7 @@ where
     /// Returns a tuple of the next [ActorHandler::State] and a flag to denote if the processing
     /// loop is done
     async fn process_message(
-        myself: ActorCell,
+        myself: ActorRef<THandler>,
         state: TState,
         handler: Arc<THandler>,
         ports: &mut ActorPortSet,
@@ -411,11 +401,15 @@ where
                 // the state and the flag to terminate
                 (state, true, None)
             }
+            Err(MessagingErr::InvalidActorType) => {
+                // not possible. Treat like a channel closed
+                (state, true, None)
+            }
         }
     }
 
     async fn handle_message(
-        myself: ActorCell,
+        myself: ActorRef<THandler>,
         state: &TState,
         handler: Arc<THandler>,
         mut msg: BoxedMessage,
@@ -434,7 +428,7 @@ where
         handler.handle(myself, typed_msg, state).await
     }
 
-    async fn handle_signal(myself: ActorCell, signal: Signal) -> Option<String> {
+    async fn handle_signal(myself: ActorRef<THandler>, signal: Signal) -> Option<String> {
         match &signal {
             Signal::Kill => {
                 myself.terminate();
@@ -444,7 +438,7 @@ where
     }
 
     async fn handle_supervision_message(
-        myself: ActorCell,
+        myself: ActorRef<THandler>,
         state: &TState,
         handler: Arc<THandler>,
         message: SupervisionEvent,
@@ -452,7 +446,10 @@ where
         handler.handle_supervisor_evt(myself, message, state).await
     }
 
-    async fn do_pre_start(myself: ActorCell, handler: Arc<THandler>) -> Result<TState, SpawnErr> {
+    async fn do_pre_start(
+        myself: ActorRef<THandler>,
+        handler: Arc<THandler>,
+    ) -> Result<TState, SpawnErr> {
         let start_result =
             handle_panickable(tokio::spawn(async move { handler.pre_start(myself).await })).await;
         match start_result {
@@ -469,7 +466,7 @@ where
     }
 
     async fn do_post_start(
-        myself: ActorCell,
+        myself: ActorRef<THandler>,
         handler: Arc<THandler>,
         state: TState,
     ) -> Result<TState, ActorErr> {
@@ -488,7 +485,7 @@ where
     }
 
     async fn do_post_stop(
-        myself: ActorCell,
+        myself: ActorRef<THandler>,
         handler: Arc<THandler>,
         state: TState,
     ) -> Result<TState, ActorErr> {
diff --git a/ractor/src/lib.rs b/ractor/src/lib.rs
index 83d0c6c..95274f9 100644
--- a/ractor/src/lib.rs
+++ b/ractor/src/lib.rs
@@ -20,7 +20,7 @@
 //! An example "ping-pong" actor might be the following
 //!
 //! ```rust
-//! use ractor::{Actor, ActorCell, ActorHandler};
+//! use ractor::{Actor, ActorRef, ActorHandler};
 //!
 //! /// [PingPong] is a basic actor that will print
 //! /// ping..pong.. repeatedly until some exit
@@ -63,22 +63,22 @@
 //!     // Initially we need to create our state, and potentially
 //!     // start some internal processing (by posting a message for
 //!     // example)
-//!     async fn pre_start(&self, myself: ActorCell) -> Self::State {
+//!     async fn pre_start(&self, myself: ActorRef<Self>) -> Self::State {
 //!         // startup the event processing
-//!         self.send_message(myself, Message::Ping).unwrap();
+//!         myself.send_message(Message::Ping).unwrap();
 //!         0u8
 //!     }
 //!
 //!     // This is our main message handler
 //!     async fn handle(
 //!         &self,
-//!         myself: ActorCell,
+//!         myself: ActorRef<Self>,
 //!         message: Self::Msg,
 //!         state: &Self::State,
 //!     ) -> Option<Self::State> {
 //!         if *state < 10u8 {
 //!             message.print();
-//!             self.send_message(myself, message.next()).unwrap();
+//!             myself.send_message(message.next()).unwrap();
 //!             Some(*state + 1)
 //!         } else {
 //!             myself.stop(None);
@@ -154,7 +154,7 @@ pub mod rpc;
 pub mod time;
 
 // re-exports
-pub use actor::actor_cell::{ActorCell, ActorStatus, ACTIVE_STATES};
+pub use actor::actor_cell::{ActorCell, ActorRef, ActorStatus, ACTIVE_STATES};
 pub use actor::errors::{ActorErr, MessagingErr, SpawnErr};
 pub use actor::messages::{Signal, SupervisionEvent};
 pub use actor::{Actor, ActorHandler};
diff --git a/ractor/src/rpc/mod.rs b/ractor/src/rpc/mod.rs
index e4c9384..b25ae34 100644
--- a/ractor/src/rpc/mod.rs
+++ b/ractor/src/rpc/mod.rs
@@ -15,7 +15,7 @@ use tokio::sync::oneshot;
 use tokio::task::JoinHandle;
 use tokio::time::{self, Duration};
 
-use crate::{ActorCell, ActorHandler, Message, MessagingErr, RpcReplyPort};
+use crate::{ActorCell, ActorHandler, ActorRef, Message, MessagingErr, RpcReplyPort};
 
 pub mod call_result;
 pub use call_result::CallResult;
@@ -175,3 +175,51 @@ where
         .map(|msg| response_forward.send_message::<TForwardActor>(forward_mapping(msg)))
     }))
 }
+
+impl<TActor> ActorRef<TActor>
+where
+    TActor: ActorHandler,
+{
+    /// Alias of [cast]
+    pub fn cast(&self, msg: TActor::Msg) -> Result<(), MessagingErr>
+    where
+        TActor: ActorHandler,
+    {
+        cast::<TActor>(&self.inner, msg)
+    }
+
+    /// Alias of [call]
+    pub async fn call<TReply, TMsgBuilder>(
+        &self,
+        msg_builder: TMsgBuilder,
+        timeout_option: Option<Duration>,
+    ) -> Result<CallResult<TReply>, MessagingErr>
+    where
+        TMsgBuilder: FnOnce(RpcReplyPort<TReply>) -> TActor::Msg,
+    {
+        call::<TActor, TReply, TMsgBuilder>(&self.inner, msg_builder, timeout_option).await
+    }
+
+    /// Alias of [call_and_forward]
+    pub fn call_and_forward<TReply, TForwardActor, TMsgBuilder, TFwdMessageBuilder>(
+        &self,
+        msg_builder: TMsgBuilder,
+        response_forward: &ActorRef<TForwardActor>,
+        forward_mapping: TFwdMessageBuilder,
+        timeout_option: Option<Duration>,
+    ) -> Result<tokio::task::JoinHandle<CallResult<Result<(), MessagingErr>>>, MessagingErr>
+    where
+        TReply: Message,
+        TMsgBuilder: FnOnce(RpcReplyPort<TReply>) -> TActor::Msg,
+        TForwardActor: ActorHandler,
+        TFwdMessageBuilder: FnOnce(TReply) -> TForwardActor::Msg + Send + 'static,
+    {
+        call_and_forward::<TActor, TForwardActor, TReply, TMsgBuilder, TFwdMessageBuilder>(
+            &self.inner,
+            msg_builder,
+            response_forward.inner.clone(),
+            forward_mapping,
+            timeout_option,
+        )
+    }
+}
diff --git a/ractor/src/time/mod.rs b/ractor/src/time/mod.rs
index 102b9c0..b789f92 100644
--- a/ractor/src/time/mod.rs
+++ b/ractor/src/time/mod.rs
@@ -104,3 +104,36 @@ pub fn kill_after(period: Duration, actor: ActorCell) -> JoinHandle<()> {
         actor.kill()
     })
 }
+
+/// Add the timing functionality on top of the [crate::ActorRef]
+impl<TActor> crate::ActorRef<TActor>
+where
+    TActor: ActorHandler,
+{
+    /// Alias of [send_interval]
+    pub fn send_interval<F>(&self, period: Duration, msg: F) -> JoinHandle<()>
+    where
+        TActor: ActorHandler,
+        F: Fn() -> TActor::Msg + Send + 'static,
+    {
+        send_interval::<TActor, F>(period, self.get_cell(), msg)
+    }
+
+    /// Alias of [send_after]
+    pub fn send_after<F>(&self, period: Duration, msg: F) -> JoinHandle<Result<(), MessagingErr>>
+    where
+        F: Fn() -> TActor::Msg + Send + 'static,
+    {
+        send_after::<TActor, F>(period, self.get_cell(), msg)
+    }
+
+    /// Alias of [exit_after]
+    pub fn exit_after(&self, period: Duration) -> JoinHandle<()> {
+        exit_after(period, self.get_cell())
+    }
+
+    /// Alias of [kill_after]
+    pub fn kill_after(&self, period: Duration) -> JoinHandle<()> {
+        kill_after(period, self.get_cell())
+    }
+}


Test patch:
diff --git a/ractor/src/actor/tests/mod.rs b/ractor/src/actor/tests/mod.rs
index e472528..f31e1e1 100644
--- a/ractor/src/actor/tests/mod.rs
+++ b/ractor/src/actor/tests/mod.rs
@@ -12,7 +12,7 @@ use std::sync::{
 
 use tokio::time::Duration;
 
-use crate::{Actor, ActorCell, ActorHandler, ActorStatus, SpawnErr, SupervisionEvent};
+use crate::{Actor, ActorCell, ActorHandler, ActorRef, ActorStatus, SpawnErr, SupervisionEvent};
 
 mod supervisor;
 
@@ -26,7 +26,7 @@ async fn test_panic_on_start_captured() {
 
         type State = ();
 
-        async fn pre_start(&self, _this_actor: crate::ActorCell) -> Self::State {
+        async fn pre_start(&self, _this_actor: crate::ActorRef<Self>) -> Self::State {
             panic!("Boom!");
         }
     }
@@ -49,11 +49,11 @@ async fn test_stop_higher_priority_over_messages() {
 
         type State = ();
 
-        async fn pre_start(&self, _this_actor: crate::ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: crate::ActorRef<Self>) -> Self::State {}
 
         async fn handle(
             &self,
-            _myself: ActorCell,
+            _myself: ActorRef<Self>,
             _message: Self::Msg,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -75,7 +75,7 @@ async fn test_stop_higher_priority_over_messages() {
     // pump 10 messages on the queue
     for _i in 0..10 {
         actor
-            .send_message::<TestActor>(())
+            .send_message(())
             .expect("Failed to send message to actor");
     }
 
@@ -113,11 +113,11 @@ async fn test_kill_terminates_work() {
 
         type State = ();
 
-        async fn pre_start(&self, _this_actor: crate::ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: crate::ActorRef<Self>) -> Self::State {}
 
         async fn handle(
             &self,
-            _myself: ActorCell,
+            _myself: ActorRef<Self>,
             _message: Self::Msg,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -131,7 +131,7 @@ async fn test_kill_terminates_work() {
         .expect("Actor failed to start");
 
     actor
-        .send_message::<TestActor>(())
+        .send_message(())
         .expect("Failed to send message to actor");
     tokio::time::sleep(Duration::from_millis(10)).await;
 
@@ -152,11 +152,11 @@ async fn test_stop_does_not_terminate_async_work() {
 
         type State = ();
 
-        async fn pre_start(&self, _this_actor: crate::ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: crate::ActorRef<Self>) -> Self::State {}
 
         async fn handle(
             &self,
-            _myself: ActorCell,
+            _myself: ActorRef<Self>,
             _message: Self::Msg,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -171,7 +171,7 @@ async fn test_stop_does_not_terminate_async_work() {
 
     // send a work message followed by a stop message
     actor
-        .send_message::<TestActor>(())
+        .send_message(())
         .expect("Failed to send message to actor");
     tokio::time::sleep(Duration::from_millis(2)).await;
     actor.stop(None);
@@ -198,11 +198,11 @@ async fn test_kill_terminates_supervision_work() {
 
         type State = ();
 
-        async fn pre_start(&self, _this_actor: crate::ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: crate::ActorRef<Self>) -> Self::State {}
 
         async fn handle_supervisor_evt(
             &self,
-            _myself: ActorCell,
+            _myself: ActorRef<Self>,
             _message: SupervisionEvent,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -216,8 +216,9 @@ async fn test_kill_terminates_supervision_work() {
         .expect("Actor failed to start");
 
     // send some dummy event to cause the supervision stuff to hang
+    let actor_cell: ActorCell = actor.clone().into();
     actor
-        .send_supervisor_evt(SupervisionEvent::ActorStarted(actor.clone()))
+        .send_supervisor_evt(SupervisionEvent::ActorStarted(actor_cell))
         .expect("Failed to send message to actor");
     tokio::time::sleep(Duration::from_millis(10)).await;
 
diff --git a/ractor/src/actor/tests/supervisor.rs b/ractor/src/actor/tests/supervisor.rs
index b8a19cd..c6ca52f 100644
--- a/ractor/src/actor/tests/supervisor.rs
+++ b/ractor/src/actor/tests/supervisor.rs
@@ -12,7 +12,7 @@ use std::sync::{
 
 use tokio::time::Duration;
 
-use crate::{Actor, ActorCell, ActorHandler, ActorStatus, SupervisionEvent};
+use crate::{Actor, ActorCell, ActorHandler, ActorRef, ActorStatus, SupervisionEvent};
 
 #[tokio::test]
 async fn test_supervision_panic_in_post_startup() {
@@ -25,10 +25,10 @@ async fn test_supervision_panic_in_post_startup() {
     impl ActorHandler for Child {
         type Msg = ();
         type State = ();
-        async fn pre_start(&self, _this_actor: ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: ActorRef<Self>) -> Self::State {}
         async fn post_start(
             &self,
-            _this_actor: ActorCell,
+            _this_actor: ActorRef<Self>,
             _state: &Self::State,
         ) -> Option<Self::State> {
             panic!("Boom");
@@ -39,10 +39,10 @@ async fn test_supervision_panic_in_post_startup() {
     impl ActorHandler for Supervisor {
         type Msg = ();
         type State = ();
-        async fn pre_start(&self, _this_actor: ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: ActorRef<Self>) -> Self::State {}
         async fn handle(
             &self,
-            _this_actor: ActorCell,
+            _this_actor: ActorRef<Self>,
             _message: Self::Msg,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -51,7 +51,7 @@ async fn test_supervision_panic_in_post_startup() {
 
         async fn handle_supervisor_evt(
             &self,
-            this_actor: ActorCell,
+            this_actor: ActorRef<Self>,
             message: SupervisionEvent,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -73,9 +73,10 @@ async fn test_supervision_panic_in_post_startup() {
         .await
         .expect("Supervisor panicked on startup");
 
-    let supervisor_tree = supervisor_ref.get_tree();
+    let supervisor_cell: ActorCell = supervisor_ref.into();
+    let supervisor_tree = supervisor_cell.get_tree();
 
-    let (child_ref, c_handle) = Actor::spawn_linked(None, Child, supervisor_ref)
+    let (child_ref, c_handle) = Actor::spawn_linked(None, Child, supervisor_cell)
         .await
         .expect("Child panicked on startup");
 
@@ -98,10 +99,10 @@ async fn test_supervision_panic_in_handle() {
     impl ActorHandler for Child {
         type Msg = ();
         type State = ();
-        async fn pre_start(&self, _this_actor: ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: ActorRef<Self>) -> Self::State {}
         async fn handle(
             &self,
-            _this_actor: ActorCell,
+            _this_actor: ActorRef<Self>,
             _message: Self::Msg,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -113,10 +114,10 @@ async fn test_supervision_panic_in_handle() {
     impl ActorHandler for Supervisor {
         type Msg = ();
         type State = ();
-        async fn pre_start(&self, _this_actor: ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: ActorRef<Self>) -> Self::State {}
         async fn handle(
             &self,
-            _this_actor: ActorCell,
+            _this_actor: ActorRef<Self>,
             _message: Self::Msg,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -125,7 +126,7 @@ async fn test_supervision_panic_in_handle() {
 
         async fn handle_supervisor_evt(
             &self,
-            this_actor: ActorCell,
+            this_actor: ActorRef<Self>,
             message: SupervisionEvent,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -147,20 +148,20 @@ async fn test_supervision_panic_in_handle() {
         .await
         .expect("Supervisor panicked on startup");
 
-    let supervisor_tree = supervisor_ref.get_tree();
+    let supervisor_cell: ActorCell = supervisor_ref.into();
+    let supervisor_tree = supervisor_cell.get_tree();
 
-    let (child_ref, c_handle) = Actor::spawn_linked(None, Child, supervisor_ref)
+    let (child_ref, c_handle) = Actor::spawn_linked(None, Child, supervisor_cell)
         .await
         .expect("Child panicked on startup");
 
     // check that the supervision is wired up correctly
     assert_eq!(1, supervisor_tree.get_num_children());
-    assert_eq!(1, child_ref.get_tree().get_num_parents());
+    let child_cell: ActorCell = child_ref.clone().into();
+    assert_eq!(1, child_cell.get_tree().get_num_parents());
 
     // trigger the child failure
-    child_ref
-        .send_message::<Child>(())
-        .expect("Failed to send message");
+    child_ref.send_message(()).expect("Failed to send message");
 
     let (_, _) = tokio::join!(s_handle, c_handle);
 
@@ -181,11 +182,11 @@ async fn test_supervision_panic_in_post_stop() {
     impl ActorHandler for Child {
         type Msg = ();
         type State = ();
-        async fn pre_start(&self, this_actor: ActorCell) -> Self::State {
+        async fn pre_start(&self, this_actor: ActorRef<Self>) -> Self::State {
             // trigger stop, which starts shutdown
             this_actor.stop(None);
         }
-        async fn post_stop(&self, _this_actor: ActorCell, _state: Self::State) -> Self::State {
+        async fn post_stop(&self, _this_actor: ActorRef<Self>, _state: Self::State) -> Self::State {
             panic!("Boom");
         }
     }
@@ -194,10 +195,10 @@ async fn test_supervision_panic_in_post_stop() {
     impl ActorHandler for Supervisor {
         type Msg = ();
         type State = ();
-        async fn pre_start(&self, _this_actor: ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: ActorRef<Self>) -> Self::State {}
         async fn handle(
             &self,
-            _this_actor: ActorCell,
+            _this_actor: ActorRef<Self>,
             _message: Self::Msg,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -206,7 +207,7 @@ async fn test_supervision_panic_in_post_stop() {
 
         async fn handle_supervisor_evt(
             &self,
-            this_actor: ActorCell,
+            this_actor: ActorRef<Self>,
             message: SupervisionEvent,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -228,9 +229,10 @@ async fn test_supervision_panic_in_post_stop() {
         .await
         .expect("Supervisor panicked on startup");
 
-    let supervisor_tree = supervisor_ref.get_tree();
+    let supervisor_cell: ActorCell = supervisor_ref.into();
+    let supervisor_tree = supervisor_cell.get_tree();
 
-    let (child_ref, c_handle) = Actor::spawn_linked(None, Child, supervisor_ref)
+    let (child_ref, c_handle) = Actor::spawn_linked(None, Child, supervisor_cell)
         .await
         .expect("Child panicked on startup");
 
@@ -256,10 +258,10 @@ async fn test_supervision_panic_in_supervisor_handle() {
     impl ActorHandler for Child {
         type Msg = ();
         type State = ();
-        async fn pre_start(&self, _this_actor: ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: ActorRef<Self>) -> Self::State {}
         async fn handle(
             &self,
-            _this_actor: ActorCell,
+            _this_actor: ActorRef<Self>,
             _message: Self::Msg,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -271,10 +273,10 @@ async fn test_supervision_panic_in_supervisor_handle() {
     impl ActorHandler for Midpoint {
         type Msg = ();
         type State = ();
-        async fn pre_start(&self, _this_actor: ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: ActorRef<Self>) -> Self::State {}
         async fn handle_supervisor_evt(
             &self,
-            _this_actor: ActorCell,
+            _this_actor: ActorRef<Self>,
             _message: SupervisionEvent,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -289,10 +291,10 @@ async fn test_supervision_panic_in_supervisor_handle() {
     impl ActorHandler for Supervisor {
         type Msg = ();
         type State = ();
-        async fn pre_start(&self, _this_actor: ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: ActorRef<Self>) -> Self::State {}
         async fn handle(
             &self,
-            _this_actor: ActorCell,
+            _this_actor: ActorRef<Self>,
             _message: Self::Msg,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -301,7 +303,7 @@ async fn test_supervision_panic_in_supervisor_handle() {
 
         async fn handle_supervisor_evt(
             &self,
-            this_actor: ActorCell,
+            this_actor: ActorRef<Self>,
             message: SupervisionEvent,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -323,16 +325,18 @@ async fn test_supervision_panic_in_supervisor_handle() {
         .await
         .expect("Supervisor panicked on startup");
 
-    let supervisor_tree = supervisor_ref.get_tree();
+    let supervisor_cell: ActorCell = supervisor_ref.into();
+    let supervisor_tree = supervisor_cell.get_tree();
 
-    let (midpoint_ref, m_handle) = Actor::spawn_linked(None, Midpoint, supervisor_ref)
+    let (midpoint_ref, m_handle) = Actor::spawn_linked(None, Midpoint, supervisor_cell)
         .await
         .expect("Midpoint actor failed to startup");
 
-    let midpoint_tree = midpoint_ref.get_tree();
+    let midpoint_cell: ActorCell = midpoint_ref.clone().into();
+    let midpoint_tree = midpoint_cell.get_tree();
     let midpoint_ref_clone = midpoint_ref.clone();
 
-    let (child_ref, c_handle) = Actor::spawn_linked(None, Child, midpoint_ref)
+    let (child_ref, c_handle) = Actor::spawn_linked(None, Child, midpoint_cell)
         .await
         .expect("Child panicked on startup");
 
@@ -340,12 +344,11 @@ async fn test_supervision_panic_in_supervisor_handle() {
     assert_eq!(1, supervisor_tree.get_num_children());
     assert_eq!(1, midpoint_tree.get_num_children());
     assert_eq!(1, midpoint_tree.get_num_parents());
-    assert_eq!(1, child_ref.get_tree().get_num_parents());
+    let child_cell: ActorCell = child_ref.clone().into();
+    assert_eq!(1, child_cell.get_tree().get_num_parents());
 
     // trigger the child failure
-    child_ref
-        .send_message::<Child>(())
-        .expect("Failed to send message");
+    child_ref.send_message(()).expect("Failed to send message");
 
     // which triggers the handler in the midpoint, which panic's in supervision
 
@@ -370,17 +373,17 @@ async fn test_killing_a_supervisor_terminates_children() {
     impl ActorHandler for Child {
         type Msg = ();
         type State = ();
-        async fn pre_start(&self, _this_actor: ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: ActorRef<Self>) -> Self::State {}
     }
 
     #[async_trait::async_trait]
     impl ActorHandler for Supervisor {
         type Msg = ();
         type State = ();
-        async fn pre_start(&self, _this_actor: ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: ActorRef<Self>) -> Self::State {}
         async fn handle(
             &self,
-            _this_actor: ActorCell,
+            _this_actor: ActorRef<Self>,
             _message: Self::Msg,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -396,17 +399,17 @@ async fn test_killing_a_supervisor_terminates_children() {
 
     let supervisor_tree = supervisor_ref.get_tree();
 
-    let (child_ref, c_handle) = Actor::spawn_linked(None, Child, supervisor_ref.clone())
+    let (child_ref, c_handle) = Actor::spawn_linked(None, Child, supervisor_ref.clone().into())
         .await
         .expect("Child panicked on startup");
 
     // check that the supervision is wired up correctly
     assert_eq!(1, supervisor_tree.get_num_children());
-    assert_eq!(1, child_ref.get_tree().get_num_parents());
+    assert_eq!(1, child_ref.clone().get_tree().get_num_parents());
 
     // initate the shutdown of the supervisor
     supervisor_ref
-        .cast::<Supervisor>(())
+        .cast(())
         .expect("Sending message to supervisor failed");
 
     s_handle
diff --git a/ractor/src/registry/tests.rs b/ractor/src/registry/tests.rs
index d437c95..fa4696e 100644
--- a/ractor/src/registry/tests.rs
+++ b/ractor/src/registry/tests.rs
@@ -17,7 +17,7 @@ async fn test_basic_registation() {
 
         type State = ();
 
-        async fn pre_start(&self, _this_actor: crate::ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: crate::ActorRef<Self>) -> Self::State {}
     }
 
     let (actor, handle) = Actor::spawn(Some("my_actor"), EmptyActor)
@@ -40,7 +40,7 @@ async fn test_duplicate_registration() {
 
         type State = ();
 
-        async fn pre_start(&self, _this_actor: crate::ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: crate::ActorRef<Self>) -> Self::State {}
     }
 
     let (actor, handle) = Actor::spawn(Some("my_second_actor"), EmptyActor)
@@ -73,7 +73,7 @@ async fn test_actor_registry_unenrollment() {
 
         type State = ();
 
-        async fn pre_start(&self, _this_actor: crate::ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: crate::ActorRef<Self>) -> Self::State {}
     }
 
     let (actor, handle) = Actor::spawn(Some("unenrollment"), EmptyActor)
diff --git a/ractor/src/rpc/tests.rs b/ractor/src/rpc/tests.rs
index c96f8f5..6910015 100644
--- a/ractor/src/rpc/tests.rs
+++ b/ractor/src/rpc/tests.rs
@@ -11,7 +11,7 @@ use std::sync::Arc;
 use tokio::time::Duration;
 
 use crate::rpc;
-use crate::{Actor, ActorCell, ActorHandler};
+use crate::{Actor, ActorHandler, ActorRef};
 
 #[tokio::test]
 async fn test_rpc_cast() {
@@ -27,11 +27,11 @@ async fn test_rpc_cast() {
 
         type State = ();
 
-        async fn pre_start(&self, _this_actor: ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: ActorRef<Self>) -> Self::State {}
 
         async fn handle(
             &self,
-            _this_actor: ActorCell,
+            _this_actor: ActorRef<Self>,
             _message: Self::Msg,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -49,10 +49,8 @@ async fn test_rpc_cast() {
     .await
     .expect("Failed to start test actor");
 
-    rpc::cast::<TestActor>(&actor_ref, ()).expect("Failed to send message");
-    actor_ref
-        .cast::<TestActor>(())
-        .expect("Failed to send message");
+    actor_ref.cast(()).expect("Failed to send message");
+    actor_ref.cast(()).expect("Failed to send message");
 
     // make sure they have time to process
     tokio::time::sleep(Duration::from_millis(100)).await;
@@ -79,11 +77,11 @@ async fn test_rpc_call() {
 
         type State = ();
 
-        async fn pre_start(&self, _this_actor: ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: ActorRef<Self>) -> Self::State {}
 
         async fn handle(
             &self,
-            _this_actor: ActorCell,
+            _this_actor: ActorRef<Self>,
             message: Self::Msg,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -104,18 +102,15 @@ async fn test_rpc_call() {
         .await
         .expect("Failed to start test actor");
 
-    let rpc_result = rpc::call::<TestActor, _, _>(
-        &actor_ref,
-        MessageFormat::TestRpc,
-        Some(Duration::from_millis(100)),
-    )
-    .await
-    .expect("Failed to send message to actor")
-    .expect("RPC didn't succeed");
+    let rpc_result = actor_ref
+        .call(MessageFormat::TestRpc, Some(Duration::from_millis(100)))
+        .await
+        .expect("Failed to send message to actor")
+        .expect("RPC didn't succeed");
     assert_eq!("howdy".to_string(), rpc_result);
 
     let rpc_result = actor_ref
-        .call::<TestActor, _, _, _>(MessageFormat::TestRpc, Some(Duration::from_millis(100)))
+        .call(MessageFormat::TestRpc, Some(Duration::from_millis(100)))
         .await
         .expect("Failed to send message to actor")
         .expect("RPC didn't succeed");
@@ -140,11 +135,11 @@ async fn test_rpc_call_forwarding() {
 
         type State = ();
 
-        async fn pre_start(&self, _this_actor: ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: ActorRef<Self>) -> Self::State {}
 
         async fn handle(
             &self,
-            _this_actor: ActorCell,
+            _this_actor: ActorRef<Self>,
             message: Self::Msg,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -176,11 +171,11 @@ async fn test_rpc_call_forwarding() {
 
         type State = ();
 
-        async fn pre_start(&self, _this_actor: ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: ActorRef<Self>) -> Self::State {}
 
         async fn handle(
             &self,
-            _this_actor: ActorCell,
+            _this_actor: ActorRef<Self>,
             message: Self::Msg,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -207,10 +202,9 @@ async fn test_rpc_call_forwarding() {
     .await
     .expect("Failed to start forwarder actor");
 
-    let forward_handle = rpc::call_and_forward::<Worker, Forwarder, _, _, _>(
-        &worker_ref,
+    let forward_handle = worker_ref.call_and_forward(
         WorkerMessage::TestRpc,
-        forwarder_ref.clone(),
+        &forwarder_ref,
         ForwarderMessage::ForwardResult,
         Some(Duration::from_millis(100)),
     );
@@ -222,9 +216,9 @@ async fn test_rpc_call_forwarding() {
         .expect("Call result didn't return success")
         .expect("Failed to forward message");
 
-    let forward_handle = worker_ref.call_and_forward::<Worker, Forwarder, _, _, _, _, _>(
+    let forward_handle = worker_ref.call_and_forward(
         WorkerMessage::TestRpc,
-        forwarder_ref.clone(),
+        &forwarder_ref,
         ForwarderMessage::ForwardResult,
         Some(Duration::from_millis(100)),
     );
diff --git a/ractor/src/time/tests.rs b/ractor/src/time/tests.rs
index 29e29c3..1191372 100644
--- a/ractor/src/time/tests.rs
+++ b/ractor/src/time/tests.rs
@@ -12,7 +12,7 @@ use std::sync::{
 
 use tokio::time::Duration;
 
-use crate::{Actor, ActorCell, ActorHandler};
+use crate::{Actor, ActorHandler, ActorRef};
 
 #[tokio::test]
 async fn test_intervals() {
@@ -26,12 +26,12 @@ async fn test_intervals() {
     impl ActorHandler for TestActor {
         type Msg = ();
         type State = Arc<AtomicU8>;
-        async fn pre_start(&self, _this_actor: ActorCell) -> Self::State {
+        async fn pre_start(&self, _this_actor: ActorRef<Self>) -> Self::State {
             self.counter.clone()
         }
         async fn handle(
             &self,
-            _this_actor: ActorCell,
+            _this_actor: ActorRef<Self>,
             _message: Self::Msg,
             state: &Self::State,
         ) -> Option<Self::State> {
@@ -52,7 +52,7 @@ async fn test_intervals() {
 
     let interval_handle = crate::time::send_interval::<TestActor, _>(
         Duration::from_millis(10),
-        actor_ref.clone(),
+        actor_ref.clone().into(),
         || (),
     );
 
@@ -86,12 +86,12 @@ async fn test_send_after() {
     impl ActorHandler for TestActor {
         type Msg = ();
         type State = Arc<AtomicU8>;
-        async fn pre_start(&self, _this_actor: ActorCell) -> Self::State {
+        async fn pre_start(&self, _this_actor: ActorRef<Self>) -> Self::State {
             self.counter.clone()
         }
         async fn handle(
             &self,
-            _this_actor: ActorCell,
+            _this_actor: ActorRef<Self>,
             _message: Self::Msg,
             state: &Self::State,
         ) -> Option<Self::State> {
@@ -112,7 +112,7 @@ async fn test_send_after() {
 
     let send_after_handle = crate::time::send_after::<TestActor, _>(
         Duration::from_millis(10),
-        actor_ref.clone(),
+        actor_ref.clone().into(),
         || (),
     );
 
@@ -142,14 +142,14 @@ async fn test_exit_after() {
     impl ActorHandler for TestActor {
         type Msg = ();
         type State = ();
-        async fn pre_start(&self, _this_actor: ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: ActorRef<Self>) -> Self::State {}
     }
 
     let (actor_ref, actor_handle) = Actor::spawn(None, TestActor)
         .await
         .expect("Failed to create test actor");
 
-    let exit_handle = crate::time::exit_after(Duration::from_millis(10), actor_ref);
+    let exit_handle = crate::time::exit_after(Duration::from_millis(10), actor_ref.into());
 
     tokio::time::sleep(Duration::from_millis(20)).await;
     // make sure the actor is dead + the interval handle doesn't send again
@@ -165,10 +165,10 @@ async fn test_kill_after() {
     impl ActorHandler for TestActor {
         type Msg = ();
         type State = ();
-        async fn pre_start(&self, _this_actor: ActorCell) -> Self::State {}
+        async fn pre_start(&self, _this_actor: ActorRef<Self>) -> Self::State {}
         async fn handle(
             &self,
-            _myself: ActorCell,
+            _myself: ActorRef<Self>,
             _message: Self::Msg,
             _state: &Self::State,
         ) -> Option<Self::State> {
@@ -183,12 +183,12 @@ async fn test_kill_after() {
 
     // put the actor into it's event processing sleep
     actor_ref
-        .send_message::<TestActor>(())
+        .send_message(())
         .expect("Failed to send message to actor");
     tokio::time::sleep(Duration::from_millis(10)).await;
 
     // kill the actor
-    let kill_handle = crate::time::kill_after(Duration::from_millis(10), actor_ref);
+    let kill_handle = crate::time::kill_after(Duration::from_millis(10), actor_ref.into());
 
     tokio::time::sleep(Duration::from_millis(20)).await;
     // make sure the actor is dead + the interval handle doesn't send again