]> git.lizzy.rs Git - rust.git/blobdiff - src/libsyntax/parse/parser.rs
[breaking-change] don't pub export ast::Stmt_ variants
[rust.git] / src / libsyntax / parse / parser.rs
index acce6ed87d00b5a25c892fba351bdf499dfddb76..93088648e932b3d4afdf2f7bc9939dac3a317e52 100644 (file)
 
 pub use self::PathParsingMode::*;
 
-use abi;
+use abi::{self, Abi};
 use ast::BareFnTy;
 use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
 use ast::{Public, Unsafety};
-use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindingMode};
-use ast::{BiBitAnd, BiBitOr, BiBitXor, BiRem, BiLt, Block};
-use ast::{BlockCheckMode, CaptureByRef, CaptureByValue, CaptureClause};
+use ast::{Mod, Arg, Arm, Attribute, BindingMode};
+use ast::Block;
+use ast::{BlockCheckMode, CaptureBy};
 use ast::{Constness, ConstTraitItem, Crate, CrateConfig};
-use ast::{Decl, DeclItem, DeclLocal, DefaultBlock, DefaultReturn};
-use ast::{UnDeref, BiDiv, EMPTY_CTXT, EnumDef, ExplicitSelf};
-use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain};
-use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox};
-use ast::{ExprBreak, ExprCall, ExprCast, ExprInPlace};
-use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex};
-use ast::{ExprLit, ExprLoop, ExprMac, ExprRange};
-use ast::{ExprMethodCall, ExprParen, ExprPath};
-use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprType, ExprUnary};
-use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl};
+use ast::{Decl, DeclKind};
+use ast::{EMPTY_CTXT, EnumDef, ExplicitSelf};
+use ast::{Expr, ExprKind};
+use ast::{Field, FnDecl};
 use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, FunctionRetTy};
 use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic};
 use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst};
 use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy, ItemDefaultImpl};
 use ast::{ItemExternCrate, ItemUse};
-use ast::{Lit, Lit_};
-use ast::{LitBool, LitChar, LitByte, LitByteStr};
-use ast::{LitStr, LitInt, Local};
+use ast::{Lit, LitKind, UintTy};
+use ast::Local;
 use ast::{MacStmtWithBraces, MacStmtWithSemicolon, MacStmtWithoutBraces};
 use ast::{MutImmutable, MutMutable, Mac_};
-use ast::{MutTy, BiMul, Mutability};
-use ast::{NamedField, UnNeg, NoReturn, UnNot};
+use ast::{MutTy, Mutability};
+use ast::NamedField;
 use ast::{Pat, PatBox, PatEnum, PatIdent, PatLit, PatQPath, PatMac, PatRange};
 use ast::{PatRegion, PatStruct, PatTup, PatVec, PatWild};
 use ast::{PolyTraitRef, QSelf};
-use ast::{Return, BiShl, BiShr, Stmt, StmtDecl};
-use ast::{StmtExpr, StmtSemi, StmtMac, VariantData, StructField};
-use ast::{BiSub, StrStyle};
-use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue};
+use ast::{Stmt, StmtKind};
+use ast::{VariantData, StructField};
+use ast::StrStyle;
+use ast::SelfKind;
 use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef};
-use ast::{Ty, Ty_, TypeBinding, TyMac};
-use ast::{TyFixedLengthVec, TyBareFn, TyTypeof, TyInfer};
-use ast::{TyParam, TyParamBounds, TyParen, TyPath, TyPtr};
-use ast::{TyRptr, TyTup, TyU32, TyVec};
+use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds};
 use ast::TypeTraitItem;
-use ast::{UnnamedField, UnsafeBlock};
+use ast::UnnamedField;
 use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
 use ast::{Visibility, WhereClause};
 use attr::{ThinAttributes, ThinAttributesExt, AttributesExt};
+use ast::{BinOpKind, UnOp};
 use ast;
 use ast_util::{self, ident_to_path};
 use codemap::{self, Span, BytePos, Spanned, spanned, mk_sp, CodeMap};
@@ -139,7 +130,7 @@ macro_rules! maybe_whole_expr {
                         _ => unreachable!()
                     };
                     let span = $p.span;
-                    Some($p.mk_expr(span.lo, span.hi, ExprPath(None, pt), None))
+                    Some($p.mk_expr(span.lo, span.hi, ExprKind::Path(None, pt), None))
                 }
                 token::Interpolated(token::NtBlock(_)) => {
                     // FIXME: The following avoids an issue with lexical borrowck scopes,
@@ -149,7 +140,7 @@ macro_rules! maybe_whole_expr {
                         _ => unreachable!()
                     };
                     let span = $p.span;
-                    Some($p.mk_expr(span.lo, span.hi, ExprBlock(b), None))
+                    Some($p.mk_expr(span.lo, span.hi, ExprKind::Block(b), None))
                 }
                 _ => None
             };
@@ -233,7 +224,6 @@ macro_rules! maybe_whole {
     )
 }
 
