1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
//! Let's `Clone` a `Cow`!
//!
//!   - **Date:** February 28, 2017
//!   - **Subject:** The final pieces of the story for (single-threaded) memory
//!     management in Rust.
//!   - [**Audio**][mp3]
//!
//! [mp3]: https://www.podtrac.com/pts/redirect.mp3/f001.backblazeb2.com/file/newrustacean/e019.mp3
//!
//! <audio style="width: 100%" title="Let's `Clone` a `Cow`!" controls preload=metadata>
//!   <source src="https://www.podtrac.com/pts/redirect.mp3/f001.backblazeb2.com/file/newrustacean/e019.mp3">
//! </audio>
//!
//!
//! Notes
//! -----
//!
//! Sometimes, we actually *do* need to copy types. Wouldn't it be nice if Rust
//! gave us a convenient way to do that when it's convenient, or when the cost
//! is low enough that the ergonomic tradeoffs are worth it? Well, perhaps
//! unsurprisingly, it does! The `Copy` and `Clone` traits, plus the `Cow` type,
//! give us everything we need!
//!
//!
//! Links
//! -----
//!
//! - [underhanded.rs]
//!
//! - The typess
//!
//!     - [`std::marker::Copy`]
//!
//!         - ["`Copy` types" in the book][copy-book]
//!
//!         - ["Stack-Only Data: Copy" in the new book][copy-new-book]
//!
//!         - [7.2.0.2 Moved and copied types]:
//!
//!             > When a local variable is used as an rvalue, the variable will be copied if its
//!               type implements `Copy`. All others are moved.
//!
//!         - [Extended example in "Traits" section of new book][copy-traits-example-new-book]
//!
//!     - [`std::clone::Clone`]
//!
//!     - [`std::borrow::Cow`]
//!
//! - Default implementations
//!
//!     - [discussion in the current book][default-book]
//!
//!     - [discussion in the new book][default-new-book]
//!
//! - Supertraits
//!
//!     - from the discussion in the reference ([6.1.9 Traits]):
//!
//!         > Traits may inherit from other traits.... The syntax `Circle : Shape` means that types
//!           that implement `Circle` must also have an implementation for `Shape`. Multiple
//!           supertraits are separated by `+`, trait `Circle : Shape + PartialEq { }`. In an
//!           implementation of `Circle` for a given type `T`, methods can refer to `Shape` methods,
//!           since the typechecker checks that any type with an implementation of `Circle` also has
//!           an implementation of `Shape`...
//!
//!     - [discussion of trait "inheritance" in the book][trait-inheritance]
//!
//!     - [discussion of trait super- and subtyping in the new book][trait-inheritance-new-book]
//!       (note: still to-be-written at the time this episode was published)
//!
//! - Marker traits
//!
//!     - [`std::marker`]
//!
//!     - in the reference: [9 Special Traits]
//!
//! - Previous episodes on traits:
//!
//!     - [e008: Just like something else][e008]
//!
//!     - [e009: Composing a Rustic tune][e009]
//!
//!
//! [underhanded.rs]: https://underhanded.rs/
//! [`std::marker::Copy`]: https://doc.rust-lang.org/stable/std/marker/trait.Copy.html
//! [copy-book]: https://doc.rust-lang.org/book/ownership.html#copy-types
//! [copy-new-book]: http://rust-lang.github.io/book/ch04-01-what-is-ownership.html#stack-only-data-copy
//! [7.2.0.2 Moved and copied types]: https://doc.rust-lang.org/reference.html#moved-and-copied-types
//! [copy-traits-example-new-book]: http://rust-lang.github.io/book/ch10-02-traits.html#fixing-the-largest-function-with-trait-bounds
//! [`std::clone::Clone`]: https://doc.rust-lang.org/stable/std/clone/trait.Clone.html
//! [`std::borrow::Cow`]: https://doc.rust-lang.org/stable/std/borrow/enum.Cow.html
//! [default-book]: https://doc.rust-lang.org/book/traits.html#default-methods
//! [default-new-book]: http://rust-lang.github.io/book/ch10-02-traits.html#default-implementations
//! [6.1.9 Traits]: https://doc.rust-lang.org/reference.html#traits
//! [trait-inheritance]: https://doc.rust-lang.org/book/traits.html#inheritance
//! [trait-inheritance-new-book]: http://rust-lang.github.io/book/ch19-00-advanced-features.html
//! [`std::marker`]: https://doc.rust-lang.org/stable/std/marker/
//! [9 Special Traits]: https://doc.rust-lang.org/reference.html#special-traits
//! [e008]: https://www.newrustacean.com/show_notes/e008/
//! [e009]: https://www.newrustacean.com/show_notes/e009/
//!
//!
//! Sponsors
//! --------
//!
//!
//!   - Aleksey Pirogov
//!   - Andreas Fischer
//!   - Andrew Thompson
//!   - Austin LeSure
//!   - Ben Whitley
//!   - [Charlie Egan]
//!   - [Chris Palmer]
//!   - [Christopher Giffard]
//!   - [Daniel Collin]
//!   - [Derek Morr]
//!   - [Jakub "Limeth" Hlusička]
//!   - Jordan Henderson
//!   - [Jupp Müller]
//!   - Keith Gray
//!   - Lachlan Collins
//!   - Luca Schmid
//!   - Matt Rudder
//!   - Matthew Piziak
//!   - [Max Jacobson]
//!   - Micael Bergeron
//!   - Ovidiu Curcan
//!   - [Pascal Hertleif]
//!   - Peter Tillemans
//!   - Philipp Keller
//!   - Ralph Giles ("rillian")
//!   - Raph Levien
//!   - reddraggone9
//!   - Steven Murawski
//!   - [Stuart Hinson]
//!   - Tyler Harper
//!   - Vesa Kaihlavirta
//!   - Vlad Bezden
//!   - [William Roe]
//!   - Zaki
//!
//! [Charlie Egan]: https://charlieegan3.com
//! [Chris Palmer]: http://home.red-oxide.org/
//! [Christopher Giffard]: http://blog.cgiffard.com
//! [Daniel Collin]: https://twitter.com/daniel_collin
//! [Derek Morr]: https://twitter.com/derekmorr
//! [Jakub "Limeth" Hlusička]: https://github.com/Limeth
//! [Jupp Müller]: https://de.linkedin.com/in/juppm
//! [Max Jacobson]: https://twitter.com/maxjacobson
//! [Pascal Hertleif]: https://pascalhertleif.de/
//! [Philipp Keller]: https://twitter.com/hansapla
//! [Stuart Hinson]: http://stuarth.github.io/
//! [William Roe]: http://willroe.me
//!
//! (Thanks to the couple people donating who opted out of the reward tier, as
//! well. You know who you are!)
//!
//! ### Become a sponsor
//!
//!   - [Patreon](https://www.patreon.com/newrustacean)
//!   - [Venmo](https://venmo.com/chriskrycho)
//!   - [Dwolla](https://www.dwolla.com/hub/chriskrycho)
//!   - [Cash.me](https://cash.me/$chriskrycho)
//!   - [Flattr](https://flattr.com/profile/chriskrycho)
//!   - [PayPal.me](https://paypal.me/chriskrycho)
//!
//!
//! Contact
//! -------
//!
//!   - New Rustacean:
//!       + Twitter: [@newrustacean](https://www.twitter.com/newrustacean)
//!       + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com)
//!   - Chris Krycho
//!       + GitHub: [chriskrycho](https://github.com/chriskrycho)
//!       + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho)

