}
fn main() {
let mut sam = Rc::new(
Human { name: "Sam".to_string(), pet_dogs: Vec::new() }
);
let rover = Dog { name: "Rover".to_string(), owner: Rc::downgrade(&sam) };
// This is not allowed, because `sam` is actually immutable
// sam.pet_dogs.push(rover);
}
```
Note:
You get an error like:
error[E0596]: cannot borrow data in an `Rc` as mutable
--> src/main.rs:12:5
|
12 | sam.pet_dogs.push(rover);
| ^^^^^^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc<Human>`
For more information about this error, try `rustc --explain E0596`.
Why do you want this structure? Because given some `&Dog` you might very well want to know who owns it!
---
## Shared Mutability
We have more on this later...
```rust []
use std::rc::{Rc, Weak};
use std::cell::RefCell;
struct Dog { name: String, owner: Weak> }
struct Human { name: String, pet_dogs: Vec }
fn main() {
let mut sam = Rc::new(RefCell::new(
Human { name: "Sam".to_string(), pet_dogs: Vec::new() }
));
let rover = Dog { name: "Rover".to_string(), owner: Rc::downgrade(&sam) };
// This is now allowed because `RefCell::borrow_mut` does a run-time borrow check
sam.borrow_mut().pet_dogs.push(rover);
}
```
---
## Maybe Boxed, maybe not?
Why is this function less than ideal?
```rust should_panic []
/// Replaces all the ` ` characters with `_`
fn replace_spaces(input: &str) -> String {
todo!()
}
fn main() {
println!("{}", replace_spaces("Hello, world!"));
println!("{}", replace_spaces("Hello!"));
}
```
Note:
Did the second call replace anything? Did you have to allocate a `String` and copy all the data anyway, even though nothing changed?
---
## Copy-On-Write
Rust has the [`Cow`](https://doc.rust-lang.org/std/borrow/enum.Cow.html) type to handle this.
```rust should_panic []
/// Replaces all the ` ` characters with `_`
fn replace_spaces(input: &str) -> std::borrow::Cow {
todo!()
}
fn main() {
println!("{}", replace_spaces("Hello, world!"));
println!("{}", replace_spaces("Hello!"));
}
```
Note:
`Cow` works on any `T` where there is both a *Borrowed* version and an *Owned* version.
For example, `&[u8]` and `Vec`.