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 — everything is as shown in this directory — 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