about summary refs log tree commit diff
path: root/src/libsyntax/parse/parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
-rw-r--r--src/libsyntax/parse/parser.rs407
1 files changed, 221 insertions, 186 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 5aa45ab3c9b..25b45a5f3b5 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -19,14 +19,14 @@ use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_infer};
 use ast::{bind_by_copy, bitand, bitor, bitxor, blk};
 use ast::{blk_check_mode, box};
 use ast::{crate, crate_cfg, decl, decl_item};
-use ast::{decl_local, default_blk, deref, div, enum_def};
+use ast::{decl_local, default_blk, deref, div, enum_def, explicit_self};
 use ast::{expr, expr_, expr_addr_of, expr_match, expr_again};
 use ast::{expr_assign, expr_assign_op, expr_binary, expr_block};
 use ast::{expr_break, expr_call, expr_cast, expr_copy, expr_do_body};
 use ast::{expr_field, expr_fn_block, expr_if, expr_index};
 use ast::{expr_lit, expr_log, expr_loop, expr_loop_body, expr_mac};
 use ast::{expr_method_call, expr_paren, expr_path, expr_repeat};
-use ast::{expr_ret, expr_struct, expr_tup, expr_unary};
+use ast::{expr_ret, expr_self, expr_struct, expr_tup, expr_unary};
 use ast::{expr_vec, expr_vstore, expr_vstore_mut_box};
 use ast::{expr_vstore_slice, expr_vstore_box};
 use ast::{expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl};
@@ -43,7 +43,7 @@ use ast::{named_field, neg, node_id, noreturn, not, pat, pat_box, pat_enum};
 use ast::{pat_ident, pat_lit, pat_range, pat_region, pat_struct};
 use ast::{pat_tup, pat_uniq, pat_wild, private};
 use ast::{rem, required};
-use ast::{ret_style, return_val, self_ty, shl, shr, stmt, stmt_decl};
+use ast::{ret_style, return_val, shl, shr, stmt, stmt_decl};
 use ast::{stmt_expr, stmt_semi, stmt_mac, struct_def, struct_field};
 use ast::{struct_variant_kind, subtract};
 use ast::{sty_box, sty_region, sty_static, sty_uniq, sty_value};
@@ -82,6 +82,7 @@ use parse::obsolete::ObsoleteMode;
 use parse::obsolete::{ObsoleteLifetimeNotation, ObsoleteConstManagedPointer};
 use parse::obsolete::{ObsoletePurity, ObsoleteStaticMethod};
 use parse::obsolete::{ObsoleteConstItem, ObsoleteFixedLengthVectorType};
+use parse::obsolete::{ObsoleteNamedExternModule};
 use parse::token::{can_begin_expr, is_ident, is_ident_or_path};
 use parse::token::{is_plain_ident, INTERPOLATED, special_idents, token_to_binop};
 use parse::token;
