diff options
| author | bors <bors@rust-lang.org> | 2015-01-06 08:25:32 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-01-06 08:25:32 +0000 |
| commit | 340ac040f7603e169a3739c65956ed2213622be5 (patch) | |
| tree | 0502e3fcb9ceaa41d36c707e95baf0d7740fc3fd /src/libsyntax | |
| parent | c7dd3c4d69aee1c4ad8cc220c194b176bba2ab62 (diff) | |
| parent | 4b359e3aeeaf97a190c5a7ecff8815b7b5734ece (diff) | |
auto merge of #20610 : alexcrichton/rust/rollup, r=alexcrichton
Diffstat (limited to 'src/libsyntax')
25 files changed, 490 insertions, 385 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index e779821342a..7aa7c4fcfb3 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -476,7 +476,7 @@ pub struct Crate { pub attrs: Vec<Attribute>, pub config: CrateConfig, pub span: Span, - pub exported_macros: Vec<P<Item>> + pub exported_macros: Vec<MacroDef>, } pub type MetaItem = Spanned<MetaItem_>; @@ -572,7 +572,7 @@ pub enum Pat_ { PatStruct(Path, Vec<Spanned<FieldPat>>, bool), PatTup(Vec<P<Pat>>), PatBox(P<Pat>), - PatRegion(P<Pat>), // reference pattern + PatRegion(P<Pat>, Mutability), // reference pattern PatLit(P<Expr>), PatRange(P<Expr>, P<Expr>), /// [a, b, ..i, y, z] is represented as: @@ -884,6 +884,7 @@ impl TokenTree { match *self { TtToken(_, token::DocComment(_)) => 2, TtToken(_, token::SubstNt(..)) => 2, + TtToken(_, token::SpecialVarNt(..)) => 2, TtToken(_, token::MatchNt(..)) => 3, TtDelimited(_, ref delimed) => { delimed.tts.len() + 2 @@ -925,6 +926,12 @@ impl TokenTree { TtToken(sp, token::Ident(name, name_st))]; v[index] } + (&TtToken(sp, token::SpecialVarNt(var)), _) => { + let v = [TtToken(sp, token::Dollar), + TtToken(sp, token::Ident(token::str_to_ident(var.as_str()), + token::Plain))]; + v[index] + } (&TtToken(sp, token::MatchNt(name, kind, name_st, kind_st)), _) => { let v = [TtToken(sp, token::SubstNt(name, name_st)), TtToken(sp, token::Colon), @@ -1689,6 +1696,21 @@ pub enum InlinedItem { IIForeign(P<ForeignItem>), } +/// A macro definition, in this crate or imported from another. +/// +/// Not parsed directly, but created on macro import or `macro_rules!` expansion. +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] +pub struct MacroDef { + pub ident: Ident, + pub attrs: Vec<Attribute>, + pub id: NodeId, + pub span: Span, + pub imported_from: Option<Ident>, + pub export: bool, + pub use_locally: bool, + pub body: Vec<TokenTree>, +} + #[cfg(test)] mod test { use serialize::json; diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 4026da6cf8e..5e03afec16c 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -633,7 +633,7 @@ pub fn walk_pat<F>(pat: &Pat, mut it: F) -> bool where F: FnMut(&Pat) -> bool { PatEnum(_, Some(ref s)) | PatTup(ref s) => { s.iter().all(|p| walk_pat_(&**p, it)) } - PatBox(ref s) | PatRegion(ref s) => { + PatBox(ref s) | PatRegion(ref s, _) => { walk_pat_(&**s, it) } PatVec(ref before, ref slice, ref after) => { diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs index 3107508a96a..34a193dffd3 100644 --- a/src/libsyntax/diagnostics/macros.rs +++ b/src/libsyntax/diagnostics/macros.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![macro_escape] - #[macro_export] macro_rules! register_diagnostic { ($code:tt, $description:tt) => (__register_diagnostic! { $code, $description }); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 91cc8a24622..91ae7396ea4 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -16,6 +16,7 @@ use codemap; use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION}; use ext; use ext::expand; +use ext::tt::macro_rules; use parse; use parse::parser; use parse::token; @@ -28,19 +29,6 @@ use fold::Folder; use std::collections::HashMap; use std::rc::Rc; -// new-style macro! tt code: -// -// MacResult, NormalTT, IdentTT -// -// also note that ast::Mac used to have a bunch of extraneous cases and -// is now probably a redundant AST node, can be merged with -// ast::MacInvocTT. - -pub struct MacroDef { - pub name: String, - pub ext: SyntaxExtension -} - pub trait ItemDecorator { fn expand(&self, ecx: &mut ExtCtxt, @@ -140,13 +128,6 @@ impl<F> IdentMacroExpander for F /// methods are spliced into the AST at the callsite of the macro (or /// just into the compiler's internal macro table, for `make_def`). pub trait MacResult { - /// Attempt to define a new macro. - // this should go away; the idea that a macro might expand into - // either a macro definition or an expression, depending on what - // the context wants, is kind of silly. - fn make_def(&mut self) -> Option<MacroDef> { - None - } /// Create an expression. fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> { None @@ -328,13 +309,8 @@ pub enum SyntaxExtension { /// 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>), + /// Represents `macro_rules!` itself. + MacroRulesTT, } pub type NamedSyntaxExtension = (Name, SyntaxExtension); @@ -364,8 +340,7 @@ fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv { } let mut syntax_expanders = SyntaxEnv::new(); - syntax_expanders.insert(intern("macro_rules"), - LetSyntaxTT(box ext::tt::macro_rules::add_new_extension, None)); + syntax_expanders.insert(intern("macro_rules"), MacroRulesTT); syntax_expanders.insert(intern("fmt"), builtin_normal_expander( ext::fmt::expand_syntax_ext)); @@ -475,7 +450,7 @@ pub struct ExtCtxt<'a> { pub mod_path: Vec<ast::Ident> , pub trace_mac: bool, - pub exported_macros: Vec<P<ast::Item>>, + pub exported_macros: Vec<ast::MacroDef>, pub syntax_env: SyntaxEnv, pub recursion_count: uint, @@ -594,6 +569,17 @@ impl<'a> ExtCtxt<'a> { } } } + + pub fn insert_macro(&mut self, def: ast::MacroDef) { + if def.export { + self.exported_macros.push(def.clone()); + } + if def.use_locally { + let ext = macro_rules::compile(self, &def); + self.syntax_env.insert(def.ident.name, ext); + } + } + /// Emit `msg` attached to `sp`, and stop compilation immediately. /// /// `span_err` should be strongly preferred where-ever possible: diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index 84d30a99004..7cb7ee3d355 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -61,7 +61,7 @@ pub fn expand_deriving_eq<F>(cx: &mut ExtCtxt, cx, span, substr) } - macro_rules! md ( + macro_rules! md { ($name:expr, $f:ident) => { { let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); @@ -77,7 +77,7 @@ pub fn expand_deriving_eq<F>(cx: &mut ExtCtxt, }) } } } - ); + } let trait_def = TraitDef { span: span, diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index f9c8d95b308..c126238be82 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -27,7 +27,7 @@ pub fn expand_deriving_ord<F>(cx: &mut ExtCtxt, push: F) where F: FnOnce(P<Item>), { - macro_rules! md ( + macro_rules! md { ($name:expr, $op:expr, $equal:expr) => { { let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); @@ -43,7 +43,7 @@ pub fn expand_deriving_ord<F>(cx: &mut ExtCtxt, }) } } } - ); + } let ordering_ty = Literal(Path::new(vec!["std", "cmp", "Ordering"])); let ret_ty = Literal(Path::new_(vec!["std", "option", "Option"], diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 1fb8189c63c..1aa430c4a08 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -937,7 +937,7 @@ impl<'a> MethodDef<'a> { &**variant, self_arg_name, ast::MutImmutable); - (cx.pat(sp, ast::PatRegion(p)), idents) + (cx.pat(sp, ast::PatRegion(p, ast::MutImmutable)), idents) }; // A single arm has form (&VariantK, &VariantK, ...) => BodyK diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index b9acde4bf6b..844bd80d161 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -25,20 +25,14 @@ pub fn expand_deriving_hash<F>(cx: &mut ExtCtxt, F: FnOnce(P<Item>), { - let (path, generics, args) = if cx.ecfg.deriving_hash_type_parameter { - (Path::new_(vec!("std", "hash", "Hash"), None, - vec!(box Literal(Path::new_local("__S"))), true), - LifetimeBounds { - lifetimes: Vec::new(), - bounds: vec!(("__S", - vec!(Path::new(vec!("std", "hash", "Writer"))))), - }, - Path::new_local("__S")) - } else { - (Path::new(vec!("std", "hash", "Hash")), - LifetimeBounds::empty(), - Path::new(vec!("std", "hash", "sip", "SipState"))) + let path = Path::new_(vec!("std", "hash", "Hash"), None, + vec!(box Literal(Path::new_local("__S"))), true); + let generics = LifetimeBounds { + lifetimes: Vec::new(), + bounds: vec!(("__S", + vec!(Path::new(vec!("std", "hash", "Writer"))))), }; + let args = Path::new_local("__S"); let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); let hash_trait_def = TraitDef { diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 14b19fee3df..e72c83b67c8 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -71,9 +71,11 @@ pub fn expand_meta_derive(cx: &mut ExtCtxt, MetaNameValue(ref tname, _) | MetaList(ref tname, _) | MetaWord(ref tname) => { - macro_rules! expand(($func:path) => ($func(cx, titem.span, - &**titem, item, - |i| push.call_mut((i,))))); + macro_rules! expand { + ($func:path) => ($func(cx, titem.span, &**titem, item, + |i| push.call_mut((i,)))) + } + match tname.get() { "Clone" => expand!(clone::expand_deriving_clone), diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index b3f30dd4581..212ec3b0903 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -7,7 +7,6 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. -use self::Either::*; use ast::{Block, Crate, DeclLocal, ExprMac, PatMac}; use ast::{Local, Ident, MacInvocTT}; @@ -33,11 +32,6 @@ use util::small_vector::SmallVector; use visit; use visit::Visitor; -enum Either<L,R> { - Left(L), - Right(R) -} - pub fn expand_type(t: P<ast::Ty>, fld: &mut MacroExpander, impl_ty: Option<P<ast::Ty>>) @@ -445,9 +439,9 @@ pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander) if valid_ident { fld.cx.mod_push(it.ident); } - let macro_escape = contains_macro_escape(new_attrs[]); + let macro_use = contains_macro_use(fld, new_attrs[]); let result = with_exts_frame!(fld.cx.syntax_env, - macro_escape, + macro_use, noop_fold_item(it, fld)); if valid_ident { fld.cx.mod_pop(); @@ -527,15 +521,34 @@ fn expand_item_underscore(item: ast::Item_, fld: &mut MacroExpander) -> ast::Ite } } -// does this attribute list contain "macro_escape" ? -fn contains_macro_escape(attrs: &[ast::Attribute]) -> bool { - attr::contains_name(attrs, "macro_escape") +// does this attribute list contain "macro_use" ? +fn contains_macro_use(fld: &mut MacroExpander, attrs: &[ast::Attribute]) -> bool { + for attr in attrs.iter() { + let mut is_use = attr.check_name("macro_use"); + if attr.check_name("macro_escape") { + fld.cx.span_warn(attr.span, "macro_escape is a deprecated synonym for macro_use"); + is_use = true; + if let ast::AttrInner = attr.node.style { + fld.cx.span_help(attr.span, "consider an outer attribute, \ + #[macro_use] mod ..."); + } + }; + + if is_use { + match attr.node.value.node { + ast::MetaWord(..) => (), + _ => fld.cx.span_err(attr.span, "arguments to macro_use are not allowed here"), + } + return true; + } + } + false } // Support for item-position macro invocations, exactly the same // logic as for expression-position macro invocations. -pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander) - -> SmallVector<P<ast::Item>> { +pub fn expand_item_mac(it: P<ast::Item>, + fld: &mut MacroExpander) -> SmallVector<P<ast::Item>> { let (extname, path_span, tts) = match it.node { ItemMac(codemap::Spanned { node: MacInvocTT(ref pth, ref tts, _), @@ -548,8 +561,8 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander) let extnamestr = token::get_ident(extname); let fm = fresh_mark(); - let def_or_items = { - let mut expanded = match fld.cx.syntax_env.find(&extname.name) { + let items = { + let expanded = match fld.cx.syntax_env.find(&extname.name) { None => { fld.cx.span_err(path_span, format!("macro undefined: '{}!'", @@ -600,11 +613,10 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander) let marked_tts = mark_tts(tts[], fm); expander.expand(fld.cx, it.span, it.ident, marked_tts) } - LetSyntaxTT(ref expander, span) => { + MacroRulesTT => { if it.ident.name == parse::token::special_idents::invalid.name { fld.cx.span_err(path_span, - format!("macro {}! expects an ident argument", - extnamestr.get())[]); + format!("macro_rules! expects an ident argument")[]); return SmallVector::zero(); } fld.cx.bt_push(ExpnInfo { @@ -612,11 +624,26 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander) callee: NameAndSpan { name: extnamestr.get().to_string(), format: MacroBang, - span: span + span: None, } }); - // DON'T mark before expansion: - expander.expand(fld.cx, it.span, it.ident, tts) + // DON'T mark before expansion. + + let def = ast::MacroDef { + ident: it.ident, + attrs: it.attrs.clone(), + id: ast::DUMMY_NODE_ID, + span: it.span, + imported_from: None, + export: attr::contains_name(it.attrs.as_slice(), "macro_export"), + use_locally: true, + body: tts, + }; + fld.cx.insert_macro(def); + + // macro_rules! has a side effect but expands to nothing. + fld.cx.bt_pop(); + return SmallVector::zero(); } _ => { fld.cx.span_err(it.span, @@ -627,31 +654,17 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander) } }; - match expanded.make_def() { - Some(def) => Left(def), - None => Right(expanded.make_items()) - } + expanded.make_items() }; - let items = match def_or_items { - Left(MacroDef { name, ext }) => { - // 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.cx.syntax_env.insert(intern(name[]), ext); - if attr::contains_name(it.attrs[], "macro_export") { - fld.cx.exported_macros.push(it); - } - SmallVector::zero() - } - Right(Some(items)) => { + let items = match items { + Some(items) => { items.into_iter() .map(|i| mark_item(i, fm)) .flat_map(|i| fld.fold_item(i).into_iter()) .collect() } - Right(None) => { + None => { fld.cx.span_err(path_span, format!("non-item macro in item position: {}", extnamestr.get())[]); @@ -664,9 +677,6 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander) } /// Expand a stmt -// -// I don't understand why this returns a vector... it looks like we're -// half done adding machinery to allow macros to expand into multiple statements. fn expand_stmt(s: Stmt, fld: &mut MacroExpander) -> SmallVector<P<Stmt>> { let (mac, style) = match s.node { StmtMac(mac, style) => (mac, style), @@ -976,8 +986,8 @@ impl<'a> Folder for IdentRenamer<'a> { ctxt: mtwt::apply_renames(self.renames, id.ctxt), } } - fn fold_mac(&mut self, macro: ast::Mac) -> ast::Mac { - fold::noop_fold_mac(macro, self) + fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { + fold::noop_fold_mac(mac, self) } } @@ -1013,8 +1023,8 @@ impl<'a> Folder for PatIdentRenamer<'a> { _ => unreachable!() }) } - fn fold_mac(&mut self, macro: ast::Mac) -> ast::Mac { - fold::noop_fold_mac(macro, self) + fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { + fold::noop_fold_mac(mac, self) } } @@ -1161,7 +1171,6 @@ fn new_span(cx: &ExtCtxt, sp: Span) -> Span { pub struct ExpansionConfig { pub crate_name: String, - pub deriving_hash_type_parameter: bool, pub enable_quotes: bool, pub recursion_limit: uint, } @@ -1170,38 +1179,23 @@ impl ExpansionConfig { pub fn default(crate_name: String) -> ExpansionConfig { ExpansionConfig { crate_name: crate_name, - deriving_hash_type_parameter: false, enable_quotes: false, recursion_limit: 64, } } } -pub struct ExportedMacros { - pub crate_name: Ident, - pub macros: Vec<String>, -} - pub fn expand_crate(parse_sess: &parse::ParseSess, cfg: ExpansionConfig, // these are the macros being imported to this crate: - imported_macros: Vec<ExportedMacros>, + imported_macros: Vec<ast::MacroDef>, user_exts: Vec<NamedSyntaxExtension>, c: Crate) -> Crate { let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg); let mut expander = MacroExpander::new(&mut cx); - for ExportedMacros { crate_name, macros } in imported_macros.into_iter() { - let name = format!("<{} macros>", token::get_ident(crate_name)); - - for source in macros.into_iter() { - let item = parse::parse_item_from_source_str(name.clone(), - source, - expander.cx.cfg(), - expander.cx.parse_sess()) - .expect("expected a serialized item"); - expand_item_mac(item, &mut expander); - } + for def in imported_macros.into_iter() { + expander.cx.insert_macro(def); } for (name, extension) in user_exts.into_iter() { @@ -1290,8 +1284,8 @@ struct MacroExterminator<'a>{ } impl<'a, 'v> Visitor<'v> for MacroExterminator<'a> { - fn visit_mac(&mut self, macro: &ast::Mac) { - self.sess.span_diagnostic.span_bug(macro.span, + fn visit_mac(&mut self, mac: &ast::Mac) { + self.sess.span_diagnostic.span_bug(mac.span, "macro exterminator: expected AST \ with no macro invocations"); } @@ -1300,7 +1294,7 @@ impl<'a, 'v> Visitor<'v> for MacroExterminator<'a> { #[cfg(test)] mod test { - use super::{pattern_bindings, expand_crate, contains_macro_escape}; + use super::{pattern_bindings, expand_crate, contains_macro_use}; use super::{PatIdentFinder, IdentRenamer, PatIdentRenamer, ExpansionConfig}; use ast; use ast::{Attribute_, AttrOuter, MetaWord, Name}; @@ -1397,9 +1391,9 @@ mod test { expand_crate(&sess,test_ecfg(),vec!(),vec!(),crate_ast); } - // macro_escape modules should allow macros to escape + // macro_use modules should allow macros to escape #[test] fn macros_can_escape_flattened_mods_test () { - let src = "#[macro_escape] mod foo {macro_rules! z (() => (3+4));}\ + let src = "#[macro_use] mod foo {macro_rules! z (() => (3+4));}\ fn inty() -> int { z!() }".to_string(); let sess = parse::new_parse_sess(); let crate_ast = parse::parse_crate_from_source_str( @@ -1409,16 +1403,6 @@ mod test { expand_crate(&sess, test_ecfg(), vec!(), vec!(), crate_ast); } - #[test] fn test_contains_flatten (){ - let attr1 = make_dummy_attr ("foo"); - let attr2 = make_dummy_attr ("bar"); - let escape_attr = make_dummy_attr ("macro_escape"); - let attrs1 = vec!(attr1.clone(), escape_attr, attr2.clone()); - assert_eq!(contains_macro_escape(attrs1[]),true); - let attrs2 = vec!(attr1,attr2); - assert_eq!(contains_macro_escape(attrs2[]),false); - } - // make a MetaWord outer attribute with the given name fn make_dummy_attr(s: &str) -> ast::Attribute { Spanned { diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index e46bd7ac4bc..f1b52fa33c3 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -85,14 +85,14 @@ pub mod rt { */ // FIXME: Move this trait to pprust and get rid of *_to_str? - pub trait ToSource for Sized? { + pub trait ToSource { // Takes a thing and generates a string containing rust code for it. fn to_source(&self) -> String; } // FIXME (Issue #16472): This should go away after ToToken impls // are revised to go directly to token-trees. - trait ToSourceWithHygiene for Sized? : ToSource { + trait ToSourceWithHygiene : ToSource { // Takes a thing and generates a string containing rust code // for it, encoding Idents as special byte sequences to // maintain hygiene across serialization and deserialization. diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 08014dc1338..9837c8088fa 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -11,7 +11,7 @@ use ast::{Ident, TtDelimited, TtSequence, TtToken}; use ast; use codemap::{Span, DUMMY_SP}; -use ext::base::{ExtCtxt, MacResult, MacroDef}; +use ext::base::{ExtCtxt, MacResult, SyntaxExtension}; use ext::base::{NormalTT, TTMacroExpander}; use ext::tt::macro_parser::{Success, Error, Failure}; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; @@ -38,8 +38,8 @@ impl<'a> ParserAnyMacro<'a> { /// Make sure we don't have any tokens left to parse, so we don't /// silently drop anything. `allow_semi` is so that "optional" /// semicolons at the end of normal expressions aren't complained - /// about e.g. the semicolon in `macro_rules! kapow( () => { - /// panic!(); } )` doesn't get picked up by .parse_expr(), but it's + /// about e.g. the semicolon in `macro_rules! kapow { () => { + /// panic!(); } }` doesn't get picked up by .parse_expr(), but it's /// allowed to be there. fn ensure_complete_parse(&self, allow_semi: bool) { let mut parser = self.parser.borrow_mut(); @@ -110,6 +110,7 @@ impl<'a> MacResult for ParserAnyMacro<'a> { struct MacroRulesMacroExpander { name: Ident, + imported_from: Option<Ident>, lhses: Vec<Rc<NamedMatch>>, rhses: Vec<Rc<NamedMatch>>, } @@ -123,25 +124,18 @@ impl TTMacroExpander for MacroRulesMacroExpander { generic_extension(cx, sp, self.name, + self.imported_from, arg, self.lhses[], self.rhses[]) } } -struct MacroRulesDefiner { - def: Option<MacroDef> -} -impl MacResult for MacroRulesDefiner { - fn make_def(&mut self) -> Option<MacroDef> { - Some(self.def.take().expect("empty MacroRulesDefiner")) - } -} - /// Given `lhses` and `rhses`, this is the new macro we create fn generic_extension<'cx>(cx: &'cx ExtCtxt, sp: Span, name: Ident, + imported_from: Option<Ident>, arg: &[ast::TokenTree], lhses: &[Rc<NamedMatch>], rhses: &[Rc<NamedMatch>]) @@ -166,6 +160,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, // `None` is because we're not interpolating let mut arg_rdr = new_tt_reader(&cx.parse_sess().span_diagnostic, None, + None, arg.iter() .map(|x| (*x).clone()) .collect()); @@ -186,6 +181,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, // rhs has holes ( `$id` and `$(...)` that need filled) let trncbr = new_tt_reader(&cx.parse_sess().span_diagnostic, Some(named_matches), + imported_from, rhs); let p = Parser::new(cx.parse_sess(), cx.cfg(), box trncbr); // Let the context choose how to interpret the result. @@ -212,14 +208,9 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, // // Holy self-referential! -/// This procedure performs the expansion of the -/// macro_rules! macro. It parses the RHS and adds -/// an extension to the current context. -pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt, - sp: Span, - name: Ident, - arg: Vec<ast::TokenTree> ) - -> Box<MacResult+'cx> { +/// Converts a `macro_rules!` invocation into a syntax extension. +pub fn compile<'cx>(cx: &'cx mut ExtCtxt, + def: &ast::MacroDef) -> SyntaxExtension { let lhs_nm = gensym_ident("lhs"); let rhs_nm = gensym_ident("rhs"); @@ -256,7 +247,8 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt, // Parse the macro_rules! invocation (`none` is for no interpolations): let arg_reader = new_tt_reader(&cx.parse_sess().span_diagnostic, None, - arg.clone()); + None, + def.body.clone()); let argument_map = parse_or_else(cx.parse_sess(), cx.cfg(), arg_reader, @@ -265,24 +257,20 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt, // Extract the arguments: let lhses = match *argument_map[lhs_nm] { MatchedSeq(ref s, _) => /* FIXME (#2543) */ (*s).clone(), - _ => cx.span_bug(sp, "wrong-structured lhs") + _ => cx.span_bug(def.span, "wrong-structured lhs") }; let rhses = match *argument_map[rhs_nm] { MatchedSeq(ref s, _) => /* FIXME (#2543) */ (*s).clone(), - _ => cx.span_bug(sp, "wrong-structured rhs") + _ => cx.span_bug(def.span, "wrong-structured rhs") }; let exp = box MacroRulesMacroExpander { - name: name, + name: def.ident, + imported_from: def.imported_from, lhses: lhses, rhses: rhses, }; - box MacroRulesDefiner { - def: Some(MacroDef { - name: token::get_ident(name).to_string(), - ext: NormalTT(exp, Some(sp)) - }) - } as Box<MacResult+'cx> + NormalTT(exp, Some(def.span)) } diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 86e81ede8b0..e4e6f5ac6b0 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -15,7 +15,7 @@ use codemap::{Span, DUMMY_SP}; use diagnostic::SpanHandler; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; use parse::token::{Eof, DocComment, Interpolated, MatchNt, SubstNt}; -use parse::token::{Token, NtIdent}; +use parse::token::{Token, NtIdent, SpecialMacroVar}; use parse::token; use parse::lexer::TokenAndSpan; @@ -39,6 +39,10 @@ pub struct TtReader<'a> { stack: Vec<TtFrame>, /* for MBE-style macro transcription */ interpolations: HashMap<Ident, Rc<NamedMatch>>, + imported_from: Option<Ident>, + + // Some => return imported_from as the next token + crate_name_next: Option<Span>, repeat_idx: Vec<uint>, repeat_len: Vec<uint>, /* cached: */ @@ -53,6 +57,7 @@ pub struct TtReader<'a> { /// should) be none. pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler, interp: Option<HashMap<Ident, Rc<NamedMatch>>>, + imported_from: Option<Ident>, src: Vec<ast::TokenTree> ) -> TtReader<'a> { let mut r = TtReader { @@ -71,6 +76,8 @@ pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler, None => HashMap::new(), Some(x) => x, }, + imported_from: imported_from, + crate_name_next: None, repeat_idx: Vec::new(), repeat_len: Vec::new(), desugar_doc_comments: false, @@ -162,6 +169,14 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { sp: r.cur_span.clone(), }; loop { + match r.crate_name_next.take() { + None => (), + Some(sp) => { + r.cur_span = sp; + r.cur_tok = token::Ident(r.imported_from.unwrap(), token::Plain); + return ret_val; + }, + } let should_pop = match r.stack.last() { None => { assert_eq!(ret_val.tok, token::Eof); @@ -307,6 +322,18 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { sep: None }); } + TtToken(sp, token::SpecialVarNt(SpecialMacroVar::CrateMacroVar)) => { + r.stack.last_mut().unwrap().idx += 1; + + if r.imported_from.is_some() { + r.cur_span = sp; + r.cur_tok = token::ModSep; + r.crate_name_next = Some(sp); + return ret_val; + } + + // otherwise emit nothing and proceed to the next token + } TtToken(sp, tok) => { r.cur_span = sp; r.cur_tok = tok; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index cb6277069e1..0810d4ee93a 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -36,15 +36,15 @@ use std::ascii::AsciiExt; // if you change this list without updating src/doc/reference.md, @cmr will be sad static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ - ("globs", Active), - ("macro_rules", Active), + ("globs", Accepted), + ("macro_rules", Accepted), ("struct_variant", Accepted), ("asm", Active), ("managed_boxes", Removed), ("non_ascii_idents", Active), ("thread_local", Active), ("link_args", Active), - ("phase", Active), + ("phase", Active), // NOTE(stage0): switch to Removed after next snapshot ("plugin_registrar", Active), ("log_syntax", Active), ("trace_macros", Active), @@ -54,7 +54,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ ("lang_items", Active), ("simd", Active), - ("default_type_params", Active), + ("default_type_params", Accepted), ("quote", Active), ("link_llvm_intrinsics", Active), ("linkage", Active), @@ -67,13 +67,15 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ ("import_shadowing", Active), ("advanced_slice_patterns", Active), ("tuple_indexing", Accepted), - ("associated_types", Active), + ("associated_types", Accepted), ("visible_private_types", Active), ("slicing_syntax", Active), ("if_let", Accepted), ("while_let", Accepted), + ("plugin", Active), + // A temporary feature gate used to enable parser extensions needed // to bootstrap fix for #5723. ("issue_5723_bootstrap", Accepted), @@ -112,7 +114,6 @@ enum Status { /// A set of features to be used by later passes. #[derive(Copy)] pub struct Features { - pub default_type_params: bool, pub unboxed_closures: bool, pub rustc_diagnostic_macros: bool, pub import_shadowing: bool, @@ -125,7 +126,6 @@ pub struct Features { impl Features { pub fn new() -> Features { Features { - default_type_params: false, unboxed_closures: false, rustc_diagnostic_macros: false, import_shadowing: false, @@ -163,32 +163,11 @@ struct MacroVisitor<'a> { } impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> { - fn visit_view_item(&mut self, i: &ast::ViewItem) { - match i.node { - ast::ViewItemExternCrate(..) => { - for attr in i.attrs.iter() { - if attr.name().get() == "phase"{ - self.context.gate_feature("phase", attr.span, - "compile time crate loading is \ - experimental and possibly buggy"); - } - } - }, - _ => { } - } - visit::walk_view_item(self, i) - } - - fn visit_mac(&mut self, macro: &ast::Mac) { - let ast::MacInvocTT(ref path, _, _) = macro.node; + fn visit_mac(&mut self, mac: &ast::Mac) { + let ast::MacInvocTT(ref path, _, _) = mac.node; let id = path.segments.last().unwrap().identifier; - if id == token::str_to_ident("macro_rules") { - self.context.gate_feature("macro_rules", path.span, "macro definitions are \ - not stable enough for use and are subject to change"); - } - - else if id == token::str_to_ident("asm") { + if id == token::str_to_ident("asm") { self.context.gate_feature("asm", path.span, "inline assembly is not \ stable enough for use and is subject to change"); } @@ -232,19 +211,13 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { fn visit_view_item(&mut self, i: &ast::ViewItem) { match i.node { - ast::ViewItemUse(ref path) => { - if let ast::ViewPathGlob(..) = path.node { - self.gate_feature("globs", path.span, - "glob import statements are \ - experimental and possibly buggy"); - } - } + ast::ViewItemUse(..) => {} ast::ViewItemExternCrate(..) => { for attr in i.attrs.iter() { - if attr.name().get() == "phase"{ - self.gate_feature("phase", attr.span, - "compile time crate loading is \ - experimental and possibly buggy"); + if attr.check_name("plugin") { + self.gate_feature("plugin", attr.span, + "compiler plugins are experimental \ + and possibly buggy"); } } } @@ -294,7 +267,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { } } - ast::ItemImpl(_, polarity, _, _, _, ref items) => { + ast::ItemImpl(_, polarity, _, _, _, _) => { match polarity { ast::ImplPolarity::Negative => { self.gate_feature("optin_builtin_traits", @@ -314,16 +287,12 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { removed in the future"); } - for item in items.iter() { - match *item { - ast::MethodImplItem(_) => {} - ast::TypeImplItem(ref typedef) => { - self.gate_feature("associated_types", - typedef.span, - "associated types are \ - experimental") - } - } + if attr::contains_name(i.attrs[], + "old_orphan_check") { + self.gate_feature( + "old_orphan_check", + i.span, + "the new orphan check rules will eventually be strictly enforced"); } } @@ -333,17 +302,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { visit::walk_item(self, i); } - fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) { - match *trait_item { - ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {} - ast::TypeTraitItem(ref ti) => { - self.gate_feature("associated_types", - ti.ty_param.span, - "associated types are experimental") - } - } - } - fn visit_foreign_item(&mut self, i: &ast::ForeignItem) { if attr::contains_name(i.attrs[], "linkage") { self.gate_feature("linkage", i.span, @@ -379,20 +337,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { visit::walk_expr(self, e); } - fn visit_generics(&mut self, generics: &ast::Generics) { - for type_parameter in generics.ty_params.iter() { - match type_parameter.default { - Some(ref ty) => { - self.gate_feature("default_type_params", ty.span, - "default type parameters are \ - experimental and possibly buggy"); - } - None => {} - } - } - visit::walk_generics(self, generics); - } - fn visit_attribute(&mut self, attr: &ast::Attribute) { if attr::contains_name(slice::ref_slice(attr), "lang") { self.gate_feature("lang_items", @@ -498,7 +442,6 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C check(&mut cx, krate); (Features { - default_type_params: cx.has_feature("default_type_params"), unboxed_closures: cx.has_feature("unboxed_closures"), rustc_diagnostic_macros: cx.has_feature("rustc_diagnostic_macros"), import_shadowing: cx.has_feature("import_shadowing"), diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 396b0033b81..c45a4005339 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -194,13 +194,13 @@ pub trait Folder : Sized { noop_fold_local(l, self) } - fn fold_mac(&mut self, _macro: Mac) -> Mac { + fn fold_mac(&mut self, _mac: Mac) -> Mac { panic!("fold_mac disabled by default"); // NB: see note about macros above. // if you really want a folder that // works on macros, use this // definition in your trait impl: - // fold::noop_fold_mac(_macro, self) + // fold::noop_fold_mac(_mac, self) } fn fold_explicit_self(&mut self, es: ExplicitSelf) -> ExplicitSelf { @@ -1104,7 +1104,7 @@ pub fn noop_fold_mod<T: Folder>(Mod {inner, view_items, items}: Mod, folder: &mu } } -pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, config, exported_macros, span}: Crate, +pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, config, mut exported_macros, span}: Crate, folder: &mut T) -> Crate { let config = folder.fold_meta_items(config); @@ -1135,6 +1135,10 @@ pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, config, exported_macros, }, Vec::new(), span) }; + for def in exported_macros.iter_mut() { + def.id = folder.new_id(def.id); + } + Crate { module: module, attrs: attrs, @@ -1257,7 +1261,7 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> { } PatTup(elts) => PatTup(elts.move_map(|x| folder.fold_pat(x))), PatBox(inner) => PatBox(folder.fold_pat(inner)), - PatRegion(inner) => PatRegion(folder.fold_pat(inner)), + PatRegion(inner, mutbl) => PatRegion(folder.fold_pat(inner), mutbl), PatRange(e1, e2) => { PatRange(folder.fold_expr(e1), folder.fold_expr(e2)) }, @@ -1472,8 +1476,8 @@ mod test { fn fold_ident(&mut self, _: ast::Ident) -> ast::Ident { token::str_to_ident("zz") } - fn fold_mac(&mut self, macro: ast::Mac) -> ast::Mac { - fold::noop_fold_mac(macro, self) + fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { + fold::noop_fold_mac(mac, self) } } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 18cdb3fc647..b7bfd346d50 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -31,11 +31,18 @@ extern crate arena; extern crate fmt_macros; -#[phase(plugin, link)] extern crate log; extern crate serialize; extern crate term; extern crate libc; +#[cfg(stage0)] +#[phase(plugin, link)] +extern crate log; + +#[cfg(not(stage0))] +#[macro_use] +extern crate log; + extern crate "serialize" as rustc_serialize; // used by deriving pub mod util { diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 8598571e5c3..b0969a573e6 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -24,8 +24,11 @@ use std::num::Int; use std::str; use std::iter; -pub mod lexer; +#[cfg_attr(stage0, macro_escape)] +#[cfg_attr(not(stage0), macro_use)] pub mod parser; + +pub mod lexer; pub mod token; pub mod attr; @@ -166,6 +169,8 @@ pub fn parse_stmt_from_source_str(name: String, // Note: keep in sync with `with_hygiene::parse_tts_from_source_str` // until #16472 is resolved. +// +// Warning: This parses with quote_depth > 0, which is not the default. pub fn parse_tts_from_source_str(name: String, source: String, cfg: ast::CrateConfig, @@ -291,7 +296,7 @@ pub fn filemap_to_tts(sess: &ParseSess, filemap: Rc<FileMap>) pub fn tts_to_parser<'a>(sess: &'a ParseSess, tts: Vec<ast::TokenTree>, cfg: ast::CrateConfig) -> Parser<'a> { - let trdr = lexer::new_tt_reader(&sess.span_diagnostic, None, tts); + let trdr = lexer::new_tt_reader(&sess.span_diagnostic, None, None, tts); Parser::new(sess, cfg, box trdr) } @@ -307,6 +312,8 @@ pub mod with_hygiene { // Note: keep this in sync with `super::parse_tts_from_source_str` until // #16472 is resolved. + // + // Warning: This parses with quote_depth > 0, which is not the default. pub fn parse_tts_from_source_str(name: String, source: String, cfg: ast::CrateConfig, diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 75b2c17b81b..a49680d7e1c 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -13,8 +13,6 @@ //! //! Obsolete syntax that becomes too hard to parse can be removed. -pub use self::ObsoleteSyntax::*; - use ast::{Expr, ExprTup}; use codemap::Span; use parse::parser; @@ -24,17 +22,19 @@ use ptr::P; /// The specific types of unsupported syntax #[derive(Copy, PartialEq, Eq, Hash)] pub enum ObsoleteSyntax { - ObsoleteOwnedType, - ObsoleteOwnedExpr, - ObsoleteOwnedPattern, - ObsoleteOwnedVector, - ObsoleteOwnedSelf, - ObsoleteImportRenaming, - ObsoleteSubsliceMatch, - ObsoleteExternCrateRenaming, - ObsoleteProcType, - ObsoleteProcExpr, - ObsoleteClosureType, + Sized, + ForSized, + OwnedType, + OwnedExpr, + OwnedPattern, + OwnedVector, + OwnedSelf, + ImportRenaming, + SubsliceMatch, + ExternCrateRenaming, + ProcType, + ProcExpr, + ClosureType, } pub trait ParserObsoleteMethods { @@ -56,50 +56,59 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> { /// Reports an obsolete syntax non-fatal error. fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) { let (kind_str, desc) = match kind { - ObsoleteProcType => ( + ObsoleteSyntax::ForSized => ( + "for Sized?", + "no longer required. Traits (and their `Self` type) do not have the `Sized` bound \ + by default", + ), + ObsoleteSyntax::ProcType => ( "the `proc` type", "use unboxed closures instead", ), - ObsoleteProcExpr => ( + ObsoleteSyntax::ProcExpr => ( "`proc` expression", "use a `move ||` expression instead", ), - ObsoleteOwnedType => ( + ObsoleteSyntax::OwnedType => ( "`~` notation for owned pointers", "use `Box<T>` in `std::owned` instead" ), - ObsoleteOwnedExpr => ( + ObsoleteSyntax::OwnedExpr => ( "`~` notation for owned pointer allocation", "use the `box` operator instead of `~`" ), - ObsoleteOwnedPattern => ( + ObsoleteSyntax::OwnedPattern => ( "`~` notation for owned pointer patterns", "use the `box` operator instead of `~`" ), - ObsoleteOwnedVector => ( + ObsoleteSyntax::OwnedVector => ( "`~[T]` is no longer a type", "use the `Vec` type instead" ), - ObsoleteOwnedSelf => ( + ObsoleteSyntax::OwnedSelf => ( "`~self` is no longer supported", "write `self: Box<Self>` instead" ), - ObsoleteImportRenaming => ( + ObsoleteSyntax::ImportRenaming => ( "`use foo = bar` syntax", "write `use bar as foo` instead" ), - ObsoleteSubsliceMatch => ( + ObsoleteSyntax::SubsliceMatch => ( "subslice match syntax", "instead of `..xs`, write `xs..` in a pattern" ), - ObsoleteExternCrateRenaming => ( + ObsoleteSyntax::ExternCrateRenaming => ( "`extern crate foo = bar` syntax", "write `extern crate bar as foo` instead" ), - ObsoleteClosureType => ( + ObsoleteSyntax::ClosureType => ( "`|uint| -> bool` closure type syntax", "use unboxed closures instead, no type annotation needed" - ) + ), + ObsoleteSyntax::Sized => ( + "`Sized? T` syntax for removing the `Sized` bound", + "write `T: ?Sized` instead" + ), }; self.report(sp, kind, kind_str, desc); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 28c7293fc26..32f8f5ee3d6 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![macro_escape] - pub use self::PathParsingMode::*; use self::ItemOrViewItem::*; @@ -74,8 +72,8 @@ use parse::classify; use parse::common::{SeqSep, seq_sep_none, seq_sep_trailing_allowed}; use parse::lexer::{Reader, TokenAndSpan}; use parse::obsolete::*; -use parse::token::{self, MatchNt, SubstNt, InternedString}; -use parse::token::{keywords, special_idents}; +use parse::token::{self, MatchNt, SubstNt, SpecialVarNt, InternedString}; +use parse::token::{keywords, special_idents, SpecialMacroVar}; use parse::{new_sub_parser_from_file, ParseSess}; use print::pprust; use ptr::P; @@ -1155,7 +1153,7 @@ impl<'a> Parser<'a> { let _ = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare); let _ = self.parse_ret_ty(); - self.obsolete(proc_span, ObsoleteProcType); + self.obsolete(proc_span, ObsoleteSyntax::ProcType); TyInfer } @@ -1246,7 +1244,7 @@ impl<'a> Parser<'a> { let _ = self.parse_ret_ty(); - self.obsolete(ty_closure_span, ObsoleteClosureType); + self.obsolete(ty_closure_span, ObsoleteSyntax::ClosureType); TyInfer } @@ -1511,8 +1509,10 @@ impl<'a> Parser<'a> { self.bump(); let last_span = self.last_span; match self.token { - token::OpenDelim(token::Bracket) => self.obsolete(last_span, ObsoleteOwnedVector), - _ => self.obsolete(last_span, ObsoleteOwnedType) + token::OpenDelim(token::Bracket) => { + self.obsolete(last_span, ObsoleteSyntax::OwnedVector) + } + _ => self.obsolete(last_span, ObsoleteSyntax::OwnedType) } TyTup(vec![self.parse_ty()]) } else if self.check(&token::BinOp(token::Star)) { @@ -2275,7 +2275,7 @@ impl<'a> Parser<'a> { let span = self.last_span; let _ = self.parse_proc_decl(); let _ = self.parse_expr(); - return self.obsolete_expr(span, ObsoleteProcExpr); + return self.obsolete_expr(span, ObsoleteSyntax::ProcExpr); } if self.eat_keyword(keywords::If) { return self.parse_if_expr(); @@ -2737,6 +2737,9 @@ impl<'a> Parser<'a> { op: repeat, num_captures: name_num })) + } else if p.token.is_keyword_allow_following_colon(keywords::Crate) { + p.bump(); + TtToken(sp, SpecialVarNt(SpecialMacroVar::CrateMacroVar)) } else { // A nonterminal that matches or not let namep = match p.token { token::Ident(_, p) => p, _ => token::Plain }; @@ -2850,9 +2853,9 @@ impl<'a> Parser<'a> { let last_span = self.last_span; match self.token { token::OpenDelim(token::Bracket) => { - self.obsolete(last_span, ObsoleteOwnedVector) + self.obsolete(last_span, ObsoleteSyntax::OwnedVector) }, - _ => self.obsolete(last_span, ObsoleteOwnedExpr) + _ => self.obsolete(last_span, ObsoleteSyntax::OwnedExpr) } let e = self.parse_prefix_expr(); @@ -2966,14 +2969,17 @@ impl<'a> Parser<'a> { /// actually, this seems to be the main entry point for /// parsing an arbitrary expression. pub fn parse_assign_expr(&mut self) -> P<Expr> { - let lo = self.span.lo; let lhs = self.parse_binops(); + self.parse_assign_expr_with(lhs) + } + + pub fn parse_assign_expr_with(&mut self, lhs: P<Expr>) -> P<Expr> { let restrictions = self.restrictions & RESTRICTION_NO_STRUCT_LITERAL; match self.token { token::Eq => { self.bump(); let rhs = self.parse_expr_res(restrictions); - self.mk_expr(lo, rhs.span.hi, ExprAssign(lhs, rhs)) + self.mk_expr(lhs.span.lo, rhs.span.hi, ExprAssign(lhs, rhs)) } token::BinOpEq(op) => { self.bump(); @@ -2991,8 +2997,9 @@ impl<'a> Parser<'a> { token::Shr => BiShr }; let rhs_span = rhs.span; + let span = lhs.span; let assign_op = self.mk_assign_op(aop, lhs, rhs); - self.mk_expr(lo, rhs_span.hi, assign_op) + self.mk_expr(span.lo, rhs_span.hi, assign_op) } _ => { lhs @@ -3223,7 +3230,7 @@ impl<'a> Parser<'a> { } else { let _ = self.parse_pat(); let span = self.span; - self.obsolete(span, ObsoleteSubsliceMatch); + self.obsolete(span, ObsoleteSyntax::SubsliceMatch); } continue } @@ -3339,7 +3346,7 @@ impl<'a> Parser<'a> { pat = PatBox(sub); let last_span = self.last_span; hi = last_span.hi; - self.obsolete(last_span, ObsoleteOwnedPattern); + self.obsolete(last_span, ObsoleteSyntax::OwnedPattern); return P(ast::Pat { id: ast::DUMMY_NODE_ID, node: pat, @@ -3347,11 +3354,16 @@ impl<'a> Parser<'a> { }) } token::BinOp(token::And) | token::AndAnd => { - // parse &pat + // parse &pat and &mut pat let lo = self.span.lo; self.expect_and(); + let mutability = if self.eat_keyword(keywords::Mut) { + ast::MutMutable + } else { + ast::MutImmutable + }; let sub = self.parse_pat(); - pat = PatRegion(sub); + pat = PatRegion(sub, mutability); hi = self.last_span.hi; return P(ast::Pat { id: ast::DUMMY_NODE_ID, @@ -3870,13 +3882,13 @@ impl<'a> Parser<'a> { &mut stmts, &mut expr); } - StmtMac(macro, MacStmtWithoutBraces) => { + StmtMac(mac, MacStmtWithoutBraces) => { // statement macro without braces; might be an // expr depending on whether a semicolon follows match self.token { token::Semi => { stmts.push(P(Spanned { - node: StmtMac(macro, + node: StmtMac(mac, MacStmtWithSemicolon), span: span, })); @@ -3885,9 +3897,10 @@ impl<'a> Parser<'a> { _ => { let e = self.mk_mac_expr(span.lo, span.hi, - macro.and_then(|m| m.node)); - let e = - self.parse_dot_or_call_expr_with(e); + mac.and_then(|m| m.node)); + let e = self.parse_dot_or_call_expr_with(e); + let e = self.parse_more_binops(e, 0); + let e = self.parse_assign_expr_with(e); self.handle_expression_like_statement( e, ast::DUMMY_NODE_ID, @@ -4080,8 +4093,8 @@ impl<'a> Parser<'a> { // unbound, and it may only be `Sized`. To avoid backtracking and other // complications, we parse an ident, then check for `?`. If we find it, // we use the ident as the unbound, otherwise, we use it as the name of - // type param. Even worse, for now, we need to check for `?` before or - // after the bound. + // type param. Even worse, we need to check for `?` before or after the + // bound. let mut span = self.span; let mut ident = self.parse_ident(); let mut unbound = None; @@ -4090,6 +4103,7 @@ impl<'a> Parser<'a> { unbound = Some(tref); span = self.span; ident = self.parse_ident(); + self.obsolete(span, ObsoleteSyntax::Sized); } let mut bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Modified); @@ -4453,7 +4467,7 @@ impl<'a> Parser<'a> { self.bump(); drop(self.expect_self_ident()); let last_span = self.last_span; - self.obsolete(last_span, ObsoleteOwnedSelf) + self.obsolete(last_span, ObsoleteSyntax::OwnedSelf) } SelfStatic } @@ -4504,7 +4518,7 @@ impl<'a> Parser<'a> { self.bump(); drop(self.expect_self_ident()); let last_span = self.last_span; - self.obsolete(last_span, ObsoleteOwnedSelf); + self.obsolete(last_span, ObsoleteSyntax::OwnedSelf); SelfStatic } else { SelfStatic @@ -4880,67 +4894,116 @@ impl<'a> Parser<'a> { self.span_err(ty.span, "`virtual` structs have been removed from the language"); } - self.parse_where_clause(&mut generics); + // There is a special case worth noting here, as reported in issue #17904. + // If we are parsing a tuple struct it is the case that the where clause + // should follow the field list. Like so: + // + // struct Foo<T>(T) where T: Copy; + // + // If we are parsing a normal record-style struct it is the case + // that the where clause comes before the body, and after the generics. + // So if we look ahead and see a brace or a where-clause we begin + // parsing a record style struct. + // + // Otherwise if we look ahead and see a paren we parse a tuple-style + // struct. + + let (fields, ctor_id) = if self.token.is_keyword(keywords::Where) { + self.parse_where_clause(&mut generics); + if self.eat(&token::Semi) { + // If we see a: `struct Foo<T> where T: Copy;` style decl. + (Vec::new(), Some(ast::DUMMY_NODE_ID)) + } else { + // If we see: `struct Foo<T> where T: Copy { ... }` + (self.parse_record_struct_body(&class_name), None) + } + // No `where` so: `struct Foo<T>;` + } else if self.eat(&token::Semi) { + (Vec::new(), Some(ast::DUMMY_NODE_ID)) + // Record-style struct definition + } else if self.token == token::OpenDelim(token::Brace) { + let fields = self.parse_record_struct_body(&class_name); + (fields, None) + // Tuple-style struct definition with optional where-clause. + } else { + let fields = self.parse_tuple_struct_body(&class_name, &mut generics); + (fields, Some(ast::DUMMY_NODE_ID)) + }; - let mut fields: Vec<StructField>; - let is_tuple_like; + (class_name, + ItemStruct(P(ast::StructDef { + fields: fields, + ctor_id: ctor_id, + }), generics), + None) + } + pub fn parse_record_struct_body(&mut self, class_name: &ast::Ident) -> Vec<StructField> { + let mut fields = Vec::new(); if self.eat(&token::OpenDelim(token::Brace)) { - // It's a record-like struct. - is_tuple_like = false; - fields = Vec::new(); while self.token != token::CloseDelim(token::Brace) { fields.push(self.parse_struct_decl_field(true)); } + if fields.len() == 0 { self.fatal(format!("unit-like struct definition should be \ - written as `struct {};`", - token::get_ident(class_name))[]); + written as `struct {};`", + token::get_ident(class_name.clone()))[]); } + self.bump(); - } else if self.check(&token::OpenDelim(token::Paren)) { - // It's a tuple-like struct. - is_tuple_like = true; - fields = self.parse_unspanned_seq( + } else { + let token_str = self.this_token_to_string(); + self.fatal(format!("expected `where`, or `{}` after struct \ + name, found `{}`", "{", + token_str)[]); + } + + fields + } + + pub fn parse_tuple_struct_body(&mut self, + class_name: &ast::Ident, + generics: &mut ast::Generics) + -> Vec<StructField> { + // This is the case where we find `struct Foo<T>(T) where T: Copy;` + if self.check(&token::OpenDelim(token::Paren)) { + let fields = self.parse_unspanned_seq( &token::OpenDelim(token::Paren), &token::CloseDelim(token::Paren), seq_sep_trailing_allowed(token::Comma), |p| { - let attrs = p.parse_outer_attributes(); - let lo = p.span.lo; - let struct_field_ = ast::StructField_ { - kind: UnnamedField(p.parse_visibility()), - id: ast::DUMMY_NODE_ID, - ty: p.parse_ty_sum(), - attrs: attrs, - }; - spanned(lo, p.span.hi, struct_field_) - }); + let attrs = p.parse_outer_attributes(); + let lo = p.span.lo; + let struct_field_ = ast::StructField_ { + kind: UnnamedField(p.parse_visibility()), + id: ast::DUMMY_NODE_ID, + ty: p.parse_ty_sum(), + attrs: attrs, + }; + spanned(lo, p.span.hi, struct_field_) + }); + if fields.len() == 0 { self.fatal(format!("unit-like struct definition should be \ - written as `struct {};`", - token::get_ident(class_name))[]); + written as `struct {};`", + token::get_ident(class_name.clone()))[]); } + + self.parse_where_clause(generics); self.expect(&token::Semi); - } else if self.eat(&token::Semi) { - // It's a unit-like struct. - is_tuple_like = true; - fields = Vec::new(); + fields + // This is the case where we just see struct Foo<T> where T: Copy; + } else if self.token.is_keyword(keywords::Where) { + self.parse_where_clause(generics); + self.expect(&token::Semi); + Vec::new() + // This case is where we see: `struct Foo<T>;` } else { let token_str = self.this_token_to_string(); - self.fatal(format!("expected `{}`, `(`, or `;` after struct \ - name, found `{}`", "{", - token_str)[]) + self.fatal(format!("expected `where`, `{}`, `(`, or `;` after struct \ + name, found `{}`", "{", token_str)[]); } - - let _ = ast::DUMMY_NODE_ID; // FIXME: Workaround for crazy bug. - let new_id = ast::DUMMY_NODE_ID; - (class_name, - ItemStruct(P(ast::StructDef { - fields: fields, - ctor_id: if is_tuple_like { Some(new_id) } else { None }, - }), generics), - None) } /// Parse a structure field declaration @@ -4993,6 +5056,7 @@ impl<'a> Parser<'a> { // re-jigged shortly in any case, so leaving the hacky version for now. if self.eat_keyword(keywords::For) { let span = self.span; + let mut ate_question = false; if self.eat(&token::Question) { ate_question = true; @@ -5010,8 +5074,11 @@ impl<'a> Parser<'a> { "expected `?Sized` after `for` in trait item"); return None; } - let tref = Parser::trait_ref_from_ident(ident, span); - Some(tref) + let _tref = Parser::trait_ref_from_ident(ident, span); + + self.obsolete(span, ObsoleteSyntax::ForSized); + + None } else { None } @@ -5333,7 +5400,7 @@ impl<'a> Parser<'a> { self.bump(); let path = self.parse_str(); let span = self.span; - self.obsolete(span, ObsoleteExternCrateRenaming); + self.obsolete(span, ObsoleteSyntax::ExternCrateRenaming); Some(path) } else if self.eat_keyword(keywords::As) { // skip the ident if there is one @@ -5960,6 +6027,10 @@ impl<'a> Parser<'a> { fn parse_view_path(&mut self) -> P<ViewPath> { let lo = self.span.lo; + // Allow a leading :: because the paths are absolute either way. + // This occurs with "use $crate::..." in macros. + self.eat(&token::ModSep); + if self.check(&token::OpenDelim(token::Brace)) { // use {foo,bar} let idents = self.parse_unspanned_seq( @@ -5990,7 +6061,7 @@ impl<'a> Parser<'a> { path.push(id); } let span = mk_sp(path_lo, self.span.hi); - self.obsolete(span, ObsoleteImportRenaming); + self.obsolete(span, ObsoleteSyntax::ImportRenaming); let path = ast::Path { span: span, global: false, diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index b7e89b32b70..094aacf3207 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -62,6 +62,21 @@ pub enum IdentStyle { } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Show, Copy)] +pub enum SpecialMacroVar { + /// `$crate` will be filled in with the name of the crate a macro was + /// imported from, if any. + CrateMacroVar, +} + +impl SpecialMacroVar { + pub fn as_str(self) -> &'static str { + match self { + SpecialMacroVar::CrateMacroVar => "crate", + } + } +} + +#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Show, Copy)] pub enum Lit { Byte(ast::Name), Char(ast::Name), @@ -143,6 +158,8 @@ pub enum Token { // In right-hand-sides of MBE macros: /// A syntactic variable that will be filled in by macro expansion. SubstNt(ast::Ident, IdentStyle), + /// A macro variable with special meaning. + SpecialVarNt(SpecialMacroVar), // Junk. These carry no data because we don't really care about the data // they *would* carry, and don't really want to allocate a new ident for @@ -265,6 +282,13 @@ impl Token { } } + pub fn is_keyword_allow_following_colon(&self, kw: keywords::Keyword) -> bool { + match *self { + Ident(sid, _) => { kw.to_name() == sid.name } + _ => { false } + } + } + /// Returns `true` if the token is either a special identifier, or a strict /// or reserved keyword. #[allow(non_upper_case_globals)] @@ -550,6 +574,7 @@ declare_special_idents_and_keywords! { (56, Abstract, "abstract"); (57, Final, "final"); (58, Override, "override"); + (59, Macro, "macro"); } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index e44cc2257c2..402583b60fa 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -272,6 +272,8 @@ pub fn token_to_string(tok: &Token) -> String { token::Comment => "/* */".to_string(), token::Shebang(s) => format!("/* shebang: {}*/", s.as_str()), + token::SpecialVarNt(var) => format!("${}", var.as_str()), + token::Interpolated(ref nt) => match *nt { token::NtExpr(ref e) => expr_to_string(&**e), token::NtMeta(ref e) => meta_item_to_string(&**e), @@ -1056,7 +1058,6 @@ impl<'a> State<'a> { span: codemap::Span) -> IoResult<()> { try!(self.print_ident(ident)); try!(self.print_generics(generics)); - try!(self.print_where_clause(generics)); if ast_util::struct_def_is_tuple_like(struct_def) { if !struct_def.fields.is_empty() { try!(self.popen()); @@ -1075,10 +1076,12 @@ impl<'a> State<'a> { )); try!(self.pclose()); } + try!(self.print_where_clause(generics)); try!(word(&mut self.s, ";")); try!(self.end()); self.end() // close the outer-box } else { + try!(self.print_where_clause(generics)); try!(self.nbsp()); try!(self.bopen()); try!(self.hardbreak_if_not_bol()); @@ -2081,8 +2084,11 @@ impl<'a> State<'a> { try!(word(&mut self.s, "box ")); try!(self.print_pat(&**inner)); } - ast::PatRegion(ref inner) => { + ast::PatRegion(ref inner, mutbl) => { try!(word(&mut self.s, "&")); + if mutbl == ast::MutMutable { + try!(word(&mut self.s, "mut ")); + } try!(self.print_pat(&**inner)); } ast::PatLit(ref e) => try!(self.print_expr(&**e)), diff --git a/src/libsyntax/show_span.rs b/src/libsyntax/show_span.rs index 354ba854b10..57520257fe1 100644 --- a/src/libsyntax/show_span.rs +++ b/src/libsyntax/show_span.rs @@ -13,27 +13,73 @@ //! This module shows spans for all expressions in the crate //! to help with compiler debugging. +use std::str::FromStr; + use ast; use diagnostic; use visit; use visit::Visitor; +enum Mode { + Expression, + Pattern, + Type, +} + +impl FromStr for Mode { + fn from_str(s: &str) -> Option<Mode> { + let mode = match s { + "expr" => Mode::Expression, + "pat" => Mode::Pattern, + "ty" => Mode::Type, + _ => return None + }; + Some(mode) + } +} + struct ShowSpanVisitor<'a> { span_diagnostic: &'a diagnostic::SpanHandler, + mode: Mode, } impl<'a, 'v> Visitor<'v> for ShowSpanVisitor<'a> { fn visit_expr(&mut self, e: &ast::Expr) { - self.span_diagnostic.span_note(e.span, "expression"); + if let Mode::Expression = self.mode { + self.span_diagnostic.span_note(e.span, "expression"); + } visit::walk_expr(self, e); } - fn visit_mac(&mut self, macro: &ast::Mac) { - visit::walk_mac(self, macro); + fn visit_pat(&mut self, p: &ast::Pat) { + if let Mode::Pattern = self.mode { + self.span_diagnostic.span_note(p.span, "pattern"); + } + visit::walk_pat(self, p); + } + + fn visit_ty(&mut self, t: &ast::Ty) { + if let Mode::Type = self.mode { + self.span_diagnostic.span_note(t.span, "type"); + } + visit::walk_ty(self, t); + } + + fn visit_mac(&mut self, mac: &ast::Mac) { + visit::walk_mac(self, mac); } } -pub fn run(span_diagnostic: &diagnostic::SpanHandler, krate: &ast::Crate) { - let mut v = ShowSpanVisitor { span_diagnostic: span_diagnostic }; +pub fn run(span_diagnostic: &diagnostic::SpanHandler, + mode: &str, + krate: &ast::Crate) { + let mode = match mode.parse() { + Some(mode) => mode, + None => return + }; + let mut v = ShowSpanVisitor { + span_diagnostic: span_diagnostic, + mode: mode, + }; visit::walk_crate(&mut v, krate); } diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 5a4d0cc3bd8..4ef7eb97a21 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -65,12 +65,8 @@ impl<'a> fold::Folder for StandardLibraryInjector<'a> { Some((actual_crate_name, ast::CookedStr)), ast::DUMMY_NODE_ID), attrs: vec!( - attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_list_item( - InternedString::new("phase"), - vec!( - attr::mk_word_item(InternedString::new("plugin")), - attr::mk_word_item(InternedString::new("link") - ))))), + attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_word_item( + InternedString::new("macro_use")))), vis: ast::Inherited, span: DUMMY_SP }); @@ -82,16 +78,6 @@ impl<'a> fold::Folder for StandardLibraryInjector<'a> { // don't add #![no_std] here, that will block the prelude injection later. // Add it during the prelude injection instead. - // Add #![feature(phase)] here, because we use #[phase] on extern crate std. - let feat_phase_attr = attr::mk_attr_inner(attr::mk_attr_id(), - attr::mk_list_item( - InternedString::new("feature"), - vec![attr::mk_word_item(InternedString::new("phase"))], - )); - // std_inject runs after feature checking so manually mark this attr - attr::mark_used(&feat_phase_attr); - krate.attrs.push(feat_phase_attr); - krate } } diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 5f416a867e8..85eea2d9daf 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -77,7 +77,7 @@ impl<T: Eq + Hash + Clone + 'static> Interner<T> { (*vect).len() } - pub fn find<Sized? Q>(&self, val: &Q) -> Option<Name> + pub fn find<Q: ?Sized>(&self, val: &Q) -> Option<Name> where Q: BorrowFrom<T> + Eq + Hash { let map = self.map.borrow(); match (*map).get(val) { @@ -202,7 +202,7 @@ impl StrInterner { self.vect.borrow().len() } - pub fn find<Sized? Q>(&self, val: &Q) -> Option<Name> + pub fn find<Q: ?Sized>(&self, val: &Q) -> Option<Name> where Q: BorrowFrom<RcStr> + Eq + Hash { match (*self.map.borrow()).get(val) { Some(v) => Some(*v), diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 737f1b73b32..3f91304dcc5 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -115,13 +115,13 @@ pub trait Visitor<'v> : Sized { fn visit_explicit_self(&mut self, es: &'v ExplicitSelf) { walk_explicit_self(self, es) } - fn visit_mac(&mut self, _macro: &'v Mac) { + fn visit_mac(&mut self, _mac: &'v Mac) { panic!("visit_mac disabled by default"); // NB: see note about macros above. // if you really want a visitor that // works on macros, use this // definition in your trait impl: - // visit::walk_mac(self, _macro) + // visit::walk_mac(self, _mac) } fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) { walk_path(self, path) @@ -334,7 +334,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_trait_item(method) } } - ItemMac(ref macro) => visitor.visit_mac(macro), + ItemMac(ref mac) => visitor.visit_mac(mac), } for attr in item.attrs.iter() { visitor.visit_attribute(attr); @@ -511,7 +511,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { } } PatBox(ref subpattern) | - PatRegion(ref subpattern) => { + PatRegion(ref subpattern, _) => { visitor.visit_pat(&**subpattern) } PatIdent(_, ref pth1, ref optional_subpattern) => { @@ -538,7 +538,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { visitor.visit_pat(&**postpattern) } } - PatMac(ref macro) => visitor.visit_mac(macro), + PatMac(ref mac) => visitor.visit_mac(mac), } } @@ -738,7 +738,7 @@ pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) { StmtExpr(ref expression, _) | StmtSemi(ref expression, _) => { visitor.visit_expr(&**expression) } - StmtMac(ref macro, _) => visitor.visit_mac(&**macro), + StmtMac(ref mac, _) => visitor.visit_mac(&**mac), } } @@ -885,7 +885,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { ExprRet(ref optional_expression) => { walk_expr_opt(visitor, optional_expression) } - ExprMac(ref macro) => visitor.visit_mac(macro), + ExprMac(ref mac) => visitor.visit_mac(mac), ExprParen(ref subexpression) => { visitor.visit_expr(&**subexpression) } |
