More useful literal api
diff --git a/tests/test_derive_input.rs b/tests/test_derive_input.rs
index 4055b7f..ae7bcfc 100644
--- a/tests/test_derive_input.rs
+++ b/tests/test_derive_input.rs
@@ -188,7 +188,7 @@
                 path: "doc".into(),
                 tts: TokenStream::from_iter(vec![
                     op('='),
-                    lit(Literal::doccomment(
+                    lit(Literal::string(
                         "/// See the std::result module documentation for details.",
                     )),
                 ]),
@@ -276,10 +276,7 @@
                         Default::default(),
                         Expr::Lit(ExprLit {
                             attrs: Vec::new(),
-                            lit: Lit {
-                                value: LitKind::Other(Literal::isize(0)),
-                                span: Default::default(),
-                            },
+                            lit: Lit::Int(LitInt::new(0, IntSuffix::Isize, Default::default())),
                         }),
                     )),
                 },
@@ -297,17 +294,11 @@
                                 elems: punctuated![
                                     Expr::Lit(ExprLit {
                                         attrs: Vec::new(),
-                                        lit: Lit {
-                                            value: LitKind::Other(Literal::integer(0)),
-                                            span: Default::default(),
-                                        },
+                                        lit: Lit::Int(LitInt::new(0, IntSuffix::None, Default::default())),
                                     }),
                                     Expr::Lit(ExprLit {
                                         attrs: Vec::new(),
-                                        lit: Lit {
-                                            value: LitKind::Other(Literal::string("data")),
-                                            span: Default::default(),
-                                        },
+                                        lit: Lit::Str(LitStr::new("data", Default::default())),
                                     }),
                                 ],
                             })),
@@ -333,12 +324,10 @@
         MetaNameValue {
             ident: "doc".into(),
             eq_token: Default::default(),
-            lit: Lit {
-                value: LitKind::Other(Literal::doccomment(
-                    "/// See the std::result module documentation for details.",
-                )),
-                span: Default::default(),
-            },
+            lit: Lit::Str(LitStr::new(
+                "/// See the std::result module documentation for details.",
+                Default::default(),
+            )),
         }.into(),
         MetaItem::Term("must_use".into()),
     ];
diff --git a/tests/test_grouping.rs b/tests/test_grouping.rs
index 7d031d2..cbf70eb 100644
--- a/tests/test_grouping.rs
+++ b/tests/test_grouping.rs
@@ -3,7 +3,7 @@
 
 #[macro_use]
 extern crate syn;
-use syn::{BinOp, Expr, ExprBinary, ExprGroup, ExprLit, Lit, LitKind};
+use syn::{BinOp, Expr, ExprBinary, ExprGroup, ExprLit, Lit};
 use syn::token::Group;
 
 extern crate proc_macro2;
@@ -28,10 +28,7 @@
 fn lit<T: Into<Literal>>(t: T) -> Expr {
     Expr::Lit(ExprLit {
         attrs: Vec::new(),
-        lit: Lit {
-            value: LitKind::Other(t.into()),
-            span: Span::default(),
-        },
+        lit: Lit::new(t.into(), Span::default()),
     })
 }
 
