diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index becceffe6d027..c1d782991b43d 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -185,7 +185,7 @@ impl TreeMap { 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 TreeMap { /// 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 TreeMap { /// 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 TreeMap { /// 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 1fae362471d9c..3230873883e19 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 { impl_to_primitive_int_to_int!($T, int) } + fn to_int(&self) -> Option { impl_to_primitive_int_to_int!($T, int, *self) } #[inline] - fn to_i8(&self) -> Option { impl_to_primitive_int_to_int!($T, i8) } + fn to_i8(&self) -> Option { impl_to_primitive_int_to_int!($T, i8, *self) } #[inline] - fn to_i16(&self) -> Option { impl_to_primitive_int_to_int!($T, i16) } + fn to_i16(&self) -> Option { impl_to_primitive_int_to_int!($T, i16, *self) } #[inline] - fn to_i32(&self) -> Option { impl_to_primitive_int_to_int!($T, i32) } + fn to_i32(&self) -> Option { impl_to_primitive_int_to_int!($T, i32, *self) } #[inline] - fn to_i64(&self) -> Option { impl_to_primitive_int_to_int!($T, i64) } + fn to_i64(&self) -> Option { impl_to_primitive_int_to_int!($T, i64, *self) } #[inline] - fn to_uint(&self) -> Option { impl_to_primitive_int_to_uint!($T, uint) } + fn to_uint(&self) -> Option { impl_to_primitive_int_to_uint!($T, uint, *self) } #[inline] - fn to_u8(&self) -> Option { impl_to_primitive_int_to_uint!($T, u8) } + fn to_u8(&self) -> Option { impl_to_primitive_int_to_uint!($T, u8, *self) } #[inline] - fn to_u16(&self) -> Option { impl_to_primitive_int_to_uint!($T, u16) } + fn to_u16(&self) -> Option { impl_to_primitive_int_to_uint!($T, u16, *self) } #[inline] - fn to_u32(&self) -> Option { impl_to_primitive_int_to_uint!($T, u32) } + fn to_u32(&self) -> Option { impl_to_primitive_int_to_uint!($T, u32, *self) } #[inline] - fn to_u64(&self) -> Option { impl_to_primitive_int_to_uint!($T, u64) } + fn to_u64(&self) -> Option { impl_to_primitive_int_to_uint!($T, u64, *self) } #[inline] fn to_f32(&self) -> Option { 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 { impl_to_primitive_uint_to_int!(int) } + fn to_int(&self) -> Option { impl_to_primitive_uint_to_int!(int, *self) } #[inline] - fn to_i8(&self) -> Option { impl_to_primitive_uint_to_int!(i8) } + fn to_i8(&self) -> Option { impl_to_primitive_uint_to_int!(i8, *self) } #[inline] - fn to_i16(&self) -> Option { impl_to_primitive_uint_to_int!(i16) } + fn to_i16(&self) -> Option { impl_to_primitive_uint_to_int!(i16, *self) } #[inline] - fn to_i32(&self) -> Option { impl_to_primitive_uint_to_int!(i32) } + fn to_i32(&self) -> Option { impl_to_primitive_uint_to_int!(i32, *self) } #[inline] - fn to_i64(&self) -> Option { impl_to_primitive_uint_to_int!(i64) } + fn to_i64(&self) -> Option { impl_to_primitive_uint_to_int!(i64, *self) } #[inline] - fn to_uint(&self) -> Option { impl_to_primitive_uint_to_uint!($T, uint) } + fn to_uint(&self) -> Option { impl_to_primitive_uint_to_uint!($T, uint, *self) } #[inline] - fn to_u8(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u8) } + fn to_u8(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u8, *self) } #[inline] - fn to_u16(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u16) } + fn to_u16(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u16, *self) } #[inline] - fn to_u32(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u32) } + fn to_u32(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u32, *self) } #[inline] - fn to_u64(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u64) } + fn to_u64(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u64, *self) } #[inline] fn to_f32(&self) -> Option { 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 { Some(*self as u64) } #[inline] - fn to_f32(&self) -> Option { impl_to_primitive_float_to_float!($T, f32) } + fn to_f32(&self) -> Option { impl_to_primitive_float_to_float!($T, f32, *self) } #[inline] - fn to_f64(&self) -> Option { impl_to_primitive_float_to_float!($T, f64) } + fn to_f64(&self) -> Option { impl_to_primitive_float_to_float!($T, f64, *self) } } ) ) @@ -1104,38 +1104,38 @@ pub fn from_f64(n: f64) -> Option { } 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 0b9ed37c8384b..8a2b95ae463b4 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 6c544e3809a07..fbf0288418ab8 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 612b29afd3e9c..129a5b7c6bed3 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, // 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 e1d43c5240059..c79e435707aee 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 d565f144f3656..90331d8f43430 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(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(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 c1a000841a4d1..a184ecac9dea6 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 cdd51c4fa7126..b0c9900be909c 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 { 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(<.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 587bedd502e15..2581ba51c2e10 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 6c40ee21040ad..af0b6a1cb21d1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -775,9 +775,9 @@ impl Clean 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 d98ae9f0e33a0..5f3adbdb54df4 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, Mutability), // `&'lt self`, `&'lt mut self` - SelfUniq // `~self` + SelfStatic, // no self + SelfValue(Ident), // `self` + SelfRegion(Option, Mutability, Ident), // `&'lt self`, `&'lt mut self` + SelfUniq(Ident), // `~self` } pub type ExplicitSelf = Spanned; +// 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 a540b23551b53..a2a442f8b6aa7 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, Option), + + /// 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, Option), } 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 7ad11b186f500..764c88cc954ed 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 28f39a4cb8c0f..b53281f99633f 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) -> (Gc, 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 74cede2a125ad..9fe431cfb6c75 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -484,6 +484,24 @@ fn expand_item_mac(it: Gc, 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, 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 { + 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) -> Gc { + 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 + = 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 - = 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 - = 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 913e0427bda22..b30ede70f0e4b 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 ee4810b4b5430..bcdf920e5dd41 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 a3917e9319798..ac4cbf3aa8e55 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 84834f54a04eb..55db3482a61a7 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 e695241472b09..a5d70a9333dde 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 4ab064a88b795..df34ff30db67f 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -202,8 +202,8 @@ pub fn walk_explicit_self>(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 9e43e3ef1aa75..75494c47dcef1 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) };