@@ -337,10 +338,10 @@ pub impl Parser {
 
     // is this one of the keywords that signals a closure type?
     fn token_is_closure_keyword(&self, tok: &token::Token) -> bool {
-        self.token_is_keyword(&~"pure", tok) ||
-            self.token_is_keyword(&~"unsafe", tok) ||
-            self.token_is_keyword(&~"once", tok) ||
-            self.token_is_keyword(&~"fn", tok)
+        self.token_is_keyword("pure", tok) ||
+            self.token_is_keyword("unsafe", tok) ||
+            self.token_is_keyword("once", tok) ||
+            self.token_is_keyword("fn", tok)
     }
 
     fn token_is_lifetime(&self, tok: &token::Token) -> bool {
@@ -377,7 +378,7 @@ pub impl Parser {
         let opt_abis = self.parse_opt_abis();
         let abis = opt_abis.get_or_default(AbiSet::Rust());
         let purity = self.parse_unsafety();
-        self.expect_keyword(&~"fn");
+        self.expect_keyword("fn");
         let (decl, lifetimes) = self.parse_ty_fn_decl();
         return ty_bare_fn(@TyBareFn {
             abis: abis,
@@ -394,12 +395,13 @@ pub impl Parser {
                         -> ty_ {
         /*
 
-        (&|~|@) ['r] [pure|unsafe] [once] fn <'lt> (S) -> T
-        ^~~~~~^ ^~~^ ^~~~~~~~~~~~^ ^~~~~^    ^~~~^ ^~^    ^
-           |     |     |             |         |    |     |
-           |     |     |             |         |    |   Return type
-           |     |     |             |         |  Argument types
-           |     |     |             |     Lifetimes
+        (&|~|@) ['r] [pure|unsafe] [once] fn [:Bounds] <'lt> (S) -> T
+        ^~~~~~^ ^~~^ ^~~~~~~~~~~~^ ^~~~~^    ^~~~~~~~^ ^~~~^ ^~^    ^
+           |     |     |             |           |       |    |     |
+           |     |     |             |           |       |    |   Return type
+           |     |     |             |           |       |  Argument types
+           |     |     |             |           |   Lifetimes
+           |     |     |             |       Closure bounds
            |     |     |          Once-ness (a.k.a., affine)
            |     |   Purity
            | Lifetime bound
@@ -412,11 +414,11 @@ pub impl Parser {
 
         let purity = self.parse_unsafety();
         let onceness = parse_onceness(self);
-        self.expect_keyword(&~"fn");
+        self.expect_keyword("fn");
+        let bounds = self.parse_optional_ty_param_bounds();
 
         if self.parse_fn_ty_sigil().is_some() {
-            self.obsolete(*self.span,
-                          ObsoletePostFnTySigil);
+            self.obsolete(*self.span, ObsoletePostFnTySigil);
         }
 
         let (decl, lifetimes) = self.parse_ty_fn_decl();
@@ -426,21 +428,26 @@ pub impl Parser {
             region: region,
             purity: purity,
             onceness: onceness,
+            bounds: bounds,
             decl: decl,
             lifetimes: lifetimes,
         });
 
-        fn parse_onceness(self: &Parser) -> Onceness {
-            if self.eat_keyword(&~"once") { Once } else { Many }
+        fn parse_onceness(this: &Parser) -> Onceness {
+            if this.eat_keyword(~"once") {
+                Once
+            } else {
+                Many
+            }
         }
     }
 
     // looks like this should be called parse_unsafety
     fn parse_unsafety(&self) -> purity {
-        if self.eat_keyword(&~"pure") {
+        if self.eat_keyword("pure") {
             self.obsolete(*self.last_span, ObsoletePurity);
             return impure_fn;
-        } else if self.eat_keyword(&~"unsafe") {
+        } else if self.eat_keyword("unsafe") {
             return unsafe_fn;
         } else {
             return impure_fn;
@@ -500,7 +507,7 @@ pub impl Parser {
 
             let generics = p.parse_generics();
 
-            let (self_ty, d) = do self.parse_fn_decl_with_self() |p| {
+            let (explicit_self, d) = do self.parse_fn_decl_with_self() |p| {
                 // This is somewhat dubious; We don't want to allow argument
                 // names to be left off if there is a definition...
                 either::Left(p.parse_arg_general(false))
@@ -522,7 +529,7 @@ pub impl Parser {
                     purity: pur,
                     decl: d,
                     generics: generics,
-                    self_ty: self_ty,
+                    explicit_self: explicit_self,
                     id: p.get_id(),
                     span: mk_sp(lo, hi)
                 })
@@ -536,7 +543,7 @@ pub impl Parser {
                     ident: ident,
                     attrs: attrs,
                     generics: generics,
-                    self_ty: self_ty,
+                    explicit_self: explicit_self,
                     purity: pur,
                     decl: d,
                     body: body,
@@ -695,7 +702,7 @@ pub impl Parser {
             // BORROWED POINTER
             self.bump();
             self.parse_borrowed_pointee()
-        } else if self.eat_keyword(&~"extern") {
+        } else if self.eat_keyword("extern") {
             // EXTERN FUNCTION
             self.parse_ty_bare_fn()
         } else if self.token_is_closure_keyword(&copy *self.token) {
@@ -704,7 +711,7 @@ pub impl Parser {
             self.obsolete(*self.last_span, ObsoleteBareFnType);
             result
         } else if *self.token == token::MOD_SEP
-            || is_ident_or_path(&*self.token) {
+            || is_ident_or_path(self.token) {
             // NAMED TYPE
             let path = self.parse_path_with_tps(false);
             ty_path(path, self.get_id())
@@ -819,7 +826,7 @@ pub impl Parser {
         let mut is_mutbl = false;
         let pat = if require_name || self.is_named_argument() {
             self.parse_arg_mode();
-            is_mutbl = self.eat_keyword(&~"mut");
+            is_mutbl = self.eat_keyword("mut");
             let pat = self.parse_pat(false);
             self.expect(&token::COLON);
             pat
@@ -847,7 +854,7 @@ pub impl Parser {
     // parse an argument in a lambda header e.g. |arg, arg|
     fn parse_fn_block_arg(&self) -> arg_or_capture_item {
         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) {
             self.parse_ty(false)
@@ -898,9 +905,9 @@ pub impl Parser {
     // matches lit = true | false | token_lit
     fn parse_lit(&self) -> lit {
         let lo = self.span.lo;
-        let lit = if self.eat_keyword(&~"true") {
+        let lit = if self.eat_keyword("true") {
             lit_bool(true)
-        } else if self.eat_keyword(&~"false") {
+        } else if self.eat_keyword("false") {
             lit_bool(false)
         } else {
             // XXX: This is a really bad copy!
@@ -911,6 +918,24 @@ pub impl Parser {
         codemap::spanned { node: lit, span: mk_sp(lo, self.last_span.hi) }
     }
 
+    // matches '-' lit | lit
+    fn parse_literal_maybe_minus(&self) -> @expr {
+        let minus_lo = self.span.lo;
+        let minus_present = self.eat(&token::BINOP(token::MINUS));
+
+        let lo = self.span.lo;
+        let literal = @self.parse_lit();
+        let hi = self.span.hi;
+        let expr = self.mk_expr(lo, hi, expr_lit(literal));
+
+        if minus_present {
+            let minus_hi = self.span.hi;
+            self.mk_expr(minus_lo, minus_hi, expr_unary(neg, expr))
+        } else {
+            expr
+        }
+    }
+
     // parse a path into a vector of idents, whether the path starts
     // with ::, and a span.
     fn parse_path(&self) -> (~[ast::ident],bool,span) {
@@ -1118,15 +1143,15 @@ pub impl Parser {
     }
 
     fn token_is_mutability(&self, tok: &token::Token) -> bool {
-        self.token_is_keyword(&~"mut", tok) ||
-        self.token_is_keyword(&~"const", tok)
+        self.token_is_keyword("mut", tok) ||
+        self.token_is_keyword("const", tok)
     }
 
     // parse mutability declaration (mut/const/imm)
     fn parse_mutability(&self) -> mutability {
-        if self.eat_keyword(&~"mut") {
+        if self.eat_keyword("mut") {
             m_mutbl
-        } else if self.eat_keyword(&~"const") {
+        } else if self.eat_keyword("const") {
             m_const
         } else {
             m_imm
@@ -1224,27 +1249,30 @@ pub impl Parser {
                                  expr_block(blk));
         } else if token::is_bar(&*self.token) {
             return self.parse_lambda_expr();
-        } else if self.eat_keyword(&~"if") {
+        } else if self.eat_keyword("self") {
+            ex = expr_self;
+            hi = self.span.hi;
+        } else if self.eat_keyword("if") {
             return self.parse_if_expr();
-        } else if self.eat_keyword(&~"for") {
+        } else if self.eat_keyword("for") {
             return self.parse_sugary_call_expr(~"for", ForSugar,
                                                expr_loop_body);
-        } else if self.eat_keyword(&~"do") {
+        } else if self.eat_keyword("do") {
             return self.parse_sugary_call_expr(~"do", DoSugar,
                                                expr_do_body);
-        } else if self.eat_keyword(&~"while") {
+        } else if self.eat_keyword("while") {
             return self.parse_while_expr();
         } else if self.token_is_lifetime(&*self.token) {
             let lifetime = self.get_lifetime(&*self.token);
             self.bump();
             self.expect(&token::COLON);
-            self.expect_keyword(&~"loop");
+            self.expect_keyword("loop");
             return self.parse_loop_expr(Some(lifetime));
-        } else if self.eat_keyword(&~"loop") {
+        } else if self.eat_keyword("loop") {
             return self.parse_loop_expr(None);
-        } else if self.eat_keyword(&~"match") {
+        } else if self.eat_keyword("match") {
             return self.parse_match_expr();
-        } else if self.eat_keyword(&~"unsafe") {
+        } else if self.eat_keyword("unsafe") {
             return self.parse_block_expr(lo, unsafe_blk);
         } else if *self.token == token::LBRACKET {
             self.bump();
@@ -1284,7 +1312,7 @@ pub impl Parser {
                 }
             }
             hi = self.span.hi;
-        } else if self.eat_keyword(&~"__log") {
+        } else if self.eat_keyword("__log") {
             // LOG expression
             self.expect(&token::LPAREN);
             let lvl = self.parse_expr();
@@ -1293,14 +1321,14 @@ pub impl Parser {
             ex = expr_log(lvl, e);
             hi = self.span.hi;
             self.expect(&token::RPAREN);
-        } else if self.eat_keyword(&~"return") {
+        } else if self.eat_keyword("return") {
             // RETURN expression
             if can_begin_expr(&*self.token) {
                 let e = self.parse_expr();
                 hi = e.span.hi;
                 ex = expr_ret(Some(e));
             } else { ex = expr_ret(None); }
-        } else if self.eat_keyword(&~"break") {
+        } else if self.eat_keyword("break") {
             // BREAK expression
             if self.token_is_lifetime(&*self.token) {
                 let lifetime = self.get_lifetime(&*self.token);
@@ -1310,14 +1338,14 @@ pub impl Parser {
                 ex = expr_break(None);
             }
             hi = self.span.hi;
-        } else if self.eat_keyword(&~"copy") {
+        } else if self.eat_keyword("copy") {
             // COPY expression
             let e = self.parse_expr();
             ex = expr_copy(e);
             hi = e.span.hi;
         } else if *self.token == token::MOD_SEP ||
-                is_ident(&*self.token) && !self.is_keyword(&~"true") &&
-                !self.is_keyword(&~"false") {
+                is_ident(&*self.token) && !self.is_keyword("true") &&
+                !self.is_keyword("false") {
             let pth = self.parse_path_with_tps(true);
 
             // `!`, as an operator, is prefix, so we know this isn't that
@@ -1531,9 +1559,12 @@ pub impl Parser {
                         |p| p.parse_token_tree()
                     );
                     let (s, z) = p.parse_sep_and_zerok();
+                    let seq = match seq {
+                        spanned { node, _ } => node,
+                    };
                     tt_seq(
-                        mk_sp(sp.lo ,p.span.hi),
-                        seq.node,
+                        mk_sp(sp.lo, p.span.hi),
+                        seq,
                         s,
                         z
                     )
@@ -1599,9 +1630,9 @@ pub impl Parser {
             token::LBRACE | token::LPAREN | token::LBRACKET => {
                 self.parse_matcher_subseq(
                     name_idx,
-                    *self.token,
+                    copy *self.token,
                     // tjc: not sure why we need a copy
-                    token::flip_delimiter(&*self.token)
+                    token::flip_delimiter(self.token)
                 )
             }
             _ => self.fatal(~"expected open delimiter")
@@ -1794,7 +1825,7 @@ pub impl Parser {
                     }
                 }
                 None => {
-                    if as_prec > min_prec && self.eat_keyword(&~"as") {
+                    if as_prec > min_prec && self.eat_keyword("as") {
                         let rhs = self.parse_ty(true);
                         let _as = self.mk_expr(lhs.span.lo,
                                                rhs.span.hi,
@@ -1868,7 +1899,7 @@ pub impl Parser {
         let thn = self.parse_block();
         let mut els: Option<@expr> = None;
         let mut hi = thn.span.hi;
-        if self.eat_keyword(&~"else") {
+        if self.eat_keyword("else") {
             let elexpr = self.parse_else_expr();
             els = Some(elexpr);
             hi = elexpr.span.hi;
@@ -1935,7 +1966,7 @@ pub impl Parser {
     }
 
     fn parse_else_expr(&self) -> @expr {
-        if self.eat_keyword(&~"if") {
+        if self.eat_keyword("if") {
             return self.parse_if_expr();
         } else {
             let blk = self.parse_block();
@@ -1961,14 +1992,15 @@ pub impl Parser {
         // them as the lambda arguments
         let e = self.parse_expr_res(RESTRICT_NO_BAR_OR_DOUBLEBAR_OP);
         match e.node {
-            expr_call(f, args, NoSugar) => {
+            expr_call(f, /*bad*/ copy args, NoSugar) => {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
                 let args = vec::append(args, ~[last_arg]);
                 self.mk_expr(lo.lo, block.span.hi, expr_call(f, args, sugar))
             }
-            expr_method_call(f, i, tps, args, NoSugar) => {
+            expr_method_call(f, i, /*bad*/ copy tps,
+                             /*bad*/ copy args, NoSugar) => {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
@@ -1976,7 +2008,7 @@ pub impl Parser {
                 self.mk_expr(lo.lo, block.span.hi,
                              expr_method_call(f, i, tps, args, sugar))
             }
-            expr_field(f, i, tps) => {
+            expr_field(f, i, /*bad*/ copy tps) => {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
@@ -2048,7 +2080,7 @@ pub impl Parser {
     fn looking_at_record_literal(&self) -> bool {
         let lookahead = self.look_ahead(1);
         *self.token == token::LBRACE &&
-            (self.token_is_keyword(&~"mut", &lookahead) ||
+            (self.token_is_keyword("mut", &lookahead) ||
              (is_plain_ident(&lookahead) &&
               self.look_ahead(2) == token::COLON))
     }
@@ -2061,7 +2093,7 @@ pub impl Parser {
         while *self.token != token::RBRACE {
             let pats = self.parse_pats();
             let mut guard = None;
-            if self.eat_keyword(&~"if") { guard = Some(self.parse_expr()); }
+            if self.eat_keyword("if") { guard = Some(self.parse_expr()); }
             self.expect(&token::FAT_ARROW);
             let expr = self.parse_expr_res(RESTRICT_STMT_EXPR);
 
@@ -2234,7 +2266,7 @@ pub impl Parser {
         let lo = self.span.lo;
         let mut hi = self.span.hi;
         let pat;
-        match *self.token {
+        match /*bad*/ copy *self.token {
             // parse _
           token::UNDERSCORE => { self.bump(); pat = pat_wild; }
             // parse @pat
@@ -2348,24 +2380,33 @@ pub impl Parser {
             self.expect(&token::RBRACKET);
             pat = ast::pat_vec(before, slice, after);
           }
-          tok => {
-            if !is_ident_or_path(&tok)
-                || self.is_keyword(&~"true")
-                || self.is_keyword(&~"false")
+          ref tok => {
+            if !is_ident_or_path(tok)
+                || self.is_keyword("true")
+                || self.is_keyword("false")
             {
-                // parse an expression pattern or exp .. exp
-                let val = self.parse_expr_res(RESTRICT_NO_BAR_OP);
+                // Parse an expression pattern or exp .. exp.
+                //
+                // These expressions are limited to literals (possibly
+                // preceded by unary-minus) or identifiers.
+                let val = self.parse_literal_maybe_minus();
                 if self.eat(&token::DOTDOT) {
-                    let end = self.parse_expr_res(RESTRICT_NO_BAR_OP);
+                    let end = if is_ident_or_path(tok) {
+                        let path = self.parse_path_with_tps(true);
+                        let hi = self.span.hi;
+                        self.mk_expr(lo, hi, expr_path(path))
+                    } else {
+                        self.parse_literal_maybe_minus()
+                    };
                     pat = pat_range(val, end);
                 } else {
                     pat = pat_lit(val);
                 }
-            } else if self.eat_keyword(&~"ref") {
+            } else if self.eat_keyword("ref") {
                 // parse ref pat
                 let mutbl = self.parse_mutability();
                 pat = self.parse_pat_ident(refutable, bind_by_ref(mutbl));
-            } else if self.eat_keyword(&~"copy") {
+            } else if self.eat_keyword("copy") {
                 // parse copy pat
                 pat = self.parse_pat_ident(refutable, bind_by_copy);
             } else {
@@ -2433,7 +2474,7 @@ pub impl Parser {
                                   }
                               },
                               _ => {
-                                  if vec::len(enum_path.idents)==1u {
+                                  if enum_path.idents.len()==1u {
                                       // it could still be either an enum
                                       // or an identifier pattern, resolve
                                       // will sort it out:
@@ -2514,7 +2555,7 @@ pub impl Parser {
 
     // parse a "let" stmt
     fn parse_let(&self) -> @decl {
-        let is_mutbl = self.eat_keyword(&~"mut");
+        let is_mutbl = self.eat_keyword("mut");
         let lo = self.span.lo;
         let mut locals = ~[self.parse_local(is_mutbl)];
         while self.eat(&token::COMMA) {
@@ -2528,7 +2569,7 @@ pub impl Parser {
                          pr: visibility,
                          attrs: ~[attribute]) -> @struct_field {
         let lo = self.span.lo;
-        if self.eat_keyword(&~"mut") {
+        if self.eat_keyword("mut") {
             // Do nothing, for backwards compatibility.
             // XXX: Remove after snapshot.
         }
@@ -2558,9 +2599,9 @@ pub impl Parser {
         }
 
         let lo = self.span.lo;
-        if self.is_keyword(&~"let") {
+        if self.is_keyword("let") {
             check_expected_item(self, first_item_attrs);
-            self.expect_keyword(&~"let");
+            self.expect_keyword("let");
             let decl = self.parse_let();
             return @spanned(lo, decl.span.hi, stmt_decl(decl, self.get_id()));
         } else if is_ident(&*self.token)
@@ -2647,7 +2688,7 @@ pub impl Parser {
         maybe_whole!(self, nt_block);
 
         let lo = self.span.lo;
-        if self.eat_keyword(&~"unsafe") {
+        if self.eat_keyword("unsafe") {
             self.obsolete(copy *self.span, ObsoleteUnsafeBlock);
         }
         self.expect(&token::LBRACE);
@@ -2662,7 +2703,7 @@ pub impl Parser {
         maybe_whole!(pair_empty self, nt_block);
 
         let lo = self.span.lo;
-        if self.eat_keyword(&~"unsafe") {
+        if self.eat_keyword("unsafe") {
             self.obsolete(copy *self.span, ObsoleteUnsafeBlock);
         }
         self.expect(&token::LBRACE);
@@ -2796,10 +2837,10 @@ pub impl Parser {
     }
 
     fn parse_optional_purity(&self) -> ast::purity {
-        if self.eat_keyword(&~"pure") {
+        if self.eat_keyword("pure") {
             self.obsolete(*self.last_span, ObsoletePurity);
             ast::impure_fn
-        } else if self.eat_keyword(&~"unsafe") {
+        } else if self.eat_keyword("unsafe") {
             ast::unsafe_fn
         } else {
             ast::impure_fn
@@ -2807,15 +2848,15 @@ pub impl Parser {
     }
 
     fn parse_optional_onceness(&self) -> ast::Onceness {
-        if self.eat_keyword(&~"once") { ast::Once } else { ast::Many }
+        if self.eat_keyword("once") { ast::Once } else { ast::Many }
     }
 
     // matches optbounds = ( ( : ( boundseq )? )? )
     // where   boundseq  = ( bound + boundseq ) | bound
     // and     bound     = 'static | ty
-    fn parse_optional_ty_param_bounds(&self) -> @OptVec<TyParamBound> {
+    fn parse_optional_ty_param_bounds(&self) -> OptVec<TyParamBound> {
         if !self.eat(&token::COLON) {
-            return @opt_vec::Empty;
+            return opt_vec::Empty;
         }
 
         let mut result = opt_vec::Empty;
@@ -2863,19 +2904,19 @@ pub impl Parser {
                 loop;
             }
 
-            if is_ident_or_path(&*self.token) {
+            if is_ident_or_path(self.token) {
                 self.obsolete(*self.span,
                               ObsoleteTraitBoundSeparator);
             }
         }
 
-        return @result;
+        return result;
     }
 
     // matches typaram = IDENT optbounds
     fn parse_ty_param(&self) -> TyParam {
         let ident = self.parse_ident();
-        let bounds = self.parse_optional_ty_param_bounds();
+        let bounds = @self.parse_optional_ty_param_bounds();
         ast::TyParam { ident: ident, id: self.get_id(), bounds: bounds }
     }
 
@@ -2964,16 +3005,16 @@ pub impl Parser {
         &self,
         parse_arg_fn:
         &fn(&Parser) -> arg_or_capture_item
-    ) -> (self_ty, fn_decl) {
-        fn maybe_parse_self_ty(
-            cnstr: &fn(v: mutability) -> ast::self_ty_,
+    ) -> (explicit_self, fn_decl) {
+        fn maybe_parse_explicit_self(
+            cnstr: &fn(v: mutability) -> ast::explicit_self_,
             p: &Parser
-        ) -> ast::self_ty_ {
+        ) -> ast::explicit_self_ {
             // We need to make sure it isn't a mode or a type
-            if p.token_is_keyword(&~"self", &p.look_ahead(1)) ||
-                ((p.token_is_keyword(&~"const", &p.look_ahead(1)) ||
-                  p.token_is_keyword(&~"mut", &p.look_ahead(1))) &&
-                 p.token_is_keyword(&~"self", &p.look_ahead(2))) {
+            if p.token_is_keyword("self", &p.look_ahead(1)) ||
+                ((p.token_is_keyword("const", &p.look_ahead(1)) ||
+                  p.token_is_keyword("mut", &p.look_ahead(1))) &&
+                 p.token_is_keyword("self", &p.look_ahead(2))) {
 
                 p.bump();
                 let mutability = p.parse_mutability();
@@ -2984,9 +3025,7 @@ pub impl Parser {
             }
         }
 
-        fn maybe_parse_borrowed_self_ty(
-            self: &Parser
-        ) -> ast::self_ty_ {
+        fn maybe_parse_borrowed_explicit_self(this: &Parser) -> ast::explicit_self_ {
             // The following things are possible to see here:
             //
             //     fn(&self)
@@ -2996,37 +3035,29 @@ pub impl Parser {
             //
             // We already know that the current token is `&`.
 
-            if (
-                self.token_is_keyword(&~"self", &self.look_ahead(1)))
-            {
-                self.bump();
-                self.expect_self_ident();
+            if (this.token_is_keyword("self", &this.look_ahead(1))) {
+                this.bump();
+                this.expect_self_ident();
                 sty_region(None, m_imm)
-            } else if (
-                self.token_is_mutability(&self.look_ahead(1)) &&
-                self.token_is_keyword(&~"self", &self.look_ahead(2)))
-            {
-                self.bump();
-                let mutability = self.parse_mutability();
-                self.expect_self_ident();
+            } else if (this.token_is_mutability(&this.look_ahead(1)) &&
+                       this.token_is_keyword("self", &this.look_ahead(2))) {
+                this.bump();
+                let mutability = this.parse_mutability();
+                this.expect_self_ident();
                 sty_region(None, mutability)
-            } else if (
-                self.token_is_lifetime(&self.look_ahead(1)) &&
-                self.token_is_keyword(&~"self", &self.look_ahead(2)))
-            {
-                self.bump();
-                let lifetime = @self.parse_lifetime();
-                self.expect_self_ident();
+            } else if (this.token_is_lifetime(&this.look_ahead(1)) &&
+                       this.token_is_keyword("self", &this.look_ahead(2))) {
+                this.bump();
+                let lifetime = @this.parse_lifetime();
+                this.expect_self_ident();
                 sty_region(Some(lifetime), m_imm)
-            } else if (
-                self.token_is_lifetime(&self.look_ahead(1)) &&
-                self.token_is_mutability(&self.look_ahead(2)) &&
-                self.token_is_keyword(&~"self", &self.look_ahead(3)))
-            {
-                self.bump();
-                let lifetime = @self.parse_lifetime();
-                let mutability = self.parse_mutability();
-                self.expect_self_ident();
+            } else if (this.token_is_lifetime(&this.look_ahead(1)) &&
+                       this.token_is_mutability(&this.look_ahead(2)) &&
+                       this.token_is_keyword("self", &this.look_ahead(3))) {
+                this.bump();
+                let lifetime = @this.parse_lifetime();
+                let mutability = this.parse_mutability();
+                this.expect_self_ident();
                 sty_region(Some(lifetime), mutability)
             } else {
                 sty_static
@@ -3038,15 +3069,15 @@ pub impl Parser {
         // A bit of complexity and lookahead is needed here in order to to be
         // backwards compatible.
         let lo = self.span.lo;
-        let self_ty = match *self.token {
+        let explicit_self = match *self.token {
           token::BINOP(token::AND) => {
-            maybe_parse_borrowed_self_ty(self)
+            maybe_parse_borrowed_explicit_self(self)
           }
           token::AT => {
-            maybe_parse_self_ty(sty_box, self)
+            maybe_parse_explicit_self(sty_box, self)
           }
           token::TILDE => {
-            maybe_parse_self_ty(sty_uniq, self)
+            maybe_parse_explicit_self(sty_uniq, self)
           }
           token::IDENT(*) if self.is_self_ident() => {
             self.bump();
@@ -3059,7 +3090,7 @@ pub impl Parser {
 
         // If we parsed a self type, expect a comma before the argument list.
         let args_or_capture_items;
-        if self_ty != sty_static {
+        if explicit_self != sty_static {
             match *self.token {
                 token::COMMA => {
                     self.bump();
@@ -3104,7 +3135,7 @@ pub impl Parser {
             cf: ret_style
         };
 
-        (spanned(lo, hi, self_ty), fn_decl)
+        (spanned(lo, hi, explicit_self), fn_decl)
     }
 
     // parse the |arg, arg| header on a lambda
@@ -3171,7 +3202,7 @@ pub impl Parser {
         let pur = self.parse_fn_purity();
         let ident = self.parse_ident();
         let generics = self.parse_generics();
-        let (self_ty, decl) = do self.parse_fn_decl_with_self() |p| {
+        let (explicit_self, decl) = do self.parse_fn_decl_with_self() |p| {
             p.parse_arg()
         };
 
@@ -3182,7 +3213,7 @@ pub impl Parser {
             ident: ident,
             attrs: attrs,
             generics: generics,
-            self_ty: self_ty,
+            explicit_self: explicit_self,
             purity: pur,
             decl: decl,
             body: body,
@@ -3231,7 +3262,7 @@ pub impl Parser {
         let mut ty = self.parse_ty(false);
 
         // Parse traits, if necessary.
-        let opt_trait = if could_be_trait && self.eat_keyword(&~"for") {
+        let opt_trait = if could_be_trait && self.eat_keyword("for") {
             // New-style trait. Reinterpret the type as a trait.
             let opt_trait_ref = match ty.node {
                 ty_path(path, node_id) => {
@@ -3406,11 +3437,11 @@ pub impl Parser {
             return ~[];
         }
 
-        if self.eat_keyword(&~"priv") {
+        if self.eat_keyword("priv") {
             return ~[self.parse_single_struct_field(private, attrs)]
         }
 
-        if self.eat_keyword(&~"pub") {
+        if self.eat_keyword("pub") {
            return ~[self.parse_single_struct_field(public, attrs)];
         }
 
@@ -3423,13 +3454,13 @@ pub impl Parser {
 
     // parse visiility: PUB, PRIV, or nothing
     fn parse_visibility(&self) -> visibility {
-        if self.eat_keyword(&~"pub") { public }
-        else if self.eat_keyword(&~"priv") { private }
+        if self.eat_keyword("pub") { public }
+        else if self.eat_keyword("priv") { private }
         else { inherited }
     }
 
     fn parse_staticness(&self) -> bool {
-        if self.eat_keyword(&~"static") {
+        if self.eat_keyword("static") {
             self.obsolete(*self.last_span, ObsoleteStaticMethod);
             true
         } else {
@@ -3507,6 +3538,7 @@ pub impl Parser {
     fn parse_item_mod(&self, outer_attrs: ~[ast::attribute]) -> item_info {
         let id_span = *self.span;
         let id = self.parse_ident();
+        let merge = ::attr::first_attr_value_str_by_name(outer_attrs, "merge");
         let info_ = if *self.token == token::SEMI {
             self.bump();
             // This mod is in an external file. Let's go get it!
@@ -3526,7 +3558,7 @@ pub impl Parser {
         // (int-template, iter-trait). If there's a 'merge' attribute
         // on the mod, then we'll go and suck in another file and merge
         // its contents
-        match ::attr::first_attr_value_str_by_name(outer_attrs, ~"merge") {
+        match merge {
             Some(path) => {
                 let prefix = Path(
                     self.sess.cm.span_to_filename(*self.span));
@@ -3612,10 +3644,7 @@ pub impl Parser {
             new_sub_parser_from_file(self.sess, copy self.cfg,
                                      &full_path, id_sp);
         let (inner, next) = p0.parse_inner_attrs_and_next();
-        let mod_attrs = vec::append(
-            /*bad*/ copy outer_attrs,
-            inner
-        );
+        let mod_attrs = vec::append(outer_attrs, inner);
         let first_item_outer_attrs = next;
         let m0 = p0.parse_mod_items(token::EOF, first_item_outer_attrs);
         return (ast::item_mod(m0), mod_attrs);
@@ -3651,10 +3680,10 @@ pub impl Parser {
         let lo = self.span.lo;
 
         // XXX: Obsolete; remove after snap.
-        if self.eat_keyword(&~"const") {
+        if self.eat_keyword("const") {
             self.obsolete(*self.last_span, ObsoleteConstItem);
         } else {
-            self.expect_keyword(&~"static");
+            self.expect_keyword("static");
         }
 
         let ident = self.parse_ident();
@@ -3672,14 +3701,14 @@ pub impl Parser {
 
     // parse safe/unsafe and fn
     fn parse_fn_purity(&self) -> purity {
-        if self.eat_keyword(&~"fn") { impure_fn }
-        else if self.eat_keyword(&~"pure") {
+        if self.eat_keyword("fn") { impure_fn }
+        else if self.eat_keyword("pure") {
             self.obsolete(*self.last_span, ObsoletePurity);
-            self.expect_keyword(&~"fn");
+            self.expect_keyword("fn");
             // NB: We parse this as impure for bootstrapping purposes.
             impure_fn
-        } else if self.eat_keyword(&~"unsafe") {
-            self.expect_keyword(&~"fn");
+        } else if self.eat_keyword("unsafe") {
+            self.expect_keyword("fn");
             unsafe_fn
         }
         else { self.unexpected(); }
@@ -3688,10 +3717,11 @@ pub impl Parser {
 
     // at this point, this is essentially a wrapper for
     // parse_foreign_items.
-    fn parse_foreign_mod_items(&self, sort: ast::foreign_mod_sort,
+    fn parse_foreign_mod_items(&self,
+                               sort: ast::foreign_mod_sort,
                                abis: AbiSet,
                                first_item_attrs: ~[attribute])
-                            -> foreign_mod {
+                               -> foreign_mod {
         let ParsedItemsAndViewItems {
             attrs_remaining: _,
             view_items: view_items,
@@ -3714,12 +3744,11 @@ pub impl Parser {
                               visibility: visibility,
                               attrs: ~[attribute],
                               items_allowed: bool)
-                           -> item_or_view_item
-    {
+                              -> item_or_view_item {
         let mut must_be_named_mod = false;
-        if self.is_keyword(&~"mod") {
+        if self.is_keyword("mod") {
             must_be_named_mod = true;
-            self.expect_keyword(&~"mod");
+            self.expect_keyword("mod");
         } else if *self.token != token::LBRACE {
             self.span_fatal(
                 copy *self.span,
@@ -3750,6 +3779,11 @@ pub impl Parser {
 
         // extern mod foo { ... } or extern { ... }
         if items_allowed && self.eat(&token::LBRACE) {
+            // `extern mod foo { ... }` is obsolete.
+            if sort == ast::named {
+                self.obsolete(*self.last_span, ObsoleteNamedExternModule);
+            }
+
             let abis = opt_abis.get_or_default(AbiSet::C());
 
             let (inner, next) = self.parse_inner_attrs_and_next();
@@ -3999,7 +4033,7 @@ pub impl Parser {
         let visibility = self.parse_visibility();
 
         // must be a view item:
-        if self.eat_keyword(&~"use") {
+        if self.eat_keyword("use") {
             // USE ITEM (iovi_view_item)
             let view_item = self.parse_use();
             self.expect(&token::SEMI);
@@ -4011,10 +4045,10 @@ pub impl Parser {
             });
         }
         // either a view item or an item:
-        if self.eat_keyword(&~"extern") {
+        if self.eat_keyword("extern") {
             let opt_abis = self.parse_opt_abis();
 
-            if self.eat_keyword(&~"fn") {
+            if self.eat_keyword("fn") {
                 // EXTERN FUNCTION ITEM
                 let abis = opt_abis.get_or_default(AbiSet::C());
                 let (ident, item_, extra_attrs) =
@@ -4030,11 +4064,11 @@ pub impl Parser {
             }
         }
         // the rest are all guaranteed to be items:
-        if (self.is_keyword(&~"const") ||
-            (self.is_keyword(&~"static") &&
-             !self.token_is_keyword(&~"fn", &self.look_ahead(1)))) {
+        if (self.is_keyword("const") ||
+            (self.is_keyword("static") &&
+             !self.token_is_keyword("fn", &self.look_ahead(1)))) {
             // CONST / STATIC ITEM
-            if self.is_keyword(&~"const") {
+            if self.is_keyword("const") {
                 self.obsolete(*self.span, ObsoleteConstItem);
             }
             self.bump();
@@ -4043,7 +4077,7 @@ pub impl Parser {
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         }
-        if self.is_keyword(&~"fn") &&
+        if self.is_keyword("fn") &&
             !self.fn_expr_lookahead(self.look_ahead(1u)) {
             // FUNCTION ITEM
             self.bump();
@@ -4053,56 +4087,57 @@ pub impl Parser {
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         }
-        if self.eat_keyword(&~"pure") {
+        if self.eat_keyword("pure") {
             // PURE FUNCTION ITEM (obsolete)
             self.obsolete(*self.last_span, ObsoletePurity);
-            self.expect_keyword(&~"fn");
+            self.expect_keyword("fn");
             let (ident, item_, extra_attrs) =
                 self.parse_item_fn(impure_fn, AbiSet::Rust());
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         }
-        if self.is_keyword(&~"unsafe")
+        if self.is_keyword("unsafe")
             && self.look_ahead(1u) != token::LBRACE {
             // UNSAFE FUNCTION ITEM
             self.bump();
-            self.expect_keyword(&~"fn");
+            self.expect_keyword("fn");
             let (ident, item_, extra_attrs) =
                 self.parse_item_fn(unsafe_fn, AbiSet::Rust());
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         }
-        if self.eat_keyword(&~"mod") {
+        if self.eat_keyword("mod") {
             // MODULE ITEM
-            let (ident, item_, extra_attrs) = self.parse_item_mod(attrs);
+            let (ident, item_, extra_attrs) =
+                self.parse_item_mod(/*bad*/ copy attrs);
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         }
-        if self.eat_keyword(&~"type") {
+        if self.eat_keyword("type") {
             // TYPE ITEM
             let (ident, item_, extra_attrs) = self.parse_item_type();
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         }
-        if self.eat_keyword(&~"enum") {
+        if self.eat_keyword("enum") {
             // ENUM ITEM
             let (ident, item_, extra_attrs) = self.parse_item_enum();
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         }
-        if self.eat_keyword(&~"trait") {
+        if self.eat_keyword("trait") {
             // TRAIT ITEM
             let (ident, item_, extra_attrs) = self.parse_item_trait();
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         }
-        if self.eat_keyword(&~"impl") {
+        if self.eat_keyword("impl") {
             // IMPL ITEM
             let (ident, item_, extra_attrs) =
                 self.parse_item_impl(visibility);
@@ -4110,7 +4145,7 @@ pub impl Parser {
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         }
-        if self.eat_keyword(&~"struct") {
+        if self.eat_keyword("struct") {
             // STRUCT ITEM
             let (ident, item_, extra_attrs) = self.parse_item_struct();
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
@@ -4131,13 +4166,13 @@ pub impl Parser {
 
         let visibility = self.parse_visibility();
 
-        if (self.is_keyword(&~"const") || self.is_keyword(&~"static")) {
+        if (self.is_keyword("const") || self.is_keyword("static")) {
             // FOREIGN CONST ITEM
             let item = self.parse_item_foreign_const(visibility, attrs);
             return iovi_foreign_item(item);
         }
-        if (self.is_keyword(&~"fn") || self.is_keyword(&~"pure") ||
-             self.is_keyword(&~"unsafe")) {
+        if (self.is_keyword("fn") || self.is_keyword("pure") ||
+             self.is_keyword("unsafe")) {
             // FOREIGN FUNCTION ITEM
                 let item = self.parse_item_foreign_fn(attrs);
                 return iovi_foreign_item(item);
@@ -4305,7 +4340,7 @@ pub impl Parser {
           }
           _ => ()
         }
-        let last = path[vec::len(path) - 1u];
+        let last = path[path.len() - 1u];
         let path = @ast::Path { span: mk_sp(lo, self.span.hi),
                                 global: false,
                                 idents: path,
@@ -4328,16 +4363,16 @@ pub impl Parser {
 
     fn is_view_item(&self) -> bool {
         let tok, next_tok;
-        if !self.is_keyword(&~"pub") && !self.is_keyword(&~"priv") {
+        if !self.is_keyword("pub") && !self.is_keyword("priv") {
             tok = copy *self.token;
             next_tok = self.look_ahead(1);
         } else {
             tok = self.look_ahead(1);
             next_tok = self.look_ahead(2);
         };
-        self.token_is_keyword(&~"use", &tok)
-            || (self.token_is_keyword(&~"extern", &tok) &&
-                self.token_is_keyword(&~"mod", &next_tok))
+        self.token_is_keyword("use", &tok)
+            || (self.token_is_keyword("extern", &tok) &&
+                self.token_is_keyword("mod", &next_tok))
     }
 
     // parse a view item.
@@ -4347,10 +4382,10 @@ pub impl Parser {
         vis: visibility
     ) -> @view_item {
         let lo = self.span.lo;
-        let node = if self.eat_keyword(&~"use") {
+        let node = if self.eat_keyword("use") {
             self.parse_use()
-        } else if self.eat_keyword(&~"extern") {
-            self.expect_keyword(&~"mod");
+        } else if self.eat_keyword("extern") {
+            self.expect_keyword("mod");
             let ident = self.parse_ident();
             let metadata = self.parse_optional_meta();
             view_item_extern_mod(ident, metadata, self.get_id())