From 1fcfee0dc8141bb5844d6a2c8e20db98da42015c Mon Sep 17 00:00:00 2001 From: Tyler Slabinski Date: Tue, 3 Nov 2020 14:18:48 -0500 Subject: [PATCH 1/8] Add Borrow and BorrowMut derives --- Cargo.toml | 4 ++ README.md | 4 ++ doc/borrow.md | 124 +++++++++++++++++++++++++++++++++++++++++++++ doc/borrow_mut.md | 125 ++++++++++++++++++++++++++++++++++++++++++++++ src/borrow.rs | 83 ++++++++++++++++++++++++++++++ src/borrow_mut.rs | 83 ++++++++++++++++++++++++++++++ src/lib.rs | 11 ++++ 7 files changed, 434 insertions(+) create mode 100644 doc/borrow.md create mode 100644 doc/borrow_mut.md create mode 100644 src/borrow.rs create mode 100644 src/borrow_mut.rs diff --git a/Cargo.toml b/Cargo.toml index 4eb37267..fa730560 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,8 @@ add_assign = [] add = [] as_mut = [] as_ref = [] +borrow = [] +borrow_mut = [] constructor = [] deref = [] deref_mut = [] @@ -69,6 +71,8 @@ default = [ "add", "as_mut", "as_ref", + "borrow", + "borrow_mut", "constructor", "deref", "deref_mut", diff --git a/README.md b/README.md index 862d4b71..023a35c5 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,8 @@ These are traits that are used to convert automatically between types. 5. [`IntoIterator`] 6. [`AsRef`] 7. [`AsMut`] +8. [`Borrow`] +9. [`BorrowMut`] ### Formatting traits @@ -161,6 +163,8 @@ extern crate derive_more; [`IntoIterator`]: https://jeltef.github.io/derive_more/derive_more/into_iterator.html [`AsRef`]: https://jeltef.github.io/derive_more/derive_more/as_ref.html [`AsMut`]: https://jeltef.github.io/derive_more/derive_more/as_mut.html +[`Borrow`]: https://jeltef.github.io/derive_more/derive_more/as_ref.html +[`BorrowMut`]: https://jeltef.github.io/derive_more/derive_more/as_mut.html [`Display`-like]: https://jeltef.github.io/derive_more/derive_more/display.html diff --git a/doc/borrow.md b/doc/borrow.md new file mode 100644 index 00000000..10747a01 --- /dev/null +++ b/doc/borrow.md @@ -0,0 +1,124 @@ +% What #[derive(Borrow)] generates + +Deriving `Borrow` generates one or more implementations of `Borrow`, each +corresponding to one of the fields of the decorated type. +This allows types which contain some `T` to be passed anywhere that an +`Borrow` is accepted. + +# Newtypes and Structs with One Field + +When `Borrow` is derived for a newtype or struct with one field, a single +implementation is generated to expose the underlying field. + +```rust +# #[macro_use] extern crate derive_more; +# fn main(){} +#[derive(Borrow)] +struct MyWrapper(String); +``` + +Generates: + +```rust +# struct MyWrapper(String); +impl Borrow for MyWrapper { + fn borrow(&self) -> &String { + &self.0 + } +} +``` + +It's also possible to use the `#[borrow(forward)]` attribute to forward +to the `borrow` implementation of the field. So here `SigleFieldForward` +implements all `Borrow` for all types that `Vec` implements `Borrow` for. + +```rust +# #[macro_use] extern crate derive_more; +#[derive(Borrow)] +#[borrow(forward)] +struct SingleFieldForward(Vec); + +fn main() { + let item = SingleFieldForward(vec![]); + let _: &[i32] = (&item).borrow(); +} + +``` + +This generates: + +```rust +# struct SingleFieldForward(Vec); +impl<__BorrowT: ?::core::marker::Sized> ::core::convert::Borrow<__BorrowT> for SingleFieldForward +where + Vec: ::core::convert::Borrow<__BorrowT>, +{ + #[inline] + fn borrow(&self) -> &__BorrowT { + as ::core::convert::Borrow<__BorrowT>>::borrow(&self.0) + } +} +``` + +# Structs with Multiple Fields + +When `Borrow` is derived for a struct with more than one field (including tuple +structs), you must also mark one or more fields with the `#[borrow]` attribute. +An implementation will be generated for each indicated field. +You can also exclude a specific field by using `#[borrow(ignore)]`. + +```rust +# #[macro_use] extern crate derive_more; +# fn main(){} +#[derive(Borrow)] +struct MyWrapper { + #[borrow] + name: String, + #[borrow] + num: i32, + valid: bool, +} + +``` + +Generates: + +```rust +# struct MyWrapper { +# name: String, +# num: i32, +# valid: bool, +# } +impl Borrow for MyWrapper { + fn borrow(&self) -> &String { + &self.name + } +} + +impl Borrow for MyWrapper { + fn borrow(&self) -> &i32 { + &self.num + } +} +``` + +Note that `Borrow` may only be implemented once for any given type `T`. +This means any attempt to mark more than one field of the same type with +`#[borrow]` will result in a compilation error. + +```compile_fail +# #[macro_use] extern crate derive_more; +# fn main(){} +// Error! Conflicting implementations of Borrow +#[derive(Borrow)] +struct MyWrapper { + #[borrow] + str1: String, + #[borrow] + str2: String, +} +``` + +# Enums + +Deriving `Borrow` for enums is not supported. diff --git a/doc/borrow_mut.md b/doc/borrow_mut.md new file mode 100644 index 00000000..331fda28 --- /dev/null +++ b/doc/borrow_mut.md @@ -0,0 +1,125 @@ +% What #[derive(BorrowMut)] generates + +Deriving `BorrowMut` generates one or more implementations of `BorrowMut`, each +corresponding to one of the fields of the decorated type. +This allows types which contain some `T` to be passed anywhere that an +`BorrowMut` is accepted. + +# Newtypes and Structs with One Field + +When `BorrowMut` is derived for a newtype or struct with one field, a single +implementation is generated to expose the underlying field. + +```rust +# #[macro_use] extern crate derive_more; +# fn main(){} +#[derive(BorrowMut)] +struct MyWrapper(String); +``` + +Generates: + +```rust +# struct MyWrapper(String); +impl BorrowMut for MyWrapper { + fn borrow_mut(&mut self) -> &mut String { + &mut self.0 + } +} +``` + +It's also possible to use the `#[borrow_mut(forward)]` attribute to forward +to the `borrow_mut` implementation of the field. So here `SigleFieldForward` +implements all `BorrowMut` for all types that `Vec` implements `BorrowMut` for. + +```rust +# #[macro_use] extern crate derive_more; +#[derive(BorrowMut)] +#[borrow_mut(forward)] +struct SingleFieldForward(Vec); + +fn main() { + let mut item = SingleFieldForward(vec![]); + let _: &mut [i32] = (&mut item).borrow_mut(); +} + +``` + +This generates: + +```rust +# struct SingleFieldForward(Vec); +impl<__BorrowMutT: ?::core::marker::Sized> ::core::convert::BorrowMut<__BorrowMutT> for SingleFieldForward +where + Vec: ::core::convert::BorrowMut<__BorrowMutT>, +{ + #[inline] + fn borrow_mut(&mut self) -> &mut __BorrowMutT { + as ::core::convert::BorrowMut<__BorrowMutT>>::borrow_mut(&mut self.0) + } +} +``` + + +# Structs with Multiple Fields + +When `BorrowMut` is derived for a struct with more than one field (including tuple +structs), you must also mark one or more fields with the `#[borrow_mut]` attribute. +An implementation will be generated for each indicated field. +You can also exclude a specific field by using `#[borrow_mut(ignore)]`. + +```rust +# #[macro_use] extern crate derive_more; +# fn main(){} +#[derive(BorrowMut)] +struct MyWrapper { + #[borrow_mut] + name: String, + #[borrow_mut] + num: i32, + valid: bool, +} + + +``` + +Generates: + +``` +# struct MyWrapper { +# name: String, +# num: i32, +# valid: bool, +# } +impl BorrowMut for MyWrapper { + fn borrow_mut(&mut self) -> &mut String { + &mut self.name + } +} + +impl BorrowMut for MyWrapper { + fn borrow_mut(&mut self) -> &mut i32 { + &mut self.num + } +} +``` + +Note that `BorrowMut` may only be implemented once for any given type `T`. This means any attempt to +mark more than one field of the same type with `#[borrow_mut]` will result in a compilation error. + +```compile_fail +# #[macro_use] extern crate derive_more; +# fn main(){} +// Error! Conflicting implementations of BorrowMut +#[derive(BorrowMut)] +struct MyWrapper { + #[borrow_mut] + str1: String, + #[borrow_mut] + str2: String, +} +``` + +# Enums + +Deriving `BorrowMut` for enums is not supported. diff --git a/src/borrow.rs b/src/borrow.rs new file mode 100644 index 00000000..49db3130 --- /dev/null +++ b/src/borrow.rs @@ -0,0 +1,83 @@ +use crate::utils::{ + add_where_clauses_for_new_ident, AttrParams, MultiFieldData, State, +}; +use proc_macro2::{Span, TokenStream}; +use quote::quote; +use syn::{parse::Result, DeriveInput, Ident}; + +pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result { + let borrow_type = &Ident::new("__BorrowT", Span::call_site()); + let state = State::with_type_bound( + input, + trait_name, + quote!(::core::borrow), + String::from("borrow"), + AttrParams::ignore_and_forward(), + false, + )?; + let MultiFieldData { + fields, + input_type, + members, + infos, + trait_path, + impl_generics, + ty_generics, + where_clause, + .. + } = state.enabled_fields_data(); + let sub_items: Vec<_> = infos + .iter() + .zip(members.iter()) + .zip(fields) + .map(|((info, member), field)| { + let field_type = &field.ty; + if info.forward { + let trait_path = quote!(#trait_path<#borrow_type>); + let type_where_clauses = quote! { + where #field_type: #trait_path + }; + let new_generics = add_where_clauses_for_new_ident( + &input.generics, + &[field], + borrow_type, + type_where_clauses, + false, + ); + let (impl_generics, _, where_clause) = new_generics.split_for_impl(); + let casted_trait = quote!(<#field_type as #trait_path>); + ( + quote!(#casted_trait::borrow(&#member)), + quote!(#impl_generics), + quote!(#where_clause), + quote!(#trait_path), + quote!(#borrow_type), + ) + } else { + ( + quote!(&#member), + quote!(#impl_generics), + quote!(#where_clause), + quote!(#trait_path<#field_type>), + quote!(#field_type), + ) + } + }) + .collect(); + let bodies = sub_items.iter().map(|i| &i.0); + let impl_generics = sub_items.iter().map(|i| &i.1); + let where_clauses = sub_items.iter().map(|i| &i.2); + let trait_paths = sub_items.iter().map(|i| &i.3); + let return_types = sub_items.iter().map(|i| &i.4); + + Ok(quote! {#( + impl#impl_generics #trait_paths for #input_type#ty_generics + #where_clauses + { + #[inline] + fn borrow(&self) -> &#return_types { + #bodies + } + } + )*}) +} diff --git a/src/borrow_mut.rs b/src/borrow_mut.rs new file mode 100644 index 00000000..ae5720c0 --- /dev/null +++ b/src/borrow_mut.rs @@ -0,0 +1,83 @@ +use crate::utils::{ + add_where_clauses_for_new_ident, AttrParams, MultiFieldData, State, +}; +use proc_macro2::{Span, TokenStream}; +use quote::quote; +use syn::{parse::Result, DeriveInput, Ident}; + +pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result { + let as_mut_type = &Ident::new("__BorrowMutT", Span::call_site()); + let state = State::with_type_bound( + input, + trait_name, + quote!(::core::borrow), + String::from("borrow_mut"), + AttrParams::ignore_and_forward(), + false, + )?; + let MultiFieldData { + fields, + input_type, + members, + infos, + trait_path, + impl_generics, + ty_generics, + where_clause, + .. + } = state.enabled_fields_data(); + let sub_items: Vec<_> = infos + .iter() + .zip(members.iter()) + .zip(fields) + .map(|((info, member), field)| { + let field_type = &field.ty; + if info.forward { + let trait_path = quote!(#trait_path<#borrow_mut_type>); + let type_where_clauses = quote! { + where #field_type: #trait_path + }; + let new_generics = add_where_clauses_for_new_ident( + &input.generics, + &[field], + borrow_mut_type, + type_where_clauses, + false, + ); + let (impl_generics, _, where_clause) = new_generics.split_for_impl(); + let casted_trait = quote!(<#field_type as #trait_path>); + ( + quote!(#casted_trait::borrow_mut(&mut #member)), + quote!(#impl_generics), + quote!(#where_clause), + quote!(#trait_path), + quote!(#borrow_mut_type), + ) + } else { + ( + quote!(&mut #member), + quote!(#impl_generics), + quote!(#where_clause), + quote!(#trait_path<#field_type>), + quote!(#field_type), + ) + } + }) + .collect(); + let bodies = sub_items.iter().map(|i| &i.0); + let impl_genericses = sub_items.iter().map(|i| &i.1); + let where_clauses = sub_items.iter().map(|i| &i.2); + let trait_paths = sub_items.iter().map(|i| &i.3); + let return_types = sub_items.iter().map(|i| &i.4); + + Ok(quote! {#( + impl#impl_genericses #trait_paths for #input_type#ty_generics + #where_clauses + { + #[inline] + fn borrow_mut(&mut self) -> &mut #return_types { + #bodies + } + } + )*}) +} diff --git a/src/lib.rs b/src/lib.rs index f9843a0d..037fd897 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,6 +82,8 @@ //! 5. [`IntoIterator`] //! 6. [`AsRef`] //! 7. [`AsMut`] +//! 8. [`Borrow`] +//! 9. [`BorrowMut`] //! //! ### Formatting traits //! @@ -162,6 +164,8 @@ //! [`IntoIterator`]: https://jeltef.github.io/derive_more/derive_more/into_iterator.html //! [`AsRef`]: https://jeltef.github.io/derive_more/derive_more/as_ref.html //! [`AsMut`]: https://jeltef.github.io/derive_more/derive_more/as_mut.html +//! [`Borrow`]: https://jeltef.github.io/derive_more/derive_more/borrow.html +//! [`BorrowMut`]: https://jeltef.github.io/derive_more/derive_more/borrow_mut.html //! //! [`Display`-like]: https://jeltef.github.io/derive_more/derive_more/display.html //! @@ -207,6 +211,10 @@ mod add_like; mod as_mut; #[cfg(feature = "as_ref")] mod as_ref; +#[cfg(feature = "borrow")] +mod borrow; +#[cfg(feature = "borrow_mut")] +mod borrow_mut; #[cfg(feature = "constructor")] mod constructor; #[cfg(feature = "deref")] @@ -406,3 +414,6 @@ create_derive!( create_derive!("as_ref", as_ref, AsRef, as_ref_derive, as_ref); create_derive!("as_mut", as_mut, AsMut, as_mut_derive, as_mut); + +create_derive!("borrow", borrow, Borrow, borrow_derive, borrow); +create_derive!("borrow_mut", borrow_mut, BorrowMut, borrow_mut_derive, borrow_mut); From de416ce22f118355fd765d50d367a3577808fcd7 Mon Sep 17 00:00:00 2001 From: Tyler Slabinski Date: Tue, 3 Nov 2020 14:20:58 -0500 Subject: [PATCH 2/8] Fix README links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 023a35c5..3775407a 100644 --- a/README.md +++ b/README.md @@ -163,8 +163,8 @@ extern crate derive_more; [`IntoIterator`]: https://jeltef.github.io/derive_more/derive_more/into_iterator.html [`AsRef`]: https://jeltef.github.io/derive_more/derive_more/as_ref.html [`AsMut`]: https://jeltef.github.io/derive_more/derive_more/as_mut.html -[`Borrow`]: https://jeltef.github.io/derive_more/derive_more/as_ref.html -[`BorrowMut`]: https://jeltef.github.io/derive_more/derive_more/as_mut.html +[`Borrow`]: https://jeltef.github.io/derive_more/derive_more/borrow.html +[`BorrowMut`]: https://jeltef.github.io/derive_more/derive_more/borrow_mut.html [`Display`-like]: https://jeltef.github.io/derive_more/derive_more/display.html From e7d220c4b1d17bf6e9c82dcac85e823c48e2d0a5 Mon Sep 17 00:00:00 2001 From: Tyler Slabinski Date: Tue, 3 Nov 2020 14:33:24 -0500 Subject: [PATCH 3/8] Fix incorrect name --- src/borrow_mut.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/borrow_mut.rs b/src/borrow_mut.rs index ae5720c0..b2709081 100644 --- a/src/borrow_mut.rs +++ b/src/borrow_mut.rs @@ -6,7 +6,7 @@ use quote::quote; use syn::{parse::Result, DeriveInput, Ident}; pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result { - let as_mut_type = &Ident::new("__BorrowMutT", Span::call_site()); + let borrow_mut_type = &Ident::new("__BorrowMutT", Span::call_site()); let state = State::with_type_bound( input, trait_name, From c21ddd6b51a79c8812046b1fd87c74f263f22533 Mon Sep 17 00:00:00 2001 From: Tyler Slabinski Date: Tue, 3 Nov 2020 14:37:14 -0500 Subject: [PATCH 4/8] Resolve rustfmt complaints --- src/lib.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 037fd897..7437d021 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -416,4 +416,10 @@ create_derive!("as_ref", as_ref, AsRef, as_ref_derive, as_ref); create_derive!("as_mut", as_mut, AsMut, as_mut_derive, as_mut); create_derive!("borrow", borrow, Borrow, borrow_derive, borrow); -create_derive!("borrow_mut", borrow_mut, BorrowMut, borrow_mut_derive, borrow_mut); +create_derive!( + "borrow_mut", + borrow_mut, + BorrowMut, + borrow_mut_derive, + borrow_mut +); From 9c76281fe92df9ac1c862fd685613bfd96c39978 Mon Sep 17 00:00:00 2001 From: Tyler Slabinski Date: Tue, 3 Nov 2020 14:52:16 -0500 Subject: [PATCH 5/8] Resolve doc checks --- doc/borrow.md | 12 +++++++++--- doc/borrow_mut.md | 36 ++++++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/doc/borrow.md b/doc/borrow.md index 10747a01..bd47af62 100644 --- a/doc/borrow.md +++ b/doc/borrow.md @@ -11,6 +11,7 @@ When `Borrow` is derived for a newtype or struct with one field, a single implementation is generated to expose the underlying field. ```rust +# use core::borrow::Borrow; # #[macro_use] extern crate derive_more; # fn main(){} #[derive(Borrow)] @@ -20,6 +21,7 @@ struct MyWrapper(String); Generates: ```rust +# use core::borrow::Borrow; # struct MyWrapper(String); impl Borrow for MyWrapper { fn borrow(&self) -> &String { @@ -33,6 +35,7 @@ to the `borrow` implementation of the field. So here `SigleFieldForward` implements all `Borrow` for all types that `Vec` implements `Borrow` for. ```rust +# use core::borrow::Borrow; # #[macro_use] extern crate derive_more; #[derive(Borrow)] #[borrow(forward)] @@ -49,13 +52,13 @@ This generates: ```rust # struct SingleFieldForward(Vec); -impl<__BorrowT: ?::core::marker::Sized> ::core::convert::Borrow<__BorrowT> for SingleFieldForward +impl<__BorrowT: ?::core::marker::Sized> ::core::borrow::Borrow<__BorrowT> for SingleFieldForward where - Vec: ::core::convert::Borrow<__BorrowT>, + Vec: ::core::borrow::Borrow<__BorrowT>, { #[inline] fn borrow(&self) -> &__BorrowT { - as ::core::convert::Borrow<__BorrowT>>::borrow(&self.0) + as ::core::borrow::Borrow<__BorrowT>>::borrow(&self.0) } } ``` @@ -68,6 +71,7 @@ An implementation will be generated for each indicated field. You can also exclude a specific field by using `#[borrow(ignore)]`. ```rust +# use core::borrow::Borrow; # #[macro_use] extern crate derive_more; # fn main(){} #[derive(Borrow)] @@ -84,6 +88,7 @@ struct MyWrapper { Generates: ```rust +# use core::borrow::Borrow; # struct MyWrapper { # name: String, # num: i32, @@ -107,6 +112,7 @@ This means any attempt to mark more than one field of the same type with `#[borrow]` will result in a compilation error. ```compile_fail +# use core::borrow::Borrow; # #[macro_use] extern crate derive_more; # fn main(){} // Error! Conflicting implementations of Borrow diff --git a/doc/borrow_mut.md b/doc/borrow_mut.md index 331fda28..972700ff 100644 --- a/doc/borrow_mut.md +++ b/doc/borrow_mut.md @@ -5,6 +5,8 @@ corresponding to one of the fields of the decorated type. This allows types which contain some `T` to be passed anywhere that an `BorrowMut` is accepted. +Note that `BorrowMut` expects the type to also implement `Borrow`. + # Newtypes and Structs with One Field When `BorrowMut` is derived for a newtype or struct with one field, a single @@ -12,14 +14,20 @@ implementation is generated to expose the underlying field. ```rust # #[macro_use] extern crate derive_more; +# use core::borrow::Borrow; +# use core::borrow::BorrowMut; # fn main(){} -#[derive(BorrowMut)] +#[derive(Borrow, BorrowMut)] struct MyWrapper(String); ``` Generates: ```rust +# #[macro_use] extern crate derive_more; +# use core::borrow::Borrow; +# use core::borrow::BorrowMut; +# #[derive(Borrow)] # struct MyWrapper(String); impl BorrowMut for MyWrapper { fn borrow_mut(&mut self) -> &mut String { @@ -34,7 +42,10 @@ implements all `BorrowMut` for all types that `Vec` implements `BorrowMut` ```rust # #[macro_use] extern crate derive_more; -#[derive(BorrowMut)] +# use core::borrow::Borrow; +# use core::borrow::BorrowMut; +#[derive(Borrow, BorrowMut)] +#[borrow(forward)] #[borrow_mut(forward)] struct SingleFieldForward(Vec); @@ -48,14 +59,17 @@ fn main() { This generates: ```rust +# #[macro_use] extern crate derive_more; +# #[derive(Borrow)] +# #[borrow(forward)] # struct SingleFieldForward(Vec); -impl<__BorrowMutT: ?::core::marker::Sized> ::core::convert::BorrowMut<__BorrowMutT> for SingleFieldForward +impl<__BorrowMutT: ?::core::marker::Sized> ::core::borrow::BorrowMut<__BorrowMutT> for SingleFieldForward where - Vec: ::core::convert::BorrowMut<__BorrowMutT>, + Vec: ::core::borrow::BorrowMut<__BorrowMutT>, { #[inline] fn borrow_mut(&mut self) -> &mut __BorrowMutT { - as ::core::convert::BorrowMut<__BorrowMutT>>::borrow_mut(&mut self.0) + as ::core::borrow::BorrowMut<__BorrowMutT>>::borrow_mut(&mut self.0) } } ``` @@ -70,11 +84,15 @@ You can also exclude a specific field by using `#[borrow_mut(ignore)]`. ```rust # #[macro_use] extern crate derive_more; +# use core::borrow::Borrow; +# use core::borrow::BorrowMut; # fn main(){} -#[derive(BorrowMut)] +#[derive(Borrow, BorrowMut)] struct MyWrapper { + #[borrow] #[borrow_mut] name: String, + #[borrow] #[borrow_mut] num: i32, valid: bool, @@ -86,6 +104,10 @@ struct MyWrapper { Generates: ``` +# #[macro_use] extern crate derive_more; +# use core::borrow::Borrow; +# use core::borrow::BorrowMut; +# #[derive(Borrow)] # struct MyWrapper { # name: String, # num: i32, @@ -109,6 +131,8 @@ mark more than one field of the same type with `#[borrow_mut]` will result in a ```compile_fail # #[macro_use] extern crate derive_more; +# use core::borrow::Borrow; +# use core::borrow::BorrowMut; # fn main(){} // Error! Conflicting implementations of BorrowMut #[derive(BorrowMut)] From 70d2049f86335c221f3ef575ec9b02533ea061a5 Mon Sep 17 00:00:00 2001 From: Tyler Slabinski Date: Mon, 22 Mar 2021 18:26:19 -0400 Subject: [PATCH 6/8] Fix doc --- doc/borrow_mut.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/borrow_mut.md b/doc/borrow_mut.md index 972700ff..7f382b81 100644 --- a/doc/borrow_mut.md +++ b/doc/borrow_mut.md @@ -103,7 +103,7 @@ struct MyWrapper { Generates: -``` +```rust # #[macro_use] extern crate derive_more; # use core::borrow::Borrow; # use core::borrow::BorrowMut; From 42f2560122d52d0c0244c4e6e0bd57d61308ff46 Mon Sep 17 00:00:00 2001 From: Tyler Slabinski Date: Mon, 22 Mar 2021 18:27:49 -0400 Subject: [PATCH 7/8] Fix typo --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 280aeb6e..5063181b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -426,7 +426,7 @@ create_derive!( BorrowMut, borrow_mut_derive, borrow_mut -}; +); create_derive!( "is_variant", From 3cc737ab0340ad3e9bb580fc109ae4619fe754cb Mon Sep 17 00:00:00 2001 From: Tyler Slabinski Date: Mon, 22 Mar 2021 19:02:51 -0400 Subject: [PATCH 8/8] Add borrow tests --- tests/borrow.rs | 110 ++++++++++++++++++++++++++++++++++++++++++ tests/borrow_mut.rs | 113 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 223 insertions(+) create mode 100644 tests/borrow.rs create mode 100644 tests/borrow_mut.rs diff --git a/tests/borrow.rs b/tests/borrow.rs new file mode 100644 index 00000000..df947de0 --- /dev/null +++ b/tests/borrow.rs @@ -0,0 +1,110 @@ +#![allow(dead_code)] + +#[macro_use] +extern crate derive_more; + +use std::borrow::Borrow; + +use std::path::PathBuf; +use std::ptr; + +#[derive(Borrow)] +struct SingleFieldTuple(String); + +#[test] +fn single_field_tuple() { + let item = SingleFieldTuple(String::from("test")); + + assert!(ptr::eq(&item.0, item.borrow())); +} + +#[derive(Borrow)] +#[borrow(forward)] +struct SingleFieldForward(Vec); + +#[test] +fn single_field_forward() { + let item = SingleFieldForward(vec![]); + let _: &[i32] = (&item).borrow(); +} + +#[derive(Borrow)] +struct SingleFieldStruct { + first: String, +} + +#[test] +fn single_field_struct() { + let item = SingleFieldStruct { + first: String::from("test"), + }; + + assert!(ptr::eq(&item.first, item.borrow())); +} + +#[derive(Borrow)] +struct MultiFieldTuple(#[borrow] String, #[borrow] PathBuf, Vec); + +#[test] +fn multi_field_tuple() { + let item = MultiFieldTuple(String::from("test"), PathBuf::new(), vec![]); + + assert!(ptr::eq(&item.0, item.borrow())); + assert!(ptr::eq(&item.1, item.borrow())); +} + +#[derive(Borrow)] +struct MultiFieldStruct { + #[borrow] + first: String, + #[borrow] + second: PathBuf, + third: Vec, +} + +#[test] +fn multi_field_struct() { + let item = MultiFieldStruct { + first: String::from("test"), + second: PathBuf::new(), + third: vec![], + }; + + assert!(ptr::eq(&item.first, item.borrow())); + assert!(ptr::eq(&item.second, item.borrow())); +} + +#[derive(Borrow)] +struct SingleFieldGenericStruct { + first: T, +} + +#[test] +fn single_field_generic_struct() { + let item = SingleFieldGenericStruct { + first: String::from("test"), + }; + + assert!(ptr::eq(&item.first, item.borrow())); +} + +#[derive(Borrow)] +struct MultiFieldGenericStruct { + #[borrow] + first: Vec, + #[borrow] + second: [U; 2], + third: Vec, +} + +#[test] +fn multi_field_generic_struct() { + let item = MultiFieldGenericStruct { + first: b"test".to_vec(), + second: [0i32, 1i32], + third: vec![], + }; + + assert!(ptr::eq(&item.first, item.borrow())); + assert!(ptr::eq(&item.second, item.borrow())); +} diff --git a/tests/borrow_mut.rs b/tests/borrow_mut.rs new file mode 100644 index 00000000..9ed928d8 --- /dev/null +++ b/tests/borrow_mut.rs @@ -0,0 +1,113 @@ +#![allow(dead_code)] + +#[macro_use] +extern crate derive_more; + +use std::borrow::{Borrow, BorrowMut}; + +use std::path::PathBuf; +use std::ptr; + +#[derive(Borrow, BorrowMut)] +struct SingleFieldTuple(String); + +#[test] +fn single_field_tuple() { + let mut item = SingleFieldTuple(String::from("test")); + + assert!(ptr::eq(&mut item.0, item.borrow_mut())); +} + +#[derive(Borrow, BorrowMut)] +#[borrow(forward)] +#[borrow_mut(forward)] +struct SingleFieldForward(Vec); + +#[test] +fn single_field_forward() { + let mut item = SingleFieldForward(vec![]); + let _: &mut [i32] = (&mut item).borrow_mut(); +} + +#[derive(Borrow, BorrowMut)] +struct SingleFieldStruct { + first: String, +} + +#[test] +fn single_field_struct() { + let mut item = SingleFieldStruct { + first: String::from("test"), + }; + + assert!(ptr::eq(&mut item.first, item.borrow_mut())); +} + +#[derive(Borrow, BorrowMut)] +struct MultiFieldTuple(#[borrow_mut] String, #[borrow_mut] PathBuf, Vec); + +#[test] +fn multi_field_tuple() { + let mut item = MultiFieldTuple(String::from("test"), PathBuf::new(), vec![]); + + assert!(ptr::eq(&mut item.0, item.borrow_mut())); + assert!(ptr::eq(&mut item.1, item.borrow_mut())); +} + +#[derive(Borrow, BorrowMut)] +struct MultiFieldStruct { + #[borrow_mut] + first: String, + #[borrow_mut] + second: PathBuf, + third: Vec, +} + +#[test] +fn multi_field_struct() { + let mut item = MultiFieldStruct { + first: String::from("test"), + second: PathBuf::new(), + third: vec![], + }; + + assert!(ptr::eq(&mut item.first, item.borrow_mut())); + assert!(ptr::eq(&mut item.second, item.borrow_mut())); +} + +#[derive(Borrow, BorrowMut)] +struct SingleFieldGenericStruct { + first: T, +} + +#[test] +fn single_field_generic_struct() { + let mut item = SingleFieldGenericStruct { + first: String::from("test"), + }; + + assert!(ptr::eq(&mut item.first, item.borrow_mut())); +} + +#[derive(Borrow, BorrowMut)] +struct MultiFieldGenericStruct { + #[borrow] + #[borrow_mut] + first: Vec, + #[borrow] + #[borrow_mut] + second: PathBuf, + third: Vec, +} + +#[test] +fn multi_field_generic_struct() { + let mut item = MultiFieldGenericStruct { + first: b"test".to_vec(), + second: PathBuf::new(), + third: vec![], + }; + + assert!(ptr::eq(&mut item.first, item.borrow_mut())); + assert!(ptr::eq(&mut item.second, item.borrow_mut())); +}