Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ add_assign = []
add = []
as_mut = []
as_ref = []
borrow = []
borrow_mut = []
constructor = []
deref = []
deref_mut = []
Expand All @@ -69,6 +71,8 @@ default = [
"add",
"as_mut",
"as_ref",
"borrow",
"borrow_mut",
"constructor",
"deref",
"deref_mut",
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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/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

Expand Down
130 changes: 130 additions & 0 deletions doc/borrow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
% 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<T>` 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
# use core::borrow::Borrow;
# #[macro_use] extern crate derive_more;
# fn main(){}
#[derive(Borrow)]
struct MyWrapper(String);
```

Generates:

```rust
# use core::borrow::Borrow;
# struct MyWrapper(String);
impl Borrow<String> 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<i32>` implements `Borrow` for.

```rust
# use core::borrow::Borrow;
# #[macro_use] extern crate derive_more;
#[derive(Borrow)]
#[borrow(forward)]
struct SingleFieldForward(Vec<i32>);

fn main() {
let item = SingleFieldForward(vec![]);
let _: &[i32] = (&item).borrow();
}

```

This generates:

```rust
# struct SingleFieldForward(Vec<i32>);
impl<__BorrowT: ?::core::marker::Sized> ::core::borrow::Borrow<__BorrowT> for SingleFieldForward
where
Vec<i32>: ::core::borrow::Borrow<__BorrowT>,
{
#[inline]
fn borrow(&self) -> &__BorrowT {
<Vec<i32> as ::core::borrow::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
# use core::borrow::Borrow;
# #[macro_use] extern crate derive_more;
# fn main(){}
#[derive(Borrow)]
struct MyWrapper {
#[borrow]
name: String,
#[borrow]
num: i32,
valid: bool,
}

```

Generates:

```rust
# use core::borrow::Borrow;
# struct MyWrapper {
# name: String,
# num: i32,
# valid: bool,
# }
impl Borrow<String> for MyWrapper {
fn borrow(&self) -> &String {
&self.name
}
}

impl Borrow<i32> for MyWrapper {
fn borrow(&self) -> &i32 {
&self.num
}
}
```

Note that `Borrow<T>` 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
# use core::borrow::Borrow;
# #[macro_use] extern crate derive_more;
# fn main(){}
// Error! Conflicting implementations of Borrow<String>
#[derive(Borrow)]
struct MyWrapper {
#[borrow]
str1: String,
#[borrow]
str2: String,
}
```

# Enums

Deriving `Borrow` for enums is not supported.
149 changes: 149 additions & 0 deletions doc/borrow_mut.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
% 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<T>` is accepted.

Note that `BorrowMut<T>` expects the type to also implement `Borrow<T>`.

# 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;
# use core::borrow::Borrow;
# use core::borrow::BorrowMut;
# fn main(){}
#[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<String> 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<i32>` implements `BorrowMut` for.

```rust
# #[macro_use] extern crate derive_more;
# use core::borrow::Borrow;
# use core::borrow::BorrowMut;
#[derive(Borrow, BorrowMut)]
#[borrow(forward)]
#[borrow_mut(forward)]
struct SingleFieldForward(Vec<i32>);

fn main() {
let mut item = SingleFieldForward(vec![]);
let _: &mut [i32] = (&mut item).borrow_mut();
}

```

This generates:

```rust
# #[macro_use] extern crate derive_more;
# #[derive(Borrow)]
# #[borrow(forward)]
# struct SingleFieldForward(Vec<i32>);
impl<__BorrowMutT: ?::core::marker::Sized> ::core::borrow::BorrowMut<__BorrowMutT> for SingleFieldForward
where
Vec<i32>: ::core::borrow::BorrowMut<__BorrowMutT>,
{
#[inline]
fn borrow_mut(&mut self) -> &mut __BorrowMutT {
<Vec<i32> as ::core::borrow::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;
# use core::borrow::Borrow;
# use core::borrow::BorrowMut;
# fn main(){}
#[derive(Borrow, BorrowMut)]
struct MyWrapper {
#[borrow]
#[borrow_mut]
name: String,
#[borrow]
#[borrow_mut]
num: i32,
valid: bool,
}


```

Generates:

```
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```
```rust

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

# #[macro_use] extern crate derive_more;
# use core::borrow::Borrow;
# use core::borrow::BorrowMut;
# #[derive(Borrow)]
# struct MyWrapper {
# name: String,
# num: i32,
# valid: bool,
# }
impl BorrowMut<String> for MyWrapper {
fn borrow_mut(&mut self) -> &mut String {
&mut self.name
}
}

impl BorrowMut<i32> for MyWrapper {
fn borrow_mut(&mut self) -> &mut i32 {
&mut self.num
}
}
```

Note that `BorrowMut<T>` 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;
# use core::borrow::Borrow;
# use core::borrow::BorrowMut;
# fn main(){}
// Error! Conflicting implementations of BorrowMut<String>
#[derive(BorrowMut)]
struct MyWrapper {
#[borrow_mut]
str1: String,
#[borrow_mut]
str2: String,
}
```

# Enums

Deriving `BorrowMut` for enums is not supported.
Loading