blob: e78955990d8e7b7f9a5cecf3e84778a57fb02769 (
plain)
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
|
A derive macro that generates trait impls.
- [`heapsize/src/lib.rs`](heapsize/src/lib.rs)
- [`heapsize_derive/src/lib.rs`](heapsize_derive/src/lib.rs)
- [`example/src/main.rs`](example/src/main.rs)
We are deriving the `HeapSize` trait which computes an estimate of the amount of
heap memory owned by a value.
```rust
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.
```rust
#[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:
```rust
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 `std::thread::Thread: HeapSize` is not satisfied
--> src/main.rs:7:5
|
7 | bad: std::thread::Thread,
| ^^^ the trait `HeapSize` is not implemented for `std::thread::Thread`
```
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 `cargo build` shows errors like the one
above and building with `RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build`
is able to show errors like the following.
```
error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
--> src/main.rs:7:5
|
7 | bad: std::thread::Thread,
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `std::thread::Thread`
```
|