Repository: redbadger/crux (language: rust)

Issue:
Capability derive macro not able to send NewEv between threads
Implementing the Delay capability as described by the guide (https://redbadger.github.io/crux/guide/capability_apis.html) the compiler showed the following error:
```
error[E0277]: `NewEv` cannot be sent between threads safely
  --> shared/src/app.rs:73:10
   |
73 | #[derive(Capability)]
   |          ^^^^^^^^^^ `NewEv` cannot be sent between threads safely
   |
note: required by a bound in `Delay::<Ev>::new`
  --> shared/src/app.rs:80:19
   |
80 |     Ev: 'static + Send
   |                   ^^^^ required by this bound in `Delay::<Ev>::new`
81 | {
82 |     pub fn new(context: CapabilityContext<DelayOperation, Ev>) -> Self {
   |            --- required by a bound in this associated function
```

The function map_events should require the Send trait for the NewEv generic, but it doesn't:
```rust
            fn map_event<F, NewEv>(&self, f: F) -> Self::MappedSelf<NewEv>
            where
                F: Fn(NewEv) -> Ev + Send + Sync + Copy + 'static,
                Ev: 'static,
                NewEv: 'static,
            {
              #name::new(self.context.map_event(f))
            }
```


Discussion / hints:

Fix patch:
diff --git a/docs/src/guide/capability_apis.md b/docs/src/guide/capability_apis.md
index 46f9bad4..875d52b8 100644
--- a/docs/src/guide/capability_apis.md
+++ b/docs/src/guide/capability_apis.md
@@ -75,7 +75,10 @@ where
         Self { context }
     }
 
-    pub fn milliseconds(&self, millis: usize, event: Ev) {
+    pub fn milliseconds(&self, millis: usize, event: Ev)
+    where
+        Ev: Send,
+    {
         let ctx = self.context.clone();
         self.context.spawn(async move {
             ctx.request_from_shell(DelayOperation { millis }).await;
diff --git a/examples/tap_to_pay/shared/src/capabilities/delay.rs b/examples/tap_to_pay/shared/src/capabilities/delay.rs
index f51b1fd6..27357361 100644
--- a/examples/tap_to_pay/shared/src/capabilities/delay.rs
+++ b/examples/tap_to_pay/shared/src/capabilities/delay.rs
@@ -1,4 +1,5 @@
-use crux_core::capability::{Capability, CapabilityContext, Operation};
+use crux_core::capability::{CapabilityContext, Operation};
+use crux_macros::Capability;
 use serde::{Deserialize, Serialize};
 
 #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
@@ -10,19 +11,23 @@ impl Operation for DelayOperation {
     type Output = ();
 }
 
+#[derive(Capability)]
 pub struct Delay<Event> {
     context: CapabilityContext<DelayOperation, Event>,
 }
 
 impl<Ev> Delay<Ev>
 where
-    Ev: 'static + Send,
+    Ev: 'static,
 {
     pub fn new(context: CapabilityContext<DelayOperation, Ev>) -> Self {
         Self { context }
     }
 
-    pub fn start(&self, millis: usize, event: Ev) {
+    pub fn start(&self, millis: usize, event: Ev)
+    where
+        Ev: Send,
+    {
         self.context.spawn({
             let context = self.context.clone();
 
@@ -36,17 +41,3 @@ where
         })
     }
 }
-
-impl<Ev> Capability<Ev> for Delay<Ev> {
-    type Operation = DelayOperation;
-    type MappedSelf<MappedEv> = Delay<MappedEv>;
-
-    fn map_event<F, NewEvent>(&self, f: F) -> Self::MappedSelf<NewEvent>
-    where
-        F: Fn(NewEvent) -> Ev + Send + Sync + Copy + 'static,
-        Ev: 'static,
-        NewEvent: 'static + Send,
-    {
-        Delay::new(self.context.map_event(f))
-    }
-}


Test patch: