# Deep dive: AFIT Send bounds and keyword generics Background (outdated) * https://smallcultfollowing.com/babysteps/blog/2023/02/13/return-type-notation-send-bounds-part-2/ * https://blog.theincredibleholk.org/blog/2023/02/13/inferred-async-send-bounds/ ###### tags: `deep-dive` Leave questions, observations, discussion topics below. --- ```rust trait ?async Iterator { type Item; ?async fn next(&mut self) -> Option<Self::Item>; fn size_hint(&self) -> (usize, Option<usize>) {..} } struct AsyncFile; // always async impl! impl async Iterator for AsyncFile { .. } ``` ```rust trait Foo { async fn bar() {} async fn baz() {} async fn bin() {} } // ... and how do we mark all methods in `Foo` as `Send` trait async Foo { async fn bar() {} } ``` ## progression! ```rust // say we start with this trait async HealthCheck { .. } async fn foo(check: impl async HealthCheck) { .. } // .. but later on we realize `HealthCheck` may also // be useful in !async contexts, so we change it to this: trait ?async HealthCheck { .. } // .. usage remains exactly as it was before!: async fn foo(check: impl async HealthCheck) { .. } // .. but maybe we want `foo` to also become `?async`, so we then can // opt into instead changing it to: ?async fn foo(check: impl ?async HealthCheck) { .. } ``` ```rust trait async HealthCheck { .. } async fn foo(check: impl async(Send) HealthCheck) { .. } ``` ## Open Questions ### What is the default? Are methods `Send` by default and we opt out? Or do we opt in to `Send`? ```rust // Do we write this? async fn foo(check: impl async(Send) HealthCheck) { .. } // Or this? async fn foo(check: impl async(?Send) HealthCheck) { .. } ``` ### Does `async` show up in imports? ```rust use my_crate::HealthCheck; // Could you do... use my_crate::async(Send) HealthCheck as async HealthCheck; // What about aliases type UsizeOption = Option<usize>; trait AsyncHealthCheck = async HealthCheck; fn foo(x: impl async(Send) AsyncHealthCheck) { .. } ``` If we can hide `async` behind a trait alias, we shouldn't require it on the trait definition. ```rust trait async HealthCheck { async fn check(...); } trait async SendHealthCheck = async(Send) HealthCheck; fn foo(check: impl async HealthCheck) { .. } fn bar(check: impl async SendHealthCheck) { .. } ``` ```rust! trait SendHealthCheck = async(Send) HealthCheck; trait async HealthCheck { async fn check(...); } trait async SendHealthCheck = async(Send) HealthCheck; fn foo(check: impl HealthCheck + Send) { .. } fn bar(check: impl SendHealthCheck) { .. } ``` ### Supertraits ```rust // Trait today! trait FixedLengthIterator: Iterator { .. } // Maybe-async variant trait ?async FixedLengthIterator: ?async Iterator { .. } // Always async variant trait async FixedLengthIterator: async Iterator { .. } ``` ### Are `async Trait` and `Trait` different names? Can I do this? ```rust trait Bar { fn foo(); } trait async Bar { async fn baz(); } ``` Yosh: probably not; they live in the same namespace. But you could imagine an `async` and `!async` impl of the same `?async` trait on a single type. ```rust struct ?async File { .. } // either.. impl ?async Read ```