Fill in remaining synom descriptions
diff --git a/src/data.rs b/src/data.rs
index f9152f2..cfea802 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -137,6 +137,10 @@
                 named: fields,
             }
         ));
+
+        fn description() -> Option<&'static str> {
+            Some("named fields in a struct or struct variant")
+        }
     }
 
     impl Synom for FieldsUnnamed {
@@ -147,6 +151,10 @@
                 unnamed: fields,
             }
         ));
+
+        fn description() -> Option<&'static str> {
+            Some("unnamed fields in a tuple struct or tuple variant")
+        }
     }
 
     impl Field {
diff --git a/src/expr.rs b/src/expr.rs
index 2dbcde3..975c635 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -1386,6 +1386,10 @@
                 lit: lit,
             })
         ));
+
+        fn description() -> Option<&'static str> {
+            Some("literal")
+        }
     }
 
     #[cfg(feature = "full")]
@@ -1397,6 +1401,10 @@
                 mac: mac,
             })
         ));
+
+        fn description() -> Option<&'static str> {
+            Some("macro invocation expression")
+        }
     }
 
     #[cfg(feature = "full")]
@@ -1409,6 +1417,10 @@
                 group_token: e.0,
             })
         ));
+
+        fn description() -> Option<&'static str> {
+            Some("expression surrounded by invisible delimiters")
+        }
     }
 
     #[cfg(feature = "full")]
@@ -1421,6 +1433,10 @@
                 expr: Box::new(e.1),
             })
         ));
+
+        fn description() -> Option<&'static str> {
+            Some("parenthesized expression")
+        }
     }
 
     #[cfg(feature = "full")]
@@ -1435,7 +1451,7 @@
         ));
 
         fn description() -> Option<&'static str> {
-            Some("array")
+            Some("array expression")
         }
     }
 
@@ -1479,6 +1495,10 @@
     impl Synom for GenericMethodArgument {
         // TODO parse const generics as well
         named!(parse -> Self, map!(ty_no_eq_after, GenericMethodArgument::Type));
+
+        fn description() -> Option<&'static str> {
+            Some("generic method argument")
+        }
     }
 
     #[cfg(feature = "full")]
@@ -1798,6 +1818,10 @@
                 label: label,
             })
         ));
+
+        fn description() -> Option<&'static str> {
+            Some("`while let` expression")
+        }
     }
 
     #[cfg(feature = "full")]
diff --git a/src/token.rs b/src/token.rs
index 706a3f1..8609fbb 100644
--- a/src/token.rs
+++ b/src/token.rs
@@ -217,6 +217,10 @@
             fn parse(tokens: $crate::buffer::Cursor) -> $crate::synom::PResult<$name> {
                 parsing::keyword($s, tokens, $name)
             }
+
+            fn description() -> Option<&'static str> {
+                Some(concat!("`", $s, "`"))
+            }
         }
     }
 }
diff --git a/src/ty.rs b/src/ty.rs
index f567afa..9538260 100644
--- a/src/ty.rs
+++ b/src/ty.rs
@@ -384,10 +384,18 @@
 
     impl Synom for TypeMacro {
         named!(parse -> Self, map!(syn!(Macro), |mac| TypeMacro { mac: mac }));
+
+        fn description() -> Option<&'static str> {
+            Some("macro invocation")
+        }
     }
 
     impl Synom for TypePath {
         named!(parse -> Self, call!(Self::parse, false));
+
+        fn description() -> Option<&'static str> {
+            Some("type path")
+        }
     }
 
     impl TypePath {
@@ -480,10 +488,18 @@
                 elem: Box::new(data.1),
             })
         ));
+
+        fn description() -> Option<&'static str> {
+            Some("type surrounded by invisible delimiters")
+        }
     }
 
     impl Synom for TypeParen {
         named!(parse -> Self, call!(Self::parse, false));
+
+        fn description() -> Option<&'static str> {
+            Some("parenthesized type")
+        }
     }
 
     impl TypeParen {
@@ -540,7 +556,7 @@
         ));
 
         fn description() -> Option<&'static str> {
-            Some("ABI qualifier")
+            Some("`extern` ABI qualifier")
         }
     }
 }