-
 fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>)
                 -> Vec<Attribute> {
     if let Some(ref attrs) = rhs {
@@ -255,6 +245,7 @@ pub struct Parser<'a> {
     pub cfg: CrateConfig,
     /// the previous token or None (only stashed sometimes).
     pub last_token: Option<Box<token::Token>>,
+    last_token_interpolated: bool,
     pub buffer: [TokenAndSpan; 4],
     pub buffer_start: isize,
     pub buffer_end: isize,
@@ -362,6 +353,7 @@ pub fn new(sess: &'a ParseSess,
             span: span,
             last_span: span,
             last_token: None,
+            last_token_interpolated: false,
             buffer: [
                 placeholder.clone(),
                 placeholder.clone(),
@@ -506,7 +498,7 @@ pub fn check_for_erroneous_unit_struct_expecting(&mut self,
     pub fn commit_expr(&mut self, e: &Expr, edible: &[token::Token],
                        inedible: &[token::Token]) -> PResult<'a, ()> {
         debug!("commit_expr {:?}", e);
-        if let ExprPath(..) = e.node {
+        if let ExprKind::Path(..) = e.node {
             // might be unit-struct construction; check for recoverableinput error.
             let expected = edible.iter()
                 .cloned()
@@ -542,6 +534,19 @@ pub fn commit_stmt_expecting(&mut self, edible: token::Token) -> PResult<'a, ()>
         self.commit_stmt(&[edible], &[])
     }
 
+    /// returns the span of expr, if it was not interpolated or the span of the interpolated token
+    fn interpolated_or_expr_span(&self,
+                                 expr: PResult<'a, P<Expr>>)
+                                 -> PResult<'a, (Span, P<Expr>)> {
+        expr.map(|e| {
+            if self.last_token_interpolated {
+                (self.last_span, e)
+            } else {
+                (e.span, e)
+            }
+        })
+    }
+
     pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
         self.check_strict_keywords();
         self.check_reserved_keywords();
@@ -668,7 +673,7 @@ fn expect_and(&mut self) -> PResult<'a, ()> {
             token::AndAnd => {
                 let span = self.span;
                 let lo = span.lo + BytePos(1);
-                Ok(self.replace_token(token::BinOp(token::And), lo, span.hi))
+                Ok(self.bump_with(token::BinOp(token::And), lo, span.hi))
             }
             _ => self.unexpected()
         }
@@ -703,7 +708,7 @@ fn eat_lt(&mut self) -> bool {
             token::BinOp(token::Shl) => {
                 let span = self.span;
                 let lo = span.lo + BytePos(1);
-                self.replace_token(token::Lt, lo, span.hi);
+                self.bump_with(token::Lt, lo, span.hi);
                 true
             }
             _ => false,
@@ -731,17 +736,17 @@ pub fn expect_gt(&mut self) -> PResult<'a, ()> {
             token::BinOp(token::Shr) => {
                 let span = self.span;
                 let lo = span.lo + BytePos(1);
-                Ok(self.replace_token(token::Gt, lo, span.hi))
+                Ok(self.bump_with(token::Gt, lo, span.hi))
             }
             token::BinOpEq(token::Shr) => {
                 let span = self.span;
                 let lo = span.lo + BytePos(1);
-                Ok(self.replace_token(token::Ge, lo, span.hi))
+                Ok(self.bump_with(token::Ge, lo, span.hi))
             }
             token::Ge => {
                 let span = self.span;
                 let lo = span.lo + BytePos(1);
-                Ok(self.replace_token(token::Eq, lo, span.hi))
+                Ok(self.bump_with(token::Eq, lo, span.hi))
             }
             _ => {
                 let gt_str = Parser::token_to_string(&token::Gt);
@@ -933,6 +938,7 @@ pub fn bump(&mut self) {
         } else {
             None
         };
+        self.last_token_interpolated = self.token.is_interpolated();
         let next = if self.buffer_start == self.buffer_end {
             self.reader.real_token()
         } else {
@@ -962,15 +968,23 @@ pub fn bump_and_get(&mut self) -> token::Token {
         old_token
     }
 
-    /// EFFECT: replace the current token and span with the given one
-    pub fn replace_token(&mut self,
-                         next: token::Token,
-                         lo: BytePos,
-                         hi: BytePos) {
+    /// Advance the parser using provided token as a next one. Use this when
+    /// consuming a part of a token. For example a single `<` from `<<`.
+    pub fn bump_with(&mut self,
+                     next: token::Token,
+                     lo: BytePos,
+                     hi: BytePos) {
         self.last_span = mk_sp(self.span.lo, lo);
-        self.token = next;
+        // It would be incorrect to just stash current token, but fortunately
+        // for tokens currently using `bump_with`, last_token will be of no
+        // use anyway.
+        self.last_token = None;
+        self.last_token_interpolated = false;
         self.span = mk_sp(lo, hi);
+        self.token = next;
+        self.expected_tokens.clear();
     }
+
     pub fn buffer_length(&mut self) -> isize {
         if self.buffer_start <= self.buffer_end {
             return self.buffer_end - self.buffer_start;
@@ -1040,7 +1054,7 @@ pub fn get_lifetime(&mut self) -> ast::Ident {
         }
     }
 
-    pub fn parse_for_in_type(&mut self) -> PResult<'a, Ty_> {
+    pub fn parse_for_in_type(&mut self) -> PResult<'a, TyKind> {
         /*
         Parses whatever can come after a `for` keyword in a type.
         The `for` has already been consumed.
@@ -1079,16 +1093,17 @@ pub fn parse_for_in_type(&mut self) -> PResult<'a, Ty_> {
                 Some(TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)).into_iter()
                 .chain(other_bounds.into_vec())
                 .collect();
-            Ok(ast::TyPolyTraitRef(all_bounds))
+            Ok(ast::TyKind::PolyTraitRef(all_bounds))
         }
     }
 
-    pub fn parse_ty_path(&mut self) -> PResult<'a, Ty_> {
-        Ok(TyPath(None, try!(self.parse_path(LifetimeAndTypesWithoutColons))))
+    pub fn parse_ty_path(&mut self) -> PResult<'a, TyKind> {
+        Ok(TyKind::Path(None, try!(self.parse_path(LifetimeAndTypesWithoutColons))))
     }
 
-    /// parse a TyBareFn type:
-    pub fn parse_ty_bare_fn(&mut self, lifetime_defs: Vec<ast::LifetimeDef>) -> PResult<'a, Ty_> {
+    /// parse a TyKind::BareFn type:
+    pub fn parse_ty_bare_fn(&mut self, lifetime_defs: Vec<ast::LifetimeDef>)
+                            -> PResult<'a, TyKind> {
         /*
 
         [unsafe] [extern "ABI"] fn <'lt> (S) -> T
@@ -1103,9 +1118,9 @@ pub fn parse_ty_bare_fn(&mut self, lifetime_defs: Vec<ast::LifetimeDef>) -> PRes
 
         let unsafety = try!(self.parse_unsafety());
         let abi = if self.eat_keyword(keywords::Extern) {
-            try!(self.parse_opt_abi()).unwrap_or(abi::C)
+            try!(self.parse_opt_abi()).unwrap_or(Abi::C)
         } else {
-            abi::Rust
+            Abi::Rust
         };
 
         try!(self.expect_keyword(keywords::Fn));
@@ -1116,7 +1131,7 @@ pub fn parse_ty_bare_fn(&mut self, lifetime_defs: Vec<ast::LifetimeDef>) -> PRes
             output: ret_ty,
             variadic: variadic
         });
-        Ok(TyBareFn(P(BareFnTy {
+        Ok(TyKind::BareFn(P(BareFnTy {
             abi: abi,
             unsafety: unsafety,
             lifetimes: lifetime_defs,
@@ -1259,13 +1274,13 @@ pub fn parse_mt(&mut self) -> PResult<'a, MutTy> {
     pub fn parse_ret_ty(&mut self) -> PResult<'a, FunctionRetTy> {
         if self.eat(&token::RArrow) {
             if self.eat(&token::Not) {
-                Ok(NoReturn(self.last_span))
+                Ok(FunctionRetTy::None(self.last_span))
             } else {
-                Ok(Return(try!(self.parse_ty())))
+                Ok(FunctionRetTy::Ty(try!(self.parse_ty())))
             }
         } else {
             let pos = self.span.lo;
-            Ok(DefaultReturn(mk_sp(pos, pos)))
+            Ok(FunctionRetTy::Default(mk_sp(pos, pos)))
         }
     }
 
@@ -1290,7 +1305,7 @@ pub fn parse_ty_sum(&mut self) -> PResult<'a, P<Ty>> {
         }
 
         let sp = mk_sp(lo, self.last_span.hi);
-        let sum = ast::TyObjectSum(lhs, bounds);
+        let sum = ast::TyKind::ObjectSum(lhs, bounds);
         Ok(P(Ty {id: ast::DUMMY_NODE_ID, node: sum, span: sp}))
     }
 
@@ -1321,14 +1336,14 @@ pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
 
             try!(self.expect(&token::CloseDelim(token::Paren)));
             if ts.len() == 1 && !last_comma {
-                TyParen(ts.into_iter().nth(0).unwrap())
+                TyKind::Paren(ts.into_iter().nth(0).unwrap())
             } else {
-                TyTup(ts)
+                TyKind::Tup(ts)
             }
         } else if self.check(&token::BinOp(token::Star)) {
             // STAR POINTER (bare pointer?)
             self.bump();
-            TyPtr(try!(self.parse_ptr()))
+            TyKind::Ptr(try!(self.parse_ptr()))
         } else if self.check(&token::OpenDelim(token::Bracket)) {
             // VECTOR
             try!(self.expect(&token::OpenDelim(token::Bracket)));
@@ -1337,8 +1352,8 @@ pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
             // Parse the `; e` in `[ i32; e ]`
             // where `e` is a const expression
             let t = match try!(self.maybe_parse_fixed_length_of_vec()) {
-                None => TyVec(t),
-                Some(suffix) => TyFixedLengthVec(t, suffix)
+                None => TyKind::Vec(t),
+                Some(suffix) => TyKind::FixedLengthVec(t, suffix)
             };
             try!(self.expect(&token::CloseDelim(token::Bracket)));
             t
@@ -1358,13 +1373,13 @@ pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
             try!(self.expect(&token::OpenDelim(token::Paren)));
             let e = try!(self.parse_expr());
             try!(self.expect(&token::CloseDelim(token::Paren)));
-            TyTypeof(e)
+            TyKind::Typeof(e)
         } else if self.eat_lt() {
 
             let (qself, path) =
                  try!(self.parse_qualified_path(NoTypesAllowed));
 
-            TyPath(Some(qself), path)
+            TyKind::Path(Some(qself), path)
         } else if self.check(&token::ModSep) ||
                   self.token.is_ident() ||
                   self.token.is_path() {
@@ -1377,14 +1392,14 @@ pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
                                                      seq_sep_none(),
                                                      |p| p.parse_token_tree()));
                 let hi = self.span.hi;
-                TyMac(spanned(lo, hi, Mac_ { path: path, tts: tts, ctxt: EMPTY_CTXT }))
+                TyKind::Mac(spanned(lo, hi, Mac_ { path: path, tts: tts, ctxt: EMPTY_CTXT }))
             } else {
                 // NAMED TYPE
-                TyPath(None, path)
+                TyKind::Path(None, path)
             }
         } else if self.eat(&token::Underscore) {
             // TYPE TO BE INFERRED
-            TyInfer
+            TyKind::Infer
         } else {
             let this_token_str = self.this_token_to_string();
             let msg = format!("expected type, found `{}`", this_token_str);
@@ -1395,12 +1410,12 @@ pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
         Ok(P(Ty {id: ast::DUMMY_NODE_ID, node: t, span: sp}))
     }
 
-    pub fn parse_borrowed_pointee(&mut self) -> PResult<'a, Ty_> {
+    pub fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
         // look for `&'lt` or `&'foo ` and interpret `foo` as the region name:
         let opt_lifetime = try!(self.parse_opt_lifetime());
 
         let mt = try!(self.parse_mt());
-        return Ok(TyRptr(opt_lifetime, mt));
+        return Ok(TyKind::Rptr(opt_lifetime, mt));
     }
 
     pub fn parse_ptr(&mut self) -> PResult<'a, MutTy> {
@@ -1480,7 +1495,7 @@ pub fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> {
         } else {
             P(Ty {
                 id: ast::DUMMY_NODE_ID,
-                node: TyInfer,
+                node: TyKind::Infer,
                 span: mk_sp(self.span.lo, self.span.hi),
             })
         };
@@ -1501,18 +1516,18 @@ pub fn maybe_parse_fixed_length_of_vec(&mut self) -> PResult<'a, Option<P<ast::E
     }
 
     /// Matches token_lit = LIT_INTEGER | ...
-    pub fn lit_from_token(&self, tok: &token::Token) -> PResult<'a, Lit_> {
+    pub fn lit_from_token(&self, tok: &token::Token) -> PResult<'a, LitKind> {
         match *tok {
             token::Interpolated(token::NtExpr(ref v)) => {
                 match v.node {
-                    ExprLit(ref lit) => { Ok(lit.node.clone()) }
+                    ExprKind::Lit(ref lit) => { Ok(lit.node.clone()) }
                     _ => { return self.unexpected_last(tok); }
                 }
             }
             token::Literal(lit, suf) => {
                 let (suffix_illegal, out) = match lit {
-                    token::Byte(i) => (true, LitByte(parse::byte_lit(&i.as_str()).0)),
-                    token::Char(i) => (true, LitChar(parse::char_lit(&i.as_str()).0)),
+                    token::Byte(i) => (true, LitKind::Byte(parse::byte_lit(&i.as_str()).0)),
+                    token::Char(i) => (true, LitKind::Char(parse::char_lit(&i.as_str()).0)),
 
                     // there are some valid suffixes for integer and
                     // float literals, so all the handling is done
@@ -1532,20 +1547,20 @@ pub fn lit_from_token(&self, tok: &token::Token) -> PResult<'a, Lit_> {
 
                     token::Str_(s) => {
                         (true,
-                         LitStr(token::intern_and_get_ident(&parse::str_lit(&s.as_str())),
-                                ast::CookedStr))
+                         LitKind::Str(token::intern_and_get_ident(&parse::str_lit(&s.as_str())),
+                                      ast::CookedStr))
                     }
                     token::StrRaw(s, n) => {
                         (true,
-                         LitStr(
+                         LitKind::Str(
                             token::intern_and_get_ident(&parse::raw_str_lit(&s.as_str())),
                             ast::RawStr(n)))
                     }
                     token::ByteStr(i) =>
-                        (true, LitByteStr(parse::byte_str_lit(&i.as_str()))),
+                        (true, LitKind::ByteStr(parse::byte_str_lit(&i.as_str()))),
                     token::ByteStrRaw(i, _) =>
                         (true,
-                         LitByteStr(Rc::new(i.to_string().into_bytes()))),
+                         LitKind::ByteStr(Rc::new(i.to_string().into_bytes()))),
                 };
 
                 if suffix_illegal {
@@ -1563,9 +1578,9 @@ pub fn lit_from_token(&self, tok: &token::Token) -> PResult<'a, Lit_> {
     pub fn parse_lit(&mut self) -> PResult<'a, Lit> {
         let lo = self.span.lo;
         let lit = if self.eat_keyword(keywords::True) {
-            LitBool(true)
+            LitKind::Bool(true)
         } else if self.eat_keyword(keywords::False) {
-            LitBool(false)
+            LitKind::Bool(false)
         } else {
             let token = self.bump_and_get();
             let lit = try!(self.lit_from_token(&token));
@@ -1581,11 +1596,11 @@ pub fn parse_pat_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
         let lo = self.span.lo;
         let literal = P(try!(self.parse_lit()));
         let hi = self.last_span.hi;
-        let expr = self.mk_expr(lo, hi, ExprLit(literal), None);
+        let expr = self.mk_expr(lo, hi, ExprKind::Lit(literal), None);
 
         if minus_present {
             let minus_hi = self.last_span.hi;
-            let unary = self.mk_unary(UnNeg, expr);
+            let unary = self.mk_unary(UnOp::Neg, expr);
             Ok(self.mk_expr(minus_lo, minus_hi, unary, None))
         } else {
             Ok(expr)
@@ -1933,7 +1948,7 @@ pub fn parse_field(&mut self) -> PResult<'a, Field> {
     }
 
     pub fn mk_expr(&mut self, lo: BytePos, hi: BytePos,
-                   node: Expr_, attrs: ThinAttributes) -> P<Expr> {
+                   node: ExprKind, attrs: ThinAttributes) -> P<Expr> {
         P(Expr {
             id: ast::DUMMY_NODE_ID,
             node: node,
@@ -1942,55 +1957,55 @@ pub fn mk_expr(&mut self, lo: BytePos, hi: BytePos,
         })
     }
 
-    pub fn mk_unary(&mut self, unop: ast::UnOp, expr: P<Expr>) -> ast::Expr_ {
-        ExprUnary(unop, expr)
+    pub fn mk_unary(&mut self, unop: ast::UnOp, expr: P<Expr>) -> ast::ExprKind {
+        ExprKind::Unary(unop, expr)
     }
 
-    pub fn mk_binary(&mut self, binop: ast::BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ast::Expr_ {
-        ExprBinary(binop, lhs, rhs)
+    pub fn mk_binary(&mut self, binop: ast::BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ast::ExprKind {
+        ExprKind::Binary(binop, lhs, rhs)
     }
 
-    pub fn mk_call(&mut self, f: P<Expr>, args: Vec<P<Expr>>) -> ast::Expr_ {
-        ExprCall(f, args)
+    pub fn mk_call(&mut self, f: P<Expr>, args: Vec<P<Expr>>) -> ast::ExprKind {
+        ExprKind::Call(f, args)
     }
 
     fn mk_method_call(&mut self,
                       ident: ast::SpannedIdent,
                       tps: Vec<P<Ty>>,
                       args: Vec<P<Expr>>)
-                      -> ast::Expr_ {
-        ExprMethodCall(ident, tps, args)
+                      -> ast::ExprKind {
+        ExprKind::MethodCall(ident, tps, args)
     }
 
-    pub fn mk_index(&mut self, expr: P<Expr>, idx: P<Expr>) -> ast::Expr_ {
-        ExprIndex(expr, idx)
+    pub fn mk_index(&mut self, expr: P<Expr>, idx: P<Expr>) -> ast::ExprKind {
+        ExprKind::Index(expr, idx)
     }
 
     pub fn mk_range(&mut self,
                     start: Option<P<Expr>>,
                     end: Option<P<Expr>>)
-                    -> ast::Expr_ {
-        ExprRange(start, end)
+                    -> ast::ExprKind {
+        ExprKind::Range(start, end)
     }
 
-    pub fn mk_field(&mut self, expr: P<Expr>, ident: ast::SpannedIdent) -> ast::Expr_ {
-        ExprField(expr, ident)
+    pub fn mk_field(&mut self, expr: P<Expr>, ident: ast::SpannedIdent) -> ast::ExprKind {
+        ExprKind::Field(expr, ident)
     }
 
-    pub fn mk_tup_field(&mut self, expr: P<Expr>, idx: codemap::Spanned<usize>) -> ast::Expr_ {
-        ExprTupField(expr, idx)
+    pub fn mk_tup_field(&mut self, expr: P<Expr>, idx: codemap::Spanned<usize>) -> ast::ExprKind {
+        ExprKind::TupField(expr, idx)
     }
 
     pub fn mk_assign_op(&mut self, binop: ast::BinOp,
-                        lhs: P<Expr>, rhs: P<Expr>) -> ast::Expr_ {
-        ExprAssignOp(binop, lhs, rhs)
+                        lhs: P<Expr>, rhs: P<Expr>) -> ast::ExprKind {
+        ExprKind::AssignOp(binop, lhs, rhs)
     }
 
     pub fn mk_mac_expr(&mut self, lo: BytePos, hi: BytePos,
                        m: Mac_, attrs: ThinAttributes) -> P<Expr> {
         P(Expr {
             id: ast::DUMMY_NODE_ID,
-            node: ExprMac(codemap::Spanned {node: m, span: mk_sp(lo, hi)}),
+            node: ExprKind::Mac(codemap::Spanned {node: m, span: mk_sp(lo, hi)}),
             span: mk_sp(lo, hi),
             attrs: attrs,
         })
@@ -1999,13 +2014,13 @@ pub fn mk_mac_expr(&mut self, lo: BytePos, hi: BytePos,
     pub fn mk_lit_u32(&mut self, i: u32, attrs: ThinAttributes) -> P<Expr> {
         let span = &self.span;
         let lv_lit = P(codemap::Spanned {
-            node: LitInt(i as u64, ast::UnsignedIntLit(TyU32)),
+            node: LitKind::Int(i as u64, ast::LitIntType::Unsigned(UintTy::U32)),
             span: *span
         });
 
         P(Expr {
             id: ast::DUMMY_NODE_ID,
-            node: ExprLit(lv_lit),
+            node: ExprKind::Lit(lv_lit),
             span: *span,
             attrs: attrs,
         })
@@ -2042,7 +2057,7 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
         let lo = self.span.lo;
         let mut hi = self.span.hi;
 
-        let ex: Expr_;
+        let ex: ExprKind;
 
         // Note: when adding new syntax here, don't forget to adjust Token::can_begin_expr().
         match self.token {
@@ -2074,17 +2089,17 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
 
                 hi = self.last_span.hi;
                 return if es.len() == 1 && !trailing_comma {
-                    Ok(self.mk_expr(lo, hi, ExprParen(es.into_iter().nth(0).unwrap()), attrs))
+                    Ok(self.mk_expr(lo, hi, ExprKind::Paren(es.into_iter().nth(0).unwrap()), attrs))
                 } else {
-                    Ok(self.mk_expr(lo, hi, ExprTup(es), attrs))
+                    Ok(self.mk_expr(lo, hi, ExprKind::Tup(es), attrs))
                 }
             },
             token::OpenDelim(token::Brace) => {
-                return self.parse_block_expr(lo, DefaultBlock, attrs);
+                return self.parse_block_expr(lo, BlockCheckMode::Default, attrs);
             },
             token::BinOp(token::Or) |  token::OrOr => {
                 let lo = self.span.lo;
-                return self.parse_lambda_expr(lo, CaptureByRef, attrs);
+                return self.parse_lambda_expr(lo, CaptureBy::Ref, attrs);
             },
             token::Ident(id @ ast::Ident {
                             name: token::SELF_KEYWORD_NAME,
@@ -2092,7 +2107,7 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                          }, token::Plain) => {
                 self.bump();
                 let path = ast_util::ident_to_path(mk_sp(lo, hi), id);
-                ex = ExprPath(None, path);
+                ex = ExprKind::Path(None, path);
                 hi = self.last_span.hi;
             }
             token::OpenDelim(token::Bracket) => {
@@ -2105,7 +2120,7 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                 if self.check(&token::CloseDelim(token::Bracket)) {
                     // Empty vector.
                     self.bump();
-                    ex = ExprVec(Vec::new());
+                    ex = ExprKind::Vec(Vec::new());
                 } else {
                     // Nonempty vector.
                     let first_expr = try!(self.parse_expr());
@@ -2114,7 +2129,7 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                         self.bump();
                         let count = try!(self.parse_expr());
                         try!(self.expect(&token::CloseDelim(token::Bracket)));
-                        ex = ExprRepeat(first_expr, count);
+                        ex = ExprKind::Repeat(first_expr, count);
                     } else if self.check(&token::Comma) {
                         // Vector with two or more elements.
                         self.bump();
@@ -2125,11 +2140,11 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                                 ));
                         let mut exprs = vec!(first_expr);
                         exprs.extend(remaining_exprs);
-                        ex = ExprVec(exprs);
+                        ex = ExprKind::Vec(exprs);
                     } else {
                         // Vector with one element.
                         try!(self.expect(&token::CloseDelim(token::Bracket)));
-                        ex = ExprVec(vec!(first_expr));
+                        ex = ExprKind::Vec(vec!(first_expr));
                     }
                 }
                 hi = self.last_span.hi;
@@ -2139,11 +2154,11 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                     let (qself, path) =
                         try!(self.parse_qualified_path(LifetimeAndTypesWithColons));
                     hi = path.span.hi;
-                    return Ok(self.mk_expr(lo, hi, ExprPath(Some(qself), path), attrs));
+                    return Ok(self.mk_expr(lo, hi, ExprKind::Path(Some(qself), path), attrs));
                 }
                 if self.eat_keyword(keywords::Move) {
                     let lo = self.last_span.lo;
-                    return self.parse_lambda_expr(lo, CaptureByValue, attrs);
+                    return self.parse_lambda_expr(lo, CaptureBy::Value, attrs);
                 }
                 if self.eat_keyword(keywords::If) {
                     return self.parse_if_expr(attrs);
@@ -2178,14 +2193,14 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                 }
                 if self.eat_keyword(keywords::Continue) {
                     let ex = if self.token.is_lifetime() {
-                        let ex = ExprAgain(Some(Spanned{
+                        let ex = ExprKind::Again(Some(Spanned{
                             node: self.get_lifetime(),
                             span: self.span
                         }));
                         self.bump();
                         ex
                     } else {
-                        ExprAgain(None)
+                        ExprKind::Again(None)
                     };
                     let hi = self.last_span.hi;
                     return Ok(self.mk_expr(lo, hi, ex, attrs));
@@ -2196,28 +2211,34 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                 if self.eat_keyword(keywords::Unsafe) {
                     return self.parse_block_expr(
                         lo,
-                        UnsafeBlock(ast::UserProvided),
+                        BlockCheckMode::Unsafe(ast::UserProvided),
                         attrs);
                 }
                 if self.eat_keyword(keywords::Return) {
                     if self.token.can_begin_expr() {
                         let e = try!(self.parse_expr());
                         hi = e.span.hi;
-                        ex = ExprRet(Some(e));
+                        ex = ExprKind::Ret(Some(e));
                     } else {
-                        ex = ExprRet(None);
+                        ex = ExprKind::Ret(None);
                     }
                 } else if self.eat_keyword(keywords::Break) {
                     if self.token.is_lifetime() {
-                        ex = ExprBreak(Some(Spanned {
+                        ex = ExprKind::Break(Some(Spanned {
                             node: self.get_lifetime(),
                             span: self.span
                         }));
                         self.bump();
                     } else {
-                        ex = ExprBreak(None);
+                        ex = ExprKind::Break(None);
                     }
                     hi = self.last_span.hi;
+                } else if self.token.is_keyword(keywords::Let) {
+                    // Catch this syntax error here, instead of in `check_strict_keywords`, so
+                    // that we can explicitly mention that let is not to be used as an expression
+                    let mut db = self.fatal("expected expression, found statement (`let`)");
+                    db.note("variable declaration using `let` is a statement");
+                    return Err(db);
                 } else if self.check(&token::ModSep) ||
                         self.token.is_ident() &&
                         !self.check_keyword(keywords::True) &&
@@ -2272,18 +2293,18 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
 
                             hi = self.span.hi;
                             try!(self.expect(&token::CloseDelim(token::Brace)));
-                            ex = ExprStruct(pth, fields, base);
+                            ex = ExprKind::Struct(pth, fields, base);
                             return Ok(self.mk_expr(lo, hi, ex, attrs));
                         }
                     }
 
                     hi = pth.span.hi;
-                    ex = ExprPath(None, pth);
+                    ex = ExprKind::Path(None, pth);
                 } else {
                     // other literal expression
                     let lit = try!(self.parse_lit());
                     hi = lit.span.hi;
-                    ex = ExprLit(P(lit));
+                    ex = ExprKind::Lit(P(lit));
                 }
             }
         }
@@ -2313,7 +2334,7 @@ pub fn parse_block_expr(&mut self, lo: BytePos, blk_mode: BlockCheckMode,
         let attrs = outer_attrs.append(inner_attrs);
 
         let blk = try!(self.parse_block_tail(lo, blk_mode));
-        return Ok(self.mk_expr(blk.span.lo, blk.span.hi, ExprBlock(blk), attrs));
+        return Ok(self.mk_expr(blk.span.lo, blk.span.hi, ExprKind::Block(blk), attrs));
     }
 
     /// parse a.b or a(13) or a[4] or just a
@@ -2322,23 +2343,25 @@ pub fn parse_dot_or_call_expr(&mut self,
                                   -> PResult<'a, P<Expr>> {
         let attrs = try!(self.parse_or_use_outer_attributes(already_parsed_attrs));
 
-        let b = try!(self.parse_bottom_expr());
-        self.parse_dot_or_call_expr_with(b, attrs)
+        let b = self.parse_bottom_expr();
+        let (span, b) = try!(self.interpolated_or_expr_span(b));
+        self.parse_dot_or_call_expr_with(b, span.lo, attrs)
     }
 
     pub fn parse_dot_or_call_expr_with(&mut self,
                                        e0: P<Expr>,
+                                       lo: BytePos,
                                        attrs: ThinAttributes)
                                        -> PResult<'a, P<Expr>> {
         // Stitch the list of outer attributes onto the return value.
         // A little bit ugly, but the best way given the current code
         // structure
-        self.parse_dot_or_call_expr_with_(e0)
+        self.parse_dot_or_call_expr_with_(e0, lo)
         .map(|expr|
             expr.map(|mut expr| {
                 expr.attrs.update(|a| a.prepend(attrs));
                 match expr.node {
-                    ExprIf(..) | ExprIfLet(..) => {
+                    ExprKind::If(..) | ExprKind::IfLet(..) => {
                         if !expr.attrs.as_attr_slice().is_empty() {
                             // Just point to the first attribute in there...
                             let span = expr.attrs.as_attr_slice()[0].span;
@@ -2360,7 +2383,8 @@ pub fn parse_dot_or_call_expr_with(&mut self,
     fn parse_dot_suffix(&mut self,
                         ident: Ident,
                         ident_span: Span,
-                        self_value: P<Expr>)
+                        self_value: P<Expr>,
+                        lo: BytePos)
                         -> PResult<'a, P<Expr>> {
         let (_, tys, bindings) = if self.eat(&token::ModSep) {
             try!(self.expect_lt());
@@ -2374,8 +2398,6 @@ fn parse_dot_suffix(&mut self,
             self.span_err(last_span, "type bindings are only permitted on trait paths");
         }
 
-        let lo = self_value.span.lo;
-
         Ok(match self.token {
             // expr.f() method call.
             token::OpenDelim(token::Paren) => {
@@ -2408,9 +2430,8 @@ fn parse_dot_suffix(&mut self,
         })
     }
 
-    fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>) -> PResult<'a, P<Expr>> {
+    fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>, lo: BytePos) -> PResult<'a, P<Expr>> {
         let mut e = e0;
-        let lo = e.span.lo;
         let mut hi;
         loop {
             // expr.f
@@ -2421,7 +2442,7 @@ fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>) -> PResult<'a, P<Expr>>
                     hi = self.span.hi;
                     self.bump();
 
-                    e = try!(self.parse_dot_suffix(i, mk_sp(dot_pos, hi), e));
+                    e = try!(self.parse_dot_suffix(i, mk_sp(dot_pos, hi), e, lo));
                   }
                   token::Literal(token::Integer(n), suf) => {
                     let sp = self.span;
@@ -2462,8 +2483,7 @@ fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>) -> PResult<'a, P<Expr>>
                                     float.trunc() as usize,
                                     format!(".{}", fstr.splitn(2, ".").last().unwrap())));
                     }
-                    err.emit();
-                    self.abort_if_errors();
+                    return Err(err);
 
                   }
                   _ => {
@@ -2474,7 +2494,7 @@ fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>) -> PResult<'a, P<Expr>>
                     let dot_pos = self.last_span.hi;
                     e = try!(self.parse_dot_suffix(special_idents::invalid,
                                                    mk_sp(dot_pos, dot_pos),
-                                                   e));
+                                                   e, lo));
                   }
                 }
                 continue;
@@ -2709,28 +2729,32 @@ pub fn parse_prefix_expr(&mut self,
         let ex = match self.token {
             token::Not => {
                 self.bump();
-                let e = try!(self.parse_prefix_expr(None));
-                hi = e.span.hi;
-                self.mk_unary(UnNot, e)
+                let e = self.parse_prefix_expr(None);
+                let (span, e) = try!(self.interpolated_or_expr_span(e));
+                hi = span.hi;
+                self.mk_unary(UnOp::Not, e)
             }
             token::BinOp(token::Minus) => {
                 self.bump();
-                let e = try!(self.parse_prefix_expr(None));
-                hi = e.span.hi;
-                self.mk_unary(UnNeg, e)
+                let e = self.parse_prefix_expr(None);
+                let (span, e) = try!(self.interpolated_or_expr_span(e));
+                hi = span.hi;
+                self.mk_unary(UnOp::Neg, e)
             }
             token::BinOp(token::Star) => {
                 self.bump();
-                let e = try!(self.parse_prefix_expr(None));
-                hi = e.span.hi;
-                self.mk_unary(UnDeref, e)
+                let e = self.parse_prefix_expr(None);
+                let (span, e) = try!(self.interpolated_or_expr_span(e));
+                hi = span.hi;
+                self.mk_unary(UnOp::Deref, e)
             }
             token::BinOp(token::And) | token::AndAnd => {
                 try!(self.expect_and());
                 let m = try!(self.parse_mutability());
-                let e = try!(self.parse_prefix_expr(None));
-                hi = e.span.hi;
-                ExprAddrOf(m, e)
+                let e = self.parse_prefix_expr(None);
+                let (span, e) = try!(self.interpolated_or_expr_span(e));
+                hi = span.hi;
+                ExprKind::AddrOf(m, e)
             }
             token::Ident(..) if self.token.is_keyword(keywords::In) => {
                 self.bump();
@@ -2741,15 +2765,16 @@ pub fn parse_prefix_expr(&mut self,
                 let blk = try!(self.parse_block());
                 let span = blk.span;
                 hi = span.hi;
-                let blk_expr = self.mk_expr(span.lo, span.hi, ExprBlock(blk),
+                let blk_expr = self.mk_expr(span.lo, span.hi, ExprKind::Block(blk),
                                             None);
-                ExprInPlace(place, blk_expr)
+                ExprKind::InPlace(place, blk_expr)
             }
             token::Ident(..) if self.token.is_keyword(keywords::Box) => {
                 self.bump();
-                let subexpression = try!(self.parse_prefix_expr(None));
-                hi = subexpression.span.hi;
-                ExprBox(subexpression)
+                let e = self.parse_prefix_expr(None);
+                let (span, e) = try!(self.interpolated_or_expr_span(e));
+                hi = span.hi;
+                ExprKind::Box(e)
             }
             _ => return self.parse_dot_or_call_expr(Some(attrs))
         };
@@ -2784,12 +2809,21 @@ pub fn parse_assoc_expr_with(&mut self,
                 try!(self.parse_prefix_expr(attrs))
             }
         };
+
+
         if self.expr_is_complete(&*lhs) {
             // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071
             return Ok(lhs);
         }
         self.expected_tokens.push(TokenType::Operator);
         while let Some(op) = AssocOp::from_token(&self.token) {
+
+            let lhs_span = if self.last_token_interpolated {
+                self.last_span
+            } else {
+                lhs.span
+            };
+
             let cur_op_span = self.span;
             let restrictions = if op.is_assign_like() {
                 self.restrictions & Restrictions::RESTRICTION_NO_STRUCT_LITERAL
@@ -2806,13 +2840,13 @@ pub fn parse_assoc_expr_with(&mut self,
             // Special cases:
             if op == AssocOp::As {
                 let rhs = try!(self.parse_ty());
-                lhs = self.mk_expr(lhs.span.lo, rhs.span.hi,
-                                   ExprCast(lhs, rhs), None);
+                lhs = self.mk_expr(lhs_span.lo, rhs.span.hi,
+                                   ExprKind::Cast(lhs, rhs), None);
                 continue
             } else if op == AssocOp::Colon {
                 let rhs = try!(self.parse_ty());
-                lhs = self.mk_expr(lhs.span.lo, rhs.span.hi,
-                                   ExprType(lhs, rhs), None);
+                lhs = self.mk_expr(lhs_span.lo, rhs.span.hi,
+                                   ExprKind::Type(lhs, rhs), None);
                 continue
             } else if op == AssocOp::DotDot {
                     // If we didn’t have to handle `x..`, it would be pretty easy to generalise
@@ -2833,7 +2867,7 @@ pub fn parse_assoc_expr_with(&mut self,
                     } else {
                         None
                     };
-                    let (lhs_span, rhs_span) = (lhs.span, if let Some(ref x) = rhs {
+                    let (lhs_span, rhs_span) = (lhs_span, if let Some(ref x) = rhs {
                         x.span
                     } else {
                         cur_op_span
@@ -2873,28 +2907,28 @@ pub fn parse_assoc_expr_with(&mut self,
                 AssocOp::Equal | AssocOp::Less | AssocOp::LessEqual | AssocOp::NotEqual |
                 AssocOp::Greater | AssocOp::GreaterEqual => {
                     let ast_op = op.to_ast_binop().unwrap();
-                    let (lhs_span, rhs_span) = (lhs.span, rhs.span);
+                    let (lhs_span, rhs_span) = (lhs_span, rhs.span);
                     let binary = self.mk_binary(codemap::respan(cur_op_span, ast_op), lhs, rhs);
                     self.mk_expr(lhs_span.lo, rhs_span.hi, binary, None)
                 }
                 AssocOp::Assign =>
-                    self.mk_expr(lhs.span.lo, rhs.span.hi, ExprAssign(lhs, rhs), None),
+                    self.mk_expr(lhs_span.lo, rhs.span.hi, ExprKind::Assign(lhs, rhs), None),
                 AssocOp::Inplace =>
-                    self.mk_expr(lhs.span.lo, rhs.span.hi, ExprInPlace(lhs, rhs), None),
+                    self.mk_expr(lhs_span.lo, rhs.span.hi, ExprKind::InPlace(lhs, rhs), None),
                 AssocOp::AssignOp(k) => {
                     let aop = match k {
-                        token::Plus =>    BiAdd,
-                        token::Minus =>   BiSub,
-                        token::Star =>    BiMul,
-                        token::Slash =>   BiDiv,
-                        token::Percent => BiRem,
-                        token::Caret =>   BiBitXor,
-                        token::And =>     BiBitAnd,
-                        token::Or =>      BiBitOr,
-                        token::Shl =>     BiShl,
-                        token::Shr =>     BiShr
+                        token::Plus =>    BinOpKind::Add,
+                        token::Minus =>   BinOpKind::Sub,
+                        token::Star =>    BinOpKind::Mul,
+                        token::Slash =>   BinOpKind::Div,
+                        token::Percent => BinOpKind::Rem,
+                        token::Caret =>   BinOpKind::BitXor,
+                        token::And =>     BinOpKind::BitAnd,
+                        token::Or =>      BinOpKind::BitOr,
+                        token::Shl =>     BinOpKind::Shl,
+                        token::Shr =>     BinOpKind::Shr,
                     };
-                    let (lhs_span, rhs_span) = (lhs.span, rhs.span);
+                    let (lhs_span, rhs_span) = (lhs_span, rhs.span);
                     let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs);
                     self.mk_expr(lhs_span.lo, rhs_span.hi, aopexpr, None)
                 }
@@ -2914,12 +2948,12 @@ pub fn parse_assoc_expr_with(&mut self,
     fn check_no_chained_comparison(&mut self, lhs: &Expr, outer_op: &AssocOp) {
         debug_assert!(outer_op.is_comparison());
         match lhs.node {
-            ExprBinary(op, _, _) if op.node.is_comparison() => {
+            ExprKind::Binary(op, _, _) if op.node.is_comparison() => {
                 // respan to include both operators
                 let op_span = mk_sp(op.span.lo, self.span.hi);
                 let mut err = self.diagnostic().struct_span_err(op_span,
                     "chained comparison operators require parentheses");
-                if op.node == BiLt && *outer_op == AssocOp::Greater {
+                if op.node == BinOpKind::Lt && *outer_op == AssocOp::Greater {
                     err.fileline_help(op_span,
                         "use `::<...>` instead of `<...>` if you meant to specify type arguments");
                 }
@@ -2981,7 +3015,7 @@ pub fn parse_if_expr(&mut self, attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
             hi = elexpr.span.hi;
             els = Some(elexpr);
         }
-        Ok(self.mk_expr(lo, hi, ExprIf(cond, thn, els), attrs))
+        Ok(self.mk_expr(lo, hi, ExprKind::If(cond, thn, els), attrs))
     }
 
     /// Parse an 'if let' expression ('if' token already eaten)
@@ -2999,18 +3033,18 @@ pub fn parse_if_let_expr(&mut self, attrs: ThinAttributes)
         } else {
             (thn.span.hi, None)
         };
-        Ok(self.mk_expr(lo, hi, ExprIfLet(pat, expr, thn, els), attrs))
+        Ok(self.mk_expr(lo, hi, ExprKind::IfLet(pat, expr, thn, els), attrs))
     }
 
     // `|args| expr`
     pub fn parse_lambda_expr(&mut self, lo: BytePos,
-                             capture_clause: CaptureClause,
+                             capture_clause: CaptureBy,
                              attrs: ThinAttributes)
                              -> PResult<'a, P<Expr>>
     {
         let decl = try!(self.parse_fn_block_decl());
         let body = match decl.output {
-            DefaultReturn(_) => {
+            FunctionRetTy::Default(_) => {
                 // If no explicit return type is given, parse any
                 // expr and wrap it up in a dummy block:
                 let body_expr = try!(self.parse_expr());
@@ -3019,7 +3053,7 @@ pub fn parse_lambda_expr(&mut self, lo: BytePos,
                     stmts: vec![],
                     span: body_expr.span,
                     expr: Some(body_expr),
-                    rules: DefaultBlock,
+                    rules: BlockCheckMode::Default,
                 })
             }
             _ => {
@@ -3032,7 +3066,7 @@ pub fn parse_lambda_expr(&mut self, lo: BytePos,
         Ok(self.mk_expr(
             lo,
             body.span.hi,
-            ExprClosure(capture_clause, decl, body), attrs))
+            ExprKind::Closure(capture_clause, decl, body), attrs))
     }
 
     // `else` token already eaten
@@ -3041,7 +3075,7 @@ pub fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
             return self.parse_if_expr(None);
         } else {
             let blk = try!(self.parse_block());
-            return Ok(self.mk_expr(blk.span.lo, blk.span.hi, ExprBlock(blk), None));
+            return Ok(self.mk_expr(blk.span.lo, blk.span.hi, ExprKind::Block(blk), None));
         }
     }
 
@@ -3060,7 +3094,7 @@ pub fn parse_for_expr(&mut self, opt_ident: Option<ast::Ident>,
         let hi = self.last_span.hi;
 
         Ok(self.mk_expr(span_lo, hi,
-                        ExprForLoop(pat, expr, loop_block, opt_ident),
+                        ExprKind::ForLoop(pat, expr, loop_block, opt_ident),
                         attrs))
     }
 
@@ -3075,7 +3109,7 @@ pub fn parse_while_expr(&mut self, opt_ident: Option<ast::Ident>,
         let (iattrs, body) = try!(self.parse_inner_attrs_and_block());
         let attrs = attrs.append(iattrs.into_thin_attrs());
         let hi = body.span.hi;
-        return Ok(self.mk_expr(span_lo, hi, ExprWhile(cond, body, opt_ident),
+        return Ok(self.mk_expr(span_lo, hi, ExprKind::While(cond, body, opt_ident),
                                attrs));
     }
 
@@ -3090,7 +3124,7 @@ pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::Ident>,
         let (iattrs, body) = try!(self.parse_inner_attrs_and_block());
         let attrs = attrs.append(iattrs.into_thin_attrs());
         let hi = body.span.hi;
-        return Ok(self.mk_expr(span_lo, hi, ExprWhileLet(pat, expr, body, opt_ident), attrs));
+        return Ok(self.mk_expr(span_lo, hi, ExprKind::WhileLet(pat, expr, body, opt_ident), attrs));
     }
 
     // parse `loop {...}`, `loop` token already eaten
@@ -3100,7 +3134,7 @@ pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::Ident>,
         let (iattrs, body) = try!(self.parse_inner_attrs_and_block());
         let attrs = attrs.append(iattrs.into_thin_attrs());
         let hi = body.span.hi;
-        Ok(self.mk_expr(span_lo, hi, ExprLoop(body, opt_ident), attrs))
+        Ok(self.mk_expr(span_lo, hi, ExprKind::Loop(body, opt_ident), attrs))
     }
 
     // `match` token already eaten
@@ -3124,7 +3158,7 @@ fn parse_match_expr(&mut self, attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
         }
         let hi = self.span.hi;
         self.bump();
-        return Ok(self.mk_expr(lo, hi, ExprMatch(discriminant, arms), attrs));
+        return Ok(self.mk_expr(lo, hi, ExprKind::Match(discriminant, arms), attrs));
     }
 
     pub fn parse_arm(&mut self) -> PResult<'a, Arm> {
@@ -3364,7 +3398,7 @@ fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
                 (None, try!(self.parse_path(LifetimeAndTypesWithColons)))
             };
             let hi = self.last_span.hi;
-            Ok(self.mk_expr(lo, hi, ExprPath(qself, path), None))
+            Ok(self.mk_expr(lo, hi, ExprKind::Path(qself, path), None))
         } else {
             self.parse_pat_literal_maybe_minus()
         }
@@ -3466,7 +3500,7 @@ pub fn parse_pat(&mut self) -> PResult<'a, P<Pat>> {
                       token::DotDotDot => {
                         // Parse range
                         let hi = self.last_span.hi;
-                        let begin = self.mk_expr(lo, hi, ExprPath(qself, path), None);
+                        let begin = self.mk_expr(lo, hi, ExprKind::Path(qself, path), None);
                         self.bump();
                         let end = try!(self.parse_pat_range_end());
                         pat = PatRange(begin, end);
@@ -3593,7 +3627,7 @@ fn parse_local(&mut self, attrs: ThinAttributes) -> PResult<'a, P<Local>> {
     fn parse_let(&mut self, attrs: ThinAttributes) -> PResult<'a, P<Decl>> {
         let lo = self.span.lo;
         let local = try!(self.parse_local(attrs));
-        Ok(P(spanned(lo, self.last_span.hi, DeclLocal(local))))
+        Ok(P(spanned(lo, self.last_span.hi, DeclKind::Local(local))))
     }
 
     /// Parse a structure field
@@ -3644,7 +3678,7 @@ fn parse_stmt_(&mut self) -> PResult<'a, Option<Stmt>> {
             try!(self.expect_keyword(keywords::Let));
             let decl = try!(self.parse_let(attrs.into_thin_attrs()));
             let hi = decl.span.hi;
-            let stmt = StmtDecl(decl, ast::DUMMY_NODE_ID);
+            let stmt = StmtKind::Decl(decl, ast::DUMMY_NODE_ID);
             spanned(lo, hi, stmt)
         } else if self.token.is_ident()
             && !self.token.is_any_keyword()
@@ -3696,11 +3730,8 @@ fn parse_stmt_(&mut self) -> PResult<'a, Option<Stmt>> {
             };
 
             if id.name == token::special_idents::invalid.name {
-                let stmt = StmtMac(P(spanned(lo,
-                                             hi,
-                                             Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT })),
-                                   style,
-                                   attrs.into_thin_attrs());
+                let mac = P(spanned(lo, hi, Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT }));
+                let stmt = StmtKind::Mac(mac, style, attrs.into_thin_attrs());
                 spanned(lo, hi, stmt)
             } else {
                 // if it has a special ident, it's definitely an item
@@ -3715,8 +3746,8 @@ fn parse_stmt_(&mut self) -> PResult<'a, Option<Stmt>> {
                                        followed by a semicolon");
                     }
                 }
-                spanned(lo, hi, StmtDecl(
-                    P(spanned(lo, hi, DeclItem(
+                spanned(lo, hi, StmtKind::Decl(
+                    P(spanned(lo, hi, DeclKind::Item(
                         self.mk_item(
                             lo, hi, id /*id is good here*/,
                             ItemMac(spanned(lo, hi,
@@ -3729,8 +3760,8 @@ fn parse_stmt_(&mut self) -> PResult<'a, Option<Stmt>> {
             match try!(self.parse_item_(attrs.clone(), false, true)) {
                 Some(i) => {
                     let hi = i.span.hi;
-                    let decl = P(spanned(lo, hi, DeclItem(i)));
-                    spanned(lo, hi, StmtDecl(decl, ast::DUMMY_NODE_ID))
+                    let decl = P(spanned(lo, hi, DeclKind::Item(i)));
+                    spanned(lo, hi, StmtKind::Decl(decl, ast::DUMMY_NODE_ID))
                 }
                 None => {
                     let unused_attrs = |attrs: &[_], s: &mut Self| {
@@ -3756,7 +3787,7 @@ fn parse_stmt_(&mut self) -> PResult<'a, Option<Stmt>> {
                     let e = try!(self.parse_expr_res(
                         Restrictions::RESTRICTION_STMT_EXPR, Some(attrs.into_thin_attrs())));
                     let hi = e.span.hi;
-                    let stmt = StmtExpr(e, ast::DUMMY_NODE_ID);
+                    let stmt = StmtKind::Expr(e, ast::DUMMY_NODE_ID);
                     spanned(lo, hi, stmt)
                 }
             }
@@ -3783,7 +3814,7 @@ pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
                                  "place this code inside a block"));
         }
 
-        self.parse_block_tail(lo, DefaultBlock)
+        self.parse_block_tail(lo, BlockCheckMode::Default)
     }
 
     /// Parse a block. Inner attrs are allowed.
@@ -3793,7 +3824,7 @@ fn parse_inner_attrs_and_block(&mut self) -> PResult<'a, (Vec<Attribute>, P<Bloc
         let lo = self.span.lo;
         try!(self.expect(&token::OpenDelim(token::Brace)));
         Ok((try!(self.parse_inner_attributes()),
-         try!(self.parse_block_tail(lo, DefaultBlock))))
+         try!(self.parse_block_tail(lo, BlockCheckMode::Default))))
     }
 
     /// Parse the rest of a block expression or function body
@@ -3810,16 +3841,16 @@ fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> PResult<'a, P<
                 continue;
             };
             match node {
-                StmtExpr(e, _) => {
+                StmtKind::Expr(e, _) => {
                     try!(self.handle_expression_like_statement(e, span, &mut stmts, &mut expr));
                 }
-                StmtMac(mac, MacStmtWithoutBraces, attrs) => {
+                StmtKind::Mac(mac, MacStmtWithoutBraces, attrs) => {
                     // 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(mac, MacStmtWithSemicolon, attrs),
+                                node: StmtKind::Mac(mac, MacStmtWithSemicolon, attrs),
                                 span: mk_sp(span.lo, self.span.hi),
                             }));
                             self.bump();
@@ -3828,7 +3859,8 @@ fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> PResult<'a, P<
                             let e = self.mk_mac_expr(span.lo, span.hi,
                                                      mac.and_then(|m| m.node),
                                                      None);
-                            let e = try!(self.parse_dot_or_call_expr_with(e, attrs));
+                            let lo = e.span.lo;
+                            let e = try!(self.parse_dot_or_call_expr_with(e, lo, attrs));
                             let e = try!(self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e)));
                             try!(self.handle_expression_like_statement(
                                 e,
@@ -3838,12 +3870,12 @@ fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> PResult<'a, P<
                         }
                     }
                 }
-                StmtMac(m, style, attrs) => {
+                StmtKind::Mac(m, style, attrs) => {
                     // statement macro; might be an expr
                     match self.token {
                         token::Semi => {
                             stmts.push(P(Spanned {
-                                node: StmtMac(m, MacStmtWithSemicolon, attrs),
+                                node: StmtKind::Mac(m, MacStmtWithSemicolon, attrs),
                                 span: mk_sp(span.lo, self.span.hi),
                             }));
                             self.bump();
@@ -3857,7 +3889,7 @@ fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> PResult<'a, P<
                         }
                         _ => {
                             stmts.push(P(Spanned {
-                                node: StmtMac(m, style, attrs),
+                                node: StmtKind::Mac(m, style, attrs),
                                 span: span
                             }));
                         }
@@ -3909,14 +3941,14 @@ fn handle_expression_like_statement(
                     expn_id: span.expn_id,
                 };
                 stmts.push(P(Spanned {
-                    node: StmtSemi(e, ast::DUMMY_NODE_ID),
+                    node: StmtKind::Semi(e, ast::DUMMY_NODE_ID),
                     span: span_with_semi,
                 }));
             }
             token::CloseDelim(token::Brace) => *last_block_expr = Some(e),
             _ => {
                 stmts.push(P(Spanned {
-                    node: StmtExpr(e, ast::DUMMY_NODE_ID),
+                    node: StmtKind::Expr(e, ast::DUMMY_NODE_ID),
                     span: span
                 }));
             }
@@ -4081,9 +4113,7 @@ fn parse_generic_values_after_lt(&mut self) -> PResult<'a, (Vec<ast::Lifetime>,
                               or did you mean the comma-separated arguments \
                               'a, Type?");
             err.span_note(mk_sp(span_lo, span_hi), &msg);
-            err.emit();
-
-            self.abort_if_errors()
+            return Err(err);
         }
 
         // First parse types.
@@ -4369,7 +4399,7 @@ fn parse_fn_decl_with_self<F>(&mut self,
         F: FnMut(&mut Parser<'a>) -> PResult<'a,  Arg>,
     {
         fn maybe_parse_borrowed_explicit_self<'b>(this: &mut Parser<'b>)
-                                                  -> PResult<'b,  ast::ExplicitSelf_> {
+                                                  -> PResult<'b, ast::SelfKind> {
             // The following things are possible to see here:
             //
             //     fn(&mut self)
@@ -4381,26 +4411,26 @@ fn maybe_parse_borrowed_explicit_self<'b>(this: &mut Parser<'b>)
 
             if this.look_ahead(1, |t| t.is_keyword(keywords::SelfValue)) {
                 this.bump();
-                Ok(SelfRegion(None, MutImmutable, try!(this.expect_self_ident())))
+                Ok(SelfKind::Region(None, MutImmutable, try!(this.expect_self_ident())))
             } else if this.look_ahead(1, |t| t.is_mutability()) &&
                       this.look_ahead(2, |t| t.is_keyword(keywords::SelfValue)) {
                 this.bump();
                 let mutability = try!(this.parse_mutability());
-                Ok(SelfRegion(None, mutability, try!(this.expect_self_ident())))
+                Ok(SelfKind::Region(None, mutability, try!(this.expect_self_ident())))
             } else if this.look_ahead(1, |t| t.is_lifetime()) &&
                       this.look_ahead(2, |t| t.is_keyword(keywords::SelfValue)) {
                 this.bump();
                 let lifetime = try!(this.parse_lifetime());
-                Ok(SelfRegion(Some(lifetime), MutImmutable, try!(this.expect_self_ident())))
+                Ok(SelfKind::Region(Some(lifetime), MutImmutable, try!(this.expect_self_ident())))
             } else if this.look_ahead(1, |t| t.is_lifetime()) &&
                       this.look_ahead(2, |t| t.is_mutability()) &&
                       this.look_ahead(3, |t| t.is_keyword(keywords::SelfValue)) {
                 this.bump();
                 let lifetime = try!(this.parse_lifetime());
                 let mutability = try!(this.parse_mutability());
-                Ok(SelfRegion(Some(lifetime), mutability, try!(this.expect_self_ident())))
+                Ok(SelfKind::Region(Some(lifetime), mutability, try!(this.expect_self_ident())))
             } else {
-                Ok(SelfStatic)
+                Ok(SelfKind::Static)
             }
         }
 
@@ -4435,7 +4465,7 @@ fn maybe_parse_borrowed_explicit_self<'b>(this: &mut Parser<'b>)
                     self.bump();
                 }
                 // error case, making bogus self ident:
-                SelfValue(special_idents::self_)
+                SelfKind::Value(special_idents::self_)
             }
             token::Ident(..) => {
                 if self.is_self_ident() {
@@ -4444,9 +4474,9 @@ fn maybe_parse_borrowed_explicit_self<'b>(this: &mut Parser<'b>)
                     // Determine whether this is the fully explicit form, `self:
                     // TYPE`.
                     if self.eat(&token::Colon) {
-                        SelfExplicit(try!(self.parse_ty_sum()), self_ident)
+                        SelfKind::Explicit(try!(self.parse_ty_sum()), self_ident)
                     } else {
-                        SelfValue(self_ident)
+                        SelfKind::Value(self_ident)
                     }
                 } else if self.token.is_mutability() &&
                         self.look_ahead(1, |t| t.is_keyword(keywords::SelfValue)) {
@@ -4456,15 +4486,15 @@ fn maybe_parse_borrowed_explicit_self<'b>(this: &mut Parser<'b>)
                     // Determine whether this is the fully explicit form,
                     // `self: TYPE`.
                     if self.eat(&token::Colon) {
-                        SelfExplicit(try!(self.parse_ty_sum()), self_ident)
+                        SelfKind::Explicit(try!(self.parse_ty_sum()), self_ident)
                     } else {
-                        SelfValue(self_ident)
+                        SelfKind::Value(self_ident)
                     }
                 } else {
-                    SelfStatic
+                    SelfKind::Static
                 }
             }
