diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 1866122454c70..a3d3c97fad8ee 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -21,7 +21,6 @@ use rustc::session::Session;
 use syntax::ast::*;
 use syntax::attr;
 use syntax::codemap::Spanned;
-use syntax::parse::token;
 use syntax::symbol::keywords;
 use syntax::visit::{self, Visitor};
 use syntax_pos::Span;
@@ -40,14 +39,15 @@ impl<'a> AstValidator<'a> {
         let valid_names = [keywords::UnderscoreLifetime.name(),
                            keywords::StaticLifetime.name(),
                            keywords::Invalid.name()];
-        if !valid_names.contains(&ident.name) &&
-            token::is_reserved_ident(ident.without_first_quote()) {
+        if !valid_names.contains(&ident.name)
+           && ident.without_first_quote().is_reserved()
+            {
             self.err_handler().span_err(ident.span, "lifetimes cannot use keyword names");
         }
     }
 
     fn check_label(&self, ident: Ident) {
-        if token::is_reserved_ident(ident.without_first_quote()) {
+        if ident.without_first_quote().is_reserved() {
             self.err_handler()
                 .span_err(ident.span, &format!("invalid label name `{}`", ident.name));
         }
diff --git a/src/libsyntax/edition.rs b/src/libsyntax/edition.rs
index 0a1eafee6d7cb..71745433a0ab9 100644
--- a/src/libsyntax/edition.rs
+++ b/src/libsyntax/edition.rs
@@ -10,7 +10,7 @@
 
 use std::fmt;
 use std::str::FromStr;
-use symbol::{self, Symbol};
+use symbol::Symbol;
 
 /// The edition of the compiler (RFC 2052)
 #[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq, Debug)]
@@ -59,8 +59,8 @@ impl Edition {
 
     pub fn is_future_edition_keyword(&self, sym: Symbol) -> bool {
         match *self {
-            Edition::Edition2015 => symbol::is_future_edition_keyword_2015(sym),
-            Edition::Edition2018 => symbol::is_future_edition_keyword_2018(sym),
+            Edition::Edition2015 => sym.is_future_edition_keyword_2015(),
+            Edition::Edition2018 => sym.is_future_edition_keyword_2018(),
         }
     }
 
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 4c5686587f7b6..7196f48584b04 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -145,14 +145,7 @@ pub fn is_path_segment_keyword(id: ast::Ident) -> bool {
 // How was it written originally? Did it use the raw form? Let's try to guess.
 pub fn is_raw_guess(ident: ast::Ident) -> bool {
     ident.name != keywords::Invalid.name() &&
-    is_reserved_ident(ident) && !is_path_segment_keyword(ident)
-}
-
-pub use syntax_pos::symbol::{is_special_ident, is_used_keyword, is_unused_keyword};
-
-/// Returns `true` if the token is either a special identifier or a keyword.
-pub fn is_reserved_ident(id: ast::Ident) -> bool {
-    is_special_ident(id) || is_used_keyword(id) || is_unused_keyword(id)
+    ident.is_reserved() && !is_path_segment_keyword(ident)
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug)]
@@ -399,7 +392,7 @@ impl Token {
     // unnamed method parameters, crate root module, error recovery etc.
     pub fn is_special_ident(&self) -> bool {
         match self.ident() {
-            Some((id, false)) => is_special_ident(id),
+            Some((id, false)) => id.is_special(),
             _ => false,
         }
     }
@@ -407,7 +400,7 @@ impl Token {
     /// Returns `true` if the token is a keyword used in the language.
     pub fn is_used_keyword(&self) -> bool {
         match self.ident() {
-            Some((id, false)) => is_used_keyword(id),
+            Some((id, false)) => id.is_used_keyword(),
             _ => false,
         }
     }
@@ -415,7 +408,7 @@ impl Token {
     /// Returns `true` if the token is a keyword reserved for possible future use.
     pub fn is_unused_keyword(&self) -> bool {
         match self.ident() {
-            Some((id, false)) => is_unused_keyword(id),
+            Some((id, false)) => id.is_unused_keyword(),
             _ => false,
         }
     }
@@ -423,7 +416,7 @@ impl Token {
     /// Returns `true` if the token is either a special identifier or a keyword.
     pub fn is_reserved_ident(&self) -> bool {
         match self.ident() {
-            Some((id, false)) => is_reserved_ident(id),
+            Some((id, false)) => id.is_reserved(),
             _ => false,
         }
     }
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 8153ce7ed7af4..ce219cbb53028 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -278,8 +278,8 @@ macro_rules! declare_keywords {(
 // NB: leaving holes in the ident table is bad! a different ident will get
 // interned with the id from the hole, but it will be between the min and max
 // of the reserved words, and thus tagged as "reserved".
-// After modifying this list adjust `is_special_ident`, `is_used_keyword`/`is_unused_keyword`,
-// this should be rarely necessary though if the keywords are kept in alphabetic order.
+// After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`
+// velow
 declare_keywords! {
     // Special reserved identifiers used internally for elided lifetimes,
     // unnamed method parameters, crate root module, error recovery etc.
@@ -363,28 +363,49 @@ declare_keywords! {
     (63, Union,              "union")
 }
 
-// Returns true for reserved identifiers used internally for elided lifetimes,
-// unnamed method parameters, crate root module, error recovery etc.
-pub fn is_special_ident(id: Ident) -> bool {
-    id.name <= self::keywords::Underscore.name()
-}
+impl Ident {
+    // Returns true for reserved identifiers used internally for elided lifetimes,
+    // unnamed method parameters, crate root module, error recovery etc.
+    #[inline]
+    pub fn is_special(self) -> bool {
+        self.name <= self::keywords::Underscore.name()
+    }
 
-/// Returns `true` if the token is a keyword used in the language.
-pub fn is_used_keyword(id: Ident) -> bool {
-    id.name >= self::keywords::As.name() && id.name <= self::keywords::While.name()
-}
+    /// Returns `true` if the token is a keyword used in the language, for
+    /// at least one edition.
+    ///
+    /// Keywords from future editions will be lexed as if they were raw identifiers
+    /// so they will not reach this step.
+    #[inline]
+    pub fn is_used_keyword(self) -> bool {
+        self.name >= self::keywords::As.name() && self.name <= self::keywords::While.name()
+    }
+
+    /// Returns `true` if the token is a keyword reserved for possible future use, for
+    /// at least one edition.
+    #[inline]
+    pub fn is_unused_keyword(self) -> bool {
+        self.name >= self::keywords::Abstract.name() && self.name <= self::keywords::Async.name()
+    }
 
-/// Returns `true` if the token is a keyword reserved for possible future use.
-pub fn is_unused_keyword(id: Ident) -> bool {
-    id.name >= self::keywords::Abstract.name() && id.name <= self::keywords::Async.name()
-}
 
-pub fn is_future_edition_keyword_2015(sym: Symbol) -> bool {
-    sym == self::keywords::Async.name()
+    /// Returns `true` if the token is either a special identifier or a keyword.
+    #[inline]
+    pub fn is_reserved(self) -> bool {
+        self.is_special() || self.is_used_keyword() || self.is_unused_keyword()
+    }
 }
 
-pub fn is_future_edition_keyword_2018(_: Symbol) -> bool {
-    false
+impl Symbol {
+    #[inline]
+    pub fn is_future_edition_keyword_2015(self) -> bool {
+        self == self::keywords::Async.name()
+    }
+
+    #[inline]
+    pub fn is_future_edition_keyword_2018(self) -> bool {
+        false
+    }
 }
 
 // If an interner exists, return it. Otherwise, prepare a fresh one.