about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-09-20 03:11:12 +0000
committerbors <bors@rust-lang.org>2014-09-20 03:11:12 +0000
commitaef6c4b1382dcf2f943bd5872656625f935c0b7c (patch)
tree95920a7c62cbc07301ec8fe4b189b33e208327cd /src/libsyntax
parent3b6e880fffb8e09b15bc6fc41d5b23f21bf5056d (diff)
parentf082416bece7cbb16ec46f870fb7f91ca15f2231 (diff)
auto merge of #17399 : alexcrichton/rust/rollup, r=alexcrichton
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs14
-rw-r--r--src/libsyntax/codemap.rs45
-rw-r--r--src/libsyntax/diagnostic.rs38
-rw-r--r--src/libsyntax/diagnostics/plugin.rs8
-rw-r--r--src/libsyntax/ext/base.rs108
-rw-r--r--src/libsyntax/ext/build.rs4
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs3
-rw-r--r--src/libsyntax/ext/expand.rs33
-rw-r--r--src/libsyntax/ext/format.rs33
-rw-r--r--src/libsyntax/ext/source_util.rs46
-rw-r--r--src/libsyntax/fold.rs30
-rw-r--r--src/libsyntax/lib.rs2
-rw-r--r--src/libsyntax/parse/lexer/mod.rs6
-rw-r--r--src/libsyntax/parse/mod.rs4
-rw-r--r--src/libsyntax/parse/parser.rs183
-rw-r--r--src/libsyntax/parse/token.rs83
-rw-r--r--src/libsyntax/print/pp.rs10
-rw-r--r--src/libsyntax/print/pprust.rs73
-rw-r--r--src/libsyntax/visit.rs5
19 files changed, 432 insertions, 296 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index eac158e664c..5c84745c20c 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -213,13 +213,20 @@ pub static DUMMY_NODE_ID: NodeId = -1;
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum TyParamBound {
     TraitTyParamBound(TraitRef),
-    UnboxedFnTyParamBound(UnboxedFnTy),
+    UnboxedFnTyParamBound(P<UnboxedFnBound>),
     RegionTyParamBound(Lifetime)
 }
 
 pub type TyParamBounds = OwnedSlice<TyParamBound>;
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
+pub struct UnboxedFnBound {
+    pub path: Path,
+    pub decl: P<FnDecl>,
+    pub ref_id: NodeId,
+}
+
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct TyParam {
     pub ident: Ident,
     pub id: NodeId,
@@ -531,6 +538,7 @@ pub enum Expr_ {
     ExprField(P<Expr>, SpannedIdent, Vec<P<Ty>>),
     ExprTupField(P<Expr>, Spanned<uint>, Vec<P<Ty>>),
     ExprIndex(P<Expr>, P<Expr>),
+    ExprSlice(P<Expr>, Option<P<Expr>>, Option<P<Expr>>, Mutability),
 
     /// Variable reference, possibly containing `::` and/or
     /// type parameters, e.g. foo::bar::<baz>
@@ -1363,7 +1371,7 @@ mod test {
                 inner: Span {
                     lo: BytePos(11),
                     hi: BytePos(19),
-                    expn_info: None,
+                    expn_id: NO_EXPANSION,
                 },
                 view_items: Vec::new(),
                 items: Vec::new(),
@@ -1373,7 +1381,7 @@ mod test {
             span: Span {
                 lo: BytePos(10),
                 hi: BytePos(20),
-                expn_info: None,
+                expn_id: NO_EXPANSION,
             },
             exported_macros: Vec::new(),
         };
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 2f30108c27b..9072889463c 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -25,7 +25,6 @@ source code snippets, etc.
 
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 use std::cell::RefCell;
-use std::gc::Gc;
 use std::rc::Rc;
 
 pub trait Pos {
@@ -93,10 +92,10 @@ pub struct Span {
     pub hi: BytePos,
     /// Information about where the macro came from, if this piece of
     /// code was created by a macro expansion.
-    pub expn_info: Option<Gc<ExpnInfo>>
+    pub expn_id: ExpnId
 }
 
-pub static DUMMY_SP: Span = Span { lo: BytePos(0), hi: BytePos(0), expn_info: None };
+pub static DUMMY_SP: Span = Span { lo: BytePos(0), hi: BytePos(0), expn_id: NO_EXPANSION };
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Spanned<T> {
@@ -140,17 +139,19 @@ pub fn dummy_spanned<T>(t: T) -> Spanned<T> {
 
 /* assuming that we're not in macro expansion */
 pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span {
-    Span {lo: lo, hi: hi, expn_info: None}
+    Span {lo: lo, hi: hi, expn_id: NO_EXPANSION}
 }
 
 /// Return the span itself if it doesn't come from a macro expansion,
 /// otherwise return the call site span up to the `enclosing_sp` by
 /// following the `expn_info` chain.
-pub fn original_sp(sp: Span, enclosing_sp: Span) -> Span {
-    match (sp.expn_info, enclosing_sp.expn_info) {
+pub fn original_sp(cm: &CodeMap, sp: Span, enclosing_sp: Span) -> Span {
+    let call_site1 = cm.with_expn_info(sp.expn_id, |ei| ei.map(|ei| ei.call_site));
+    let call_site2 = cm.with_expn_info(enclosing_sp.expn_id, |ei| ei.map(|ei| ei.call_site));
+    match (call_site1, call_site2) {
         (None, _) => sp,
-        (Some(expn1), Some(expn2)) if expn1.call_site == expn2.call_site => sp,
-        (Some(expn1), _) => original_sp(expn1.call_site, enclosing_sp),
+        (Some(call_site1), Some(call_site2)) if call_site1 == call_site2 => sp,
+        (Some(call_site1), _) => original_sp(cm, call_site1, enclosing_sp),
     }
 }
 
@@ -222,6 +223,11 @@ pub struct ExpnInfo {
     pub callee: NameAndSpan
 }
 
+#[deriving(PartialEq, Eq, Clone, Show, Hash)]
+pub struct ExpnId(u32);
+
+pub static NO_EXPANSION: ExpnId = ExpnId(-1);
+
 pub type FileName = String;
 
 pub struct FileLines {
@@ -299,13 +305,15 @@ impl FileMap {
 }
 
 pub struct CodeMap {
-    pub files: RefCell<Vec<Rc<FileMap>>>
+    pub files: RefCell<Vec<Rc<FileMap>>>,
+    expansions: RefCell<Vec<ExpnInfo>>
 }
 
 impl CodeMap {
     pub fn new() -> CodeMap {
         CodeMap {
             files: RefCell::new(Vec::new()),
+            expansions: RefCell::new(Vec::new()),
         }
     }
 
@@ -527,6 +535,19 @@ impl CodeMap {
             col: chpos - linechpos
         }
     }
+
+    pub fn record_expansion(&self, expn_info: ExpnInfo) -> ExpnId {
+        let mut expansions = self.expansions.borrow_mut();
+        expansions.push(expn_info);
+        ExpnId(expansions.len().to_u32().expect("too many ExpnInfo's!") - 1)
+    }
+
+    pub fn with_expn_info<T>(&self, id: ExpnId, f: |Option<&ExpnInfo>| -> T) -> T {
+        match id {
+            NO_EXPANSION => f(None),
+            ExpnId(i) => f(Some(&(*self.expansions.borrow())[i as uint]))
+        }
+    }
 }
 
 #[cfg(test)]
@@ -665,7 +686,7 @@ mod test {
     fn t7() {
         // Test span_to_lines for a span ending at the end of filemap
         let cm = init_code_map();
-        let span = Span {lo: BytePos(12), hi: BytePos(23), expn_info: None};
+        let span = Span {lo: BytePos(12), hi: BytePos(23), expn_id: NO_EXPANSION};
         let file_lines = cm.span_to_lines(span);
 
         assert_eq!(file_lines.file.name, "blork.rs".to_string());
@@ -677,7 +698,7 @@ mod test {
     fn t8() {
         // Test span_to_snippet for a span ending at the end of filemap
         let cm = init_code_map();
-        let span = Span {lo: BytePos(12), hi: BytePos(23), expn_info: None};
+        let span = Span {lo: BytePos(12), hi: BytePos(23), expn_id: NO_EXPANSION};
         let snippet = cm.span_to_snippet(span);
 
         assert_eq!(snippet, Some("second line".to_string()));
@@ -687,7 +708,7 @@ mod test {
     fn t9() {
         // Test span_to_str for a span ending at the end of filemap
         let cm = init_code_map();
-        let span = Span {lo: BytePos(12), hi: BytePos(23), expn_info: None};
+        let span = Span {lo: BytePos(12), hi: BytePos(23), expn_id: NO_EXPANSION};
         let sstr =  cm.span_to_string(span);
 
         assert_eq!(sstr, "blork.rs:2:1: 2:12".to_string());
diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs
index faa3946b74d..f33c768d647 100644
--- a/src/libsyntax/diagnostic.rs
+++ b/src/libsyntax/diagnostic.rs
@@ -389,7 +389,7 @@ fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan,
         // we want to tell compiletest/runtest to look at the last line of the
         // span (since `custom_highlight_lines` displays an arrow to the end of
         // the span)
-        let span_end = Span { lo: sp.hi, hi: sp.hi, expn_info: sp.expn_info};
+        let span_end = Span { lo: sp.hi, hi: sp.hi, expn_id: sp.expn_id};
         let ses = cm.span_to_string(span_end);
         try!(print_diagnostic(dst, ses.as_slice(), lvl, msg, code));
         if rsp.is_full_span() {
@@ -523,24 +523,24 @@ fn print_macro_backtrace(w: &mut EmitterWriter,
                          cm: &codemap::CodeMap,
                          sp: Span)
                          -> io::IoResult<()> {
-    for ei in sp.expn_info.iter() {
-        let ss = ei.callee
-                   .span
-                   .as_ref()
-                   .map_or("".to_string(), |span| cm.span_to_string(*span));
-        let (pre, post) = match ei.callee.format {
-            codemap::MacroAttribute => ("#[", "]"),
-            codemap::MacroBang => ("", "!")
-        };
-        try!(print_diagnostic(w, ss.as_slice(), Note,
-                              format!("in expansion of {}{}{}", pre,
-                                      ei.callee.name,
-                                      post).as_slice(), None));
-        let ss = cm.span_to_string(ei.call_site);
-        try!(print_diagnostic(w, ss.as_slice(), Note, "expansion site", None));
-        try!(print_macro_backtrace(w, cm, ei.call_site));
-    }
-    Ok(())
+    let cs = try!(cm.with_expn_info(sp.expn_id, |expn_info| match expn_info {
+        Some(ei) => {
+            let ss = ei.callee.span.map_or(String::new(), |span| cm.span_to_string(span));
+            let (pre, post) = match ei.callee.format {
+                codemap::MacroAttribute => ("#[", "]"),
+                codemap::MacroBang => ("", "!")
+            };
+            try!(print_diagnostic(w, ss.as_slice(), Note,
+                                  format!("in expansion of {}{}{}", pre,
+                                          ei.callee.name,
+                                          post).as_slice(), None));
+            let ss = cm.span_to_string(ei.call_site);
+            try!(print_diagnostic(w, ss.as_slice(), Note, "expansion site", None));
+            Ok(Some(ei.call_site))
+        }
+        None => Ok(None)
+    }));
+    cs.map_or(Ok(()), |call_site| print_macro_backtrace(w, cm, call_site))
 }
 
 pub fn expect<T>(diag: &SpanHandler, opt: Option<T>, msg: || -> String) -> T {
diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs
index 132b59c89b2..d3c39284f55 100644
--- a/src/libsyntax/diagnostics/plugin.rs
+++ b/src/libsyntax/diagnostics/plugin.rs
@@ -13,7 +13,7 @@ use std::collections::HashMap;
 use ast;
 use ast::{Ident, Name, TokenTree};
 use codemap::Span;
-use ext::base::{ExtCtxt, MacExpr, MacItem, MacResult};
+use ext::base::{ExtCtxt, MacExpr, MacResult, MacItems};
 use ext::build::AstBuilder;
 use parse::token;
 use ptr::P;
@@ -102,7 +102,7 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt,
     let sym = Ident::new(token::gensym((
         "__register_diagnostic_".to_string() + token::get_ident(*code).get()
     ).as_slice()));
-    MacItem::new(quote_item!(ecx, mod $sym {}).unwrap())
+    MacItems::new(vec![quote_item!(ecx, mod $sym {}).unwrap()].into_iter())
 }
 
 pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
@@ -133,7 +133,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
             (descriptions.len(), ecx.expr_vec(span, descriptions))
         })
     });
-    MacItem::new(quote_item!(ecx,
+    MacItems::new(vec![quote_item!(ecx,
         pub static $name: [(&'static str, &'static str), ..$count] = $expr;
-    ).unwrap())
+    ).unwrap()].into_iter())
 }
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 773daa4a4c5..b35a9456757 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -11,7 +11,7 @@
 use ast;
 use ast::Name;
 use codemap;
-use codemap::{CodeMap, Span, ExpnInfo};
+use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION};
 use ext;
 use ext::expand;
 use parse;
@@ -24,7 +24,6 @@ use ext::mtwt;
 use fold::Folder;
 
 use std::collections::HashMap;
-use std::gc::{Gc, GC};
 use std::rc::Rc;
 
 // new-style macro! tt code:
@@ -203,25 +202,20 @@ impl MacResult for MacPat {
         Some(self.p)
     }
 }
-/// A convenience type for macros that return a single item.
-pub struct MacItem {
-    i: P<ast::Item>
+/// A type for macros that return multiple items.
+pub struct MacItems {
+    items: SmallVector<P<ast::Item>>
 }
-impl MacItem {
-    pub fn new(i: P<ast::Item>) -> Box<MacResult+'static> {
-        box MacItem { i: i } as Box<MacResult+'static>
+
+impl MacItems {
+    pub fn new<I: Iterator<P<ast::Item>>>(mut it: I) -> Box<MacResult+'static> {
+        box MacItems { items: it.collect() } as Box<MacResult+'static>
     }
 }
-impl MacResult for MacItem {
-    fn make_items(self: Box<MacItem>) -> Option<SmallVector<P<ast::Item>>> {
-        Some(SmallVector::one(self.i))
-    }
-    fn make_stmt(self: Box<MacItem>) -> Option<P<ast::Stmt>> {
-        Some(P(codemap::respan(
-            self.i.span,
-            ast::StmtDecl(
-                P(codemap::respan(self.i.span, ast::DeclItem(self.i))),
-                ast::DUMMY_NODE_ID))))
+
+impl MacResult for MacItems {
+    fn make_items(self: Box<MacItems>) -> Option<SmallVector<P<ast::Item>>> {
+        Some(self.items)
     }
 }
 
@@ -305,11 +299,11 @@ pub enum SyntaxExtension {
     /// based upon it.
     ///
     /// `#[deriving(...)]` is an `ItemDecorator`.
-    ItemDecorator(Box<ItemDecorator + 'static>),
+    Decorator(Box<ItemDecorator + 'static>),
 
     /// A syntax extension that is attached to an item and modifies it
     /// in-place.
-    ItemModifier(Box<ItemModifier + 'static>),
+    Modifier(Box<ItemModifier + 'static>),
 
     /// A normal, function-like syntax extension.
     ///
@@ -387,7 +381,7 @@ fn initial_syntax_expander_table() -> SyntaxEnv {
                             builtin_normal_expander(
                                     ext::log_syntax::expand_syntax_ext));
     syntax_expanders.insert(intern("deriving"),
-                            ItemDecorator(box ext::deriving::expand_meta_deriving));
+                            Decorator(box ext::deriving::expand_meta_deriving));
 
     // Quasi-quoting expanders
     syntax_expanders.insert(intern("quote_tokens"),
@@ -457,7 +451,7 @@ fn initial_syntax_expander_table() -> SyntaxEnv {
 pub struct ExtCtxt<'a> {
     pub parse_sess: &'a parse::ParseSess,
     pub cfg: ast::CrateConfig,
-    pub backtrace: Option<Gc<ExpnInfo>>,
+    pub backtrace: ExpnId,
     pub ecfg: expand::ExpansionConfig,
 
     pub mod_path: Vec<ast::Ident> ,
@@ -473,7 +467,7 @@ impl<'a> ExtCtxt<'a> {
         ExtCtxt {
             parse_sess: parse_sess,
             cfg: cfg,
-            backtrace: None,
+            backtrace: NO_EXPANSION,
             mod_path: Vec::new(),
             ecfg: ecfg,
             trace_mac: false,
@@ -501,13 +495,49 @@ impl<'a> ExtCtxt<'a> {
     pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess }
     pub fn cfg(&self) -> ast::CrateConfig { self.cfg.clone() }
     pub fn call_site(&self) -> Span {
-        match self.backtrace {
+        self.codemap().with_expn_info(self.backtrace, |ei| match ei {
             Some(expn_info) => expn_info.call_site,
             None => self.bug("missing top span")
-        }
+        })
     }
     pub fn print_backtrace(&self) { }
-    pub fn backtrace(&self) -> Option<Gc<ExpnInfo>> { self.backtrace }
+    pub fn backtrace(&self) -> ExpnId { self.backtrace }
+    pub fn original_span(&self) -> Span {
+        let mut expn_id = self.backtrace;
+        let mut call_site = None;
+        loop {
+            match self.codemap().with_expn_info(expn_id, |ei| ei.map(|ei| ei.call_site)) {
+                None => break,
+                Some(cs) => {
+                    call_site = Some(cs);
+                    expn_id = cs.expn_id;
+                }
+            }
+        }
+        call_site.expect("missing expansion backtrace")
+    }
+    pub fn original_span_in_file(&self) -> Span {
+        let mut expn_id = self.backtrace;
+        let mut call_site = None;
+        loop {
+            let expn_info = self.codemap().with_expn_info(expn_id, |ei| {
+                ei.map(|ei| (ei.call_site, ei.callee.name.as_slice() == "include"))
+            });
+            match expn_info {
+                None => break,
+                Some((cs, is_include)) => {
+                    if is_include {
+                        // Don't recurse into file using "include!".
+                        break;
+                    }
+                    call_site = Some(cs);
+                    expn_id = cs.expn_id;
+                }
+            }
+        }
+        call_site.expect("missing expansion backtrace")
+    }
+
     pub fn mod_push(&mut self, i: ast::Ident) { self.mod_path.push(i); }
     pub fn mod_pop(&mut self) { self.mod_path.pop().unwrap(); }
     pub fn mod_path(&self) -> Vec<ast::Ident> {
@@ -516,22 +546,22 @@ impl<'a> ExtCtxt<'a> {
         v.extend(self.mod_path.iter().map(|a| *a));
         return v;
     }
-    pub fn bt_push(&mut self, ei: codemap::ExpnInfo) {
-        match ei {
-            ExpnInfo {call_site: cs, callee: ref callee} => {
-                self.backtrace =
-                    Some(box(GC) ExpnInfo {
-                        call_site: Span {lo: cs.lo, hi: cs.hi,
-                                         expn_info: self.backtrace.clone()},
-                        callee: (*callee).clone()
-                    });
-            }
-        }
+    pub fn bt_push(&mut self, ei: ExpnInfo) {
+        let mut call_site = ei.call_site;
+        call_site.expn_id = self.backtrace;
+        self.backtrace = self.codemap().record_expansion(ExpnInfo {
+            call_site: call_site,
+            callee: ei.callee
+        });
     }
     pub fn bt_pop(&mut self) {
         match self.backtrace {
-            Some(expn_info) => self.backtrace = expn_info.call_site.expn_info,
-            _ => self.bug("tried to pop without a push")
+            NO_EXPANSION => self.bug("tried to pop without a push"),
+            expn_id => {
+                self.backtrace = self.codemap().with_expn_info(expn_id, |expn_info| {
+                    expn_info.map_or(NO_EXPANSION, |ei| ei.call_site.expn_id)
+                });
+            }
         }
     }
     /// Emit `msg` attached to `sp`, and stop compilation immediately.
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 7b2613d4e8b..16ecd83180e 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -573,7 +573,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         let field_span = Span {
             lo: sp.lo - Pos::from_uint(field_name.get().len()),
             hi: sp.hi,
-            expn_info: sp.expn_info,
+            expn_id: sp.expn_id,
         };
 
         let id = Spanned { node: ident, span: field_span };
@@ -583,7 +583,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         let field_span = Span {
             lo: sp.lo - Pos::from_uint(idx.to_string().len()),
             hi: sp.hi,
-            expn_info: sp.expn_info,
+            expn_id: sp.expn_id,
         };
 
         let id = Spanned { node: idx, span: field_span };
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index ff249495bd7..142adc9b721 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -181,7 +181,6 @@
 //! ~~~
 
 use std::cell::RefCell;
-use std::gc::GC;
 use std::vec;
 
 use abi::Abi;
@@ -1169,7 +1168,7 @@ impl<'a> TraitDef<'a> {
             None => cx.span_bug(self.span, "trait with empty path in generic `deriving`"),
             Some(name) => *name
         };
-        to_set.expn_info = Some(box(GC) codemap::ExpnInfo {
+        to_set.expn_id = cx.codemap().record_expansion(codemap::ExpnInfo {
             call_site: to_set,
             callee: codemap::NameAndSpan {
                 name: format!("deriving({})", trait_name),
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 4ff9912645a..e173b93e468 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -30,8 +30,6 @@ use util::small_vector::SmallVector;
 use visit;
 use visit::Visitor;
 
-use std::gc::Gc;
-
 enum Either<L,R> {
     Left(L),
     Right(R)
@@ -161,11 +159,11 @@ fn expand_mac_invoc<T>(mac: ast::Mac, span: codemap::Span,
                         // be the root of the call stack. That's the most
                         // relevant span and it's the actual invocation of
                         // the macro.
-                        let mac_span = original_span(fld.cx);
+                        let mac_span = fld.cx.original_span();
 
                         let opt_parsed = {
                             let expanded = expandfun.expand(fld.cx,
-                                                            mac_span.call_site,
+                                                            mac_span,
                                                             marked_before.as_slice());
                             parse_thunk(expanded)
                         };
@@ -254,7 +252,7 @@ pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander)
 
         match fld.cx.syntax_env.find(&intern(mname.get())) {
             Some(rc) => match *rc {
-                ItemDecorator(ref dec) => {
+                Decorator(ref dec) => {
                     attr::mark_used(attr);
 
                     fld.cx.bt_push(ExpnInfo {
@@ -311,7 +309,7 @@ fn expand_item_modifiers(mut it: P<ast::Item>, fld: &mut MacroExpander)
     // partition the attributes into ItemModifiers and others
     let (modifiers, other_attrs) = it.attrs.partitioned(|attr| {
         match fld.cx.syntax_env.find(&intern(attr.name().get())) {
-            Some(rc) => match *rc { ItemModifier(_) => true, _ => false },
+            Some(rc) => match *rc { Modifier(_) => true, _ => false },
             _ => false
         }
     });
@@ -330,7 +328,7 @@ fn expand_item_modifiers(mut it: P<ast::Item>, fld: &mut MacroExpander)
 
         match fld.cx.syntax_env.find(&intern(mname.get())) {
             Some(rc) => match *rc {
-                ItemModifier(ref mac) => {
+                Modifier(ref mac) => {
                     attr::mark_used(attr);
                     fld.cx.bt_push(ExpnInfo {
                         call_site: attr.span,
@@ -759,9 +757,9 @@ fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> {
 
                     let fm = fresh_mark();
                     let marked_before = mark_tts(tts.as_slice(), fm);
-                    let mac_span = original_span(fld.cx);
+                    let mac_span = fld.cx.original_span();
                     let expanded = match expander.expand(fld.cx,
-                                        mac_span.call_site,
+                                        mac_span,
                                         marked_before.as_slice()).make_pat() {
                         Some(e) => e,
                         None => {
@@ -969,7 +967,7 @@ fn new_span(cx: &ExtCtxt, sp: Span) -> Span {
     Span {
         lo: sp.lo,
         hi: sp.hi,
-        expn_info: cx.backtrace(),
+        expn_id: cx.backtrace(),
     }
 }
 
@@ -1083,21 +1081,6 @@ fn mark_method(expr: P<ast::Method>, m: Mrk) -> P<ast::Method> {
         .expect_one("marking an item didn't return exactly one method")
 }
 
-fn original_span(cx: &ExtCtxt) -> Gc<codemap::ExpnInfo> {
-    let mut relevant_info = cx.backtrace();
-    let mut einfo = relevant_info.unwrap();
-    loop {
-        match relevant_info {
-            None => { break }
-            Some(e) => {
-                einfo = e;
-                relevant_info = einfo.call_site.expn_info;
-            }
-        }
-    }
-    return einfo;
-}
-
 /// Check that there are no macro invocations left in the AST:
 pub fn check_for_macros(sess: &parse::ParseSess, krate: &ast::Crate) {
     visit::walk_crate(&mut MacroExterminator{sess:sess}, krate);
diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs
index 26586684309..b760c893a10 100644
--- a/src/libsyntax/ext/format.rs
+++ b/src/libsyntax/ext/format.rs
@@ -19,17 +19,18 @@ use parse::token;
 use ptr::P;
 
 use std::collections::HashMap;
+use std::string;
 
 #[deriving(PartialEq)]
 enum ArgumentType {
-    Known(String),
+    Known(string::String),
     Unsigned,
     String,
 }
 
 enum Position {
     Exact(uint),
-    Named(String),
+    Named(string::String),
 }
 
 struct Context<'a, 'b:'a> {
@@ -44,12 +45,12 @@ struct Context<'a, 'b:'a> {
     /// Note that we keep a side-array of the ordering of the named arguments
     /// found to be sure that we can translate them in the same order that they
     /// were declared in.
-    names: HashMap<String, P<ast::Expr>>,
-    name_types: HashMap<String, ArgumentType>,
-    name_ordering: Vec<String>,
+    names: HashMap<string::String, P<ast::Expr>>,
+    name_types: HashMap<string::String, ArgumentType>,
+    name_ordering: Vec<string::String>,
 
     /// The latest consecutive literal strings, or empty if there weren't any.
-    literal: String,
+    literal: string::String,
 
     /// Collection of the compiled `rt::Argument` structures
     pieces: Vec<P<ast::Expr>>,
@@ -58,7 +59,7 @@ struct Context<'a, 'b:'a> {
     /// Stays `true` if all formatting parameters are default (as in "{}{}").
     all_pieces_simple: bool,
 
-    name_positions: HashMap<String, uint>,
+    name_positions: HashMap<string::String, uint>,
     method_statics: Vec<P<ast::Item>>,
 
     /// Updated as arguments are consumed or methods are entered
@@ -81,10 +82,10 @@ pub enum Invocation {
 ///           named arguments))
 fn parse_args(ecx: &mut ExtCtxt, sp: Span, allow_method: bool,
               tts: &[ast::TokenTree])
-    -> (Invocation, Option<(P<ast::Expr>, Vec<P<ast::Expr>>, Vec<String>,
-                            HashMap<String, P<ast::Expr>>)>) {
+    -> (Invocation, Option<(P<ast::Expr>, Vec<P<ast::Expr>>, Vec<string::String>,
+                            HashMap<string::String, P<ast::Expr>>)>) {
     let mut args = Vec::new();
-    let mut names = HashMap::<String, P<ast::Expr>>::new();
+    let mut names = HashMap::<string::String, P<ast::Expr>>::new();
     let mut order = Vec::new();
 
     let mut p = ecx.new_parser_from_tts(tts);
@@ -167,7 +168,7 @@ impl<'a, 'b> Context<'a, 'b> {
     fn verify_piece(&mut self, p: &parse::Piece) {
         match *p {
             parse::String(..) => {}
-            parse::Argument(ref arg) => {
+            parse::NextArgument(ref arg) => {
                 // width/precision first, if they have implicit positional
                 // parameters it makes more sense to consume them first.
                 self.verify_count(arg.format.width);
@@ -222,7 +223,7 @@ impl<'a, 'b> Context<'a, 'b> {
         }
     }
 
-    fn describe_num_args(&self) -> String {
+    fn describe_num_args(&self) -> string::String {
         match self.args.len() {
             0 => "no arguments given".to_string(),
             1 => "there is 1 argument".to_string(),
@@ -391,7 +392,7 @@ impl<'a, 'b> Context<'a, 'b> {
                 self.literal.push_str(s);
                 None
             }
-            parse::Argument(ref arg) => {
+            parse::NextArgument(ref arg) => {
                 // Translate the position
                 let pos = match arg.position {
                     // These two have a direct mapping
@@ -747,8 +748,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
                                     invocation: Invocation,
                                     efmt: P<ast::Expr>,
                                     args: Vec<P<ast::Expr>>,
-                                    name_ordering: Vec<String>,
-                                    names: HashMap<String, P<ast::Expr>>)
+                                    name_ordering: Vec<string::String>,
+                                    names: HashMap<string::String, P<ast::Expr>>)
                                     -> P<ast::Expr> {
     let arg_types = Vec::from_fn(args.len(), |_| None);
     let mut cx = Context {
@@ -761,7 +762,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
         name_ordering: name_ordering,
         nest_level: 0,
         next_arg: 0,
-        literal: String::new(),
+        literal: string::String::new(),
         pieces: Vec::new(),
         str_pieces: Vec::new(),
         all_pieces_simple: true,
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index 5cc0ec4a122..41967b0680c 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -11,7 +11,6 @@
 use ast;
 use codemap;
 use codemap::{Pos, Span};
-use codemap::{ExpnInfo, NameAndSpan};
 use ext::base::*;
 use ext::base;
 use ext::build::AstBuilder;
@@ -19,7 +18,6 @@ use parse;
 use parse::token;
 use print::pprust;
 
-use std::gc::Gc;
 use std::io::File;
 use std::rc::Rc;
 
@@ -32,10 +30,10 @@ pub fn expand_line(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                    -> Box<base::MacResult+'static> {
     base::check_zero_tts(cx, sp, tts, "line!");
 
-    let topmost = topmost_expn_info(cx.backtrace().unwrap());
-    let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo);
+    let topmost = cx.original_span_in_file();
+    let loc = cx.codemap().lookup_char_pos(topmost.lo);
 
-    base::MacExpr::new(cx.expr_uint(topmost.call_site, loc.line))
+    base::MacExpr::new(cx.expr_uint(topmost, loc.line))
 }
 
 /* col!(): expands to the current column number */
@@ -43,9 +41,9 @@ pub fn expand_col(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                   -> Box<base::MacResult+'static> {
     base::check_zero_tts(cx, sp, tts, "col!");
 
-    let topmost = topmost_expn_info(cx.backtrace().unwrap());
-    let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo);
-    base::MacExpr::new(cx.expr_uint(topmost.call_site, loc.col.to_uint()))
+    let topmost = cx.original_span_in_file();
+    let loc = cx.codemap().lookup_char_pos(topmost.lo);
+    base::MacExpr::new(cx.expr_uint(topmost, loc.col.to_uint()))
 }
 
 /// file!(): expands to the current filename */
@@ -55,10 +53,10 @@ pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                    -> Box<base::MacResult+'static> {
     base::check_zero_tts(cx, sp, tts, "file!");
 
-    let topmost = topmost_expn_info(cx.backtrace().unwrap());
-    let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo);
+    let topmost = cx.original_span_in_file();
+    let loc = cx.codemap().lookup_char_pos(topmost.lo);
     let filename = token::intern_and_get_ident(loc.file.name.as_slice());
-    base::MacExpr::new(cx.expr_str(topmost.call_site, filename))
+    base::MacExpr::new(cx.expr_str(topmost, filename))
 }
 
 pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
@@ -162,32 +160,6 @@ pub fn expand_include_bin(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
     }
 }
 
-// recur along an ExpnInfo chain to find the original expression
-fn topmost_expn_info(expn_info: Gc<codemap::ExpnInfo>) -> Gc<codemap::ExpnInfo> {
-    match *expn_info {
-        ExpnInfo { call_site: ref call_site, .. } => {
-            match call_site.expn_info {
-                Some(next_expn_info) => {
-                    match *next_expn_info {
-                        ExpnInfo {
-                            callee: NameAndSpan { name: ref name, .. },
-                            ..
-                        } => {
-                            // Don't recurse into file using "include!"
-                            if "include" == name.as_slice() {
-                                expn_info
-                            } else {
-                                topmost_expn_info(next_expn_info)
-                            }
-                        }
-                    }
-                },
-                None => expn_info
-            }
-        }
-    }
-}
-
 // resolve a file-system path to an absolute file-system path (if it
 // isn't already)
 fn res_rel_file(cx: &mut ExtCtxt, sp: codemap::Span, arg: &Path) -> Path {
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 3beba5bcda4..7ebb11c148b 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -657,16 +657,26 @@ pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> {
     })
 }
 
-pub fn noop_fold_ty_param_bound<T: Folder>(tpb: TyParamBound, fld: &mut T)
-                                           -> TyParamBound {
+pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T)
+                                   -> TyParamBound
+                                   where T: Folder {
     match tpb {
         TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_trait_ref(ty)),
         RegionTyParamBound(lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)),
-        UnboxedFnTyParamBound(UnboxedFnTy {decl, kind}) => {
-            UnboxedFnTyParamBound(UnboxedFnTy {
-                decl: fld.fold_fn_decl(decl),
-                kind: kind,
-            })
+        UnboxedFnTyParamBound(bound) => {
+            match *bound {
+                UnboxedFnBound {
+                    ref path,
+                    ref decl,
+                    ref_id
+                } => {
+                    UnboxedFnTyParamBound(P(UnboxedFnBound {
+                        path: fld.fold_path(path.clone()),
+                        decl: fld.fold_fn_decl(decl.clone()),
+                        ref_id: fld.new_id(ref_id),
+                    }))
+                }
+            }
         }
     }
 }
@@ -1242,6 +1252,12 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
             ExprIndex(el, er) => {
                 ExprIndex(folder.fold_expr(el), folder.fold_expr(er))
             }
+            ExprSlice(e, e1, e2, m) => {
+                ExprSlice(folder.fold_expr(e),
+                          e1.map(|x| folder.fold_expr(x)),
+                          e2.map(|x| folder.fold_expr(x)),
+                          m)
+            }
             ExprPath(pth) => ExprPath(folder.fold_path(pth)),
             ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))),
             ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))),
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 457d77efb70..153b3cc90d6 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -23,7 +23,7 @@
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/master/")]
 
-#![feature(macro_rules, globs, managed_boxes, default_type_params, phase)]
+#![feature(macro_rules, globs, default_type_params, phase)]
 #![feature(quote, struct_variant, unsafe_destructor, import_shadowing)]
 #![allow(deprecated)]
 
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index da43f08a4e5..68ddd17dd01 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -1406,7 +1406,7 @@ fn ident_continue(c: Option<char>) -> bool {
 mod test {
     use super::*;
 
-    use codemap::{BytePos, CodeMap, Span};
+    use codemap::{BytePos, CodeMap, Span, NO_EXPANSION};
     use diagnostic;
     use parse::token;
     use parse::token::{str_to_ident};
@@ -1436,7 +1436,7 @@ mod test {
         let tok1 = string_reader.next_token();
         let tok2 = TokenAndSpan{
             tok:token::IDENT(id, false),
-            sp:Span {lo:BytePos(21),hi:BytePos(23),expn_info: None}};
+            sp:Span {lo:BytePos(21),hi:BytePos(23),expn_id: NO_EXPANSION}};
         assert_eq!(tok1,tok2);
         assert_eq!(string_reader.next_token().tok, token::WS);
         // the 'main' id is already read:
@@ -1445,7 +1445,7 @@ mod test {
         let tok3 = string_reader.next_token();
         let tok4 = TokenAndSpan{
             tok:token::IDENT(str_to_ident("main"), false),
-            sp:Span {lo:BytePos(24),hi:BytePos(28),expn_info: None}};
+            sp:Span {lo:BytePos(24),hi:BytePos(28),expn_id: NO_EXPANSION}};
         assert_eq!(tok3,tok4);
         // the lparen is already read:
         assert_eq!(string_reader.last_pos.clone(), BytePos(29))
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index d73cb211694..66ecdbfca02 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -721,7 +721,7 @@ pub fn integer_lit(s: &str, sd: &SpanHandler, sp: Span) -> ast::Lit_ {
 mod test {
     use super::*;
     use serialize::json;
-    use codemap::{Span, BytePos, Spanned};
+    use codemap::{Span, BytePos, Spanned, NO_EXPANSION};
     use owned_slice::OwnedSlice;
     use ast;
     use abi;
@@ -736,7 +736,7 @@ mod test {
 
     // produce a codemap::span
     fn sp(a: u32, b: u32) -> Span {
-        Span{lo:BytePos(a),hi:BytePos(b),expn_info:None}
+        Span {lo: BytePos(a), hi: BytePos(b), expn_id: NO_EXPANSION}
     }
 
     #[test] fn path_exprs_1() {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index ff4fd41fbd7..069d30cbd83 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -23,7 +23,7 @@ use ast::{DeclLocal, DefaultBlock, UnDeref, BiDiv, EMPTY_CTXT, EnumDef, Explicit
 use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain};
 use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox};
 use ast::{ExprBreak, ExprCall, ExprCast};
-use ast::{ExprField, ExprTupField, ExprFnBlock, ExprIf, ExprIndex};
+use ast::{ExprField, ExprTupField, ExprFnBlock, ExprIf, ExprIndex, ExprSlice};
 use ast::{ExprLit, ExprLoop, ExprMac};
 use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc};
 use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary, ExprUnboxedFn};
@@ -55,7 +55,8 @@ use ast::{TyTypeof, TyInfer, TypeMethod};
 use ast::{TyNil, TyParam, TyParamBound, TyParen, TyPath, TyPtr, TyQPath};
 use ast::{TyRptr, TyTup, TyU32, TyUnboxedFn, TyUniq, TyVec, UnUniq};
 use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind};
-use ast::{UnboxedFnTy, UnboxedFnTyParamBound, UnnamedField, UnsafeBlock};
+use ast::{UnboxedFnBound, UnboxedFnTy, UnboxedFnTyParamBound};
+use ast::{UnnamedField, UnsafeBlock};
 use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
 use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
 use ast::{Visibility, WhereClause, WherePredicate};
@@ -1986,6 +1987,14 @@ impl<'a> Parser<'a> {
         ExprIndex(expr, idx)
     }
 
+    pub fn mk_slice(&mut self, expr: P<Expr>,
+                    start: Option<P<Expr>>,
+                    end: Option<P<Expr>>,
+                    mutbl: Mutability)
+                    -> ast::Expr_ {
+        ExprSlice(expr, start, end, mutbl)
+    }
+
     pub fn mk_field(&mut self, expr: P<Expr>, ident: ast::SpannedIdent,
                     tys: Vec<P<Ty>>) -> ast::Expr_ {
         ExprField(expr, ident, tys)
@@ -2400,13 +2409,87 @@ impl<'a> Parser<'a> {
               }
 
               // expr[...]
+              // Could be either an index expression or a slicing expression.
+              // Any slicing non-terminal can have a mutable version with `mut`
+              // after the opening square bracket.
               token::LBRACKET => {
                 self.bump();
-                let ix = self.parse_expr();
-                hi = self.span.hi;
-                self.commit_expr_expecting(&*ix, token::RBRACKET);
-                let index = self.mk_index(e, ix);
-                e = self.mk_expr(lo, hi, index)
+                let mutbl = if self.eat_keyword(keywords::Mut) {
+                    MutMutable
+                } else {
+                    MutImmutable
+                };
+                match self.token {
+                    // e[]
+                    token::RBRACKET => {
+                        self.bump();
+                        hi = self.span.hi;
+                        let slice = self.mk_slice(e, None, None, mutbl);
+                        e = self.mk_expr(lo, hi, slice)
+                    }
+                    // e[..e]
+                    token::DOTDOT => {
+                        self.bump();
+                        match self.token {
+                            // e[..]
+                            token::RBRACKET => {
+                                self.bump();
+                                hi = self.span.hi;
+                                let slice = self.mk_slice(e, None, None, mutbl);
+                                e = self.mk_expr(lo, hi, slice);
+
+                                self.span_err(e.span, "incorrect slicing expression: `[..]`");
+                                self.span_note(e.span,
+                                    "use `expr[]` to construct a slice of the whole of expr");
+                            }
+                            // e[..e]
+                            _ => {
+                                hi = self.span.hi;
+                                let e2 = self.parse_expr();
+                                self.commit_expr_expecting(&*e2, token::RBRACKET);
+                                let slice = self.mk_slice(e, None, Some(e2), mutbl);
+                                e = self.mk_expr(lo, hi, slice)
+                            }
+                        }
+                    }
+                    // e[e] | e[e..] | e[e..e]
+                    _ => {
+                        let ix = self.parse_expr();
+                        match self.token {
+                            // e[e..] | e[e..e]
+                            token::DOTDOT => {
+                                self.bump();
+                                let e2 = match self.token {
+                                    // e[e..]
+                                    token::RBRACKET => {
+                                        self.bump();
+                                        None
+                                    }
+                                    // e[e..e]
+                                    _ => {
+                                        let e2 = self.parse_expr();
+                                        self.commit_expr_expecting(&*e2, token::RBRACKET);
+                                        Some(e2)
+                                    }
+                                };
+                                hi = self.span.hi;
+                                let slice = self.mk_slice(e, Some(ix), e2, mutbl);
+                                e = self.mk_expr(lo, hi, slice)
+                            }
+                            // e[e]
+                            _ => {
+                                if mutbl == ast::MutMutable {
+                                    self.span_err(e.span,
+                                                  "`mut` keyword is invalid in index expressions");
+                                }
+                                hi = self.span.hi;
+                                self.commit_expr_expecting(&*ix, token::RBRACKET);
+                                let index = self.mk_index(e, ix);
+                                e = self.mk_expr(lo, hi, index)
+                            }
+                        }
+                    }
+                }
               }
 
               _ => return e
@@ -3153,7 +3236,8 @@ impl<'a> Parser<'a> {
             // These expressions are limited to literals (possibly
             // preceded by unary-minus) or identifiers.
             let val = self.parse_literal_maybe_minus();
-            if self.token == token::DOTDOT &&
+            // FIXME(#17295) remove the DOTDOT option.
+            if (self.token == token::DOTDOTDOT || self.token == token::DOTDOT) &&
                     self.look_ahead(1, |t| {
                         *t != token::COMMA && *t != token::RBRACKET
                     }) {
@@ -3198,12 +3282,16 @@ impl<'a> Parser<'a> {
                 }
             });
 
-            if self.look_ahead(1, |t| *t == token::DOTDOT) &&
+            // FIXME(#17295) remove the DOTDOT option.
+            if self.look_ahead(1, |t| *t == token::DOTDOTDOT || *t == token::DOTDOT) &&
                     self.look_ahead(2, |t| {
                         *t != token::COMMA && *t != token::RBRACKET
                     }) {
                 let start = self.parse_expr_res(RestrictionNoBarOp);
-                self.eat(&token::DOTDOT);
+                // FIXME(#17295) remove the DOTDOT option (self.eat(&token::DOTDOTDOT)).
+                if self.token == token::DOTDOTDOT || self.token == token::DOTDOT {
+                    self.bump();
+                }
                 let end = self.parse_expr_res(RestrictionNoBarOp);
                 pat = PatRange(start, end);
             } else if is_plain_ident(&self.token) && !can_be_enum_or_struct {
@@ -3590,7 +3678,7 @@ impl<'a> Parser<'a> {
                                     let span_with_semi = Span {
                                         lo: span.lo,
                                         hi: self.last_span.hi,
-                                        expn_info: span.expn_info,
+                                        expn_id: span.expn_id,
                                     };
                                     stmts.push(P(Spanned {
                                         node: StmtSemi(e, stmt_id),
@@ -3666,39 +3754,6 @@ impl<'a> Parser<'a> {
         })
     }
 
-    fn parse_unboxed_function_type(&mut self) -> UnboxedFnTy {
-        let (optional_unboxed_closure_kind, inputs) =
-            if self.eat(&token::OROR) {
-                (None, Vec::new())
-            } else {
-                self.expect_or();
-
-                let optional_unboxed_closure_kind =
-                    self.parse_optional_unboxed_closure_kind();
-
-                let inputs = self.parse_seq_to_before_or(&token::COMMA,
-                                                         |p| {
-                    p.parse_arg_general(false)
-                });
-                self.expect_or();
-                (optional_unboxed_closure_kind, inputs)
-            };
-
-        let (return_style, output) = self.parse_ret_ty();
-        UnboxedFnTy {
-            decl: P(FnDecl {
-                inputs: inputs,
-                output: output,
-                cf: return_style,
-                variadic: false,
-            }),
-            kind: match optional_unboxed_closure_kind {
-                Some(kind) => kind,
-                None => FnMutUnboxedClosureKind,
-            },
-        }
-    }
-
     // Parses a sequence of bounds if a `:` is found,
     // otherwise returns empty list.
     fn parse_colon_then_ty_param_bounds(&mut self)
@@ -3730,13 +3785,31 @@ impl<'a> Parser<'a> {
                     self.bump();
                 }
                 token::MOD_SEP | token::IDENT(..) => {
-                    let tref = self.parse_trait_ref();
-                    result.push(TraitTyParamBound(tref));
-                }
-                token::BINOP(token::OR) | token::OROR => {
-                    let unboxed_function_type =
-                        self.parse_unboxed_function_type();
-                    result.push(UnboxedFnTyParamBound(unboxed_function_type));
+                    let path =
+                        self.parse_path(LifetimeAndTypesWithoutColons).path;
+                    if self.token == token::LPAREN {
+                        self.bump();
+                        let inputs = self.parse_seq_to_end(
+                            &token::RPAREN,
+                            seq_sep_trailing_allowed(token::COMMA),
+                            |p| p.parse_arg_general(false));
+                        let (return_style, output) = self.parse_ret_ty();
+                        result.push(UnboxedFnTyParamBound(P(UnboxedFnBound {
+                            path: path,
+                            decl: P(FnDecl {
+                                inputs: inputs,
+                                output: output,
+                                cf: return_style,
+                                variadic: false,
+                            }),
+                            ref_id: ast::DUMMY_NODE_ID,
+                        })));
+                    } else {
+                        result.push(TraitTyParamBound(ast::TraitRef {
+                            path: path,
+                            ref_id: ast::DUMMY_NODE_ID,
+                        }))
+                    }
                 }
                 _ => break,
             }
@@ -4423,14 +4496,6 @@ impl<'a> Parser<'a> {
          Some(attrs))
     }
 
-    /// Parse a::B<String,int>
-    fn parse_trait_ref(&mut self) -> TraitRef {
-        ast::TraitRef {
-            path: self.parse_path(LifetimeAndTypesWithoutColons).path,
-            ref_id: ast::DUMMY_NODE_ID,
-        }
-    }
-
     /// Parse struct Foo { ... }
     fn parse_item_struct(&mut self, is_virtual: bool) -> ItemInfo {
         let class_name = self.parse_ident();
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 5a0aeece272..f71190da430 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -431,9 +431,11 @@ macro_rules! declare_special_idents_and_keywords {(
 // If the special idents get renumbered, remember to modify these two as appropriate
 pub static SELF_KEYWORD_NAME: Name = Name(SELF_KEYWORD_NAME_NUM);
 static STATIC_KEYWORD_NAME: Name = Name(STATIC_KEYWORD_NAME_NUM);
+static SUPER_KEYWORD_NAME: Name = Name(SUPER_KEYWORD_NAME_NUM);
 
 pub static SELF_KEYWORD_NAME_NUM: u32 = 1;
 static STATIC_KEYWORD_NAME_NUM: u32 = 2;
+static SUPER_KEYWORD_NAME_NUM: u32 = 3;
 
 // NB: leaving holes in the ident table is bad! a different ident will get
 // interned with the id from the hole, but it will be between the min and max
@@ -443,52 +445,53 @@ declare_special_idents_and_keywords! {
     pub mod special_idents {
         // These ones are statics
         (0,                          invalid,                "");
-        (super::SELF_KEYWORD_NAME_NUM,   self_,                  "self");
-        (super::STATIC_KEYWORD_NAME_NUM, statik,                 "static");
-        (3,                          static_lifetime,        "'static");
+        (super::SELF_KEYWORD_NAME_NUM,   self_,              "self");
+        (super::STATIC_KEYWORD_NAME_NUM, statik,             "static");
+        (super::SUPER_KEYWORD_NAME_NUM, super_,              "super");
+        (4,                          static_lifetime,        "'static");
 
         // for matcher NTs
-        (4,                          tt,                     "tt");
-        (5,                          matchers,               "matchers");
+        (5,                          tt,                     "tt");
+        (6,                          matchers,               "matchers");
 
         // outside of libsyntax
-        (6,                          clownshoe_abi,          "__rust_abi");
-        (7,                          opaque,                 "<opaque>");
-        (8,                          unnamed_field,          "<unnamed_field>");
-        (9,                          type_self,              "Self");
-        (10,                         prelude_import,         "prelude_import");
+        (7,                          clownshoe_abi,          "__rust_abi");
+        (8,                          opaque,                 "<opaque>");
+        (9,                          unnamed_field,          "<unnamed_field>");
+        (10,                         type_self,              "Self");
+        (11,                         prelude_import,         "prelude_import");
     }
 
     pub mod keywords {
         // These ones are variants of the Keyword enum
 
         'strict:
-        (11,                         As,         "as");
-        (12,                         Break,      "break");
-        (13,                         Crate,      "crate");
-        (14,                         Else,       "else");
-        (15,                         Enum,       "enum");
-        (16,                         Extern,     "extern");
-        (17,                         False,      "false");
-        (18,                         Fn,         "fn");
-        (19,                         For,        "for");
-        (20,                         If,         "if");
-        (21,                         Impl,       "impl");
-        (22,                         In,         "in");
-        (23,                         Let,        "let");
-        (24,                         Loop,       "loop");
-        (25,                         Match,      "match");
-        (26,                         Mod,        "mod");
-        (27,                         Mut,        "mut");
-        (28,                         Once,       "once");
-        (29,                         Pub,        "pub");
-        (30,                         Ref,        "ref");
-        (31,                         Return,     "return");
+        (12,                         As,         "as");
+        (13,                         Break,      "break");
+        (14,                         Crate,      "crate");
+        (15,                         Else,       "else");
+        (16,                         Enum,       "enum");
+        (17,                         Extern,     "extern");
+        (18,                         False,      "false");
+        (19,                         Fn,         "fn");
+        (20,                         For,        "for");
+        (21,                         If,         "if");
+        (22,                         Impl,       "impl");
+        (23,                         In,         "in");
+        (24,                         Let,        "let");
+        (25,                         Loop,       "loop");
+        (26,                         Match,      "match");
+        (27,                         Mod,        "mod");
+        (28,                         Mut,        "mut");
+        (29,                         Once,       "once");
+        (30,                         Pub,        "pub");
+        (31,                         Ref,        "ref");
+        (32,                         Return,     "return");
         // Static and Self are also special idents (prefill de-dupes)
-        (super::STATIC_KEYWORD_NAME_NUM, Static,     "static");
-        (super::SELF_KEYWORD_NAME_NUM,   Self,       "self");
-        (32,                         Struct,     "struct");
-        (33,                         Super,      "super");
+        (super::STATIC_KEYWORD_NAME_NUM, Static, "static");
+        (super::SELF_KEYWORD_NAME_NUM,   Self,   "self");
+        (33,                         Struct,     "struct");
+        (super::SUPER_KEYWORD_NAME_NUM, Super,   "super");
         (34,                         True,       "true");
         (35,                         Trait,      "trait");
         (36,                         Type,       "type");
@@ -713,6 +716,7 @@ pub fn is_any_keyword(tok: &Token) -> bool {
 
                n == SELF_KEYWORD_NAME
             || n == STATIC_KEYWORD_NAME
+            || n == SUPER_KEYWORD_NAME
             || STRICT_KEYWORD_START <= n
             && n <= RESERVED_KEYWORD_FINAL
         },
@@ -727,9 +731,18 @@ pub fn is_strict_keyword(tok: &Token) -> bool {
 
                n == SELF_KEYWORD_NAME
             || n == STATIC_KEYWORD_NAME
+            || n == SUPER_KEYWORD_NAME
             || STRICT_KEYWORD_START <= n
             && n <= STRICT_KEYWORD_FINAL
         },
+        token::IDENT(sid, true) => {
+            let n = sid.name;
+
+               n != SELF_KEYWORD_NAME
+            && n != SUPER_KEYWORD_NAME
+            && STRICT_KEYWORD_START <= n
+            && n <= STRICT_KEYWORD_FINAL
+        }
         _ => false,
     }
 }
diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs
index 70da4e11961..f1fdc71b9c6 100644
--- a/src/libsyntax/print/pp.rs
+++ b/src/libsyntax/print/pp.rs
@@ -60,7 +60,7 @@
 //! avoid combining it with other lines and making matters even worse.
 
 use std::io;
-use std::string::String;
+use std::string;
 
 #[deriving(Clone, PartialEq)]
 pub enum Breaks {
@@ -82,7 +82,7 @@ pub struct BeginToken {
 
 #[deriving(Clone)]
 pub enum Token {
-    String(String, int),
+    String(string::String, int),
     Break(BreakToken),
     Begin(BeginToken),
     End,
@@ -107,7 +107,7 @@ impl Token {
     }
 }
 
-pub fn tok_str(t: Token) -> String {
+pub fn tok_str(t: Token) -> string::String {
     match t {
         String(s, len) => return format!("STR({},{})", s, len),
         Break(_) => return "BREAK".to_string(),
@@ -122,12 +122,12 @@ pub fn buf_str(toks: Vec<Token>,
                left: uint,
                right: uint,
                lim: uint)
-               -> String {
+               -> string::String {
     let n = toks.len();
     assert_eq!(n, szs.len());
     let mut i = left;
     let mut l = lim;
-    let mut s = String::from_str("[");
+    let mut s = string::String::from_str("[");
     while i != right && l != 0u {
         l -= 1u;
         if i != left {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 0ae5303641b..473179a037a 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1651,6 +1651,28 @@ impl<'a> State<'a> {
                 try!(self.print_expr(&**index));
                 try!(word(&mut self.s, "]"));
             }
+            ast::ExprSlice(ref e, ref start, ref end, ref mutbl) => {
+                try!(self.print_expr(&**e));
+                try!(word(&mut self.s, "["));
+                if mutbl == &ast::MutMutable {
+                    try!(word(&mut self.s, "mut"));
+                    if start.is_some() || end.is_some() {
+                        try!(space(&mut self.s));
+                    }
+                }
+                match start {
+                    &Some(ref e) => try!(self.print_expr(&**e)),
+                    _ => {}
+                }
+                if start.is_some() || end.is_some() {
+                    try!(word(&mut self.s, ".."));
+                }
+                match end {
+                    &Some(ref e) => try!(self.print_expr(&**e)),
+                    _ => {}
+                }
+                try!(word(&mut self.s, "]"));
+            }
             ast::ExprPath(ref path) => try!(self.print_path(path, true)),
             ast::ExprBreak(opt_ident) => {
                 try!(word(&mut self.s, "break"));
@@ -1944,7 +1966,7 @@ impl<'a> State<'a> {
             ast::PatRange(ref begin, ref end) => {
                 try!(self.print_expr(&**begin));
                 try!(space(&mut self.s));
-                try!(word(&mut self.s, ".."));
+                try!(word(&mut self.s, "..."));
                 try!(self.print_expr(&**end));
             }
             ast::PatVec(ref before, ref slice, ref after) => {
@@ -2190,16 +2212,13 @@ impl<'a> State<'a> {
                         self.print_lifetime(lt)
                     }
                     UnboxedFnTyParamBound(ref unboxed_function_type) => {
-                        self.print_ty_fn(None,
-                                         None,
-                                         ast::NormalFn,
-                                         ast::Many,
-                                         &*unboxed_function_type.decl,
-                                         None,
-                                         &OwnedSlice::empty(),
-                                         None,
-                                         None,
-                                         Some(unboxed_function_type.kind))
+                        try!(self.print_path(&unboxed_function_type.path,
+                                             false));
+                        try!(self.popen());
+                        try!(self.print_fn_args(&*unboxed_function_type.decl,
+                                                None));
+                        try!(self.pclose());
+                        self.print_fn_output(&*unboxed_function_type.decl)
                     }
                 })
             }
@@ -2430,6 +2449,23 @@ impl<'a> State<'a> {
         self.end()
     }
 
+    pub fn print_fn_output(&mut self, decl: &ast::FnDecl) -> IoResult<()> {
+        match decl.output.node {
+            ast::TyNil => Ok(()),
+            _ => {
+                try!(self.space_if_not_bol());
+                try!(self.ibox(indent_unit));
+                try!(self.word_space("->"));
+                if decl.cf == ast::NoReturn {
+                    try!(self.word_nbsp("!"));
+                } else {
+                    try!(self.print_type(&*decl.output));
+                }
+                self.end()
+            }
+        }
+    }
+
     pub fn print_ty_fn(&mut self,
                        opt_abi: Option<abi::Abi>,
                        opt_sigil: Option<char>,
@@ -2510,20 +2546,7 @@ impl<'a> State<'a> {
 
         try!(self.maybe_print_comment(decl.output.span.lo));
 
-        match decl.output.node {
-            ast::TyNil => {}
-            _ => {
-                try!(self.space_if_not_bol());
-                try!(self.ibox(indent_unit));
-                try!(self.word_space("->"));
-                if decl.cf == ast::NoReturn {
-                    try!(self.word_nbsp("!"));
-                } else {
-                    try!(self.print_type(&*decl.output));
-                }
-                try!(self.end());
-            }
-        }
+        try!(self.print_fn_output(decl));
 
         match generics {
             Some(generics) => try!(self.print_where_clause(generics)),
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index d425c60f4c9..32084856817 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -785,6 +785,11 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             visitor.visit_expr(&**main_expression);
             visitor.visit_expr(&**index_expression)
         }
+        ExprSlice(ref main_expression, ref start, ref end, _) => {
+            visitor.visit_expr(&**main_expression);
+            walk_expr_opt(visitor, start);
+            walk_expr_opt(visitor, end)
+        }
         ExprPath(ref path) => {
             visitor.visit_path(path, expression.id)
         }