/// A non-copyable point type
///
/// # Examples
///
/// ```rust,ignore
/// # use show_notes::e019::ANoCopyOrClonePoint;
/// let a_point = ANoCopyOrClonePoint::origin();
/// let moved_point = a_point;  // <- moves the value
/// println!("{:?}", a_point);  // <- so this is a problem!
/// println!("{:?}", moved_point)
/// ```
///
/// The output is just what we would expect from the discussion on the show:
///
/// ```plain
/// error[E0382]: use of moved value: `a_point`
/// --> <anon>:6:18
/// |
/// 5 | let moved_point = a_point;  // <- moves the value
/// |     ----------- value moved here
/// 6 | println!("{:?}", a_point);  // <- so this is a problem!
/// |                  ^^^^^^^ value used here after move
/// |
/// = note: move occurs because `a_point` has type `show_notes::e019::ANoCopyOrClonePoint`, which does not implement the `Copy` trait
/// ```
///
/// If we comment the offending line out, however, it compiles just fine.
///
/// ```rust
/// # use show_notes::e019::ANoCopyOrClonePoint;
/// let a_point = ANoCopyOrClonePoint::origin();
/// let moved_point = a_point;
/// // println!("{:?}", a_point);
/// println!("{:?}", moved_point);  // <- not a problem!
/// ```
///
/// [(You can confirm this in the playground.)][playground]
///
/// [playground]: https://is.gd/PZBWw0
#[derive(Debug)]
pub struct ANoCopyOrClonePoint {
    x: f64,
    y: f64,
    z: f64,
}

