Newtype ident
diff --git a/src/attr.rs b/src/attr.rs
index d2d78ed..7d7557c 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -50,7 +50,7 @@
             content: take_until_s!("\n") >>
             (Attribute {
                 value: MetaItem::NameValue(
-                    "doc".to_string(),
+                    "doc".into(),
                     format!("///{}{}", space, content),
                 ),
                 is_sugared_doc: true,
diff --git a/src/common.rs b/src/common.rs
index a5173d7..9c5de75 100644
--- a/src/common.rs
+++ b/src/common.rs
@@ -1,4 +1,40 @@
-pub type Ident = String;
+use std::fmt::{self, Display};
+use std::ops::Deref;
+
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct Ident(String);
+
+impl Ident {
+    pub fn new<T: Into<Ident>>(t: T) -> Self {
+        t.into()
+    }
+}
+
+impl<'a> From<&'a str> for Ident {
+    fn from(s: &str) -> Self {
+        Ident(s.to_owned())
+    }
+}
+
+impl From<String> for Ident {
+    fn from(s: String) -> Self {
+        Ident(s)
+    }
+}
+
+impl Deref for Ident {
+    type Target = str;
+
+    fn deref(&self) -> &str {
+        &self.0
+    }
+}
+
+impl Display for Ident {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+        self.0.fmt(formatter)
+    }
+}
 
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub enum Visibility {
@@ -16,7 +52,7 @@
 
     named!(pub word<&str, Ident>, preceded!(
         opt!(call!(::nom::multispace)),
-        map!(take_while1_s!(ident_ch), String::from)
+        map!(take_while1_s!(ident_ch), Into::into)
     ));
 
     named!(pub visibility<&str, Visibility>, preceded!(
diff --git a/src/generics.rs b/src/generics.rs
index a2a66a5..9b60510 100644
--- a/src/generics.rs
+++ b/src/generics.rs
@@ -102,7 +102,7 @@
     named!(pub lifetime<&str, Lifetime>, preceded!(
         punct!("'"),
         map!(word, |ident| Lifetime {
-            ident: format!("'{}", ident),
+            ident: format!("'{}", ident).into(),
         })
     ));
 
diff --git a/tests/test.rs b/tests/test.rs
index 65b8cc5..290a300 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -4,7 +4,7 @@
 fn simple_ty(ident: &str) -> Ty {
     Ty::Path(None, Path {
         global: false,
-        segments: vec![PathSegment::ident(ident.to_string())],
+        segments: vec![PathSegment::ident(ident.into())],
     })
 }
 
@@ -19,13 +19,13 @@
     ";
 
     let expected = Item {
-        ident: "Item".to_string(),
+        ident: "Item".into(),
         vis: Visibility::Public,
         attrs: vec![
             Attribute {
-                value: MetaItem::List("derive".to_string(), vec![
-                    MetaItem::Word("Debug".to_string()),
-                    MetaItem::Word("Clone".to_string()),
+                value: MetaItem::List("derive".into(), vec![
+                    MetaItem::Word("Debug".into()),
+                    MetaItem::Word("Clone".into()),
                 ]),
                 is_sugared_doc: false,
             },
@@ -33,20 +33,20 @@
         generics: Generics::default(),
         body: Body::Struct(Style::Struct, vec![
             Field {
-                ident: Some("ident".to_string()),
+                ident: Some("ident".into()),
                 vis: Visibility::Public,
                 attrs: Vec::new(),
                 ty: simple_ty("Ident"),
             },
             Field {
-                ident: Some("attrs".to_string()),
+                ident: Some("attrs".into()),
                 vis: Visibility::Public,
                 attrs: Vec::new(),
                 ty: Ty::Path(None, Path {
                     global: false,
                     segments: vec![
                         PathSegment {
-                            ident: "Vec".to_string(),
+                            ident: "Vec".into(),
                             parameters: PathParameters::AngleBracketed(
                                 AngleBracketedParameterData {
                                     lifetimes: Vec::new(),
@@ -76,18 +76,18 @@
     ";
 
     let expected = Item {
-        ident: "Result".to_string(),
+        ident: "Result".into(),
         vis: Visibility::Public,
         attrs: vec![
             Attribute {
                 value: MetaItem::NameValue(
-                    "doc".to_string(),
-                    "/// See the std::result module documentation for details.".to_string(),
+                    "doc".into(),
+                    "/// See the std::result module documentation for details.".into(),
                 ),
                 is_sugared_doc: true,
             },
             Attribute {
-                value: MetaItem::Word("must_use".to_string()),
+                value: MetaItem::Word("must_use".into()),
                 is_sugared_doc: false,
             },
         ],
@@ -95,12 +95,12 @@
             lifetimes: Vec::new(),
             ty_params: vec![
                 TyParam {
-                    ident: "T".to_string(),
+                    ident: "T".into(),
                     bounds: Vec::new(),
                     default: None,
                 },
                 TyParam {
-                    ident: "E".to_string(),
+                    ident: "E".into(),
                     bounds: Vec::new(),
                     default: None,
                 },
@@ -109,7 +109,7 @@
         },
         body: Body::Enum(vec![
             Variant {
-                ident: "Ok".to_string(),
+                ident: "Ok".into(),
                 attrs: Vec::new(),
                 style: Style::Tuple,
                 fields: vec![
@@ -122,7 +122,7 @@
                 ],
             },
             Variant {
-                ident: "Err".to_string(),
+                ident: "Err".into(),
                 attrs: Vec::new(),
                 style: Style::Tuple,
                 fields: vec![