1fad3a1d3Sopenharmony_ciA derive macro that generates trait impls.
2fad3a1d3Sopenharmony_ci
3fad3a1d3Sopenharmony_ci- [`heapsize/src/lib.rs`](heapsize/src/lib.rs)
4fad3a1d3Sopenharmony_ci- [`heapsize_derive/src/lib.rs`](heapsize_derive/src/lib.rs)
5fad3a1d3Sopenharmony_ci- [`example/src/main.rs`](example/src/main.rs)
6fad3a1d3Sopenharmony_ci
7fad3a1d3Sopenharmony_ciWe are deriving the `HeapSize` trait which computes an estimate of the amount of
8fad3a1d3Sopenharmony_ciheap memory owned by a value.
9fad3a1d3Sopenharmony_ci
10fad3a1d3Sopenharmony_ci```rust
11fad3a1d3Sopenharmony_cipub trait HeapSize {
12fad3a1d3Sopenharmony_ci    /// Total number of bytes of heap memory owned by `self`.
13fad3a1d3Sopenharmony_ci    fn heap_size_of_children(&self) -> usize;
14fad3a1d3Sopenharmony_ci}
15fad3a1d3Sopenharmony_ci```
16fad3a1d3Sopenharmony_ci
17fad3a1d3Sopenharmony_ciThe derive macro allows users to write `#[derive(HeapSize)]` on data structures
18fad3a1d3Sopenharmony_ciin their program.
19fad3a1d3Sopenharmony_ci
20fad3a1d3Sopenharmony_ci```rust
21fad3a1d3Sopenharmony_ci#[derive(HeapSize)]
22fad3a1d3Sopenharmony_cistruct Demo<'a, T: ?Sized> {
23fad3a1d3Sopenharmony_ci    a: Box<T>,
24fad3a1d3Sopenharmony_ci    b: u8,
25fad3a1d3Sopenharmony_ci    c: &'a str,
26fad3a1d3Sopenharmony_ci    d: String,
27fad3a1d3Sopenharmony_ci}
28fad3a1d3Sopenharmony_ci```
29fad3a1d3Sopenharmony_ci
30fad3a1d3Sopenharmony_ciThe trait impl generated by the derive macro here would look like:
31fad3a1d3Sopenharmony_ci
32fad3a1d3Sopenharmony_ci```rust
33fad3a1d3Sopenharmony_ciimpl<'a, T: ?Sized + heapsize::HeapSize> heapsize::HeapSize for Demo<'a, T> {
34fad3a1d3Sopenharmony_ci    fn heap_size_of_children(&self) -> usize {
35fad3a1d3Sopenharmony_ci        0 + heapsize::HeapSize::heap_size_of_children(&self.a)
36fad3a1d3Sopenharmony_ci            + heapsize::HeapSize::heap_size_of_children(&self.b)
37fad3a1d3Sopenharmony_ci            + heapsize::HeapSize::heap_size_of_children(&self.c)
38fad3a1d3Sopenharmony_ci            + heapsize::HeapSize::heap_size_of_children(&self.d)
39fad3a1d3Sopenharmony_ci    }
40fad3a1d3Sopenharmony_ci}
41fad3a1d3Sopenharmony_ci```
42fad3a1d3Sopenharmony_ci
43fad3a1d3Sopenharmony_ciThe implementation of `heapsize_derive` demonstrates some attention to "spans"
44fad3a1d3Sopenharmony_ciof error messages. For each subexpression in the generated code we apply the
45fad3a1d3Sopenharmony_cispan of the input fragment under which we would want to trigger a compiler error
46fad3a1d3Sopenharmony_ciif the subexpression fails to compile. In this example, each recursive call to
47fad3a1d3Sopenharmony_ci`heap_size_of_children` is associated with the span of the corresponding struct
48fad3a1d3Sopenharmony_cifield. Thus we get errors in the right place if any of the field types do not
49fad3a1d3Sopenharmony_ciimplement the `HeapSize` trait.
50fad3a1d3Sopenharmony_ci
51fad3a1d3Sopenharmony_ci```
52fad3a1d3Sopenharmony_cierror[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
53fad3a1d3Sopenharmony_ci --> src/main.rs:7:5
54fad3a1d3Sopenharmony_ci  |
55fad3a1d3Sopenharmony_ci7 |     bad: std::thread::Thread,
56fad3a1d3Sopenharmony_ci  |     ^^^ the trait `HeapSize` is not implemented for `std::thread::Thread`
57fad3a1d3Sopenharmony_ci```
58fad3a1d3Sopenharmony_ci
59fad3a1d3Sopenharmony_ciSome unstable APIs in the `proc-macro2` crate let us improve this further by
60fad3a1d3Sopenharmony_cijoining together the span of the field name and the field type. There is no
61fad3a1d3Sopenharmony_cidifference in our code &mdash; everything is as shown in this directory &mdash;
62fad3a1d3Sopenharmony_cibut building the example crate with `cargo build` shows errors like the one
63fad3a1d3Sopenharmony_ciabove and building with `RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build`
64fad3a1d3Sopenharmony_ciis able to show errors like the following.
65fad3a1d3Sopenharmony_ci
66fad3a1d3Sopenharmony_ci```
67fad3a1d3Sopenharmony_cierror[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
68fad3a1d3Sopenharmony_ci --> src/main.rs:7:5
69fad3a1d3Sopenharmony_ci  |
70fad3a1d3Sopenharmony_ci7 |     bad: std::thread::Thread,
71fad3a1d3Sopenharmony_ci  |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `std::thread::Thread`
72fad3a1d3Sopenharmony_ci```
73