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