examples/heapsize/README.md
A derive macro that generates trait impls.
We are deriving the HeapSize trait which computes an estimate of the amount of
heap memory owned by a value.
pub trait HeapSize {
/// Total number of bytes of heap memory owned by `self`.
fn heap_size_of_children(&self) -> usize;
}
The derive macro allows users to write #[derive(HeapSize)] on data structures
in their program.
#[derive(HeapSize)]
struct Demo<'a, T: ?Sized> {
a: Box<T>,
b: u8,
c: &'a str,
d: String,
}
The trait impl generated by the derive macro here would look like:
impl<'a, T: ?Sized + heapsize::HeapSize> heapsize::HeapSize for Demo<'a, T> {
fn heap_size_of_children(&self) -> usize {
0 + heapsize::HeapSize::heap_size_of_children(&self.a)
+ heapsize::HeapSize::heap_size_of_children(&self.b)
+ heapsize::HeapSize::heap_size_of_children(&self.c)
+ heapsize::HeapSize::heap_size_of_children(&self.d)
}
}
The implementation of heapsize_derive demonstrates some attention to "spans"
of error messages. For each subexpression in the generated code we apply the
span of the input fragment under which we would want to trigger a compiler error
if the subexpression fails to compile. In this example, each recursive call to
heap_size_of_children is associated with the span of the corresponding struct
field. Thus we get errors in the right place if any of the field types do not
implement the HeapSize trait.
error[E0277]: the trait bound `Thread: HeapSize` is not satisfied
--> src/main.rs:9:5
|
3 | #[derive(HeapSize)]
| -------- required by a bound introduced by this call
...
9 | bad: std::thread::Thread,
| ^^^ the trait `HeapSize` is not implemented for `Thread`
|
= help: the following other types implement trait `HeapSize`:
&'a T
Box<T>
Demo<'a, T>
String
[T]
u8
Some unstable APIs in the proc-macro2 crate let us improve this further by
joining together the span of the field name and the field type. There is no
difference in our code — everything is as shown in this directory —
but building the example crate with a stable compiler shows errors like the one
above (underlining the field name only) and building with nightly is able to
show errors like the following (underlining the name and type).
9 | bad: std::thread::Thread,
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `Thread`