diff --git a/tests/test_lit.rs b/tests/test_lit.rs
new file mode 100644
index 0000000..bd8a980
--- /dev/null
+++ b/tests/test_lit.rs
@@ -0,0 +1,178 @@
+extern crate syn;
+extern crate quote;
+extern crate proc_macro2;
+
+use syn::{Lit, IntSuffix, FloatSuffix};
+use quote::ToTokens;
+use proc_macro2::{TokenStream, TokenNode, Span};
+use std::str::FromStr;
+
+fn lit(s: &str) -> Lit {
+    match TokenStream::from_str(s).unwrap().into_iter().next().unwrap().kind {
+        TokenNode::Literal(lit) => Lit::new(lit, Span::default()),
+        _ => panic!(),
+    }
+}
+
+#[test]
+fn strings() {
+    fn test_string(s: &str, value: &str) {
+        match lit(s) {
+            Lit::Str(lit) => {
+                assert_eq!(lit.value(), value);
+                let again = lit.into_tokens().to_string();
+                if again != s {
+                    test_string(&again, value);
+                }
+            }
+            wrong => panic!("{:?}", wrong),
+        }
+    }
+
+    test_string("\"a\"", "a");
+    test_string("\"\\n\"", "\n");
+    test_string("\"\\r\"", "\r");
+    test_string("\"\\t\"", "\t");
+    test_string("\"🐕\"", "🐕"); // NOTE: This is an emoji
+    test_string("\"\\\"\"", "\"");
+    test_string("\"'\"", "'");
+    test_string("\"\"", "");
+    test_string("\"\\u{1F415}\"", "\u{1F415}");
+    test_string("\"contains\nnewlines\\\nescaped newlines\"",
+                "contains\nnewlinesescaped newlines");
+    test_string("r\"raw\nstring\\\nhere\"", "raw\nstring\\\nhere");
+}
+
+#[test]
+fn byte_strings() {
+    fn test_byte_string(s: &str, value: &[u8]) {
+        match lit(s) {
+            Lit::ByteStr(lit) => {
+                assert_eq!(lit.value(), value);
+                let again = lit.into_tokens().to_string();
+                if again != s {
+                    test_byte_string(&again, value);
+                }
+            }
+            wrong => panic!("{:?}", wrong),
+        }
+    }
+
+    test_byte_string("b\"a\"", b"a");
+    test_byte_string("b\"\\n\"", b"\n");
+    test_byte_string("b\"\\r\"", b"\r");
+    test_byte_string("b\"\\t\"", b"\t");
+    test_byte_string("b\"\\\"\"", b"\"");
+    test_byte_string("b\"'\"", b"'");
+    test_byte_string("b\"\"", b"");
+    test_byte_string("b\"contains\nnewlines\\\nescaped newlines\"",
+                b"contains\nnewlinesescaped newlines");
+    test_byte_string("br\"raw\nstring\\\nhere\"", b"raw\nstring\\\nhere");
+}
+
+#[test]
+fn bytes() {
+    fn test_byte(s: &str, value: u8) {
+        match lit(s) {
+            Lit::Byte(lit) => {
+                assert_eq!(lit.value(), value);
+                let again = lit.into_tokens().to_string();
+                assert_eq!(again, s);
+            }
+            wrong => panic!("{:?}", wrong),
+        }
+    }
+
+    test_byte("b'a'", b'a');
+    test_byte("b'\\n'", b'\n');
+    test_byte("b'\\r'", b'\r');
+    test_byte("b'\\t'", b'\t');
+    test_byte("b'\\''", b'\'');
+    test_byte("b'\"'", b'"');
+}
+
+#[test]
+fn chars() {
+    fn test_char(s: &str, value: char) {
+        match lit(s) {
+            Lit::Char(lit) => {
+                assert_eq!(lit.value(), value);
+                let again = lit.into_tokens().to_string();
+                if again != s {
+                    test_char(&again, value);
+                }
+            }
+            wrong => panic!("{:?}", wrong),
+        }
+    }
+
+    test_char("'a'", 'a');
+    test_char("'\\n'", '\n');
+    test_char("'\\r'", '\r');
+    test_char("'\\t'", '\t');
+    test_char("'🐕'", '🐕'); // NOTE: This is an emoji
+    test_char("'\\''", '\'');
+    test_char("'\"'", '"');
+    test_char("'\\u{1F415}'", '\u{1F415}');
+}
+
+#[test]
+fn ints() {
+    fn test_int(s: &str, value: u64, suffix: IntSuffix) {
+        match lit(s) {
+            Lit::Int(lit) => {
+                assert_eq!(lit.value(), value);
+                assert_eq!(lit.suffix(), suffix);
+                let again = lit.into_tokens().to_string();
+                if again != s {
+                    test_int(&again, value, suffix);
+                }
+            }
+            wrong => panic!("{:?}", wrong),
+        }
+    }
+
+    use syn::IntSuffix::*;
+    test_int("5", 5, None);
+    test_int("5u32", 5, U32);
+    test_int("5_0", 50, None);
+    test_int("5_____0_____", 50, None);
+    test_int("0x7f", 127, None);
+    test_int("0x7F", 127, None);
+    test_int("0b1001", 9, None);
+    test_int("0o73", 59, None);
+    test_int("0x7Fu8", 127, U8);
+    test_int("0b1001i8", 9, I8);
+    test_int("0o73u32", 59, U32);
+    test_int("0x__7___f_", 127, None);
+    test_int("0x__7___F_", 127, None);
+    test_int("0b_1_0__01", 9, None);
+    test_int("0o_7__3", 59, None);
+    test_int("0x_7F__u8", 127, U8);
+    test_int("0b__10__0_1i8", 9, I8);
+    test_int("0o__7__________________3u32", 59, U32);
+}
+
+#[test]
+fn floats() {
+    fn test_float(s: &str, value: f64, suffix: FloatSuffix) {
+        match lit(s) {
+            Lit::Float(lit) => {
+                assert_eq!(lit.value(), value);
+                assert_eq!(lit.suffix(), suffix);
+                let again = lit.into_tokens().to_string();
+                if again != s {
+                    test_float(&again, value, suffix);
+                }
+            }
+            wrong => panic!("{:?}", wrong),
+        }
+    }
+
+    use syn::FloatSuffix::*;
+    test_float("5.5", 5.5, None);
+    test_float("5.5E12", 5.5e12, None);
+    test_float("5.5e12", 5.5e12, None);
+    test_float("1.0__3e-12", 1.03e-12, None);
+    test_float("1.03e+12", 1.03e12, None);
+}
diff --git a/tests/test_meta_item.rs b/tests/test_meta_item.rs
index 859507d..e9ae846 100644
--- a/tests/test_meta_item.rs
+++ b/tests/test_meta_item.rs
@@ -11,10 +11,7 @@
 mod macros;
 
 fn lit<T: Into<Literal>>(t: T) -> Lit {
-    Lit {
-        value: LitKind::Other(t.into()),
-        span: Default::default(),
-    }
+    Lit::new(t.into(), Default::default())
 }
 
 #[test]