-            _ => SelfStatic,
+            _ => SelfKind::Static,
         };
 
         let explicit_self_sp = mk_sp(self_ident_lo, self_ident_hi);
@@ -4500,14 +4530,14 @@ macro_rules! parse_remaining_arguments {
         }
 
         let fn_inputs = match explicit_self {
-            SelfStatic =>  {
+            SelfKind::Static =>  {
                 let sep = seq_sep_trailing_allowed(token::Comma);
                 try!(self.parse_seq_to_before_end(&token::CloseDelim(token::Paren),
                                                   sep, parse_arg_fn))
             }
-            SelfValue(id) => parse_remaining_arguments!(id),
-            SelfRegion(_,_,id) => parse_remaining_arguments!(id),
-            SelfExplicit(_,id) => parse_remaining_arguments!(id),
+            SelfKind::Value(id) => parse_remaining_arguments!(id),
+            SelfKind::Region(_,_,id) => parse_remaining_arguments!(id),
+            SelfKind::Explicit(_,id) => parse_remaining_arguments!(id),
         };
 
 
@@ -4605,12 +4635,12 @@ pub fn parse_fn_front_matter(&mut self)
         let is_const_fn = self.eat_keyword(keywords::Const);
         let unsafety = try!(self.parse_unsafety());
         let (constness, unsafety, abi) = if is_const_fn {
-            (Constness::Const, unsafety, abi::Rust)
+            (Constness::Const, unsafety, Abi::Rust)
         } else {
             let abi = if self.eat_keyword(keywords::Extern) {
-                try!(self.parse_opt_abi()).unwrap_or(abi::C)
+                try!(self.parse_opt_abi()).unwrap_or(Abi::C)
             } else {
-                abi::Rust
+                Abi::Rust
             };
             (Constness::NotConst, unsafety, abi)
         };
@@ -4773,7 +4803,7 @@ fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> PResult<'a, ItemInfo>
         let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
             // New-style trait. Reinterpret the type as a trait.
             match ty.node {
-                TyPath(None, ref path) => {
+                TyKind::Path(None, ref path) => {
                     Some(TraitRef {
                         path: (*path).clone(),
                         ref_id: ty.id,
@@ -5153,8 +5183,7 @@ fn submod_path(&mut self,
                                         of possibly redeclaring it",
                                        paths.name));
             }
-            err.emit();
-            self.abort_if_errors();
+            return Err(err);
         }
 
         match paths.result {
@@ -5309,7 +5338,7 @@ fn parse_item_foreign_mod(&mut self,
                               -> PResult<'a, P<Item>> {
         try!(self.expect(&token::OpenDelim(token::Brace)));
 
-        let abi = opt_abi.unwrap_or(abi::C);
+        let abi = opt_abi.unwrap_or(Abi::C);
 
         attrs.extend(try!(self.parse_inner_attributes()));
 
@@ -5481,7 +5510,7 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
 
             if self.eat_keyword(keywords::Fn) {
                 // EXTERN FUNCTION ITEM
-                let abi = opt_abi.unwrap_or(abi::C);
+                let abi = opt_abi.unwrap_or(Abi::C);
                 let (ident, item_, extra_attrs) =
                     try!(self.parse_item_fn(Unsafety::Normal, Constness::NotConst, abi));
                 let last_span = self.last_span;
@@ -5524,7 +5553,7 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
                 };
                 self.bump();
                 let (ident, item_, extra_attrs) =
-                    try!(self.parse_item_fn(unsafety, Constness::Const, abi::Rust));
+                    try!(self.parse_item_fn(unsafety, Constness::Const, Abi::Rust));
                 let last_span = self.last_span;
                 let item = self.mk_item(lo,
                                         last_span.hi,
@@ -5589,7 +5618,7 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
             // FUNCTION ITEM
             self.bump();
             let (ident, item_, extra_attrs) =
-                try!(self.parse_item_fn(Unsafety::Normal, Constness::NotConst, abi::Rust));
+                try!(self.parse_item_fn(Unsafety::Normal, Constness::NotConst, Abi::Rust));
             let last_span = self.last_span;
             let item = self.mk_item(lo,
                                     last_span.hi,
@@ -5604,9 +5633,9 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
             // UNSAFE FUNCTION ITEM
             self.bump();
             let abi = if self.eat_keyword(keywords::Extern) {
-                try!(self.parse_opt_abi()).unwrap_or(abi::C)
+                try!(self.parse_opt_abi()).unwrap_or(Abi::C)
             } else {
-                abi::Rust
+                Abi::Rust
             };
             try!(self.expect_keyword(keywords::Fn));
             let (ident, item_, extra_attrs) =