From 914915543443a2bece53f45a43be74363c5b911e Mon Sep 17 00:00:00 2001 From: DoHyung Kim Date: Sat, 25 Apr 2020 00:46:16 +0900 Subject: [PATCH] Update docs for the API changes so far --- README.md | 25 +++++++++++++++++-------- macros/src/lib.rs | 31 ++++++++++++++++++++++++++++++- src/cast.rs | 10 ++++++++++ src/lib.rs | 9 +++++++-- 4 files changed, 64 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 18af84d..022c632 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ fn main() { Target traits must be explicitly designated beforehand. There are three ways of doing it: -## `#[cast_to]` to `impl` item +### `#[cast_to]` to `impl` item The trait implemented is designated as a target trait. ```rust @@ -63,7 +63,7 @@ impl Greet for Data { } ``` -## `#[cast_to(Trait)]` to type definition +### `#[cast_to(Trait)]` to type definition For the type, the traits specified as arguments to the `#[cast_to(...)]` attribute are designated as target traits. ```rust @@ -82,7 +82,7 @@ impl Greet for Data { struct Data; ``` -## `castable_to!(Type => Trait1, Trait2)` +### `castable_to!(Type => Trait1, Trait2)` For the type, the traits following `:` are designated as target traits. ```rust @@ -103,14 +103,22 @@ castable_to!(Data => Greet, std::fmt::Debug); fn main() {} ``` +## `Arc` Support +`std::sync::Arc` is unique in that it implement `downcast` method only on `dyn Any + Send + Sync + 'static'. +To use with `Arc`, the following steps should be taken: + +* Mark source traits with [`CastFromSync`] instead of [`CastFrom`] +* Add `[sync]` flag to `#[cast_to]` and `castable_to!` as follows: + ```ignore + #[cast_to([sync])] + #[cast_to([sync] Trait1, Trait2)] + castable_to!(Type => [sync] Trait, Trait2); + ``` + # How it works First of all, [`CastFrom`] trait makes it possible to retrieve an object of [`std::any::Any`] from an object for a sub-trait of [`CastFrom`]. -> [`CastFrom`] will become obsolete and be replaced with [`std::any::Any`] -> once [unsized coercion](https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions) -> from a trait object to another trait object for its super-trait is implemented in the stable Rust. - And the macros provided by `intertrait` generates trampoline functions for downcasting a trait object for [`std::any::Any`] back to its concrete type and then creating a trait object for the target trait from it. @@ -143,4 +151,5 @@ dual licensed as above, without any additional terms or conditions. [`std::any::Any`]: https://doc.rust-lang.org/std/any/trait.Any.html [`TypeId`]: https://doc.rust-lang.org/std/any/struct.TypeId.html -[`CastFrom`]: https://docs.rs/intertrait/*/intertrait/trait.CastFrom.html \ No newline at end of file +[`CastFrom`]: https://docs.rs/intertrait/*/intertrait/trait.CastFrom.html +[`CastFromSync`]: https://docs.rs/intertrait/*/intertrait/trait.CastFromSync.html \ No newline at end of file diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 189362e..937a9f0 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -17,6 +17,9 @@ mod item_type; /// If on an `impl` item, no argument is allowed. But on a type definition, the target traits /// must be listed explicitly. /// +/// Add `[sync]` before the list of traits if the underlying type is `Sync + Send` and you +/// need `std::sync::Arc`. +/// /// # Examples /// ## On a trait impl /// ``` @@ -43,6 +46,15 @@ mod item_type; /// #[derive(std::fmt::Debug)] /// struct Data; /// ``` +/// +/// ## For Arc +/// Use when the underlying type is `Sync + Send` and you want to use `Arc`. +/// ``` +/// // Debug can be cast into from any sub-trait of CastFrom implemented by Data +/// #[cast_to([sync] std::fmt::Debug)] +/// #[derive(std::fmt::Debug)] +/// struct Data; +/// ``` #[proc_macro_attribute] pub fn cast_to(args: TokenStream, input: TokenStream) -> TokenStream { match parse::(args) { @@ -60,7 +72,7 @@ pub fn cast_to(args: TokenStream, input: TokenStream) -> TokenStream { .into() } -/// Declare target traits for casting implemented by a type. +/// Declares target traits for casting implemented by a type. /// /// This macro is for registering both a concrete type and its traits to be targets for casting. /// Useful when the type definition and the trait implementations are in an external crate. @@ -84,6 +96,23 @@ pub fn cast_to(args: TokenStream, input: TokenStream) -> TokenStream { /// } /// castable_to! { Data => std::fmt::Debug, Greet } /// ``` +/// +/// When the type is `Sync + Send` and is used with `Arc`: +/// ``` +/// #[derive(std::fmt::Debug)] +/// enum Data { +/// A, B, C +/// } +/// trait Greet { +/// fn greet(&self); +/// } +/// impl Greet for Data { +/// fn greet(&self) { +/// println!("Hello"); +/// } +/// } +/// castable_to! { Data => [sync] std::fmt::Debug, Greet } +/// ``` #[proc_macro] pub fn castable_to(input: TokenStream) -> TokenStream { let Casts { diff --git a/src/cast.rs b/src/cast.rs index 27bde1c..0806d6f 100644 --- a/src/cast.rs +++ b/src/cast.rs @@ -1,3 +1,13 @@ +//! `cast` module contains traits to provide `cast` method for various references +//! and smart pointers. +//! +//! In source files requiring casts, import all of the traits as follows: +//! +//! ```ignore +//! use intertrait::cast::*; +//! ``` +//! +//! Since there exists single trait for each receiver type, the same `cast` method is overloaded. mod cast_arc; mod cast_box; mod cast_mut; diff --git a/src/lib.rs b/src/lib.rs index 824b246..b4ed28b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ //! A library providing direct casting among trait objects implemented by a type. //! -//! In Rust, an object of a sub-trait of [`std::any::Any`] can be downcast to a concrete type +//! In Rust, an object of a sub-trait of [`Any`] can be downcast to a concrete type //! at runtime if the type is known. But no direct casting between two trait objects //! (i.e. without involving the concrete type of the backing value) are possible //! (even no coercion from a trait object to that of its super-trait yet). @@ -45,14 +45,19 @@ //! * [`#[cast_to(Trait)]`][cast_to] to type definition //! * [`castable_to!(Type => Trait1, Trait2)`][castable_to] //! -//! Refer to the documents for each of macros for details. +//! If the underlying type involved is `Sync + Send` and you want to use it with [`Arc`], +//! use [`CastFromSync`] in place of [`CastFrom`] and add `[sync]` flag before the list +//! of traits in the macros. Refer to the documents for each of macros for details. //! //! For casting, refer to traits defined in [`cast`] module. //! //! [cast_to]: ./attr.cast_to.html //! [castable_to]: ./macro.castable_to.html +//! [`CastFrom`]: ./trait.CastFrom.html +//! [`CastFromSync`]: ./trait.CastFromSync.html //! [`cast`]: ./cast/index.html //! [`Any`]: https://doc.rust-lang.org/std/any/trait.Any.html +//! [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html use std::any::{Any, TypeId}; use std::collections::HashMap; use std::rc::Rc;