about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-07-09 05:11:38 +0000
committerbors <bors@rust-lang.org>2014-07-09 05:11:38 +0000
commit5716abe3f019ab7d9c8cdde9879332040191cf88 (patch)
treeb493f77b0890971676a0eecb880a79ee2f20714a
parentec3efa8055069e285a4bfcba892f8463ce925d68 (diff)
parent4c312b6d0ddc4de7e00176d5099dad299473aabd (diff)
downloadrust-5716abe3f019ab7d9c8cdde9879332040191cf88.tar.gz
rust-5716abe3f019ab7d9c8cdde9879332040191cf88.zip
auto merge of #15537 : jbclements/rust/hygiene-for-methods, r=pcwalton
This patch adds hygiene for methods. This one was more difficult than the others, due principally to issues surrounding `self`. Specifically, there were a whole bunch of places in the code that assumed that a `self` identifier could be discarded and then made up again later, causing the discard of contexts and hygiene breakage.
-rw-r--r--src/libcollections/treemap.rs12
-rw-r--r--src/libcore/num/mod.rs134
-rw-r--r--src/librustc/metadata/decoder.rs7
-rw-r--r--src/librustc/metadata/encoder.rs8
-rw-r--r--src/librustc/middle/resolve.rs18
-rw-r--r--src/librustc/middle/trans/meth.rs15
-rw-r--r--src/librustc/middle/typeck/astconv.rs6
-rw-r--r--src/librustc/middle/typeck/check/method.rs12
-rw-r--r--src/librustc/middle/typeck/infer/error_reporting.rs6
-rw-r--r--src/librustc/plugin/registry.rs4
-rw-r--r--src/librustdoc/clean/mod.rs6
-rw-r--r--src/libsyntax/ast.rs16
-rw-r--r--src/libsyntax/ext/base.rs11
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs4
-rw-r--r--src/libsyntax/ext/deriving/generic/ty.rs10
-rw-r--r--src/libsyntax/ext/expand.rs152
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs3
-rw-r--r--src/libsyntax/fold.rs6
-rw-r--r--src/libsyntax/parse/parser.rs474
-rw-r--r--src/libsyntax/parse/token.rs23
-rw-r--r--src/libsyntax/print/pprust.rs6
-rw-r--r--src/libsyntax/visit.rs4
-rw-r--r--src/test/run-pass/issue-7911.rs8
23 files changed, 540 insertions, 405 deletions
diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs
index becceffe6d0..c1d782991b4 100644
--- a/src/libcollections/treemap.rs
+++ b/src/libcollections/treemap.rs
@@ -185,7 +185,7 @@ impl<K: Ord, V> TreeMap<K, V> {
 
 macro_rules! bound_setup {
     // initialiser of the iterator to manipulate
-    ($iter:expr,
+    ($iter:expr, $k:expr,
      // whether we are looking for the lower or upper bound.
      $is_lower_bound:expr) => {
         {
@@ -193,7 +193,7 @@ macro_rules! bound_setup {
             loop {
                 if !iter.node.is_null() {
                     let node_k = unsafe {&(*iter.node).key};
-                    match k.cmp(node_k) {
+                    match $k.cmp(node_k) {
                         Less => iter.traverse_left(),
                         Greater => iter.traverse_right(),
                         Equal => {
@@ -230,13 +230,13 @@ impl<K: Ord, V> TreeMap<K, V> {
     /// Return a lazy iterator to the first key-value pair whose key is not less than `k`
     /// If all keys in map are less than `k` an empty iterator is returned.
     pub fn lower_bound<'a>(&'a self, k: &K) -> Entries<'a, K, V> {
-        bound_setup!(self.iter_for_traversal(), true)
+        bound_setup!(self.iter_for_traversal(), k, true)
     }
 
     /// Return a lazy iterator to the first key-value pair whose key is greater than `k`
     /// If all keys in map are not greater than `k` an empty iterator is returned.
     pub fn upper_bound<'a>(&'a self, k: &K) -> Entries<'a, K, V> {
-        bound_setup!(self.iter_for_traversal(), false)
+        bound_setup!(self.iter_for_traversal(), k, false)
     }
 
     /// Get a lazy iterator that should be initialized using
@@ -256,7 +256,7 @@ impl<K: Ord, V> TreeMap<K, V> {
     /// If all keys in map are less than `k` an empty iterator is
     /// returned.
     pub fn mut_lower_bound<'a>(&'a mut self, k: &K) -> MutEntries<'a, K, V> {
-        bound_setup!(self.mut_iter_for_traversal(), true)
+        bound_setup!(self.mut_iter_for_traversal(), k, true)
     }
 
     /// Return a lazy iterator to the first key-value pair (with the
@@ -265,7 +265,7 @@ impl<K: Ord, V> TreeMap<K, V> {
     /// If all keys in map are not greater than `k` an empty iterator
     /// is returned.
     pub fn mut_upper_bound<'a>(&'a mut self, k: &K) -> MutEntries<'a, K, V> {
-        bound_setup!(self.mut_iter_for_traversal(), false)
+        bound_setup!(self.mut_iter_for_traversal(), k, false)
     }
 }
 
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 1fae362471d..3230873883e 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -769,16 +769,16 @@ pub trait ToPrimitive {
 }
 
 macro_rules! impl_to_primitive_int_to_int(
-    ($SrcT:ty, $DstT:ty) => (
+    ($SrcT:ty, $DstT:ty, $slf:expr) => (
         {
             if size_of::<$SrcT>() <= size_of::<$DstT>() {
-                Some(*self as $DstT)
+                Some($slf as $DstT)
             } else {
-                let n = *self as i64;
+                let n = $slf as i64;
                 let min_value: $DstT = Bounded::min_value();
                 let max_value: $DstT = Bounded::max_value();
                 if min_value as i64 <= n && n <= max_value as i64 {
-                    Some(*self as $DstT)
+                    Some($slf as $DstT)
                 } else {
                     None
                 }
@@ -788,12 +788,12 @@ macro_rules! impl_to_primitive_int_to_int(
 )
 
 macro_rules! impl_to_primitive_int_to_uint(
-    ($SrcT:ty, $DstT:ty) => (
+    ($SrcT:ty, $DstT:ty, $slf:expr) => (
         {
             let zero: $SrcT = Zero::zero();
             let max_value: $DstT = Bounded::max_value();
-            if zero <= *self && *self as u64 <= max_value as u64 {
-                Some(*self as $DstT)
+            if zero <= $slf && $slf as u64 <= max_value as u64 {
+                Some($slf as $DstT)
             } else {
                 None
             }
@@ -805,26 +805,26 @@ macro_rules! impl_to_primitive_int(
     ($T:ty) => (
         impl ToPrimitive for $T {
             #[inline]
-            fn to_int(&self) -> Option<int> { impl_to_primitive_int_to_int!($T, int) }
+            fn to_int(&self) -> Option<int> { impl_to_primitive_int_to_int!($T, int, *self) }
             #[inline]
-            fn to_i8(&self) -> Option<i8> { impl_to_primitive_int_to_int!($T, i8) }
+            fn to_i8(&self) -> Option<i8> { impl_to_primitive_int_to_int!($T, i8, *self) }
             #[inline]
-            fn to_i16(&self) -> Option<i16> { impl_to_primitive_int_to_int!($T, i16) }
+            fn to_i16(&self) -> Option<i16> { impl_to_primitive_int_to_int!($T, i16, *self) }
             #[inline]
-            fn to_i32(&self) -> Option<i32> { impl_to_primitive_int_to_int!($T, i32) }
+            fn to_i32(&self) -> Option<i32> { impl_to_primitive_int_to_int!($T, i32, *self) }
             #[inline]
-            fn to_i64(&self) -> Option<i64> { impl_to_primitive_int_to_int!($T, i64) }
+            fn to_i64(&self) -> Option<i64> { impl_to_primitive_int_to_int!($T, i64, *self) }
 
             #[inline]
-            fn to_uint(&self) -> Option<uint> { impl_to_primitive_int_to_uint!($T, uint) }
+            fn to_uint(&self) -> Option<uint> { impl_to_primitive_int_to_uint!($T, uint, *self) }
             #[inline]
-            fn to_u8(&self) -> Option<u8> { impl_to_primitive_int_to_uint!($T, u8) }
+            fn to_u8(&self) -> Option<u8> { impl_to_primitive_int_to_uint!($T, u8, *self) }
             #[inline]
-            fn to_u16(&self) -> Option<u16> { impl_to_primitive_int_to_uint!($T, u16) }
+            fn to_u16(&self) -> Option<u16> { impl_to_primitive_int_to_uint!($T, u16, *self) }
             #[inline]
-            fn to_u32(&self) -> Option<u32> { impl_to_primitive_int_to_uint!($T, u32) }
+            fn to_u32(&self) -> Option<u32> { impl_to_primitive_int_to_uint!($T, u32, *self) }
             #[inline]
-            fn to_u64(&self) -> Option<u64> { impl_to_primitive_int_to_uint!($T, u64) }
+            fn to_u64(&self) -> Option<u64> { impl_to_primitive_int_to_uint!($T, u64, *self) }
 
             #[inline]
             fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
@@ -841,11 +841,11 @@ impl_to_primitive_int!(i32)
 impl_to_primitive_int!(i64)
 
 macro_rules! impl_to_primitive_uint_to_int(
-    ($DstT:ty) => (
+    ($DstT:ty, $slf:expr) => (
         {
             let max_value: $DstT = Bounded::max_value();
-            if *self as u64 <= max_value as u64 {
-                Some(*self as $DstT)
+            if $slf as u64 <= max_value as u64 {
+                Some($slf as $DstT)
             } else {
                 None
             }
@@ -854,15 +854,15 @@ macro_rules! impl_to_primitive_uint_to_int(
 )
 
 macro_rules! impl_to_primitive_uint_to_uint(
-    ($SrcT:ty, $DstT:ty) => (
+    ($SrcT:ty, $DstT:ty, $slf:expr) => (
         {
             if size_of::<$SrcT>() <= size_of::<$DstT>() {
-                Some(*self as $DstT)
+                Some($slf as $DstT)
             } else {
                 let zero: $SrcT = Zero::zero();
                 let max_value: $DstT = Bounded::max_value();
-                if zero <= *self && *self as u64 <= max_value as u64 {
-                    Some(*self as $DstT)
+                if zero <= $slf && $slf as u64 <= max_value as u64 {
+                    Some($slf as $DstT)
                 } else {
                     None
                 }
@@ -875,26 +875,26 @@ macro_rules! impl_to_primitive_uint(
     ($T:ty) => (
         impl ToPrimitive for $T {
             #[inline]
-            fn to_int(&self) -> Option<int> { impl_to_primitive_uint_to_int!(int) }
+            fn to_int(&self) -> Option<int> { impl_to_primitive_uint_to_int!(int, *self) }
             #[inline]
-            fn to_i8(&self) -> Option<i8> { impl_to_primitive_uint_to_int!(i8) }
+            fn to_i8(&self) -> Option<i8> { impl_to_primitive_uint_to_int!(i8, *self) }
             #[inline]
-            fn to_i16(&self) -> Option<i16> { impl_to_primitive_uint_to_int!(i16) }
+            fn to_i16(&self) -> Option<i16> { impl_to_primitive_uint_to_int!(i16, *self) }
             #[inline]
-            fn to_i32(&self) -> Option<i32> { impl_to_primitive_uint_to_int!(i32) }
+            fn to_i32(&self) -> Option<i32> { impl_to_primitive_uint_to_int!(i32, *self) }
             #[inline]
-            fn to_i64(&self) -> Option<i64> { impl_to_primitive_uint_to_int!(i64) }
+            fn to_i64(&self) -> Option<i64> { impl_to_primitive_uint_to_int!(i64, *self) }
 
             #[inline]
-            fn to_uint(&self) -> Option<uint> { impl_to_primitive_uint_to_uint!($T, uint) }
+            fn to_uint(&self) -> Option<uint> { impl_to_primitive_uint_to_uint!($T, uint, *self) }
             #[inline]
-            fn to_u8(&self) -> Option<u8> { impl_to_primitive_uint_to_uint!($T, u8) }
+            fn to_u8(&self) -> Option<u8> { impl_to_primitive_uint_to_uint!($T, u8, *self) }
             #[inline]
-            fn to_u16(&self) -> Option<u16> { impl_to_primitive_uint_to_uint!($T, u16) }
+            fn to_u16(&self) -> Option<u16> { impl_to_primitive_uint_to_uint!($T, u16, *self) }
             #[inline]
-            fn to_u32(&self) -> Option<u32> { impl_to_primitive_uint_to_uint!($T, u32) }
+            fn to_u32(&self) -> Option<u32> { impl_to_primitive_uint_to_uint!($T, u32, *self) }
             #[inline]
-            fn to_u64(&self) -> Option<u64> { impl_to_primitive_uint_to_uint!($T, u64) }
+            fn to_u64(&self) -> Option<u64> { impl_to_primitive_uint_to_uint!($T, u64, *self) }
 
             #[inline]
             fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
@@ -911,14 +911,14 @@ impl_to_primitive_uint!(u32)
 impl_to_primitive_uint!(u64)
 
 macro_rules! impl_to_primitive_float_to_float(
-    ($SrcT:ty, $DstT:ty) => (
+    ($SrcT:ty, $DstT:ty, $slf:expr) => (
         if size_of::<$SrcT>() <= size_of::<$DstT>() {
-            Some(*self as $DstT)
+            Some($slf as $DstT)
         } else {
-            let n = *self as f64;
+            let n = $slf as f64;
             let max_value: $SrcT = Bounded::max_value();
             if -max_value as f64 <= n && n <= max_value as f64 {
-                Some(*self as $DstT)
+                Some($slf as $DstT)
             } else {
                 None
             }
@@ -952,9 +952,9 @@ macro_rules! impl_to_primitive_float(
             fn to_u64(&self) -> Option<u64> { Some(*self as u64) }
 
             #[inline]
-            fn to_f32(&self) -> Option<f32> { impl_to_primitive_float_to_float!($T, f32) }
+            fn to_f32(&self) -> Option<f32> { impl_to_primitive_float_to_float!($T, f32, *self) }
             #[inline]
-            fn to_f64(&self) -> Option<f64> { impl_to_primitive_float_to_float!($T, f64) }
+            fn to_f64(&self) -> Option<f64> { impl_to_primitive_float_to_float!($T, f64, *self) }
         }
     )
 )
@@ -1104,38 +1104,38 @@ pub fn from_f64<A: FromPrimitive>(n: f64) -> Option<A> {
 }
 
 macro_rules! impl_from_primitive(
-    ($T:ty, $to_ty:expr) => (
+    ($T:ty, $to_ty:ident) => (
         impl FromPrimitive for $T {
-            #[inline] fn from_int(n: int) -> Option<$T> { $to_ty }
-            #[inline] fn from_i8(n: i8) -> Option<$T> { $to_ty }
-            #[inline] fn from_i16(n: i16) -> Option<$T> { $to_ty }
-            #[inline] fn from_i32(n: i32) -> Option<$T> { $to_ty }
-            #[inline] fn from_i64(n: i64) -> Option<$T> { $to_ty }
-
-            #[inline] fn from_uint(n: uint) -> Option<$T> { $to_ty }
-            #[inline] fn from_u8(n: u8) -> Option<$T> { $to_ty }
-            #[inline] fn from_u16(n: u16) -> Option<$T> { $to_ty }
-            #[inline] fn from_u32(n: u32) -> Option<$T> { $to_ty }
-            #[inline] fn from_u64(n: u64) -> Option<$T> { $to_ty }
-
-            #[inline] fn from_f32(n: f32) -> Option<$T> { $to_ty }
-            #[inline] fn from_f64(n: f64) -> Option<$T> { $to_ty }
+            #[inline] fn from_int(n: int) -> Option<$T> { n.$to_ty() }
+            #[inline] fn from_i8(n: i8) -> Option<$T> { n.$to_ty() }
+            #[inline] fn from_i16(n: i16) -> Option<$T> { n.$to_ty() }
+            #[inline] fn from_i32(n: i32) -> Option<$T> { n.$to_ty() }
+            #[inline] fn from_i64(n: i64) -> Option<$T> { n.$to_ty() }
+
+            #[inline] fn from_uint(n: uint) -> Option<$T> { n.$to_ty() }
+            #[inline] fn from_u8(n: u8) -> Option<$T> { n.$to_ty() }
+            #[inline] fn from_u16(n: u16) -> Option<$T> { n.$to_ty() }
+            #[inline] fn from_u32(n: u32) -> Option<$T> { n.$to_ty() }
+            #[inline] fn from_u64(n: u64) -> Option<$T> { n.$to_ty() }
+
+            #[inline] fn from_f32(n: f32) -> Option<$T> { n.$to_ty() }
+            #[inline] fn from_f64(n: f64) -> Option<$T> { n.$to_ty() }
         }
     )
 )
 
-impl_from_primitive!(int, n.to_int())
-impl_from_primitive!(i8, n.to_i8())
-impl_from_primitive!(i16, n.to_i16())
-impl_from_primitive!(i32, n.to_i32())
-impl_from_primitive!(i64, n.to_i64())
-impl_from_primitive!(uint, n.to_uint())
-impl_from_primitive!(u8, n.to_u8())
-impl_from_primitive!(u16, n.to_u16())
-impl_from_primitive!(u32, n.to_u32())
-impl_from_primitive!(u64, n.to_u64())
-impl_from_primitive!(f32, n.to_f32())
-impl_from_primitive!(f64, n.to_f64())
+impl_from_primitive!(int, to_int)
+impl_from_primitive!(i8, to_i8)
+impl_from_primitive!(i16, to_i16)
+impl_from_primitive!(i32, to_i32)
+impl_from_primitive!(i64, to_i64)
+impl_from_primitive!(uint, to_uint)
+impl_from_primitive!(u8, to_u8)
+impl_from_primitive!(u16, to_u16)
+impl_from_primitive!(u32, to_u32)
+impl_from_primitive!(u64, to_u64)
+impl_from_primitive!(f32, to_f32)
+impl_from_primitive!(f64, to_f64)
 
 /// Cast from one machine scalar to another.
 ///
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 0b9ed37c838..8a2b95ae463 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -739,10 +739,11 @@ fn get_explicit_self(item: ebml::Doc) -> ast::ExplicitSelf_ {
     let explicit_self_kind = string.as_bytes()[0];
     match explicit_self_kind as char {
         's' => ast::SelfStatic,
-        'v' => ast::SelfValue,
-        '~' => ast::SelfUniq,
+        'v' => ast::SelfValue(special_idents::self_),
+        '~' => ast::SelfUniq(special_idents::self_),
         // FIXME(#4846) expl. region
-        '&' => ast::SelfRegion(None, get_mutability(string.as_bytes()[1])),
+        '&' => ast::SelfRegion(None, get_mutability(string.as_bytes()[1]),
+                               special_idents::self_),
         _ => fail!("unknown self type code: `{}`", explicit_self_kind as char)
     }
 }
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 6c544e3809a..fbf0288418a 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -628,10 +628,10 @@ fn encode_explicit_self(ebml_w: &mut Encoder, explicit_self: ast::ExplicitSelf_)
 
     // Encode the base self type.
     match explicit_self {
-        SelfStatic => { ebml_w.writer.write(&[ 's' as u8 ]); }
-        SelfValue  => { ebml_w.writer.write(&[ 'v' as u8 ]); }
-        SelfUniq   => { ebml_w.writer.write(&[ '~' as u8 ]); }
-        SelfRegion(_, m) => {
+        SelfStatic   => { ebml_w.writer.write(&[ 's' as u8 ]); }
+        SelfValue(_) => { ebml_w.writer.write(&[ 'v' as u8 ]); }
+        SelfUniq(_)  => { ebml_w.writer.write(&[ '~' as u8 ]); }
+        SelfRegion(_, m, _) => {
             // FIXME(#4846) encode custom lifetime
             ebml_w.writer.write(&['&' as u8]);
             encode_mutability(ebml_w, m);
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 612b29afd3e..129a5b7c6be 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -25,6 +25,7 @@ use syntax::ast;
 use syntax::ast_util::{local_def};
 use syntax::ast_util::{walk_pat, trait_method_to_ty_method};
 use syntax::ext::mtwt;
+use syntax::parse::token::special_names;
 use syntax::parse::token::special_idents;
 use syntax::parse::token;
 use syntax::codemap::{Span, DUMMY_SP, Pos};
@@ -830,9 +831,9 @@ struct Resolver<'a> {
     current_self_type: Option<Ty>,
 
     // The ident for the keyword "self".
-    self_ident: Ident,
+    self_name: Name,
     // The ident for the non-keyword "Self".
-    type_self_ident: Ident,
+    type_self_name: Name,
 
     // The idents for the primitive types.
     primitive_type_table: PrimitiveTypeTable,
@@ -926,8 +927,8 @@ impl<'a> Resolver<'a> {
             current_trait_ref: None,
             current_self_type: None,
 
-            self_ident: special_idents::self_,
-            type_self_ident: special_idents::type_self,
+            self_name: special_names::self_,
+            type_self_name: special_names::type_self,
 
             primitive_type_table: PrimitiveTypeTable::new(),
 
@@ -3628,8 +3629,8 @@ impl<'a> Resolver<'a> {
                 // Create a new rib for the self type.
                 let self_type_rib = Rib::new(ItemRibKind);
 
-                // plain insert (no renaming)
-                let name = self.type_self_ident.name;
+                // plain insert (no renaming, types are not currently hygienic....)
+                let name = self.type_self_name;
                 self_type_rib.bindings.borrow_mut()
                              .insert(name, DlDef(DefSelfTy(item.id)));
                 self.type_ribs.borrow_mut().push(self_type_rib);
@@ -5159,8 +5160,8 @@ impl<'a> Resolver<'a> {
                                     false // Stop advancing
                                 });
 
-                                if method_scope && token::get_name(self.self_ident.name).get()
-                                                                        == wrong_name.as_slice() {
+                                if method_scope && token::get_name(self.self_name).get()
+                                                                   == wrong_name.as_slice() {
                                         self.resolve_error(
                                             expr.span,
                                             "`self` is not available \
@@ -5532,6 +5533,7 @@ impl<'a> Resolver<'a> {
                     collect_mod(idents, &*module.upgrade().unwrap());
                 }
                 BlockParentLink(ref module, _) => {
+                    // danger, shouldn't be ident?
                     idents.push(special_idents::opaque);
                     collect_mod(idents, &*module.upgrade().unwrap());
                 }
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index e1d43c52400..c79e435707a 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -502,12 +502,15 @@ fn emit_vtable_methods(bcx: &Block,
                                                        ExprId(0),
                                                        substs.clone(),
                                                        vtables.clone());
-            if m.explicit_self == ast::SelfValue {
-                fn_ref = trans_unboxing_shim(bcx,
-                                             fn_ref,
-                                             &*m,
-                                             m_id,
-                                             substs.clone());
+            match m.explicit_self {
+                ast::SelfValue(_) => {
+                    fn_ref = trans_unboxing_shim(bcx,
+                                                 fn_ref,
+                                                 &*m,
+                                                 m_id,
+                                                 substs.clone());
+                },
+                _ => {}
             }
             fn_ref
         }
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index d565f144f36..90331d8f434 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -938,10 +938,10 @@ fn ty_of_method_or_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
     let self_ty = opt_self_info.and_then(|self_info| {
         match self_info.explicit_self.node {
             ast::SelfStatic => None,
-            ast::SelfValue => {
+            ast::SelfValue(_) => {
                 Some(self_info.untransformed_self_ty)
             }
-            ast::SelfRegion(ref lifetime, mutability) => {
+            ast::SelfRegion(ref lifetime, mutability, _) => {
                 let region =
                     opt_ast_region_to_region(this, &rb,
                                              self_info.explicit_self.span,
@@ -950,7 +950,7 @@ fn ty_of_method_or_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
                                  ty::mt {ty: self_info.untransformed_self_ty,
                                          mutbl: mutability}))
             }
-            ast::SelfUniq => {
+            ast::SelfUniq(_) => {
                 Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty))
             }
         }
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index c1a000841a4..a184ecac9de 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -270,12 +270,12 @@ fn construct_transformed_self_ty_for_object(
         ast::SelfStatic => {
             tcx.sess.span_bug(span, "static method for object type receiver");
         }
-        ast::SelfValue => {
+        ast::SelfValue(_) => {
             let tr = ty::mk_trait(tcx, trait_def_id, obj_substs,
                                   ty::empty_builtin_bounds());
             ty::mk_uniq(tcx, tr)
         }
-        ast::SelfRegion(..) | ast::SelfUniq => {
+        ast::SelfRegion(..) | ast::SelfUniq(..) => {
             let transformed_self_ty = *method_ty.fty.sig.inputs.get(0);
             match ty::get(transformed_self_ty).sty {
                 ty::ty_rptr(r, mt) => { // must be SelfRegion
@@ -1227,7 +1227,7 @@ impl<'a> LookupContext<'a> {
                      through an object");
             }
 
-            ast::SelfValue | ast::SelfRegion(..) | ast::SelfUniq => {}
+            ast::SelfValue(_) | ast::SelfRegion(..) | ast::SelfUniq(_) => {}
         }
 
         // reason (a) above
@@ -1296,7 +1296,7 @@ impl<'a> LookupContext<'a> {
                 self.report_statics == ReportStaticMethods
             }
 
-            SelfValue => {
+            SelfValue(_) => {
                 debug!("(is relevant?) explicit self is by-value");
                 match ty::get(rcvr_ty).sty {
                     ty::ty_uniq(typ) => {
@@ -1319,7 +1319,7 @@ impl<'a> LookupContext<'a> {
                 }
             }
 
-            SelfRegion(_, m) => {
+            SelfRegion(_, m, _) => {
                 debug!("(is relevant?) explicit self is a region");
                 match ty::get(rcvr_ty).sty {
                     ty::ty_rptr(_, mt) => {
@@ -1339,7 +1339,7 @@ impl<'a> LookupContext<'a> {
                 }
             }
 
-            SelfUniq => {
+            SelfUniq(_) => {
                 debug!("(is relevant?) explicit self is a unique pointer");
                 match ty::get(rcvr_ty).sty {
                     ty::ty_uniq(typ) => {
diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs
index cdd51c4fa71..b0c9900be90 100644
--- a/src/librustc/middle/typeck/infer/error_reporting.rs
+++ b/src/librustc/middle/typeck/infer/error_reporting.rs
@@ -947,16 +947,16 @@ impl<'a> Rebuilder<'a> {
                          -> Option<ast::ExplicitSelf_> {
         match expl_self_opt {
             Some(expl_self) => match expl_self {
-                ast::SelfRegion(lt_opt, muta) => match lt_opt {
+                ast::SelfRegion(lt_opt, muta, id) => match lt_opt {
                     Some(lt) => if region_names.contains(&lt.name) {
-                        return Some(ast::SelfRegion(Some(lifetime), muta));
+                        return Some(ast::SelfRegion(Some(lifetime), muta, id));
                     },
                     None => {
                         let anon = self.cur_anon.get();
                         self.inc_and_offset_cur_anon(1);
                         if anon_nums.contains(&anon) {
                             self.track_anon(anon);
-                            return Some(ast::SelfRegion(Some(lifetime), muta));
+                            return Some(ast::SelfRegion(Some(lifetime), muta, id));
                         }
                     }
                 },
diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs
index 587bedd502e..2581ba51c2e 100644
--- a/src/librustc/plugin/registry.rs
+++ b/src/librustc/plugin/registry.rs
@@ -13,7 +13,7 @@
 use lint::LintPassObject;
 
 use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
-use syntax::ext::base::{IdentTT, ItemDecorator, ItemModifier, BasicMacroExpander};
+use syntax::ext::base::{IdentTT, LetSyntaxTT, ItemDecorator, ItemModifier, BasicMacroExpander};
 use syntax::ext::base::{MacroExpanderFn};
 use syntax::codemap::Span;
 use syntax::parse::token;
@@ -57,6 +57,8 @@ impl Registry {
             IdentTT(ext, _) => IdentTT(ext, Some(self.krate_span)),
             ItemDecorator(ext) => ItemDecorator(ext),
             ItemModifier(ext) => ItemModifier(ext),
+            // there's probably a nicer way to signal this:
+            LetSyntaxTT(_, _) => fail!("can't register a new LetSyntax!"),
         }));
     }
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 6c40ee21040..af0b6a1cb21 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -775,9 +775,9 @@ impl Clean<SelfTy> for ast::ExplicitSelf_ {
     fn clean(&self) -> SelfTy {
         match *self {
             ast::SelfStatic => SelfStatic,
-            ast::SelfValue => SelfValue,
-            ast::SelfUniq => SelfOwned,
-            ast::SelfRegion(lt, mt) => SelfBorrowed(lt.clean(), mt.clean()),
+            ast::SelfValue(_) => SelfValue,
+            ast::SelfUniq(_) => SelfOwned,
+            ast::SelfRegion(lt, mt, _) => SelfBorrowed(lt.clean(), mt.clean()),
         }
     }
 }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index d98ae9f0e33..5f3adbdb54d 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -14,7 +14,7 @@ use codemap::{Span, Spanned, DUMMY_SP};
 use abi::Abi;
 use ast_util;
 use owned_slice::OwnedSlice;
-use parse::token::{InternedString, special_idents, str_to_ident};
+use parse::token::{InternedString, str_to_ident};
 use parse::token;
 
 use std::fmt;
@@ -824,8 +824,8 @@ pub struct Arg {
 }
 
 impl Arg {
-    pub fn new_self(span: Span, mutability: Mutability) -> Arg {
-        let path = Spanned{span:span,node:special_idents::self_};
+    pub fn new_self(span: Span, mutability: Mutability, self_ident: Ident) -> Arg {
+        let path = Spanned{span:span,node:self_ident};
         Arg {
             // HACK(eddyb) fake type for the self argument.
             ty: P(Ty {
@@ -874,16 +874,18 @@ pub enum RetStyle {
     Return, // everything else
 }
 
+/// Represents the kind of 'self' associated with a method
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
 pub enum ExplicitSelf_ {
-    SelfStatic,                                // no self
-    SelfValue,                                 // `self`
-    SelfRegion(Option<Lifetime>, Mutability),  // `&'lt self`, `&'lt mut self`
-    SelfUniq                                   // `~self`
+    SelfStatic,                                       // no self
+    SelfValue(Ident),                                 // `self`
+    SelfRegion(Option<Lifetime>, Mutability, Ident),  // `&'lt self`, `&'lt mut self`
+    SelfUniq(Ident),                                  // `~self`
 }
 
 pub type ExplicitSelf = Spanned<ExplicitSelf_>;
 
+// Represents a method declaration
 #[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
 pub struct Method {
     pub ident: Ident,
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index a540b23551b..a2a442f8b6a 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -264,8 +264,15 @@ pub enum SyntaxExtension {
     /// A function-like syntax extension that has an extra ident before
     /// the block.
     ///
-    /// `macro_rules!` is an `IdentTT`.
     IdentTT(Box<IdentMacroExpander + 'static>, Option<Span>),
+
+    /// An ident macro that has two properties:
+    /// - it adds a macro definition to the environment, and
+    /// - the definition it adds doesn't introduce any new
+    ///   identifiers.
+    ///
+    /// `macro_rules!` is a LetSyntaxTT
+    LetSyntaxTT(Box<IdentMacroExpander + 'static>, Option<Span>),
 }
 
 pub type NamedSyntaxExtension = (Name, SyntaxExtension);
@@ -300,7 +307,7 @@ pub fn syntax_expander_table() -> SyntaxEnv {
 
     let mut syntax_expanders = SyntaxEnv::new();
     syntax_expanders.insert(intern("macro_rules"),
-                            IdentTT(box BasicIdentMacroExpander {
+                            LetSyntaxTT(box BasicIdentMacroExpander {
                                 expander: ext::tt::macro_rules::add_new_extension,
                                 span: None,
                             },
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index 7ad11b186f5..764c88cc954 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -191,6 +191,7 @@ use codemap;
 use codemap::Span;
 use owned_slice::OwnedSlice;
 use parse::token::InternedString;
+use parse::token::special_idents;
 
 use self::ty::*;
 
@@ -617,7 +618,8 @@ impl<'a> MethodDef<'a> {
 
         let self_arg = match explicit_self.node {
             ast::SelfStatic => None,
-            _ => Some(ast::Arg::new_self(trait_.span, ast::MutImmutable))
+            // creating fresh self id
+            _ => Some(ast::Arg::new_self(trait_.span, ast::MutImmutable, special_idents::self_))
         };
         let args = {
             let args = arg_types.move_iter().map(|(name, ty)| {
diff --git a/src/libsyntax/ext/deriving/generic/ty.rs b/src/libsyntax/ext/deriving/generic/ty.rs
index 28f39a4cb8c..b53281f9963 100644
--- a/src/libsyntax/ext/deriving/generic/ty.rs
+++ b/src/libsyntax/ext/deriving/generic/ty.rs
@@ -19,6 +19,7 @@ use ext::base::ExtCtxt;
 use ext::build::AstBuilder;
 use codemap::{Span,respan};
 use owned_slice::OwnedSlice;
+use parse::token::special_idents;
 
 use std::gc::Gc;
 
@@ -244,22 +245,23 @@ impl<'a> LifetimeBounds<'a> {
     }
 }
 
-
 pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
     -> (Gc<Expr>, ast::ExplicitSelf) {
+    // this constructs a fresh `self` path, which will match the fresh `self` binding
+    // created below.
     let self_path = cx.expr_self(span);
     match *self_ptr {
         None => {
-            (self_path, respan(span, ast::SelfValue))
+            (self_path, respan(span, ast::SelfValue(special_idents::self_)))
         }
         Some(ref ptr) => {
             let self_ty = respan(
                 span,
                 match *ptr {
-                    Send => ast::SelfUniq,
+                    Send => ast::SelfUniq(special_idents::self_),
                     Borrowed(ref lt, mutbl) => {
                         let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s).name));
-                        ast::SelfRegion(lt, mutbl)
+                        ast::SelfRegion(lt, mutbl, special_idents::self_)
                     }
                 });
             let self_expr = cx.expr_deref(span, self_path);
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 74cede2a125..9fe431cfb6c 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -484,6 +484,24 @@ fn expand_item_mac(it: Gc<ast::Item>, fld: &mut MacroExpander)
             let marked_tts = mark_tts(tts.as_slice(), fm);
             expander.expand(fld.cx, it.span, it.ident, marked_tts)
         }
+        Some(&LetSyntaxTT(ref expander, span)) => {
+            if it.ident.name == parse::token::special_idents::invalid.name {
+                fld.cx.span_err(pth.span,
+                                format!("macro {}! expects an ident argument",
+                                        extnamestr.get()).as_slice());
+                return SmallVector::zero();
+            }
+            fld.cx.bt_push(ExpnInfo {
+                call_site: it.span,
+                callee: NameAndSpan {
+                    name: extnamestr.get().to_string(),
+                    format: MacroBang,
+                    span: span
+                }
+            });
+            // DON'T mark before expansion:
+            expander.expand(fld.cx, it.span, it.ident, tts)
+        }
         _ => {
             fld.cx.span_err(it.span,
                             format!("{}! is not legal in item position",
@@ -494,8 +512,10 @@ fn expand_item_mac(it: Gc<ast::Item>, fld: &mut MacroExpander)
 
     let items = match expanded.make_def() {
         Some(MacroDef { name, ext }) => {
-            // yikes... no idea how to apply the mark to this. I'm afraid
-            // we're going to have to wait-and-see on this one.
+            // hidden invariant: this should only be possible as the
+            // result of expanding a LetSyntaxTT, and thus doesn't
+            // need to be marked. Not that it could be marked anyway.
+            // create issue to recommend refactoring here?
             fld.extsbox.insert(intern(name.as_slice()), ext);
             if attr::contains_name(it.attrs.as_slice(), "macro_export") {
                 SmallVector::one(it)
@@ -914,6 +934,27 @@ impl<'a> Folder for PatIdentRenamer<'a> {
     }
 }
 
+// expand a method
+fn expand_method(m: &ast::Method, fld: &mut MacroExpander) -> Gc<ast::Method> {
+    let id = fld.new_id(m.id);
+    let (rewritten_fn_decl, rewritten_body)
+        = expand_and_rename_fn_decl_and_block(m.decl,m.body,fld);
+
+    // all of the other standard stuff:
+    box(GC) ast::Method {
+        id: id,
+        ident: fld.fold_ident(m.ident),
+        attrs: m.attrs.iter().map(|a| fld.fold_attribute(*a)).collect(),
+        generics: fold_generics(&m.generics, fld),
+        explicit_self: fld.fold_explicit_self(&m.explicit_self),
+        fn_style: m.fn_style,
+        decl: rewritten_fn_decl,
+        body: rewritten_body,
+        span: fld.new_span(m.span),
+        vis: m.vis
+    }
+}
+
 /// Given a fn_decl and a block and a MacroExpander, expand the fn_decl, then use the
 /// PatIdents in its arguments to perform renaming in the FnDecl and
 /// the block, returning both the new FnDecl and the new Block.
@@ -968,6 +1009,10 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
         expand_arm(arm, self)
     }
 
+    fn fold_method(&mut self, method: Gc<ast::Method>) -> Gc<ast::Method> {
+        expand_method(method, self)
+    }
+
     fn new_span(&mut self, span: Span) -> Span {
         new_span(self.cx, span)
     }
@@ -1280,6 +1325,14 @@ mod test {
             "macro_rules! m((a)=>(13)) fn main(){m!(a);}".to_string());
     }
 
+    // should be able to use a bound identifier as a literal in a macro definition:
+    #[test] fn self_macro_parsing(){
+        expand_crate_str(
+            "macro_rules! foo ((zz) => (287u;))
+            fn f(zz : int) {foo!(zz);}".to_string()
+            );
+    }
+
     // renaming tests expand a crate and then check that the bindings match
     // the right varrefs. The specification of the test case includes the
     // text of the crate, and also an array of arrays.  Each element in the
@@ -1390,6 +1443,32 @@ mod test {
     // but *shouldn't* bind because it was inserted by a different macro....
     // can't write this test case until we have macro-generating macros.
 
+    // method arg hygiene
+    // method expands to fn get_x(&self_0, x_1:int) {self_0 + self_2 + x_3 + x_1}
+    #[test] fn method_arg_hygiene(){
+        run_renaming_test(
+            &("macro_rules! inject_x (()=>(x))
+              macro_rules! inject_self (()=>(self))
+              struct A;
+              impl A{fn get_x(&self, x: int) {self + inject_self!() + inject_x!() + x;} }",
+              vec!(vec!(0),vec!(3)),
+              true),
+            0)
+    }
+
+    // ooh, got another bite?
+    // expands to struct A; impl A {fn thingy(&self_1) {self_1;}}
+    #[test] fn method_arg_hygiene_2(){
+        run_renaming_test(
+            &("struct A;
+              macro_rules! add_method (($T:ty) =>
+              (impl $T {  fn thingy(&self) {self;} }))
+              add_method!(A)",
+              vec!(vec!(0)),
+              true),
+            0)
+    }
+
     // item fn hygiene
     // expands to fn q(x_1:int){fn g(x_2:int){x_2 + x_1};}
     #[test] fn issue_9383(){
@@ -1422,6 +1501,28 @@ mod test {
             0)
     }
 
+    // macro_rules in method position. Sadly, unimplemented.
+    #[ignore] #[test] fn macro_in_method_posn(){
+        expand_crate_str(
+            "macro_rules! my_method (() => fn thirteen(&self) -> int {13})
+            struct A;
+            impl A{ my_method!()}
+            fn f(){A.thirteen;}".to_string());
+    }
+
+    // another nested macro
+    // expands to impl Entries {fn size_hint(&self_1) {self_1;}
+    #[test] fn item_macro_workaround(){
+        run_renaming_test(
+            &("macro_rules! item { ($i:item) => {$i}}
+              struct Entries;
+              macro_rules! iterator_impl {
+              () => { item!( impl Entries { fn size_hint(&self) { self;}})}}
+              iterator_impl! { }",
+              vec!(vec!(0)), true),
+            0)
+    }
+
     // run one of the renaming tests
     fn run_renaming_test(t: &RenamingTest, test_idx: uint) {
         let invalid_name = token::special_idents::invalid.name;
@@ -1441,27 +1542,36 @@ mod test {
             assert!((shouldmatch.len() == 0) ||
                     (varrefs.len() > *shouldmatch.iter().max().unwrap()));
             for (idx,varref) in varrefs.iter().enumerate() {
+                let print_hygiene_debug_info = || {
+                    // good lord, you can't make a path with 0 segments, can you?
+                    let final_varref_ident = match varref.segments.last() {
+                        Some(pathsegment) => pathsegment.identifier,
+                        None => fail!("varref with 0 path segments?")
+                    };
+                    let varref_name = mtwt::resolve(final_varref_ident);
+                    let varref_idents : Vec<ast::Ident>
+                        = varref.segments.iter().map(|s| s.identifier)
+                        .collect();
+                    println!("varref #{}: {}, resolves to {}",idx, varref_idents, varref_name);
+                    let string = token::get_ident(final_varref_ident);
+                    println!("varref's first segment's string: \"{}\"", string.get());
+                    println!("binding #{}: {}, resolves to {}",
+                             binding_idx, *bindings.get(binding_idx), binding_name);
+                    mtwt::with_sctable(|x| mtwt::display_sctable(x));
+                };
                 if shouldmatch.contains(&idx) {
                     // it should be a path of length 1, and it should
                     // be free-identifier=? or bound-identifier=? to the given binding
                     assert_eq!(varref.segments.len(),1);
-                    let varref_name = mtwt::resolve(varref.segments
-                                                          .get(0)
-                                                          .identifier);
+                    let varref_name = mtwt::resolve(varref.segments.get(0).identifier);
                     let varref_marks = mtwt::marksof(varref.segments
                                                            .get(0)
                                                            .identifier
                                                            .ctxt,
                                                      invalid_name);
                     if !(varref_name==binding_name) {
-                        let varref_idents : Vec<ast::Ident>
-                            = varref.segments.iter().map(|s|
-                                                         s.identifier)
-                            .collect();
                         println!("uh oh, should match but doesn't:");
-                        println!("varref #{}: {}",idx, varref_idents);
-                        println!("binding #{}: {}", binding_idx, *bindings.get(binding_idx));
-                        mtwt::with_sctable(|x| mtwt::display_sctable(x));
+                        print_hygiene_debug_info();
                     }
                     assert_eq!(varref_name,binding_name);
                     if bound_ident_check {
@@ -1475,27 +1585,11 @@ mod test {
                         && (varref_name == binding_name);
                     // temp debugging:
                     if fail {
-                        let varref_idents : Vec<ast::Ident>
-                            = varref.segments.iter().map(|s|
-                                                         s.identifier)
-                            .collect();
                         println!("failure on test {}",test_idx);
                         println!("text of test case: \"{}\"", teststr);
                         println!("");
                         println!("uh oh, matches but shouldn't:");
-                        println!("varref #{}: {}, resolves to {}",idx, varref_idents,
-                                 varref_name);
-                        // good lord, you can't make a path with 0 segments, can you?
-                        let string = token::get_ident(varref.segments
-                                                            .get(0)
-                                                            .identifier);
-                        println!("varref's first segment's uint: {}, and string: \"{}\"",
-                                 varref.segments.get(0).identifier.name,
-                                 string.get());
-                        println!("binding #{}: {}, resolves to {}",
-                                 binding_idx, *bindings.get(binding_idx),
-                                 binding_name);
-                        mtwt::with_sctable(|x| mtwt::display_sctable(x));
+                        print_hygiene_debug_info();
                     }
                     assert!(!fail);
                 }
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index 913e0427bda..b30ede70f0e 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -354,8 +354,7 @@ pub fn parse(sess: &ParseSess,
                   MatchNonterminal(_,_,_) => { bb_eis.push(ei) }
                   MatchTok(ref t) => {
                     let mut ei_t = ei.clone();
-                    //if (token_name_eq(t,&tok)) {
-                    if token::mtwt_token_eq(t,&tok) {
+                    if token_name_eq(t,&tok) {
                         ei_t.idx += 1;
                         next_eis.push(ei_t);
                     }
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index ee4810b4b54..bcdf920e5dd 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -334,9 +334,9 @@ pub trait Folder {
 
     fn fold_explicit_self_(&mut self, es: &ExplicitSelf_) -> ExplicitSelf_ {
         match *es {
-            SelfStatic | SelfValue | SelfUniq => *es,
-            SelfRegion(ref lifetime, m) => {
-                SelfRegion(fold_opt_lifetime(lifetime, self), m)
+            SelfStatic | SelfValue(_) | SelfUniq(_) => *es,
+            SelfRegion(ref lifetime, m, id) => {
+                SelfRegion(fold_opt_lifetime(lifetime, self), m, id)
             }
         }
     }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index a3917e93197..ac4cbf3aa8e 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -541,12 +541,13 @@ impl<'a> Parser<'a> {
     // if the next token is the given keyword, eat it and return
     // true. Otherwise, return false.
     pub fn eat_keyword(&mut self, kw: keywords::Keyword) -> bool {
-        let is_kw = match self.token {
-            token::IDENT(sid, false) => kw.to_ident().name == sid.name,
+        match self.token {
+            token::IDENT(sid, false) if kw.to_name() == sid.name => {
+                self.bump();
+                true
+            }
             _ => false
-        };
-        if is_kw { self.bump() }
-        is_kw
+        }
     }
 
     // if the given word is not a keyword, signal an error.
@@ -554,7 +555,7 @@ impl<'a> Parser<'a> {
     // otherwise, eat it.
     pub fn expect_keyword(&mut self, kw: keywords::Keyword) {
         if !self.eat_keyword(kw) {
-            let id_interned_str = token::get_ident(kw.to_ident());
+            let id_interned_str = token::get_name(kw.to_name());
             let token_str = self.this_token_to_string();
             self.fatal(format!("expected `{}`, found `{}`",
                                id_interned_str, token_str).as_slice())
@@ -1877,211 +1878,230 @@ impl<'a> Parser<'a> {
 
         let ex: Expr_;
 
-        if self.token == token::LPAREN {
-            self.bump();
-            // (e) is parenthesized e
-            // (e,) is a tuple with only one field, e
-            let mut trailing_comma = false;
-            if self.token == token::RPAREN {
-                hi = self.span.hi;
-                self.bump();
-                let lit = box(GC) spanned(lo, hi, LitNil);
-                return self.mk_expr(lo, hi, ExprLit(lit));
-            }
-            let mut es = vec!(self.parse_expr());
-            self.commit_expr(*es.last().unwrap(), &[], &[token::COMMA, token::RPAREN]);
-            while self.token == token::COMMA {
+        match self.token {
+            token::LPAREN => {
                 self.bump();
-                if self.token != token::RPAREN {
-                    es.push(self.parse_expr());
-                    self.commit_expr(*es.last().unwrap(), &[], &[token::COMMA, token::RPAREN]);
+                // (e) is parenthesized e
+                // (e,) is a tuple with only one field, e
+                let mut trailing_comma = false;
+                if self.token == token::RPAREN {
+                    hi = self.span.hi;
+                    self.bump();
+                    let lit = box(GC) spanned(lo, hi, LitNil);
+                    return self.mk_expr(lo, hi, ExprLit(lit));
                 }
-                else {
-                    trailing_comma = true;
+                let mut es = vec!(self.parse_expr());
+                self.commit_expr(*es.last().unwrap(), &[], &[token::COMMA, token::RPAREN]);
+                while self.token == token::COMMA {
+                    self.bump();
+                    if self.token != token::RPAREN {
+                        es.push(self.parse_expr());
+                        self.commit_expr(*es.last().unwrap(), &[], &[token::COMMA, token::RPAREN]);
+                    }
+                        else {
+                        trailing_comma = true;
+                    }
                 }
-            }
-            hi = self.span.hi;
-            self.commit_expr_expecting(*es.last().unwrap(), token::RPAREN);
-
-            return if es.len() == 1 && !trailing_comma {
-                self.mk_expr(lo, hi, ExprParen(*es.get(0)))
-            }
-            else {
-                self.mk_expr(lo, hi, ExprTup(es))
-            }
-        } else if self.token == token::LBRACE {
-            self.bump();
-            let blk = self.parse_block_tail(lo, DefaultBlock);
-            return self.mk_expr(blk.span.lo, blk.span.hi,
-                                 ExprBlock(blk));
-        } else if token::is_bar(&self.token) {
-            return self.parse_lambda_expr();
-        } else if self.eat_keyword(keywords::Proc) {
-            let decl = self.parse_proc_decl();
-            let body = self.parse_expr();
-            let fakeblock = P(ast::Block {
-                view_items: Vec::new(),
-                stmts: Vec::new(),
-                expr: Some(body),
-                id: ast::DUMMY_NODE_ID,
-                rules: DefaultBlock,
-                span: body.span,
-            });
+                hi = self.span.hi;
+                self.commit_expr_expecting(*es.last().unwrap(), token::RPAREN);
 
-            return self.mk_expr(lo, body.span.hi, ExprProc(decl, fakeblock));
-        } else if self.eat_keyword(keywords::Self) {
-            let path = ast_util::ident_to_path(mk_sp(lo, hi), special_idents::self_);
-            ex = ExprPath(path);
-            hi = self.last_span.hi;
-        } else if self.eat_keyword(keywords::If) {
-            return self.parse_if_expr();
-        } else if self.eat_keyword(keywords::For) {
-            return self.parse_for_expr(None);
-        } else if self.eat_keyword(keywords::While) {
-            return self.parse_while_expr();
-        } else if Parser::token_is_lifetime(&self.token) {
-            let lifetime = self.get_lifetime();
-            self.bump();
-            self.expect(&token::COLON);
-            if self.eat_keyword(keywords::For) {
-                return self.parse_for_expr(Some(lifetime))
-            } else if self.eat_keyword(keywords::Loop) {
-                return self.parse_loop_expr(Some(lifetime))
-            } else {
-                self.fatal("expected `for` or `loop` after a label")
+                return if es.len() == 1 && !trailing_comma {
+                    self.mk_expr(lo, hi, ExprParen(*es.get(0)))
+                }
+                    else {
+                    self.mk_expr(lo, hi, ExprTup(es))
+                }
+            },
+            token::LBRACE => {
+                self.bump();
+                let blk = self.parse_block_tail(lo, DefaultBlock);
+                return self.mk_expr(blk.span.lo, blk.span.hi,
+                                    ExprBlock(blk));
+            },
+            token::BINOP(token::OR) |  token::OROR => {
+                return self.parse_lambda_expr();
+            },
+            _ if self.eat_keyword(keywords::Proc) => {
+                let decl = self.parse_proc_decl();
+                let body = self.parse_expr();
+                let fakeblock = P(ast::Block {
+                        view_items: Vec::new(),
+                        stmts: Vec::new(),
+                        expr: Some(body),
+                        id: ast::DUMMY_NODE_ID,
+                        rules: DefaultBlock,
+                        span: body.span,
+                    });
+                return self.mk_expr(lo, body.span.hi, ExprProc(decl, fakeblock));
+            },
+            token::IDENT(id @ ast::Ident{name:token::SELF_KEYWORD_NAME,ctxt:_},false) => {
+                self.bump();
+                let path = ast_util::ident_to_path(mk_sp(lo, hi), id);
+                ex = ExprPath(path);
+                hi = self.last_span.hi;
             }
-        } else if self.eat_keyword(keywords::Loop) {
-            return self.parse_loop_expr(None);
-        } else if self.eat_keyword(keywords::Continue) {
-            let lo = self.span.lo;
-            let ex = if Parser::token_is_lifetime(&self.token) {
+            _ if self.eat_keyword(keywords::If) => {
+                return self.parse_if_expr();
+            },
+            _ if self.eat_keyword(keywords::For) => {
+                return self.parse_for_expr(None);
+            },
+            _ if self.eat_keyword(keywords::While) => {
+                return self.parse_while_expr();
+            },
+            _ if Parser::token_is_lifetime(&self.token) => {
                 let lifetime = self.get_lifetime();
                 self.bump();
-                ExprAgain(Some(lifetime))
-            } else {
-                ExprAgain(None)
-            };
-            let hi = self.span.hi;
-            return self.mk_expr(lo, hi, ex);
-        } else if self.eat_keyword(keywords::Match) {
-            return self.parse_match_expr();
-        } else if self.eat_keyword(keywords::Unsafe) {
-            return self.parse_block_expr(lo, UnsafeBlock(ast::UserProvided));
-        } else if self.token == token::LBRACKET {
-            self.bump();
-
-            if self.token == token::RBRACKET {
-                // Empty vector.
-                self.bump();
-                ex = ExprVec(Vec::new());
-            } else {
-                // Nonempty vector.
-                let first_expr = self.parse_expr();
-                if self.token == token::COMMA &&
-                        self.look_ahead(1, |t| *t == token::DOTDOT) {
-                    // Repeating vector syntax: [ 0, ..512 ]
+                self.expect(&token::COLON);
+                if self.eat_keyword(keywords::For) {
+                    return self.parse_for_expr(Some(lifetime))
+                } else if self.eat_keyword(keywords::Loop) {
+                    return self.parse_loop_expr(Some(lifetime))
+                } else {
+                    self.fatal("expected `for` or `loop` after a label")
+                }
+            },
+            _ if self.eat_keyword(keywords::Loop) => {
+                return self.parse_loop_expr(None);
+            },
+            _ if self.eat_keyword(keywords::Continue) => {
+                let lo = self.span.lo;
+                let ex = if Parser::token_is_lifetime(&self.token) {
+                    let lifetime = self.get_lifetime();
                     self.bump();
+                    ExprAgain(Some(lifetime))
+                } else {
+                    ExprAgain(None)
+                };
+                let hi = self.span.hi;
+                return self.mk_expr(lo, hi, ex);
+            },
+            _ if self.eat_keyword(keywords::Match) => {
+                return self.parse_match_expr();
+            },
+            _ if self.eat_keyword(keywords::Unsafe) => {
+                return self.parse_block_expr(lo, UnsafeBlock(ast::UserProvided));
+            },
+            token::LBRACKET => {
+                self.bump();
+
+                if self.token == token::RBRACKET {
+                    // Empty vector.
                     self.bump();
-                    let count = self.parse_expr();
-                    self.expect(&token::RBRACKET);
-                    ex = ExprRepeat(first_expr, count);
-                } else if self.token == token::COMMA {
-                    // Vector with two or more elements.
+                    ex = ExprVec(Vec::new());
+                } else {
+                    // Nonempty vector.
+                    let first_expr = self.parse_expr();
+                    if self.token == token::COMMA &&
+                        self.look_ahead(1, |t| *t == token::DOTDOT) {
+                        // Repeating vector syntax: [ 0, ..512 ]
+                        self.bump();
+                        self.bump();
+                        let count = self.parse_expr();
+                        self.expect(&token::RBRACKET);
+                        ex = ExprRepeat(first_expr, count);
+                    } else if self.token == token::COMMA {
+                        // Vector with two or more elements.
+                        self.bump();
+                        let remaining_exprs = self.parse_seq_to_end(
+                            &token::RBRACKET,
+                            seq_sep_trailing_allowed(token::COMMA),
+                            |p| p.parse_expr()
+                                );
+                        let mut exprs = vec!(first_expr);
+                        exprs.push_all_move(remaining_exprs);
+                        ex = ExprVec(exprs);
+                    } else {
+                        // Vector with one element.
+                        self.expect(&token::RBRACKET);
+                        ex = ExprVec(vec!(first_expr));
+                    }
+                }
+                hi = self.last_span.hi;
+            },
+            _ if self.eat_keyword(keywords::Return) => {
+                // RETURN expression
+                if can_begin_expr(&self.token) {
+                    let e = self.parse_expr();
+                    hi = e.span.hi;
+                    ex = ExprRet(Some(e));
+                } else { ex = ExprRet(None); }
+            },
+            _ if self.eat_keyword(keywords::Break) => {
+                // BREAK expression
+                if Parser::token_is_lifetime(&self.token) {
+                    let lifetime = self.get_lifetime();
                     self.bump();
-                    let remaining_exprs = self.parse_seq_to_end(
-                        &token::RBRACKET,
-                        seq_sep_trailing_allowed(token::COMMA),
-                        |p| p.parse_expr()
-                    );
-                    let mut exprs = vec!(first_expr);
-                    exprs.push_all_move(remaining_exprs);
-                    ex = ExprVec(exprs);
+                    ex = ExprBreak(Some(lifetime));
                 } else {
-                    // Vector with one element.
-                    self.expect(&token::RBRACKET);
-                    ex = ExprVec(vec!(first_expr));
+                    ex = ExprBreak(None);
                 }
-            }
-            hi = self.last_span.hi;
-        } else if self.eat_keyword(keywords::Return) {
-            // RETURN expression
-            if can_begin_expr(&self.token) {
-                let e = self.parse_expr();
-                hi = e.span.hi;
-                ex = ExprRet(Some(e));
-            } else { ex = ExprRet(None); }
-        } else if self.eat_keyword(keywords::Break) {
-            // BREAK expression
-            if Parser::token_is_lifetime(&self.token) {
-                let lifetime = self.get_lifetime();
-                self.bump();
-                ex = ExprBreak(Some(lifetime));
-            } else {
-                ex = ExprBreak(None);
-            }
-            hi = self.span.hi;
-        } else if self.token == token::MOD_SEP ||
+                hi = self.span.hi;
+            },
+            _ if self.token == token::MOD_SEP ||
                 is_ident(&self.token) && !self.is_keyword(keywords::True) &&
-                !self.is_keyword(keywords::False) {
-            let pth = self.parse_path(LifetimeAndTypesWithColons).path;
+                !self.is_keyword(keywords::False) => {
+                let pth = self.parse_path(LifetimeAndTypesWithColons).path;
 
-            // `!`, as an operator, is prefix, so we know this isn't that
-            if self.token == token::NOT {
-                // MACRO INVOCATION expression
-                self.bump();
+                // `!`, as an operator, is prefix, so we know this isn't that
+                if self.token == token::NOT {
+                    // MACRO INVOCATION expression
+                    self.bump();
 
-                let ket = token::close_delimiter_for(&self.token)
-                                .unwrap_or_else(|| self.fatal("expected open delimiter"));
-                self.bump();
+                    let ket = token::close_delimiter_for(&self.token)
+                        .unwrap_or_else(|| self.fatal("expected open delimiter"));
+                    self.bump();
 
-                let tts = self.parse_seq_to_end(&ket,
-                                                seq_sep_none(),
-                                                |p| p.parse_token_tree());
-                let hi = self.span.hi;
+                    let tts = self.parse_seq_to_end(&ket,
+                                                    seq_sep_none(),
+                                                    |p| p.parse_token_tree());
+                    let hi = self.span.hi;
 
-                return self.mk_mac_expr(lo, hi, MacInvocTT(pth, tts, EMPTY_CTXT));
-            } else if self.token == token::LBRACE {
-                // This is a struct literal, unless we're prohibited from
-                // parsing struct literals here.
-                if self.restriction != RESTRICT_NO_STRUCT_LITERAL {
-                    // It's a struct literal.
-                    self.bump();
-                    let mut fields = Vec::new();
-                    let mut base = None;
+                    return self.mk_mac_expr(lo, hi, MacInvocTT(pth, tts, EMPTY_CTXT));
+                } else if self.token == token::LBRACE {
+                    // This is a struct literal, unless we're prohibited from
+                    // parsing struct literals here.
+                    if self.restriction != RESTRICT_NO_STRUCT_LITERAL {
+                        // It's a struct literal.
+                        self.bump();
+                        let mut fields = Vec::new();
+                        let mut base = None;
 
-                    while self.token != token::RBRACE {
-                        if self.eat(&token::DOTDOT) {
-                            base = Some(self.parse_expr());
-                            break;
+                        while self.token != token::RBRACE {
+                            if self.eat(&token::DOTDOT) {
+                                base = Some(self.parse_expr());
+                                break;
+                            }
+
+                            fields.push(self.parse_field());
+                            self.commit_expr(fields.last().unwrap().expr,
+                                             &[token::COMMA], &[token::RBRACE]);
                         }
 
-                        fields.push(self.parse_field());
-                        self.commit_expr(fields.last().unwrap().expr,
-                                         &[token::COMMA], &[token::RBRACE]);
-                    }
+                        if fields.len() == 0 && base.is_none() {
+                            let last_span = self.last_span;
+                            self.span_err(last_span,
+                                          "structure literal must either have at \
+                                          least one field or use functional \
+                                          structure update syntax");
+                        }
 
-                    if fields.len() == 0 && base.is_none() {
-                        let last_span = self.last_span;
-                        self.span_err(last_span,
-                                      "structure literal must either have at \
-                                       least one field or use functional \
-                                       structure update syntax");
+                        hi = self.span.hi;
+                        self.expect(&token::RBRACE);
+                        ex = ExprStruct(pth, fields, base);
+                        return self.mk_expr(lo, hi, ex);
                     }
-
-                    hi = self.span.hi;
-                    self.expect(&token::RBRACE);
-                    ex = ExprStruct(pth, fields, base);
-                    return self.mk_expr(lo, hi, ex);
                 }
-            }
 
             hi = pth.span.hi;
             ex = ExprPath(pth);
-        } else {
-            // other literal expression
-            let lit = self.parse_lit();
-            hi = lit.span.hi;
-            ex = ExprLit(box(GC) lit);
+            },
+            _ => {
+                // other literal expression
+                let lit = self.parse_lit();
+                hi = lit.span.hi;
+                ex = ExprLit(box(GC) lit);
+            }
         }
 
         return self.mk_expr(lo, hi, ex);
@@ -3213,18 +3233,6 @@ impl<'a> Parser<'a> {
         } else if is_ident(&self.token)
             && !token::is_any_keyword(&self.token)
             && self.look_ahead(1, |t| *t == token::NOT) {
-            // parse a macro invocation. Looks like there's serious
-            // overlap here; if this clause doesn't catch it (and it
-            // won't, for brace-delimited macros) it will fall through
-            // to the macro clause of parse_item_or_view_item. This
-            // could use some cleanup, it appears to me.
-
-            // whoops! I now have a guess: I'm guessing the "parens-only"
-            // rule here is deliberate, to allow macro users to use parens
-            // for things that should be parsed as stmt_mac, and braces
-            // for things that should expand into items. Tricky, and
-            // somewhat awkward... and probably undocumented. Of course,
-            // I could just be wrong.
 
             check_expected_item(self, !item_attrs.is_empty());
 
@@ -3740,13 +3748,18 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn expect_self_ident(&mut self) {
-        if !self.is_self_ident() {
-            let token_str = self.this_token_to_string();
-            self.fatal(format!("expected `self` but found `{}`",
-                               token_str).as_slice())
+    fn expect_self_ident(&mut self) -> ast::Ident {
+        match self.token {
+            token::IDENT(id, false) if id.name == special_idents::self_.name => {
+                self.bump();
+                id
+            },
+            _ => {
+                let token_str = self.this_token_to_string();
+                self.fatal(format!("expected `self` but found `{}`",
+                                   token_str).as_slice())
+            }
         }
-        self.bump();
     }
 
     // parse the argument list and result type of a function
@@ -3766,24 +3779,21 @@ impl<'a> Parser<'a> {
 
             if this.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) {
                 this.bump();
-                this.expect_self_ident();
-                SelfRegion(None, MutImmutable)
+                SelfRegion(None, MutImmutable, this.expect_self_ident())
             } else if this.look_ahead(1, |t| Parser::token_is_mutability(t)) &&
                     this.look_ahead(2,
                                     |t| token::is_keyword(keywords::Self,
                                                           t)) {
                 this.bump();
                 let mutability = this.parse_mutability();
-                this.expect_self_ident();
-                SelfRegion(None, mutability)
+                SelfRegion(None, mutability, this.expect_self_ident())
             } else if this.look_ahead(1, |t| Parser::token_is_lifetime(t)) &&
                        this.look_ahead(2,
                                        |t| token::is_keyword(keywords::Self,
                                                              t)) {
                 this.bump();
                 let lifetime = this.parse_lifetime();
-                this.expect_self_ident();
-                SelfRegion(Some(lifetime), MutImmutable)
+                SelfRegion(Some(lifetime), MutImmutable, this.expect_self_ident())
             } else if this.look_ahead(1, |t| Parser::token_is_lifetime(t)) &&
                       this.look_ahead(2, |t| {
                           Parser::token_is_mutability(t)
@@ -3793,8 +3803,7 @@ impl<'a> Parser<'a> {
                 this.bump();
                 let lifetime = this.parse_lifetime();
                 let mutability = this.parse_mutability();
-                this.expect_self_ident();
-                SelfRegion(Some(lifetime), mutability)
+                SelfRegion(Some(lifetime), mutability, this.expect_self_ident())
             } else {
                 SelfStatic
             }
@@ -3814,15 +3823,13 @@ impl<'a> Parser<'a> {
                 // We need to make sure it isn't a type
                 if self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) {
                     self.bump();
-                    self.expect_self_ident();
-                    SelfUniq
+                    SelfUniq(self.expect_self_ident())
                 } else {
                     SelfStatic
                 }
             }
             token::IDENT(..) if self.is_self_ident() => {
-                self.bump();
-                SelfValue
+                SelfValue(self.expect_self_ident())
             }
             token::BINOP(token::STAR) => {
                 // Possibly "*self" or "*mut self" -- not supported. Try to avoid
@@ -3836,29 +3843,32 @@ impl<'a> Parser<'a> {
                     self.span_err(span, "cannot pass self by unsafe pointer");
                     self.bump();
                 }
-                SelfValue
+                // error case, making bogus self ident:
+                SelfValue(special_idents::self_)
             }
             _ if Parser::token_is_mutability(&self.token) &&
                     self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) => {
                 mutbl_self = self.parse_mutability();
-                self.expect_self_ident();
-                SelfValue
+                SelfValue(self.expect_self_ident())
             }
             _ if Parser::token_is_mutability(&self.token) &&
                     self.look_ahead(1, |t| *t == token::TILDE) &&
                     self.look_ahead(2, |t| token::is_keyword(keywords::Self, t)) => {
                 mutbl_self = self.parse_mutability();
                 self.bump();
-                self.expect_self_ident();
-                SelfUniq
+                SelfUniq(self.expect_self_ident())
             }
             _ => SelfStatic
         };
 
         let explicit_self_sp = mk_sp(lo, self.span.hi);
 
-        // If we parsed a self type, expect a comma before the argument list.
-        let fn_inputs = if explicit_self != SelfStatic {
+        // shared fall-through for the three cases below. borrowing prevents simply
+        // writing this as a closure
+        macro_rules! parse_remaining_arguments {
+            ($self_id:ident) =>
+            {
+            // If we parsed a self type, expect a comma before the argument list.
             match self.token {
                 token::COMMA => {
                     self.bump();
@@ -3868,11 +3878,11 @@ impl<'a> Parser<'a> {
                         sep,
                         parse_arg_fn
                     );
-                    fn_inputs.unshift(Arg::new_self(explicit_self_sp, mutbl_self));
+                    fn_inputs.unshift(Arg::new_self(explicit_self_sp, mutbl_self, $self_id));
                     fn_inputs
                 }
                 token::RPAREN => {
-                    vec!(Arg::new_self(explicit_self_sp, mutbl_self))
+                    vec!(Arg::new_self(explicit_self_sp, mutbl_self, $self_id))
                 }
                 _ => {
                     let token_str = self.this_token_to_string();
@@ -3880,11 +3890,21 @@ impl<'a> Parser<'a> {
                                        token_str).as_slice())
                 }
             }
-        } else {
-            let sep = seq_sep_trailing_disallowed(token::COMMA);
-            self.parse_seq_to_before_end(&token::RPAREN, sep, parse_arg_fn)
+            }
+        }
+
+        let fn_inputs = match explicit_self {
+            SelfStatic =>  {
+                let sep = seq_sep_trailing_disallowed(token::COMMA);
+                self.parse_seq_to_before_end(&token::RPAREN, sep, parse_arg_fn)
+            }
+            SelfValue(id) => parse_remaining_arguments!(id),
+            SelfRegion(_,_,id) => parse_remaining_arguments!(id),
+            SelfUniq(id) => parse_remaining_arguments!(id)
+
         };
 
+
         self.expect(&token::RPAREN);
 
         let hi = self.span.hi;
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 84834f54a04..55db3482a61 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -365,10 +365,6 @@ pub fn is_plain_ident(t: &Token) -> bool {
     match *t { IDENT(_, false) => true, _ => false }
 }
 
-pub fn is_bar(t: &Token) -> bool {
-    match *t { BINOP(OR) | OROR => true, _ => false }
-}
-
 // Get the first "argument"
 macro_rules! first {
     ( $first:expr, $( $remainder:expr, )* ) => ( $first )
@@ -409,6 +405,11 @@ macro_rules! declare_special_idents_and_keywords {(
         $( pub static $si_static: Ident = Ident { name: $si_name, ctxt: 0 }; )*
     }
 
+    pub mod special_names {
+        use ast::Name;
+        $( pub static $si_static: Name =  $si_name; )*
+    }
+
     /**
      * All the valid words that have meaning in the Rust language.
      *
@@ -417,7 +418,7 @@ macro_rules! declare_special_idents_and_keywords {(
      * the language and may not appear as identifiers.
      */
     pub mod keywords {
-        use ast::Ident;
+        use ast::Name;
 
         pub enum Keyword {
             $( $sk_variant, )*
@@ -425,10 +426,10 @@ macro_rules! declare_special_idents_and_keywords {(
         }
 
         impl Keyword {
-            pub fn to_ident(&self) -> Ident {
+            pub fn to_name(&self) -> Name {
                 match *self {
-                    $( $sk_variant => Ident { name: $sk_name, ctxt: 0 }, )*
-                    $( $rk_variant => Ident { name: $rk_name, ctxt: 0 }, )*
+                    $( $sk_variant => $sk_name, )*
+                    $( $rk_variant => $rk_name, )*
                 }
             }
         }
@@ -436,7 +437,7 @@ macro_rules! declare_special_idents_and_keywords {(
 
     fn mk_fresh_ident_interner() -> IdentInterner {
         // The indices here must correspond to the numbers in
-        // special_idents, in Keyword to_ident(), and in static
+        // special_idents, in Keyword to_name(), and in static
         // constants below.
         let mut init_vec = Vec::new();
         $(init_vec.push($si_str);)*
@@ -447,7 +448,7 @@ macro_rules! declare_special_idents_and_keywords {(
 }}
 
 // If the special idents get renumbered, remember to modify these two as appropriate
-static SELF_KEYWORD_NAME: Name = 1;
+pub static SELF_KEYWORD_NAME: Name = 1;
 static STATIC_KEYWORD_NAME: Name = 2;
 
 // NB: leaving holes in the ident table is bad! a different ident will get
@@ -714,7 +715,7 @@ pub fn fresh_mark() -> Mrk {
 
 pub fn is_keyword(kw: keywords::Keyword, tok: &Token) -> bool {
     match *tok {
-        token::IDENT(sid, false) => { kw.to_ident().name == sid.name }
+        token::IDENT(sid, false) => { kw.to_name() == sid.name }
         _ => { false }
     }
 }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index e695241472b..a5d70a9333d 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1967,13 +1967,13 @@ impl<'a> State<'a> {
         try!(self.print_mutability(mutbl));
         match explicit_self {
             ast::SelfStatic => { return Ok(false); }
-            ast::SelfValue => {
+            ast::SelfValue(_) => {
                 try!(word(&mut self.s, "self"));
             }
-            ast::SelfUniq => {
+            ast::SelfUniq(_) => {
                 try!(word(&mut self.s, "~self"));
             }
-            ast::SelfRegion(ref lt, m) => {
+            ast::SelfRegion(ref lt, m, _) => {
                 try!(word(&mut self.s, "&"));
                 try!(self.print_opt_lifetime(lt));
                 try!(self.print_mutability(m));
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 4ab064a88b7..df34ff30db6 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -202,8 +202,8 @@ pub fn walk_explicit_self<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                                    explicit_self: &ExplicitSelf,
                                                    env: E) {
     match explicit_self.node {
-        SelfStatic | SelfValue | SelfUniq => {}
-        SelfRegion(ref lifetime, _) => {
+        SelfStatic | SelfValue(_) | SelfUniq(_) => {},
+        SelfRegion(ref lifetime, _, _) => {
             visitor.visit_opt_lifetime_ref(explicit_self.span, lifetime, env)
         }
     }
diff --git a/src/test/run-pass/issue-7911.rs b/src/test/run-pass/issue-7911.rs
index 9e43e3ef1aa..75494c47dce 100644
--- a/src/test/run-pass/issue-7911.rs
+++ b/src/test/run-pass/issue-7911.rs
@@ -27,19 +27,19 @@ trait Test {
     fn get_mut<'r>(&'r mut self) -> &'r mut FooBar;
 }
 
-macro_rules! generate_test(($type_:path, $field:expr) => (
+macro_rules! generate_test(($type_:path, $slf:ident, $field:expr) => (
     impl Test for $type_ {
-        fn get_immut<'r>(&'r self) -> &'r FooBar {
+        fn get_immut<'r>(&'r $slf) -> &'r FooBar {
             &$field as &FooBar
         }
 
-        fn get_mut<'r>(&'r mut self) -> &'r mut FooBar {
+        fn get_mut<'r>(&'r mut $slf) -> &'r mut FooBar {
             &mut $field as &mut FooBar
         }
     }
 ))
 
-generate_test!(Foo, self.bar)
+generate_test!(Foo, self, self.bar)
 
 pub fn main() {
     let mut foo: Foo = Foo { bar: Bar(42) };