]> git.lizzy.rs Git - rust.git/commitdiff
Merge remote-tracking branch 'remotes/origin/incoming' into incoming
authorErick Tryzelaar <erick.tryzelaar@gmail.com>
Wed, 27 Feb 2013 19:03:21 +0000 (11:03 -0800)
committerErick Tryzelaar <erick.tryzelaar@gmail.com>
Wed, 27 Feb 2013 19:03:21 +0000 (11:03 -0800)
35 files changed:
1  2 
src/libfuzzer/fuzzer.rc
src/librustc/middle/astencode.rs
src/librustc/middle/check_match.rs
src/librustc/middle/freevars.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/lint.rs
src/librustc/middle/liveness.rs
src/librustc/middle/resolve.rs
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/callee.rs
src/librustc/middle/trans/foreign.rs
src/librustc/middle/trans/meth.rs
src/librustc/middle/trans/type_use.rs
src/librustc/middle/ty.rs
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/collect.rs
src/librustc/util/ppaux.rs
src/libsyntax/ast.rs
src/libsyntax/ast_map.rs
src/libsyntax/ast_util.rs
src/libsyntax/ext/auto_encode.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/pipes/ast_builder.rs
src/libsyntax/ext/pipes/parse_proto.rs
src/libsyntax/ext/pipes/pipec.rs
src/libsyntax/ext/pipes/proto.rs
src/libsyntax/ext/source_util.rs
src/libsyntax/fold.rs
src/libsyntax/parse/lexer.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/obsolete.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs

Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 282506929ffdec8fe509cf2d5f167b995b3d22c8,9a3e8da2b814570e3bc8bc714eba8c62db37ed04..14f4cd5c19f9237045b3f0efbe74042500c0ff77
@@@ -21,75 -21,67 +21,76 @@@ use parse::{parser, parse_item_from_sou
  
  use core::option;
  use core::vec;
- use std::oldmap::HashMap;
+ use core::hashmap::LinearMap;
  
- pub fn expand_expr(exts: SyntaxExtensions, cx: ext_ctxt,
+ pub fn expand_expr(extsbox: @mut SyntaxEnv, cx: ext_ctxt,
 -                   e: expr_, s: span, fld: ast_fold,
 -                   orig: fn@(expr_, span, ast_fold) -> (expr_, span))
 +                   e: &expr_, s: span, fld: ast_fold,
 +                   orig: fn@(&expr_, span, ast_fold) -> (expr_, span))
                  -> (expr_, span) {
 -    return match e {
 -      // expr_mac should really be expr_ext or something; it's the
 -      // entry-point for all syntax extensions.
 -          expr_mac(ref mac) => {
 -
 +    match *e {
 +        // expr_mac should really be expr_ext or something; it's the
 +        // entry-point for all syntax extensions.
 +        expr_mac(ref mac) => {
              match (*mac).node {
 -
 -              // Token-tree macros, these will be the only case when we're
 -              // finished transitioning.
 -              mac_invoc_tt(pth, ref tts) => {
 -                assert (vec::len(pth.idents) == 1u);
 -                /* using idents and token::special_idents would make the
 -                the macro names be hygienic */
 -                let extname = cx.parse_sess().interner.get(pth.idents[0]);
 -                // leaving explicit deref here to highlight unbox op:
 -                match (*extsbox).find(&extname) {
 -                  None => {
 -                    cx.span_fatal(pth.span,
 -                                  fmt!("macro undefined: '%s'", *extname))
 -                  }
 -                  Some(@SE(NormalTT(SyntaxExpanderTT{expander: exp,
 -                                                 span: exp_sp}))) => {
 -                    cx.bt_push(ExpandedFrom(CallInfo{
 -                        call_site: s,
 -                        callee: NameAndSpan {
 -                            name: *extname, span: exp_sp
 +                // Token-tree macros, these will be the only case when we're
 +                // finished transitioning.
 +                mac_invoc_tt(pth, ref tts) => {
 +                    assert (vec::len(pth.idents) == 1u);
 +                    /* using idents and token::special_idents would make the
 +                    the macro names be hygienic */
 +                    let extname = cx.parse_sess().interner.get(pth.idents[0]);
-                     match exts.find(&extname) {
++                    // leaving explicit deref here to highlight unbox op:
++                    match (*extsbox).find(&extname) {
 +                        None => {
 +                            cx.span_fatal(
 +                                pth.span,
 +                                fmt!("macro undefined: '%s'", *extname))
                          }
-                         Some(NormalTT(SyntaxExpanderTT{
 -                    }));
 -
 -                    let expanded = match exp(cx, (*mac).span, (*tts)) {
 -                      MRExpr(e) => e,
 -                      MRAny(expr_maker,_,_) => expr_maker(),
 -                      _ => cx.span_fatal(
 -                          pth.span, fmt!("non-expr macro in expr pos: %s",
 -                                         *extname))
 -                    };
 -
 -                    //keep going, outside-in
 -                    let fully_expanded = fld.fold_expr(expanded).node;
 -                    cx.bt_pop();
 -
 -                    (fully_expanded, s)
 -                  }
 -                  _ => {
 -                    cx.span_fatal(pth.span,
 -                                  fmt!("'%s' is not a tt-style macro",
 -                                       *extname))
 -                  }
 -
++                        Some(@SE(NormalTT(SyntaxExpanderTT{
 +                            expander: exp,
 +                            span: exp_sp
-                         })) => {
++                        }))) => {
 +                            cx.bt_push(ExpandedFrom(CallInfo {
 +                                call_site: s,
 +                                callee: NameAndSpan {
 +                                    name: copy *extname,
 +                                    span: exp_sp,
 +                                },
 +                            }));
 +
 +                            let expanded = match exp(cx, mac.span, *tts) {
 +                                MRExpr(e) => e,
 +                                MRAny(expr_maker,_,_) => expr_maker(),
 +                                _ => {
 +                                    cx.span_fatal(
 +                                        pth.span,
 +                                        fmt!(
 +                                            "non-expr macro in expr pos: %s",
 +                                            *extname
 +                                        )
 +                                    )
 +                                }
 +                            };
 +
 +                            //keep going, outside-in
 +                            let fully_expanded =
 +                                copy fld.fold_expr(expanded).node;
 +                            cx.bt_pop();
 +
 +                            (fully_expanded, s)
 +                        }
 +                        _ => {
 +                            cx.span_fatal(
 +                                pth.span,
 +                                fmt!("'%s' is not a tt-style macro", *extname)
 +                            )
 +                        }
 +                    }
                  }
 -              }
              }
 -          }
 -          _ => orig(e, s, fld)
 -        };
 +        }
 +        _ => orig(e, s, fld)
 +    }
  }
  
  // This is a secondary mechanism for invoking syntax extensions on items:
  //
  // NB: there is some redundancy between this and expand_item, below, and
  // they might benefit from some amount of semantic and language-UI merger.
- pub fn expand_mod_items(exts: SyntaxExtensions, cx: ext_ctxt,
+ pub fn expand_mod_items(extsbox: @mut SyntaxEnv, cx: ext_ctxt,
 -                        module_: ast::_mod, fld: ast_fold,
 -                        orig: fn@(ast::_mod, ast_fold) -> ast::_mod)
 +                        module_: &ast::_mod, fld: ast_fold,
 +                        orig: fn@(&ast::_mod, ast_fold) -> ast::_mod)
                       -> ast::_mod {
      // Fold the contents first:
      let module_ = orig(module_, fld);
  }
  
  
+ // eval $e with a new exts frame:
+ macro_rules! with_exts_frame (
+     ($extsboxexpr:expr,$e:expr) =>
+     ({let extsbox = $extsboxexpr;
+       let oldexts = *extsbox;
+       *extsbox = oldexts.push_frame();
+       let result = $e;
+       *extsbox = oldexts;
+       result
+      })
+ )
  // When we enter a module, record it, for the sake of `module!`
- pub fn expand_item(exts: SyntaxExtensions,
+ pub fn expand_item(extsbox: @mut SyntaxEnv,
 -                   cx: ext_ctxt, &&it: @ast::item, fld: ast_fold,
 -                   orig: fn@(&&v: @ast::item, ast_fold) -> Option<@ast::item>)
 +                   cx: ext_ctxt, it: @ast::item, fld: ast_fold,
 +                   orig: fn@(@ast::item, ast_fold) -> Option<@ast::item>)
                  -> Option<@ast::item> {
-     let is_mod = match it.node {
-       ast::item_mod(_) | ast::item_foreign_mod(_) => true,
-       _ => false
-     };
+     // need to do expansion first... it might turn out to be a module.
      let maybe_it = match it.node {
-       ast::item_mac(*) => expand_item_mac(exts, cx, it, fld),
+       ast::item_mac(*) => expand_item_mac(extsbox, cx, it, fld),
        _ => Some(it)
      };
      match maybe_it {
        Some(it) => {
-         if is_mod { cx.mod_push(it.ident); }
-         let ret_val = orig(it, fld);
-         if is_mod { cx.mod_pop(); }
-         return ret_val;
+           match it.node {
+               ast::item_mod(_) | ast::item_foreign_mod(_) => {
+                   cx.mod_push(it.ident);
+                   let result =
+                       // don't push a macro scope for macro_escape:
+                       if contains_macro_escape(it.attrs) {
+                       orig(it,fld)
+                   } else {
+                       // otherwise, push a scope:
+                       with_exts_frame!(extsbox,orig(it,fld))
+                   };
+                   cx.mod_pop();
+                   result
+               }
+               _ => orig(it,fld)
+           }
        }
-       None => return None
+       None => None
      }
  }
  
@@@ -231,17 -283,16 +292,18 @@@ pub fn expand_item_mac(+extsbox: @mut S
      return maybe_it;
  }
  
- pub fn expand_stmt(exts: SyntaxExtensions, cx: ext_ctxt,
+ // expand a stmt
+ pub fn expand_stmt(extsbox: @mut SyntaxEnv, cx: ext_ctxt,
 -                   && s: stmt_, sp: span, fld: ast_fold,
 -                   orig: fn@(&&s: stmt_, span, ast_fold) -> (stmt_, span))
 +                   s: &stmt_, sp: span, fld: ast_fold,
 +                   orig: fn@(s: &stmt_, span, ast_fold) -> (stmt_, span))
                  -> (stmt_, span) {
  
 -    let (mac, pth, tts, semi) = match s {
 +    let (mac, pth, tts, semi) = match *s {
          stmt_mac(ref mac, semi) => {
 -            match (*mac).node {
 -                mac_invoc_tt(pth, ref tts) => ((*mac), pth, (*tts), semi)
 +            match mac.node {
 +                mac_invoc_tt(pth, ref tts) => {
 +                    (copy *mac, pth, copy *tts, semi)
 +                }
              }
          }
          _ => return orig(s, sp, fld)
          None =>
              cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", *extname)),
  
-         Some(NormalTT(
-             SyntaxExpanderTT{expander: exp, span: exp_sp})) => {
+         Some(@SE(NormalTT(
+             SyntaxExpanderTT{expander: exp, span: exp_sp}))) => {
              cx.bt_push(ExpandedFrom(CallInfo {
                  call_site: sp,
 -                callee: NameAndSpan { name: *extname, span: exp_sp }
 +                callee: NameAndSpan { name: copy *extname, span: exp_sp }
              }));
              let expanded = match exp(cx, mac.span, tts) {
                  MRExpr(e) =>
  }
  
  
 -                    && blk: blk_, sp: span, fld: ast_fold,
 -                    orig: fn@(&&s: blk_, span, ast_fold) -> (blk_, span))
+ pub fn expand_block(extsbox: @mut SyntaxEnv, cx: ext_ctxt,
++                    blk: &blk_, sp: span, fld: ast_fold,
++                    orig: fn@(&blk_, span, ast_fold) -> (blk_, span))
+     -> (blk_, span) {
+     match (*extsbox).find(&@~" block") {
+         // no scope limit on macros in this block, no need
+         // to push an exts frame:
+         Some(@ScopeMacros(false)) => {
+             orig (blk,sp,fld)
+         },
+         // this block should limit the scope of its macros:
+         Some(@ScopeMacros(true)) => {
+             // see note below about treatment of exts table
+             with_exts_frame!(extsbox,orig(blk,sp,fld))
+         },
+         _ => cx.span_bug(sp,
+                          ~"expected ScopeMacros binding for \" block\"")
+     }
+ }
  pub fn new_span(cx: ext_ctxt, sp: span) -> span {
      /* this discards information in the case of macro-defining macros */
      return span {lo: sp.lo, hi: sp.hi, expn_info: cx.backtrace()};
@@@ -352,28 -423,160 +434,166 @@@ pub fn core_macros() -> ~str 
  
  pub fn expand_crate(parse_sess: @mut parse::ParseSess,
                      cfg: ast::crate_cfg, c: @crate) -> @crate {
-     let exts = syntax_expander_table();
+     // adding *another* layer of indirection here so that the block
+     // visitor can swap out one exts table for another for the duration
+     // of the block.  The cleaner alternative would be to thread the
+     // exts table through the fold, but that would require updating
+     // every method/element of AstFoldFns in fold.rs.
+     let extsbox = @mut syntax_expander_table();
      let afp = default_ast_fold();
 -    let cx: ext_ctxt = mk_ctxt(parse_sess, cfg);
 +    let cx: ext_ctxt = mk_ctxt(parse_sess, copy cfg);
      let f_pre = @AstFoldFns {
-         fold_expr: |a,b,c| expand_expr(exts, cx, a, b, c, afp.fold_expr),
-         fold_mod: |a,b| expand_mod_items(exts, cx, a, b, afp.fold_mod),
-         fold_item: |a,b| expand_item(exts, cx, a, b, afp.fold_item),
-         fold_stmt: |a,b,c| expand_stmt(exts, cx, a, b, c, afp.fold_stmt),
+         fold_expr: |expr,span,recur|
+             expand_expr(extsbox, cx, expr, span, recur, afp.fold_expr),
+         fold_mod: |modd,recur|
+             expand_mod_items(extsbox, cx, modd, recur, afp.fold_mod),
+         fold_item: |item,recur|
+             expand_item(extsbox, cx, item, recur, afp.fold_item),
+         fold_stmt: |stmt,span,recur|
+             expand_stmt(extsbox, cx, stmt, span, recur, afp.fold_stmt),
+         fold_block: |blk,span,recur|
 -            expand_block (extsbox, cx, blk, span, recur, afp.fold_block),
++            expand_block(extsbox, cx, blk, span, recur, afp.fold_block),
          new_span: |a| new_span(cx, a),
          .. *afp};
      let f = make_fold(f_pre);
-     let cm = parse_expr_from_source_str(~"<core-macros>",
-                                         @core_macros(),
-                                         copy cfg,
-                                         parse_sess);
+     // add a bunch of macros as though they were placed at the
+     // head of the program (ick).
 -    let attrs = ~[spanned {span:codemap::dummy_sp(),
 -                           node: attribute_
 -                               {style:attr_outer,
 -                                value:spanned
 -                                    {node:meta_word(@~"macro_escape"),
 -                                     span:codemap::dummy_sp()},
 -                                is_sugared_doc:false}}];
++    let attrs = ~[
++        spanned {
++            span: codemap::dummy_sp(),
++            node: attribute_ {
++                style: attr_outer,
++                value: @spanned {
++                    node: meta_word(@~"macro_escape"),
++                    span: codemap::dummy_sp(),
++                },
++                is_sugared_doc: false,
++            }
++        }
++    ];
+     let cm = match parse_item_from_source_str(~"<core-macros>",
+                                               @core_macros(),
 -                                              cfg,attrs,
++                                              copy cfg,
++                                              attrs,
+                                               parse_sess) {
+         Some(item) => item,
+         None => cx.bug(~"expected core macros to parse correctly")
+     };
      // This is run for its side-effects on the expander env,
      // as it registers all the core macros as expanders.
-     f.fold_expr(cm);
+     f.fold_item(cm);
  
 -    let res = @f.fold_crate(*c);
 -    return res;
 +    @f.fold_crate(&*c)
  }
+ #[cfg(test)]
+ mod test {
+     use super::*;
+     use util::testing::check_equal;
+     // make sure that fail! is present
+     #[test] fn fail_exists_test () {
+         let src = ~"fn main() { fail!(~\"something appropriately gloomy\");}";
+         let sess = parse::new_parse_sess(None);
+         let cfg = ~[];
+         let crate_ast = parse::parse_crate_from_source_str(
+             ~"<test>",
+             @src,
+             cfg,sess);
+         expand_crate(sess,cfg,crate_ast);
+     }
+     // these following tests are quite fragile, in that they don't test what
+     // *kind* of failure occurs.
+     // make sure that macros can leave scope
+     #[should_fail]
+     #[test] fn macros_cant_escape_fns_test () {
+         let src = ~"fn bogus() {macro_rules! z (() => (3+4))}\
+                     fn inty() -> int { z!() }";
+         let sess = parse::new_parse_sess(None);
+         let cfg = ~[];
+         let crate_ast = parse::parse_crate_from_source_str(
+             ~"<test>",
+             @src,
+             cfg,sess);
+         // should fail:
+         expand_crate(sess,cfg,crate_ast);
+     }
+     // make sure that macros can leave scope for modules
+     #[should_fail]
+     #[test] fn macros_cant_escape_mods_test () {
+         let src = ~"mod foo {macro_rules! z (() => (3+4))}\
+                     fn inty() -> int { z!() }";
+         let sess = parse::new_parse_sess(None);
+         let cfg = ~[];
+         let crate_ast = parse::parse_crate_from_source_str(
+             ~"<test>",
+             @src,
+             cfg,sess);
+         // should fail:
+         expand_crate(sess,cfg,crate_ast);
+     }
+     // macro_escape modules shouldn't cause macros to leave scope
+     #[test] fn macros_can_escape_flattened_mods_test () {
+         let src = ~"#[macro_escape] mod foo {macro_rules! z (() => (3+4))}\
+                     fn inty() -> int { z!() }";
+         let sess = parse::new_parse_sess(None);
+         let cfg = ~[];
+         let crate_ast = parse::parse_crate_from_source_str(
+             ~"<test>",
+             @src,
+             cfg,sess);
+         // should fail:
+         expand_crate(sess,cfg,crate_ast);
+     }
+     #[test] fn core_macros_must_parse () {
+         let src = ~"
+   pub mod macros {
+     macro_rules! ignore (($($x:tt)*) => (()))
+     macro_rules! error ( ($( $arg:expr ),+) => (
+         log(::core::error, fmt!( $($arg),+ )) ))
+ }";
+         let sess = parse::new_parse_sess(None);
+         let cfg = ~[];
+         let item_ast = parse::parse_item_from_source_str(
+             ~"<test>",
+             @src,
+             cfg,~[make_dummy_attr (@~"macro_escape")],sess);
+         match item_ast {
+             Some(_) => (), // success
+             None => fail!(~"expected this to parse")
+         }
+     }
+     #[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 = ~[attr1, escape_attr, attr2];
+         check_equal (contains_macro_escape (attrs1),true);
+         let attrs2 = ~[attr1,attr2];
+         check_equal (contains_macro_escape (attrs2),false);
+     }
+     // make a "meta_word" outer attribute with the given name
+     fn make_dummy_attr(s: @~str) -> ast::attribute {
+         spanned {span:codemap::dummy_sp(),
+                  node: attribute_
+                      {style:attr_outer,
+                       value:spanned
+                           {node:meta_word(s),
+                            span:codemap::dummy_sp()},
+                       is_sugared_doc:false}}
+     }
+ }
  // Local Variables:
  // mode: rust
  // fill-column: 78;
index 7917a072414a6fb63839164edfef8f4f0e1bca0b,6adea6395a356f6dd71a3df8ae31276d4ac2576d..88b77ec7970a5571721f8575e8818c20bfcfef6e
@@@ -50,23 -50,19 +50,23 @@@ pub fn path_global(+ids: ~[ident], span
  }
  
  pub trait append_types {
 -    fn add_ty(ty: @ast::Ty) -> @ast::path;
 -    fn add_tys(+tys: ~[@ast::Ty]) -> @ast::path;
 +    fn add_ty(&self, ty: @ast::Ty) -> @ast::path;
 +    fn add_tys(&self, +tys: ~[@ast::Ty]) -> @ast::path;
  }
  
pub impl append_types for @ast::path {
+ impl append_types for @ast::path {
 -    fn add_ty(ty: @ast::Ty) -> @ast::path {
 -        @ast::path { types: vec::append_one(self.types, ty),
 -                     .. *self}
 +    fn add_ty(&self, ty: @ast::Ty) -> @ast::path {
 +        @ast::path {
 +            types: vec::append_one(copy self.types, ty),
 +            .. copy **self
 +        }
      }
  
 -    fn add_tys(+tys: ~[@ast::Ty]) -> @ast::path {
 -        @ast::path { types: vec::append(self.types, tys),
 -                     .. *self}
 +    fn add_tys(&self, +tys: ~[@ast::Ty]) -> @ast::path {
 +        @ast::path {
 +            types: vec::append(copy self.types, tys),
 +            .. copy **self
 +        }
      }
  }
  
index ce253f6156b5f3d2e85529981aa6babaec642ecd,9a330db9f1825e7ab804052ce4b6f62d9375bede..12603200ef31fcc0d56bdeabb1588c7e88720e87
@@@ -23,18 -23,14 +23,18 @@@ pub trait proto_parser 
      fn parse_message(&self, state: state);
  }
  
pub impl proto_parser for parser::Parser {
+ impl proto_parser for parser::Parser {
 -    fn parse_proto(&self, id: ~str) -> protocol {
 +    fn parse_proto(&self, +id: ~str) -> protocol {
          let proto = protocol(id, *self.span);
  
 -        self.parse_seq_to_before_end(token::EOF, SeqSep {
 -                                        sep: None,
 -                                        trailing_sep_allowed: false
 -                                     }, |self| self.parse_state(proto));
 +        self.parse_seq_to_before_end(
 +            &token::EOF,
 +            SeqSep {
 +                sep: None,
 +                trailing_sep_allowed: false,
 +            },
 +            |self| self.parse_state(proto)
 +        );
  
          return proto;
      }
Simple merge
Simple merge
index c4049b796c5502311c299d4a3c6e4408458c1e97,808a80e6ad049d769d5a07cf74fbe77266184580..a8a7ad4c7493096b80e8a7368260121c35eee50b
@@@ -22,39 -22,12 +22,12 @@@ use core::result
  use core::str;
  use core::vec;
  
- fn topmost_expn_info(expn_info: @codemap::ExpnInfo) -> @codemap::ExpnInfo {
-     // FIXME(#3874): this would be better written as:
-     // let @ExpandedFrom(CallInfo {
-     //     call_site: ref call_site,
-     //     _
-     //  }) = expn_info;
-     match *expn_info {
-         ExpandedFrom(CallInfo { call_site: ref call_site, _}) => {
-             match call_site.expn_info {
-                 Some(next_expn_info) => {
-                     // Don't recurse into file using "include!"
-                     match *next_expn_info {
-                         ExpandedFrom(
-                             CallInfo { callee: NameAndSpan {
-                                 name: ref name,
-                                 _
-                             },
-                             _
-                         }) => {
-                             if *name == ~"include" { return expn_info; }
-                         }
-                     }
-                     topmost_expn_info(next_expn_info)
-                 },
-                 None => expn_info
-             }
-         }
-     }
- }
+ // These macros all relate to the file system; they either return
+ // the column/row/filename of the expression, or they include
+ // a given file into the current one.
  
  /* line!(): expands to the current line number */
 -pub fn expand_line(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree])
 +pub fn expand_line(cx: ext_ctxt, sp: span, tts: &[ast::token_tree])
      -> base::MacResult {
      base::check_zero_tts(cx, sp, tts, "line!");
  
@@@ -101,7 -74,10 +74,10 @@@ pub fn expand_mod(cx: ext_ctxt, sp: spa
                                    |x| cx.str_of(*x)), ~"::")))
  }
  
 -pub fn expand_include(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree])
+ // include! : parse the given file as an expr
+ // This is generally a bad idea because it's going to behave
+ // unhygienically.
 +pub fn expand_include(cx: ext_ctxt, sp: span, tts: &[ast::token_tree])
      -> base::MacResult {
      let file = get_single_str_from_tts(cx, sp, tts, "include!");
      let p = parse::new_sub_parser_from_file(
      base::MRExpr(p.parse_expr())
  }
  
 -pub fn expand_include_str(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree])
+ // include_str! : read the given file, insert it as a literal string expr
 +pub fn expand_include_str(cx: ext_ctxt, sp: span, tts: &[ast::token_tree])
      -> base::MacResult {
      let file = get_single_str_from_tts(cx, sp, tts, "include_str!");
      let res = io::read_whole_file_str(&res_rel_file(cx, sp, &Path(file)));
index 68d05e11171c591bb4206007f44a7917d80cc91a,2d8b62629ee277a88329070476b6fefd858c11ec..c23ce1c14a2f7156bd587a580ccd1d86322c7629
@@@ -753,40 -669,38 +753,40 @@@ fn noop_id(i: node_id) -> node_id { ret
  fn noop_span(sp: span) -> span { return sp; }
  
  pub fn default_ast_fold() -> ast_fold_fns {
 -    return @AstFoldFns {fold_crate: wrap(noop_fold_crate),
 -          fold_view_item: noop_fold_view_item,
 -          fold_foreign_item: noop_fold_foreign_item,
 -          fold_item: noop_fold_item,
 -          fold_struct_field: noop_fold_struct_field,
 -          fold_item_underscore: noop_fold_item_underscore,
 -          fold_method: noop_fold_method,
 -          fold_block: wrap(noop_fold_block),
 -          fold_stmt: wrap(noop_fold_stmt),
 -          fold_arm: noop_fold_arm,
 -          fold_pat: wrap(noop_fold_pat),
 -          fold_decl: wrap(noop_fold_decl),
 -          fold_expr: wrap(noop_fold_expr),
 -          fold_ty: wrap(noop_fold_ty),
 -          fold_mod: noop_fold_mod,
 -          fold_foreign_mod: noop_fold_foreign_mod,
 -          fold_variant: wrap(noop_fold_variant),
 -          fold_ident: noop_fold_ident,
 -          fold_path: noop_fold_path,
 -          fold_local: wrap(noop_fold_local),
 -          map_exprs: noop_map_exprs,
 -          new_id: noop_id,
 -          new_span: noop_span};
 +    @AstFoldFns {
 +        fold_crate: wrap(noop_fold_crate),
 +        fold_view_item: noop_fold_view_item,
 +        fold_foreign_item: noop_fold_foreign_item,
 +        fold_item: noop_fold_item,
 +        fold_struct_field: noop_fold_struct_field,
 +        fold_item_underscore: noop_fold_item_underscore,
 +        fold_method: noop_fold_method,
 +        fold_block: wrap(noop_fold_block),
 +        fold_stmt: wrap(noop_fold_stmt),
 +        fold_arm: noop_fold_arm,
 +        fold_pat: wrap(noop_fold_pat),
 +        fold_decl: wrap(noop_fold_decl),
 +        fold_expr: wrap(noop_fold_expr),
 +        fold_ty: wrap(noop_fold_ty),
 +        fold_mod: noop_fold_mod,
 +        fold_foreign_mod: noop_fold_foreign_mod,
 +        fold_variant: wrap(noop_fold_variant),
 +        fold_ident: noop_fold_ident,
 +        fold_path: noop_fold_path,
 +        fold_local: wrap(noop_fold_local),
 +        map_exprs: noop_map_exprs,
 +        new_id: noop_id,
 +        new_span: noop_span
 +    }
  }
  
pub impl ast_fold for ast_fold_fns {
+ impl ast_fold for ast_fold_fns {
      /* naturally, a macro to write these would be nice */
 -    fn fold_crate(c: crate) -> crate {
 -        let (n, s) = (self.fold_crate)(c.node, c.span, self as ast_fold);
 +    fn fold_crate(c: &crate) -> crate {
 +        let (n, s) = (self.fold_crate)(&c.node, c.span, self as ast_fold);
          spanned { node: n, span: (self.new_span)(s) }
      }
 -    fn fold_view_item(&&x: @view_item) ->
 +    fn fold_view_item(x: @view_item) ->
         @view_item {
          @ast::view_item {
              node: (self.fold_view_item)(x.node, self as ast_fold),
Simple merge
index d8c3ca06d76e52c5f4ead0c9d722fc7523e92c20,a31a73f594ad2e332a91f4f47bd782cf3923a2dd..816e4137126b792454666afb8cffa97b9029955a
@@@ -91,113 -88,63 +91,103 @@@ pub fn parse_crate_from_file
      // why is there no p.abort_if_errors here?
  }
  
 -pub fn parse_crate_from_source_str(name: ~str,
 -                                   source: @~str,
 -                                   cfg: ast::crate_cfg,
 -                                   sess: @mut ParseSess) -> @ast::crate {
 -    let p = new_parser_from_source_str(sess, cfg, name,
 -                                       codemap::FssNone, source);
 -    maybe_aborted(p.parse_crate_mod(cfg),p)
 +pub fn parse_crate_from_source_str(
 +    name: ~str,
 +    source: @~str,
 +    cfg: ast::crate_cfg,
 +    sess: @mut ParseSess
 +) -> @ast::crate {
 +    let p = new_parser_from_source_str(
 +        sess,
 +        /*bad*/ copy cfg,
 +        /*bad*/ copy name,
 +        codemap::FssNone,
 +        source
 +    );
-     let r = p.parse_crate_mod(/*bad*/ copy cfg);
-     p.abort_if_errors();
-     r
++    maybe_aborted(p.parse_crate_mod(/*bad*/ copy cfg),p)
  }
  
 -pub fn parse_expr_from_source_str(name: ~str,
 -                                  source: @~str,
 -                                  cfg: ast::crate_cfg,
 -                                  sess: @mut ParseSess) -> @ast::expr {
 -    let p = new_parser_from_source_str(sess, cfg, name,
 -                                       codemap::FssNone, source);
 +pub fn parse_expr_from_source_str(
 +    name: ~str,
 +    source: @~str,
 +    +cfg: ast::crate_cfg,
 +    sess: @mut ParseSess
 +) -> @ast::expr {
 +    let p = new_parser_from_source_str(
 +        sess,
 +        cfg,
 +        /*bad*/ copy name,
 +        codemap::FssNone,
 +        source
 +    );
-     let r = p.parse_expr();
-     p.abort_if_errors();
-     r
+     maybe_aborted(p.parse_expr(), p)
  }
  
 -pub fn parse_item_from_source_str(name: ~str,
 -                                  source: @~str,
 -                                  cfg: ast::crate_cfg,
 -                                  +attrs: ~[ast::attribute],
 -                                  sess: @mut ParseSess)
 -                               -> Option<@ast::item> {
 -    let p = new_parser_from_source_str(sess, cfg, name,
 -                                       codemap::FssNone, source);
 +pub fn parse_item_from_source_str(
 +    name: ~str,
 +    source: @~str,
 +    +cfg: ast::crate_cfg,
 +    +attrs: ~[ast::attribute],
 +    sess: @mut ParseSess
 +) -> Option<@ast::item> {
 +    let p = new_parser_from_source_str(
 +        sess,
 +        cfg,
 +        /*bad*/ copy name,
 +        codemap::FssNone,
 +        source
 +    );
-     let r = p.parse_item(attrs);
-     p.abort_if_errors();
-     r
+     maybe_aborted(p.parse_item(attrs),p)
  }
  
 -pub fn parse_stmt_from_source_str(name: ~str,
 -                                  source: @~str,
 -                                  cfg: ast::crate_cfg,
 -                                  +attrs: ~[ast::attribute],
 -                                  sess: @mut ParseSess) -> @ast::stmt {
 -    let p = new_parser_from_source_str(sess, cfg, name,
 -                                       codemap::FssNone, source);
 +pub fn parse_stmt_from_source_str(
 +    name: ~str,
 +    source: @~str,
 +    +cfg: ast::crate_cfg,
 +    +attrs: ~[ast::attribute],
 +    sess: @mut ParseSess
 +) -> @ast::stmt {
 +    let p = new_parser_from_source_str(
 +        sess,
 +        cfg,
 +        /*bad*/ copy name,
 +        codemap::FssNone,
 +        source
 +    );
-     let r = p.parse_stmt(attrs);
-     p.abort_if_errors();
-     r
+     maybe_aborted(p.parse_stmt(attrs),p)
  }
  
 -pub fn parse_tts_from_source_str(name: ~str,
 -                                 source: @~str,
 -                                 cfg: ast::crate_cfg,
 -                                 sess: @mut ParseSess) -> ~[ast::token_tree] {
 -    let p = new_parser_from_source_str(sess, cfg, name,
 -                                       codemap::FssNone, source);
 +pub fn parse_tts_from_source_str(
 +    name: ~str,
 +    source: @~str,
 +    +cfg: ast::crate_cfg,
 +    sess: @mut ParseSess
 +) -> ~[ast::token_tree] {
 +    let p = new_parser_from_source_str(
 +        sess,
 +        cfg,
 +        /*bad*/ copy name,
 +        codemap::FssNone,
 +        source
 +    );
      *p.quote_depth += 1u;
-     let r = p.parse_all_token_trees();
-     p.abort_if_errors();
-     r
+     maybe_aborted(p.parse_all_token_trees(),p)
  }
  
 -pub fn parse_from_source_str<T>(f: fn (p: Parser) -> T,
 -                            name: ~str, ss: codemap::FileSubstr,
 -                            source: @~str, cfg: ast::crate_cfg,
 -                            sess: @mut ParseSess)
 -    -> T
 -{
 -    let p = new_parser_from_source_str(sess, cfg, name, ss,
 -                                       source);
 +pub fn parse_from_source_str<T>(
 +    f: fn (Parser) -> T,
 +    name: ~str, ss: codemap::FileSubstr,
 +    source: @~str,
 +    +cfg: ast::crate_cfg,
 +    sess: @mut ParseSess
 +) -> T {
 +    let p = new_parser_from_source_str(
 +        sess,
 +        cfg,
 +        /*bad*/ copy name,
 +        /*bad*/ copy ss,
 +        source
 +    );
      let r = f(p);
      if !p.reader.is_eof() {
          p.reader.fatal(~"expected end-of-string");
@@@ -214,51 -160,40 +203,51 @@@ pub fn next_node_id(sess: @mut ParseSes
      return rv;
  }
  
 -pub fn new_parser_from_source_str(sess: @mut ParseSess, cfg: ast::crate_cfg,
 -                              +name: ~str, +ss: codemap::FileSubstr,
 -                              source: @~str) -> Parser {
 +pub fn new_parser_from_source_str(
 +    sess: @mut ParseSess,
 +    +cfg: ast::crate_cfg,
 +    +name: ~str,
 +    +ss: codemap::FileSubstr,
 +    source: @~str
 +) -> Parser {
      let filemap = sess.cm.new_filemap_w_substr(name, ss, source);
 -    let srdr = lexer::new_string_reader(copy sess.span_diagnostic,
 -                                        filemap,
 -                                        sess.interner);
 -    return Parser(sess, cfg, srdr as reader);
 +    let srdr = lexer::new_string_reader(
 +        copy sess.span_diagnostic,
 +        filemap,
 +        sess.interner
 +    );
 +    Parser(sess, cfg, srdr as reader)
  }
  
- // Read the entire source file, return a parser
- // that draws from that string
+ /// Read the entire source file, return a parser
+ /// that draws from that string
 -pub fn new_parser_result_from_file(sess: @mut ParseSess,
 -                            cfg: ast::crate_cfg,
 -                            path: &Path)
 -                         -> Result<Parser, ~str> {
 +pub fn new_parser_result_from_file(
 +    sess: @mut ParseSess,
 +    +cfg: ast::crate_cfg,
 +    path: &Path
 +) -> Result<Parser, ~str> {
      match io::read_whole_file_str(path) {
 -      result::Ok(src) => {
 +        Ok(src) => {
 +            let filemap = sess.cm.new_filemap(path.to_str(), @src);
 +            let srdr = lexer::new_string_reader(
 +                copy sess.span_diagnostic,
 +                filemap,
 +                sess.interner
 +            );
 +            Ok(Parser(sess, cfg, srdr as reader))
  
 -          let filemap = sess.cm.new_filemap(path.to_str(), @src);
 -          let srdr = lexer::new_string_reader(copy sess.span_diagnostic,
 -                                              filemap,
 -                                              sess.interner);
 -          Ok(Parser(sess, cfg, srdr as reader))
 -
 -      }
 -      result::Err(e) => Err(e)
 +        }
 +        Err(e) => Err(e)
      }
  }
  
- /// Create a new parser for an entire crate, handling errors as appropriate
+ /// Create a new parser, handling errors as appropriate
  /// if the file doesn't exist
 -pub fn new_parser_from_file(sess: @mut ParseSess, cfg: ast::crate_cfg,
 -                              path: &Path) -> Parser {
 +pub fn new_parser_from_file(
 +    sess: @mut ParseSess,
 +    +cfg: ast::crate_cfg,
 +    path: &Path
 +) -> Parser {
      match new_parser_result_from_file(sess, cfg, path) {
          Ok(parser) => parser,
          Err(e) => {
@@@ -283,20 -214,20 +272,27 @@@ pub fn new_sub_parser_from_file
      }
  }
  
 -pub fn new_parser_from_tts(sess: @mut ParseSess, cfg: ast::crate_cfg,
 -                       tts: ~[ast::token_tree]) -> Parser {
 -    let trdr = lexer::new_tt_reader(copy sess.span_diagnostic, sess.interner,
 -                                    None, tts);
 -    return Parser(sess, cfg, trdr as reader)
 +pub fn new_parser_from_tts(
 +    sess: @mut ParseSess,
 +    +cfg: ast::crate_cfg,
 +    +tts: ~[ast::token_tree]
 +) -> Parser {
 +    let trdr = lexer::new_tt_reader(
 +        copy sess.span_diagnostic,
 +        sess.interner,
 +        None,
 +        tts
 +    );
 +    Parser(sess, cfg, trdr as reader)
  }
  
+ // abort if necessary
+ pub fn maybe_aborted<T>(+result : T, p: Parser) -> T {
+     p.abort_if_errors();
+     result
+ }
  
  #[cfg(test)]
  mod test {
Simple merge
index dffa04ac1cab081cee246e78fc723288fe5fde76,59ad35b38e4ff99a8c61773e679d8c9d5b3bc792..3d4e0f9020bdc22159b046b7f01648fbd2ce64a4
@@@ -651,8 -623,11 +652,11 @@@ pub impl Parser 
              }
              ty_rec(elems)
          } else if *self.token == token::LBRACKET {
 -            self.expect(token::LBRACKET);
 +            self.expect(&token::LBRACKET);
              let mt = self.parse_mt();
+             if mt.mutbl == m_mutbl {    // `m_const` too after snapshot
+                 self.obsolete(*self.last_span, ObsoleteMutVector);
+             }
  
              // Parse the `* 3` in `[ int * 3 ]`
              let t = match self.maybe_parse_fixed_vstore_with_star() {
          either::Left(self.parse_arg_general(true))
      }
  
-     fn parse_arg_or_capture_item() -> arg_or_capture_item {
-         self.parse_capture_item_or(|p| p.parse_arg())
-     }
      fn parse_fn_block_arg() -> arg_or_capture_item {
-         do self.parse_capture_item_or |p| {
-             let m = p.parse_arg_mode();
-             let is_mutbl = self.eat_keyword(&~"mut");
-             let pat = p.parse_pat(false);
-             let t = if p.eat(&token::COLON) {
-                 p.parse_ty(false)
-             } else {
-                 @Ty {
-                     id: p.get_id(),
-                     node: ty_infer,
-                     span: mk_sp(p.span.lo, p.span.hi),
-                 }
-             };
-             either::Left(ast::arg {
-                 mode: m,
-                 is_mutbl: is_mutbl,
-                 ty: t,
-                 pat: pat,
-                 id: p.get_id()
-             })
-         }
+         let m = self.parse_arg_mode();
 -        let is_mutbl = self.eat_keyword(~"mut");
++        let is_mutbl = self.eat_keyword(&~"mut");
+         let pat = self.parse_pat(false);
 -        let t = if self.eat(token::COLON) {
++        let t = if self.eat(&token::COLON) {
+             self.parse_ty(false)
+         } else {
+             @Ty {
+                 id: self.get_id(),
+                 node: ty_infer,
+                 span: mk_sp(self.span.lo, self.span.hi),
+             }
+         };
+         either::Left(ast::arg {
+             mode: m,
+             is_mutbl: is_mutbl,
+             ty: t,
+             pat: pat,
+             id: self.get_id()
+         })
      }
  
      fn maybe_parse_fixed_vstore_with_star() -> Option<uint> {
      }
  
      // Parses two variants (with the region/type params always optional):
-     //    impl<T> ~[T] : to_str { ... }
-     //    impl<T> to_str for ~[T] { ... }
-     fn parse_item_impl() -> item_info {
+     //    impl<T> Foo { ... }
+     //    impl<T> ToStr for ~[T] { ... }
+     fn parse_item_impl(visibility: ast::visibility) -> item_info {
 -        fn wrap_path(p: Parser, pt: @path) -> @Ty {
 +        fn wrap_path(p: &Parser, pt: @path) -> @Ty {
              @Ty {
                  id: p.get_id(),
                  node: ty_path(pt, p.get_id()),
              None
          };
  
+         // Do not allow visibility to be specified in `impl...for...`. It is
+         // meaningless.
+         if opt_trait.is_some() && visibility != ast::inherited {
+             self.obsolete(*self.span, ObsoleteTraitImplVisibility);
+         }
          let mut meths = ~[];
 -        if !self.eat(token::SEMI) {
 -            self.expect(token::LBRACE);
 -            while !self.eat(token::RBRACE) {
 +        if !self.eat(&token::SEMI) {
 +            self.expect(&token::LBRACE);
 +            while !self.eat(&token::RBRACE) {
                  meths.push(self.parse_method());
              }
          }
              return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                            visibility,
                                            maybe_append(attrs, extra_attrs)));
 -        } else if items_allowed && self.eat_keyword(~"impl") {
 +        } else if items_allowed && self.eat_keyword(&~"impl") {
              // IMPL ITEM
-             let (ident, item_, extra_attrs) = self.parse_item_impl();
+             let (ident, item_, extra_attrs) =
+                 self.parse_item_impl(visibility);
              return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                            visibility,
                                            maybe_append(attrs, extra_attrs)));
Simple merge