Repository: actix/actix (language: rust)

Issue:
Please make `Context::new()` public
Say we have three actors, each needs the address of the other two:
```rust
struct Actor1 {
    actor2: Addr<Actor2>,
    actor3: Addr<Actor3>,
}

struct Actor2 {
    actor1: Addr<Actor1>,
    actor3: Addr<Actor3>,
}

struct Actor3 {
    actor1: Addr<Actor1>,
    actor2: Addr<Actor2>,
}
```

If we want to actually launch all these actors, we'd have to do use an abomination like that:
```rust
Actor1::create(|ctx1| {
    let mut actor3_addr = None;
    let actor2 = Actor2::create(|ctx2| {
        let actor3 = Actor3 {
            actor1: ctx1.address(),
            actor2: ctx2.address(),
        }.start();
        actor3_addr = Some(actor3.clone());
        Actor2 {
            actor1: ctx1.address(),
            actor3
        }
    });
    let actor3 = actor3_addr.unwrap();
    Actor1 {
        actor2,
        actor3,
    }
});
```

But if `Context::new()` was public, we could do:
```rust
let ctx1 = Context::<Actor1>::new();
let ctx2 = Context::<Actor2>::new();
let ctx3 = Context::<Actor3>::new();

let actor1 = Actor1 {
    actor2: ctx2.address(),
    actor3: ctx3.address(),
};

let actor2 = Actor2 {
    actor1: ctx1.address(),
    actor3: ctx3.address(),
};

let actor3 = Actor3 {
    actor1: ctx1.address(),
    actor2: ctx2.address(),
};

ctx1.run(actor1);
ctx2.run(actor2);
ctx3.run(actor3);
```

Note that this is currently doable with `Context::with_receiver()`:
```rust
let (_, rx) = actix::dev::channel::channel(16);
let ctx1 = Context::<Actor1>::with_receiver(rx);
// ...
```

But this feels hacky and ugly, and it would be much better if we could just use `Context::new()` directly. It's already there - it just needs to be made public [instead of crate public](https://github.com/actix/actix/blob/2cb738a48c8283c25956c660d597734429d58c75/actix/src/context.rs#L86).
Please make `Context::new()` public
Say we have three actors, each needs the address of the other two:
```rust
struct Actor1 {
    actor2: Addr<Actor2>,
    actor3: Addr<Actor3>,
}

struct Actor2 {
    actor1: Addr<Actor1>,
    actor3: Addr<Actor3>,
}

struct Actor3 {
    actor1: Addr<Actor1>,
    actor2: Addr<Actor2>,
}
```

If we want to actually launch all these actors, we'd have to do use an abomination like that:
```rust
Actor1::create(|ctx1| {
    let mut actor3_addr = None;
    let actor2 = Actor2::create(|ctx2| {
        let actor3 = Actor3 {
            actor1: ctx1.address(),
            actor2: ctx2.address(),
        }.start();
        actor3_addr = Some(actor3.clone());
        Actor2 {
            actor1: ctx1.address(),
            actor3
        }
    });
    let actor3 = actor3_addr.unwrap();
    Actor1 {
        actor2,
        actor3,
    }
});
```

But if `Context::new()` was public, we could do:
```rust
let ctx1 = Context::<Actor1>::new();
let ctx2 = Context::<Actor2>::new();
let ctx3 = Context::<Actor3>::new();

let actor1 = Actor1 {
    actor2: ctx2.address(),
    actor3: ctx3.address(),
};

let actor2 = Actor2 {
    actor1: ctx1.address(),
    actor3: ctx3.address(),
};

let actor3 = Actor3 {
    actor1: ctx1.address(),
    actor2: ctx2.address(),
};

ctx1.run(actor1);
ctx2.run(actor2);
ctx3.run(actor3);
```

Note that this is currently doable with `Context::with_receiver()`:
```rust
let (_, rx) = actix::dev::channel::channel(16);
let ctx1 = Context::<Actor1>::with_receiver(rx);
// ...
```

But this feels hacky and ugly, and it would be much better if we could just use `Context::new()` directly. It's already there - it just needs to be made public [instead of crate public](https://github.com/actix/actix/blob/2cb738a48c8283c25956c660d597734429d58c75/actix/src/context.rs#L86).


Discussion / hints:
I don't see any reason not to make it public, PRs welcome.
I don't see any reason not to make it public, PRs welcome.

Fix patch:
diff --git a/actix/CHANGES.md b/actix/CHANGES.md
index eefcfd644..7e5f2e8bf 100644
--- a/actix/CHANGES.md
+++ b/actix/CHANGES.md
@@ -5,7 +5,11 @@
 * Add `fut::try_future::ActorTryFuture`. [#419]
 * Add `fut::try_future::ActorTryFutureExt` trait with `map_ok`, `map_err` and `and_then` combinator. [#419] 
 
+### Changed
+- Make `Context::new` public. [#491]
+
 [#419]: https://github.com/actix/actix/pull/419
+[#491]: https://github.com/actix/actix/pull/491
 
 
 ## 0.11.1 - 2021-03-23
diff --git a/actix/src/context.rs b/actix/src/context.rs
index 811711066..6e04d4a7d 100644
--- a/actix/src/context.rs
+++ b/actix/src/context.rs
@@ -82,8 +82,42 @@ impl<A> Context<A>
 where
     A: Actor<Context = Self>,
 {
+    /// Create a context without spawning it.
+    ///
+    /// The context can be spawned into an actor using its [`run`](`Context::run`) method.
+    ///
+    /// ```
+    /// # use actix::prelude::*;
+    /// struct Actor1 {
+    ///     actor2_addr: Addr<Actor2>,
+    /// }
+    /// # impl Actor for Actor1 {
+    /// #     type Context = Context<Self>;
+    /// # }
+    ///
+    /// struct Actor2 {
+    ///     actor1_addr: Addr<Actor1>,
+    /// }
+    /// # impl Actor for Actor2 {
+    /// #     type Context = Context<Self>;
+    /// # }
+    ///
+    /// # fn main() {
+    /// # let mut sys = System::new();
+    /// # System::new().block_on(async {
+    /// let ctx1 = Context::<Actor1>::new();
+    /// let ctx2 = Context::<Actor2>::new();
+    ///
+    /// let actor1 = Actor1 { actor2_addr: ctx2.address() };
+    /// let actor2 = Actor2 { actor1_addr: ctx1.address() };
+    ///
+    /// ctx1.run(actor1);
+    /// ctx2.run(actor2);
+    /// # });
+    /// # }
+    /// ```
     #[inline]
-    pub(crate) fn new() -> Self {
+    pub fn new() -> Self {
         let mb = Mailbox::default();
         Self {
             parts: ContextParts::new(mb.sender_producer()),


Test patch: