Wrap up heapsize2 example
diff --git a/examples/heapsize/heapsize_derive/src/lib.rs b/examples/heapsize/heapsize_derive/src/lib.rs
index 9eb492e..acf1e27 100644
--- a/examples/heapsize/heapsize_derive/src/lib.rs
+++ b/examples/heapsize/heapsize_derive/src/lib.rs
@@ -55,7 +55,7 @@
                 Fields::Named(ref fields) => {
                     // Expands to an expression like
                     //
-                    //     0 + self.x.heap_size + self.y.heap_size() + self.z.heap_size()
+                    //     0 + self.x.heap_size() + self.y.heap_size() + self.z.heap_size()
                     //
                     // but using fully qualified function call syntax.
                     let fnames = fields.named.iter().map(|f| f.ident);
@@ -68,7 +68,7 @@
                 Fields::Unnamed(ref fields) => {
                     // Expands to an expression like
                     //
-                    //     0 + self.0.heap_size + self.1.heap_size() + self.2.heap_size()
+                    //     0 + self.0.heap_size() + self.1.heap_size() + self.2.heap_size()
                     let indices = 0..fields.unnamed.len();
                     quote! {
                         0 #(
diff --git a/examples/heapsize2/example/src/main.rs b/examples/heapsize2/example/src/main.rs
index 710bab0..4e7d478 100644
--- a/examples/heapsize2/example/src/main.rs
+++ b/examples/heapsize2/example/src/main.rs
@@ -1,12 +1,55 @@
 #[macro_use]
 extern crate heapsize_derive;
 
+// Demonstrate that hygiene is working correctly by having no `extern crate
+// heapsize` in scope here. The macro-generated impl is not for something like
+// `::heapsize::HeapSize` like is common in Macros 1.1. It is for the `HeapSize`
+// trait brought into scope by the procedural macro definition.
 #[derive(HeapSize)]
 struct Demo<'a, T: ?Sized> {
     a: Box<T>,
     b: u8,
     c: &'a str,
-    d: String,
+    d: HeapSize,
 }
 
-fn main() {}
+// This derive is going to generate `impl HeapSize for HeapSize` which is fine
+// because the two `HeapSize` tokens have different hygiene context. The first
+// one resolves to the `HeapSize` trait brough into scop eby the procedural
+// macro definition, and the second one refers to this struct.
+//
+// Also demonstrate that even though both `impl HeapSize for Demo` and `impl
+// HeapSize for HeapSize` spit out a `mod scope`, they do not conflict because
+// of hygiene.
+#[derive(HeapSize)]
+struct HeapSize {
+    e: String,
+}
+
+// Try to trip up the custom derive by having an inherent method with the same
+// name as the trait method. The `impl HeapSize for Demo` is going to generate
+// an expression that calls `self.d.heap_size_of_children()`. Ordinarily
+// inherent methods take precedence over trait methods, so an unhygienic macro
+// implementation would resolve to this method. Instead the call in the
+// generated code resolves correctly to the `HeapSize` trait method because that
+// is what is in scope within the macro definition.
+impl HeapSize {
+    #[allow(dead_code)]
+    fn heap_size_of_children(&self) -> usize {
+        unimplemented!()
+    }
+}
+
+fn main() {
+    extern crate heapsize;
+
+    let demo = Demo {
+        a: b"bytestring".to_vec().into_boxed_slice(),
+        b: 255,
+        c: "&'static str",
+        d: HeapSize {
+            e: "String".to_owned(),
+        },
+    };
+    println!("heap size = {}", heapsize::HeapSize::heap_size_of_children(&demo));
+}
diff --git a/examples/heapsize2/heapsize_derive/src/lib.rs b/examples/heapsize2/heapsize_derive/src/lib.rs
index 818bd76..3389b61 100644
--- a/examples/heapsize2/heapsize_derive/src/lib.rs
+++ b/examples/heapsize2/heapsize_derive/src/lib.rs
@@ -1,30 +1,102 @@
 extern crate proc_macro;
-use proc_macro::TokenStream;
-
 extern crate syn;
-use syn::DeriveInput;
 
 #[macro_use]
 extern crate quote;
 
+use proc_macro::TokenStream;
+use syn::{DeriveInput, Data, Fields, Generics, GenericParam};
+use quote::Tokens;
+
 #[proc_macro_derive(HeapSize)]
 pub fn derive_heap_size(input: TokenStream) -> TokenStream {
+    // Parse the input tokens into a syntax tree.
     let input: DeriveInput = syn::parse(input).unwrap();
+
+    // Used in the quasi-quotation below as `#name`.
     let name = input.ident;
-    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
+
+    // Add a bound `T: HeapSize` to every type parameter T.
+    let generics = add_trait_bounds(input.generics);
+    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+    // Generate an expression to sum up the heap size of each field.
+    let sum = heap_size_sum(&input.data);
 
     let expanded = quote! {
         mod scope {
             extern crate heapsize;
             use self::heapsize::HeapSize;
 
+            // The generated impl. Okay to use `HeapSize` unqualified here, it
+            // is guaranteed to resolve to the import on the previous line. This
+            // works even in edge cases like the user's struct having the name
+            // `HeapSize` as demonstrated in main.rs, in which case the
+            // generated code looks like `impl HeapSize for HeapSize`.
             impl #impl_generics HeapSize for #name #ty_generics #where_clause {
                 fn heap_size_of_children(&self) -> usize {
-                    0
+                    #sum
                 }
             }
         }
     };
 
+    // Hand the output tokens back to the compiler.
     expanded.into()
 }
+
+// Add a bound `T: HeapSize` to every type parameter T.
+fn add_trait_bounds(mut generics: Generics) -> Generics {
+    for param in &mut generics.params {
+        if let GenericParam::Type(ref mut type_param) = *param {
+            let bound = syn::parse(quote!(HeapSize).into()).unwrap();
+            type_param.bounds.push(bound);
+        }
+    }
+    generics
+}
+
+// Generate an expression to sum up the heap size of each field.
+fn heap_size_sum(data: &Data) -> Tokens {
+    match *data {
+        Data::Struct(ref data) => {
+            match data.fields {
+                Fields::Named(ref fields) => {
+                    // Expands to an expression like
+                    //
+                    //     0 + self.x.heap_size() + self.y.heap_size() + self.z.heap_size()
+                    //
+                    // Does not need to use fully qualified function call syntax
+                    // like `::heapsize::HeapSize::heap_size_of_children(&...)`.
+                    // Our procedural macro places the `HeapSize` trait in scope
+                    // within the generated code so this is guaranteed to
+                    // resolve to the right trait method, even if one of these
+                    // fields has an inherent method with a conflicting name as
+                    // demonstrated in main.rs.
+                    let fnames = fields.named.iter().map(|f| f.ident);
+                    quote! {
+                        0 #(
+                            + self.#fnames.heap_size_of_children()
+                        )*
+                    }
+                }
+                Fields::Unnamed(ref fields) => {
+                    // Expands to an expression like
+                    //
+                    //     0 + self.0.heap_size() + self.1.heap_size() + self.2.heap_size()
+                    let indices = 0..fields.unnamed.len();
+                    quote! {
+                        0 #(
+                            + self.#indices.heap_size_of_children()
+                        )*
+                    }
+                }
+                Fields::Unit => {
+                    // Unit structs cannot own more than 0 bytes of heap memory.
+                    quote!(0)
+                }
+            }
+        }
+        Data::Enum(_) | Data::Union(_) => unimplemented!(),
+    }
+}