impl ANoCopyOrClonePoint {
    /// Generate a point at 0, 0, 0
    pub fn origin() -> ANoCopyOrClonePoint {
        ANoCopyOrClonePoint {
            x: 0.0,
            y: 0.0,
            z: 0.0,
        }
    }
}

/// A struct which implements `Clone` but not `Copy`.
///
/// # Examples
///
/// If you don't do anything, the item will be moved on assignment:
///
/// ```rust,ignore
/// # use show_notes::e019::BJustClonePoint;
/// let a_point = BJustClonePoint::origin();
/// let cloned_point = a_point;  // <- moves the value
/// println!("{:?}", a_point);  // <- compile error!
/// println!("{:?}", cloned_point);
/// ```
///
/// The output is just what we would expect from the discussion on the show:
///
/// ```plain
/// error[E0382]: use of moved value: `a_point`
/// --> <anon>:6:18
/// |
/// 5 | let cloned_point = a_point;  // <- moves the value
/// |     ------------ value moved here
/// 6 | println!("{:?}", a_point);  // <- compile error!
/// |                  ^^^^^^^ value used here after move
/// |
/// = note: move occurs because `a_point` has type `show_notes::e019::BJustClonePoint`, which does not implement the `Copy` trait
/// ```
///
///
/// But you can manually call the `clone` method, and it will work:
///
/// ```rust
/// # use show_notes::e019::BJustClonePoint;
/// let a_point = BJustClonePoint::origin();
/// let cloned_point = a_point.clone();
/// println!("{:?}", a_point);  // <- not a problem
/// println!("{:?}", cloned_point);
/// ```
#[derive(Clone, Debug)]
pub struct BJustClonePoint {
    x: f64,
    y: f64,
    z: f64,
}

impl BJustClonePoint {
    pub fn origin() -> BJustClonePoint {
        BJustClonePoint {
            x: 0.0,
            y: 0.0,
            z: 0.0,
        }
    }
}

/// A struct with identical behavior to `ANoCopyOrClonePoint`, except with `Copy`.
///
/// Note that we have `Clone` as well as `Copy` here---we have to, since
/// `Clone` is a supertrait for `Copy`.
///
/// # Examples
///
/// Note that this is just like the non-compiling example in [`ANoCopyOrClonePoint`], but because
/// `CCopyPoint` implements `Copy`, the line which previously caused a compile
/// error now works without any issue.
///
/// ```rust
/// # use show_notes::e019::CCopyPoint;
/// let a_point = CCopyPoint::origin();
/// let copied_point = a_point;
/// println!("{:?}", a_point);  // <- not a problem
/// println!("{:?}", copied_point)
/// ```
///
/// [`ANoCopyOrClonePoint`]: /show_notes/e019/struct.ANoCopyOrClonePoint.html
#[derive(Clone, Copy, Debug)]
pub struct CCopyPoint {
    x: f64,
    y: f64,
    z: f64,
}

impl CCopyPoint {
    /// Generate a point at 0, 0, 0
    pub fn origin() -> CCopyPoint {
        CCopyPoint {
            x: 0.0,
            y: 0.0,
            z: 0.0,
        }
    }
}

/// The `Cow` type can wrap around other types and make them "reusable".
///
/// Note that the body of this function is identical with that of the body of
/// the example below.
///
/// # Examples
///
/// We'll reuse the `BJustClonePoint` since `Cow::Owned` requires that the
/// underlying type implement `Clone`.
///
/// ```rust
/// # use std::borrow::Cow;
/// # use show_notes::e019::{BJustClonePoint,demonstrate_cow};
/// let a_point = Cow::Owned(BJustClonePoint::origin());
/// demonstrate_cow(&a_point);
/// ```
///
/// Note that even though `demonstrate_cow` takes a reference to
/// `BJustClonePoint`, we can pass it the `Cow` instance; this is where the
/// `Deref` implementation on `Cow` comes in handy.
pub fn demonstrate_cow(_point: &BJustClonePoint) {}

/// What if we need a mutable reference to the wrapped type?
///
/// # Examples
///
/// We can get a mutable reference to the wrapped item, even if the wrapped item
/// isn't itself mutable, as long as it's `Clone`-able. In this case, we're
/// making a copy---this is explicit in the `to_mut()` call. If the underlying
/// item isn't mutably accessible, we'll just get a mutable copy.
///
/// ```rust
/// # use std::borrow::Cow;
/// # use show_notes::e019::{BJustClonePoint,demonstrate_mut_cow};
/// let mut a_point: Cow<BJustClonePoint> = Cow::Owned(BJustClonePoint::origin());
/// demonstrate_mut_cow(a_point.to_mut());
/// ```
pub fn demonstrate_mut_cow(_point: &mut BJustClonePoint) {}