Bug 1319199 - Re-vendor webrender dependencies. r=autogenerated
authorKartikaya Gupta <kgupta@mozilla.com>
Tue, 22 Nov 2016 09:53:34 -0500
changeset 388521 e28254753756ce93c76dedf34e00216cfefa8511
parent 388520 80c13604db5344312b03fc587f0bb8fba68698b3
child 388522 1ff17ad606b1dc2cf1135337b52acd80579889b2
push id7198
push userjlorenzo@mozilla.com
push dateTue, 18 Apr 2017 12:07:49 +0000
treeherdermozilla-beta@d57aa49c3948 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersautogenerated
bugs1319199
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1319199 - Re-vendor webrender dependencies. r=autogenerated MozReview-Commit-ID: Kjw2iLNL3Xv
third_party/rust/dwrote/.cargo-checksum.json
third_party/rust/dwrote/Cargo.toml
third_party/rust/dwrote/src/font.rs
third_party/rust/dwrote/src/lib.rs
third_party/rust/dwrote/src/types.rs
third_party/rust/post-expansion/.cargo-checksum.json
third_party/rust/post-expansion/.cargo-ok
third_party/rust/post-expansion/Cargo.toml
third_party/rust/post-expansion/src/lib.rs
third_party/rust/serde/.cargo-checksum.json
third_party/rust/serde/Cargo.toml
third_party/rust/serde_codegen/.cargo-checksum.json
third_party/rust/serde_codegen/Cargo.toml
third_party/rust/serde_codegen/src/lib.rs
third_party/rust/serde_codegen_internals/.cargo-checksum.json
third_party/rust/serde_codegen_internals/Cargo.toml
third_party/rust/serde_codegen_internals/src/attr.rs
third_party/rust/syn/.cargo-checksum.json
third_party/rust/syn/Cargo.toml
third_party/rust/syn/src/aster/lifetime.rs
third_party/rust/syn/src/aster/qpath.rs
third_party/rust/syn/src/aster/ty_param.rs
third_party/rust/syn/src/attr.rs
third_party/rust/syn/src/constant.rs
third_party/rust/syn/src/data.rs
third_party/rust/syn/src/escape.rs
third_party/rust/syn/src/expr.rs
third_party/rust/syn/src/generics.rs
third_party/rust/syn/src/helper.rs
third_party/rust/syn/src/ident.rs
third_party/rust/syn/src/item.rs
third_party/rust/syn/src/krate.rs
third_party/rust/syn/src/lib.rs
third_party/rust/syn/src/lit.rs
third_party/rust/syn/src/mac.rs
third_party/rust/syn/src/macro_input.rs
third_party/rust/syn/src/nom.rs
third_party/rust/syn/src/registry.rs
third_party/rust/syn/src/space.rs
third_party/rust/syn/src/ty.rs
third_party/rust/syn/src/visit.rs
third_party/rust/syntex/.cargo-checksum.json
third_party/rust/syntex/Cargo.toml
third_party/rust/syntex/src/resolver.rs
third_party/rust/syntex_errors/.cargo-checksum.json
third_party/rust/syntex_errors/Cargo.toml
third_party/rust/syntex_errors/src/diagnostic.rs
third_party/rust/syntex_errors/src/diagnostic_builder.rs
third_party/rust/syntex_errors/src/lib.rs
third_party/rust/syntex_pos/.cargo-checksum.json
third_party/rust/syntex_pos/Cargo.toml
third_party/rust/syntex_pos/src/lib.rs
third_party/rust/syntex_syntax/.cargo-checksum.json
third_party/rust/syntex_syntax/Cargo.toml
third_party/rust/syntex_syntax/src/ast.rs
third_party/rust/syntex_syntax/src/attr.rs
third_party/rust/syntex_syntax/src/config.rs
third_party/rust/syntex_syntax/src/ext/base.rs
third_party/rust/syntex_syntax/src/ext/build.rs
third_party/rust/syntex_syntax/src/ext/expand.rs
third_party/rust/syntex_syntax/src/ext/quote.rs
third_party/rust/syntex_syntax/src/ext/source_util.rs
third_party/rust/syntex_syntax/src/ext/tt/macro_parser.rs
third_party/rust/syntex_syntax/src/ext/tt/macro_rules.rs
third_party/rust/syntex_syntax/src/ext/tt/transcribe.rs
third_party/rust/syntex_syntax/src/feature_gate.rs
third_party/rust/syntex_syntax/src/fold.rs
third_party/rust/syntex_syntax/src/parse/attr.rs
third_party/rust/syntex_syntax/src/parse/lexer/mod.rs
third_party/rust/syntex_syntax/src/parse/parser.rs
third_party/rust/syntex_syntax/src/parse/token.rs
third_party/rust/syntex_syntax/src/print/pprust.rs
third_party/rust/syntex_syntax/src/test.rs
third_party/rust/syntex_syntax/src/tokenstream.rs
third_party/rust/syntex_syntax/src/util/node_count.rs
third_party/rust/syntex_syntax/src/util/small_vector.rs
third_party/rust/syntex_syntax/src/visit.rs
toolkit/library/gtest/rust/Cargo.lock
toolkit/library/rust/Cargo.lock
--- a/third_party/rust/dwrote/.cargo-checksum.json
+++ b/third_party/rust/dwrote/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"172610b244a5ee8a8e2f1f045058b8abf9291d84bb76bf8779d2fd420419c2d6","Cargo.toml":"8e69669ba7b48400a9f12c8e2ee3c9d6e18490071e7ecb84f9207b0f3f842463","README.md":"d69d75705e2582721cbfb2d3b4b2af052c71679057a0b2ac53a22c03f1755bba","build.rs":"fea382a72243440bcfc334229684fecd2e0021f740dd95d2e2df267744cce402","src/bitmap_render_target.rs":"ff1c34aad7e3930c0a1f5778f01056a2bc7a41c8edce892b5672d92cdba78c89","src/comptr.rs":"fdea6d9d860fc6820af26a57177a1c70a319dde86957249b51cf86f11feef1a2","src/font.rs":"b7e48990e2be1c99680673e10334f3e8563f575b4901204a6ec902aa5be12be6","src/font_collection.rs":"969fa3abf141dc3504774886f4783fda4a74cd5a198c643f8a77fc1af4e75258","src/font_face.rs":"cfce3df6c28e070f6f37bc5ca61587d6d8cd8092e716327a625e1eb72a69446b","src/font_family.rs":"403da9f8f9903cbe7f9f79636497b273f9885e200f53af99f9d4e483f11d6889","src/font_file.rs":"36313b4c6f1e29797f2da79e9ade2a5d15bcd8867707fc9746cdb98da973a550","src/gdi_interop.rs":"627a39c72d162308826ac1090972179d39f9962c8e7f29925983744a96862d84","src/helpers.rs":"5d6f164468234ca8806dc1cea117b42dbfae80cc4c9ae965cb0556efdb364682","src/lib.rs":"61b57da3a1d590a69d59dad6873c9f39e50930bf8757ce8b6e51a6b9e9bd75e4","src/rendering_params.rs":"9b132aef922f1ff3df06a1b126eccb6a397e81a04625afdb7b72dc2f968c92cd","src/test.rs":"3bc96cc2aeef45eb0a8f12439147a69d0d001af1d8800528e829aed874ea79be","src/types.rs":"ef82336fbb30d272b201f22b23719399089301ea34c60f63858b53552d09ac61"},"package":"c85f0fecf7e4d1f47b25a84adbdb5bfa9662e51c0d0fb59935a0147ace261216"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"172610b244a5ee8a8e2f1f045058b8abf9291d84bb76bf8779d2fd420419c2d6","Cargo.toml":"723df885daa9cb28a857226c9ade9b7f498558c3b9d372e42e5f692b37ac6c2a","README.md":"d69d75705e2582721cbfb2d3b4b2af052c71679057a0b2ac53a22c03f1755bba","build.rs":"fea382a72243440bcfc334229684fecd2e0021f740dd95d2e2df267744cce402","src/bitmap_render_target.rs":"ff1c34aad7e3930c0a1f5778f01056a2bc7a41c8edce892b5672d92cdba78c89","src/comptr.rs":"fdea6d9d860fc6820af26a57177a1c70a319dde86957249b51cf86f11feef1a2","src/font.rs":"e792eed304dfcc6ab99d16076d48b5ec941bd18113e506970898a58db4df5d5b","src/font_collection.rs":"969fa3abf141dc3504774886f4783fda4a74cd5a198c643f8a77fc1af4e75258","src/font_face.rs":"cfce3df6c28e070f6f37bc5ca61587d6d8cd8092e716327a625e1eb72a69446b","src/font_family.rs":"403da9f8f9903cbe7f9f79636497b273f9885e200f53af99f9d4e483f11d6889","src/font_file.rs":"36313b4c6f1e29797f2da79e9ade2a5d15bcd8867707fc9746cdb98da973a550","src/gdi_interop.rs":"627a39c72d162308826ac1090972179d39f9962c8e7f29925983744a96862d84","src/helpers.rs":"5d6f164468234ca8806dc1cea117b42dbfae80cc4c9ae965cb0556efdb364682","src/lib.rs":"ef2f947cba9943cbf657e687417309f47aacd0c2a19bdca4c85ecd8ea9ef3547","src/rendering_params.rs":"9b132aef922f1ff3df06a1b126eccb6a397e81a04625afdb7b72dc2f968c92cd","src/test.rs":"3bc96cc2aeef45eb0a8f12439147a69d0d001af1d8800528e829aed874ea79be","src/types.rs":"53e81cee77c3011b6a82088adf890bd508c779c2ed6d6b0c92502e08d3c21ff0"},"package":"caec6baccdd686cb9b7aac3775bb08bab9f732584d74f3a6c0071be60d250deb"}
\ No newline at end of file
--- a/third_party/rust/dwrote/Cargo.toml
+++ b/third_party/rust/dwrote/Cargo.toml
@@ -1,14 +1,14 @@
 [package]
 name = "dwrote"
 description = "Lightweight binding to DirectWrite."
 repository = "https://github.com/vvuk/dwrote-rs"
 license = "MPL-2.0"
-version = "0.1.1"
+version = "0.1.3"
 authors = ["Vladimir Vukicevic <vladimir@pobox.com>"]
 build = "build.rs"
 
 [lib]
 name = "dwrote"
 
 [features]
 default = ["codegen"]
--- a/third_party/rust/dwrote/src/font.rs
+++ b/third_party/rust/dwrote/src/font.rs
@@ -33,29 +33,29 @@ impl Font {
             stretch: self.stretch(),
             style: self.style(),
             weight: self.weight(),
         }
     }
 
     pub fn stretch(&self) -> FontStretch {
         unsafe {
-            mem::transmute((*self.native.get()).GetStretch().0)
+            mem::transmute::<u32, FontStretch>((*self.native.get()).GetStretch().0)
         }
     }
 
     pub fn style(&self) -> FontStyle {
         unsafe {
-            mem::transmute((*self.native.get()).GetStyle().0)
+            mem::transmute::<u32, FontStyle>((*self.native.get()).GetStyle().0)
         }
     }
 
     pub fn weight(&self) -> FontWeight {
         unsafe {
-            mem::transmute((*self.native.get()).GetWeight().0)
+            mem::transmute::<u32, FontWeight>((*self.native.get()).GetWeight().0)
         }
     }
 
     pub fn family_name(&self) -> String {
         unsafe {
             let mut family: ComPtr<winapi::IDWriteFontFamily> = ComPtr::new();
             let hr = (*self.native.get()).GetFontFamily(family.getter_addrefs());
             assert!(hr == 0);
--- a/third_party/rust/dwrote/src/lib.rs
+++ b/third_party/rust/dwrote/src/lib.rs
@@ -29,16 +29,17 @@ use winapi::IDWriteFactory;
 use std::ffi::CString;
 
 use comptr::ComPtr;
 use winapi::S_OK;
 
 mod comptr;
 mod helpers;
 use helpers::ToWide;
+use std::os::raw::c_void;
 
 #[cfg(test)]
 mod test;
 
 
 // We still use the DWrite structs for things like metrics; re-export them
 // here
 pub use winapi::DWRITE_FONT_METRICS as FontMetrics;
@@ -65,18 +66,18 @@ lazy_static! {
 
             let dwrite_dll = kernel32::LoadLibraryW("dwrite.dll".to_wide_null().as_ptr());
             assert!(!dwrite_dll.is_null());
             let create_factory_name = CString::new("DWriteCreateFactory").unwrap();
             let dwrite_create_factory_ptr =
                 kernel32::GetProcAddress(dwrite_dll, create_factory_name.as_ptr() as winapi::LPCSTR);
             assert!(!dwrite_create_factory_ptr.is_null());
 
-            println!("create_factory_ptr: {:?}", dwrite_create_factory_ptr);
-            let dwrite_create_factory: DWriteCreateFactoryType = mem::transmute(dwrite_create_factory_ptr);
+            let dwrite_create_factory =
+                mem::transmute::<*const c_void, DWriteCreateFactoryType>(dwrite_create_factory_ptr);
 
             let mut factory: ComPtr<IDWriteFactory> = ComPtr::new();
             let hr = dwrite_create_factory(
                 DWRITE_FACTORY_TYPE_SHARED,
                 &UuidOfIDWriteFactory,
                 factory.getter_addrefs());
             assert!(hr == S_OK);
             factory.forget() as usize
--- a/third_party/rust/dwrote/src/types.rs
+++ b/third_party/rust/dwrote/src/types.rs
@@ -18,19 +18,21 @@ pub enum FontWeight {
     SemiBold = 600,
     Bold = 700,
     ExtraBold = 800,
     Black = 900,
     ExtraBlack = 950,
 }
 
 impl FontWeight {
-    fn t(&self) -> winapi::DWRITE_FONT_WEIGHT { unsafe { mem::transmute(*self) } }
-    pub fn to_u32(&self) -> u32 { unsafe { mem::transmute(*self) } }
-    pub fn from_u32(v: u32) -> FontStretch { unsafe { mem::transmute(v) } }
+    fn t(&self) -> winapi::DWRITE_FONT_WEIGHT {
+        unsafe { mem::transmute::<FontWeight, winapi::DWRITE_FONT_WEIGHT>(*self) }
+    }
+    pub fn to_u32(&self) -> u32 { unsafe { mem::transmute::<FontWeight, u32>(*self) } }
+    pub fn from_u32(v: u32) -> FontWeight { unsafe { mem::transmute::<u32, FontWeight>(v) } }
 }
 
 // mirrors DWRITE_FONT_STRETCH
 #[repr(u32)]
 #[derive(Deserialize, Serialize, PartialEq, Debug, Clone, Copy)]
 pub enum FontStretch {
     Undefined = 0,
     UltraCondensed = 1,
@@ -40,34 +42,38 @@ pub enum FontStretch {
     Normal = 5,
     SemiExpanded = 6,
     Expanded = 7,
     ExtraExpanded = 8,
     UltraExpanded = 9,
 }
 
 impl FontStretch {
-    fn t(&self) -> winapi::DWRITE_FONT_STRETCH { unsafe { mem::transmute(*self) } }
-    pub fn to_u32(&self) -> u32 { unsafe { mem::transmute(*self) } }
-    pub fn from_u32(v: u32) -> FontStretch { unsafe { mem::transmute(v) } }
+    fn t(&self) -> winapi::DWRITE_FONT_STRETCH {
+        unsafe { mem::transmute::<FontStretch, winapi::DWRITE_FONT_STRETCH>(*self) }
+    }
+    pub fn to_u32(&self) -> u32 { unsafe { mem::transmute::<FontStretch, u32>(*self) } }
+    pub fn from_u32(v: u32) -> FontStretch { unsafe { mem::transmute::<u32, FontStretch>(v) } }
 }
 
 // mirrors DWRITE_FONT_STYLE
 #[repr(u32)]
 #[derive(Deserialize, Serialize, PartialEq, Debug, Clone, Copy)]
 pub enum FontStyle {
     Normal = 0,
     Oblique = 1,
     Italic = 2,
 }
 
 impl FontStyle {
-    fn t(&self) -> winapi::DWRITE_FONT_STYLE { unsafe { mem::transmute(*self) } }
-    pub fn to_u32(&self) -> u32 { unsafe { mem::transmute(*self) } }
-    pub fn from_u32(v: u32) -> FontStretch { unsafe { mem::transmute(v) } }
+    fn t(&self) -> winapi::DWRITE_FONT_STYLE {
+        unsafe { mem::transmute::<FontStyle, winapi::DWRITE_FONT_STYLE>(*self) }
+    }
+    pub fn to_u32(&self) -> u32 { unsafe { mem::transmute::<FontStyle, u32>(*self) } }
+    pub fn from_u32(v: u32) -> FontStyle { unsafe { mem::transmute::<u32, FontStyle>(v) } }
 }
 
 #[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
 pub struct FontDescriptor {
     pub family_name: String,
     pub weight: FontWeight,
     pub stretch: FontStretch,
     pub style: FontStyle,
deleted file mode 100644
--- a/third_party/rust/post-expansion/.cargo-checksum.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"23b1c5b9134c13c8bf2d1ef26ab87b84eabf894c2920dc50d801fde2186c3ea8","src/lib.rs":"633f8db980684fb14dda46696982c7e4616750ed12ae31291225af609241e54c"},"package":"31a834a6060acaef74a8d878f6ca37a2b86fefe042bbfe70689ba587e42526f9"}
\ No newline at end of file
deleted file mode 100644
deleted file mode 100644
--- a/third_party/rust/post-expansion/Cargo.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-[package]
-name = "post-expansion"
-version = "0.1.0"
-authors = ["David Tolnay <dtolnay@gmail.com>"]
-license = "MIT/Apache-2.0"
-description = "Strip attributes after #[derive(...)] expansion"
-repository = "https://github.com/dtolnay/post-expansion"
-documentation = "https://docs.rs/post-expansion/"
-include = ["Cargo.toml", "src/**/*.rs"]
-
-[dependencies]
-syn = "0.9"
-quote = "0.3"
deleted file mode 100644
--- a/third_party/rust/post-expansion/src/lib.rs
+++ /dev/null
@@ -1,433 +0,0 @@
-//! # Why?
-//!
-//! Custom derives commonly use [attributes] to customize the behavior of
-//! generated code. For example to control the name of a field when serialized
-//! as JSON:
-//!
-//! [attributes]: https://doc.rust-lang.org/book/attributes.html
-//!
-//! ```ignore
-//! #[derive(Serialize, Deserialize)]
-//! struct Person {
-//!     #[serde(rename = "firstName")]
-//!     first_name: String,
-//!     #[serde(rename = "lastName")]
-//!     last_name: String,
-//! }
-//! ```
-//!
-//! In the old compiler plugin infrastructure, plugins were provided with a
-//! mechanism to mark attributes as "used" so the compiler would know to ignore
-//! them after running the plugin. The new Macros 1.1 infrastructure is
-//! deliberately minimal and does not provide this mechanism. Instead, proc
-//! macros are expected to strip away attributes after using them. Any
-//! unrecognized attributes that remain after proc macro expansion are turned
-//! into errors.
-//!
-//! This approach causes problems when multiple custom derives want to process
-//! the same attributes. For example multiple crates (for JSON, Postgres, and
-//! Elasticsearch code generation) may want to standardize on a common rename
-//! attribute. If each custom derive is stripping away attributes after using
-//! them, subsequent custom derives on the same struct will not see the
-//! attributes they should.
-//!
-//! This crate provides a way to strip attributes (and possibly other cleanup
-//! tasks in the future) in a post-expansion pass that happens after other
-//! custom derives have been run.
-//!
-//! # How?
-//!
-//! Suppose `#[derive(ElasticType)]` wants to piggy-back on Serde's `rename`
-//! attributes for types that are serializable by both Serde and Elasticsearch:
-//!
-//! ```ignore
-//! #[derive(Serialize, Deserialize, ElasticType)]
-//! struct Point {
-//!     #[serde(rename = "xCoord")]
-//!     x: f64,
-//!     #[serde(rename = "yCoord")]
-//!     y: f64,
-//! }
-//! ```
-//!
-//! A workable but poor solution would be to have Serde's code generation know
-//! that ElasticType expects to read the same attributes, so it should not strip
-//! attributes when ElasticType is present in the list of derives. An ideal
-//! solution would not require Serde's code generation to know anything about
-//! other custom derives.
-//!
-//! We can handle this by having the Serialize and Deserialize derives register
-//! a post-expansion pass to strip the attributes after all other custom derives
-//! have been executed. Serde should expand the above code into:
-//!
-//! ```ignore
-//! impl Serialize for Point { /* ... */ }
-//! impl Deserialize for Point { /* ... */ }
-//!
-//! #[derive(ElasticType)]
-//! #[derive(PostExpansion)] // insert a post-expansion pass after all other derives
-//! #[post_expansion(strip = "serde")] // during post-expansion, strip "serde" attributes
-//! struct Point {
-//!     #[serde(rename = "xCoord")]
-//!     x: f64,
-//!     #[serde(rename = "yCoord")]
-//!     y: f64,
-//! }
-//! ```
-//!
-//! Now the ElasticType custom derive can run and see all the right attributes.
-//!
-//! ```ignore
-//! impl Serialize for Point { /* ... */ }
-//! impl Deserialize for Point { /* ... */ }
-//! impl ElasticType for Point { /* ... */ }
-//!
-//! #[derive(PostExpansion)]
-//! #[post_expansion(strip = "serde")]
-//! struct Point {
-//!     #[serde(rename = "xCoord")]
-//!     x: f64,
-//!     #[serde(rename = "yCoord")]
-//!     y: f64,
-//! }
-//! ```
-//!
-//! Once all other derives have been expanded the `PostExpansion` pass strips
-//! the attributes.
-//!
-//! ```ignore
-//! impl Serialize for Point { /* ... */ }
-//! impl Deserialize for Point { /* ... */ }
-//! impl ElasticType for Point { /* ... */ }
-//!
-//! struct Point {
-//!     x: f64,
-//!     y: f64,
-//! }
-//! ```
-//!
-//! There are some complications beyond what is shown in the example. For one,
-//! ElasticType needs to register its own post-expansion pass in case somebody
-//! does `#[derive(ElasticType, Serialize)]`. The post-expansion passes from
-//! Serde and ElasticType cannot both be called "PostExpansion" because that
-//! would be a conflict.
-//!
-//! There are also performance considerations. Stripping attributes in a
-//! post-expansion pass requires an extra round trip of syn -> tokenstream ->
-//! libsyntax -> tokenstream -> syn, which can be avoided if the current custom
-//! derive knows that it is the last custom derive.
-//!
-//! This crate provides helpers to make the whole process **easy, correct, and
-//! performant**.
-//!
-//! # How Exactly?
-//!
-//! There are two pieces. Proc macros that process attributes need to register a
-//! post-expansion pass using the `register_post_expansion!` macro. During
-//! expansion, they need to wire up the custom derive corresponding to the
-//! post-expansion pass.
-//!
-//! ```ignore
-//! extern crate syn;
-//! #[macro_use]
-//! extern crate post_expansion;
-//!
-//! register_post_expansion!(PostExpansion_my_macro);
-//!
-//! #[proc_macro_derive(MyMacro)]
-//! pub fn my_macro(input: TokenStream) -> TokenStream {
-//!     let source = input.to_string();
-//!     let ast = syn::parse_macro_input(&source).unwrap();
-//!
-//!     let derived_impl = expand_my_macro(&ast);
-//!
-//!     let stripped = post_expansion::strip_attrs_later(ast, &["my_attr"], "my_macro");
-//!
-//!     let tokens = quote! {
-//!         #stripped
-//!         #derived_impl
-//!     };
-//!
-//!     tokens.to_string().parse().unwrap()
-//! }
-//! ```
-
-extern crate syn;
-use syn::*;
-
-#[macro_use]
-extern crate quote;
-
-/// Register a Macros 1.1 custom derive mode corresponding to a post-expansion
-/// pass for the current crate. Must be called at the top level of a proc-macro
-/// crate. Must be called with an identifier for the post-expansion pass, which
-/// must be "PostExpansion_" + unique identifier. Recommended to use the crate
-/// name of the current crate as the unique identifier.
-///
-/// Only needed if using `strip_attrs_later`. The identifier passed to
-/// `strip_attrs_later` must match the unique identifier here.
-///
-/// ```ignore
-/// register_post_expansion!(PostExpansion_elastic_types);
-/// ```
-#[macro_export]
-macro_rules! register_post_expansion {
-    ($id:ident) => {
-        #[proc_macro_derive($id)]
-        pub fn post_expansion(input: ::proc_macro::TokenStream) -> ::proc_macro::TokenStream {
-            let source = input.to_string();
-            let clean = ::post_expansion::run(source);
-            clean.parse().unwrap()
-        }
-    };
-}
-
-/// Run post-expansion pass. This is called from the `register_post_expansion!`
-/// macro and should not need to be called directly.
-///
-/// The post-expansion pass strips any remaining `PostExpansion` derives and
-/// strips the attributes that were queued to be stripped "later".
-///
-/// ```ignore
-/// #[proc_macro_derive(PostExpansion_elastic_types)]
-/// pub fn post_expansion(input: TokenStream) -> TokenStream {
-///     let source = input.to_string();
-///     let clean = post_expansion::run(source);
-///     clean.parse().unwrap()
-/// }
-/// ```
-pub fn run(input: String) -> String {
-    let ast = parse_macro_input(&input).unwrap();
-    let clean = post_expansion(ast);
-    quote!(#clean).to_string()
-}
-
-// Called by `run`, but also by `strip_attrs_later` in the fast path case where
-// it determines it is safe to strip attrs now rather than later.
-fn post_expansion(mut ast: MacroInput) -> MacroInput {
-    // Attributes to be stripped "later"; these come from attributes that look
-    // like `#[post_expansion(strip = "serde")]`
-    let mut strip = Vec::new();
-
-    // Strip any remaining PostExpansion derives and collect the set of
-    // attributes to strip
-    ast.attrs = ast.attrs
-        .into_iter()
-        .filter_map(|attr| {
-            if attr.is_sugared_doc || attr.style != AttrStyle::Outer {
-                // Neither `#[derive(...)]` nor `#[post_expansion(...)]`
-                return Some(attr);
-            }
-            let (name, nested) = match attr.value {
-                MetaItem::List(name, nested) => (name, nested),
-                _ => {
-                    // Neither `#[derive(...)]` nor `#[post_expansion(...)]`
-                    return Some(attr);
-                }
-            };
-            match name.as_ref() {
-                "post_expansion" => {
-                    for nested in nested {
-                        // Look for `#[post_expansion(strip = "...")]`
-                        if let MetaItem::NameValue(name, Lit::Str(attr, _)) = nested {
-                            if name == "strip" && !strip.contains(&attr) {
-                                strip.push(attr);
-                            }
-                        }
-                    }
-                    // Drop the `#[post_expansion(...)]` attribute
-                    None
-                }
-                "derive" => {
-                    // Drop any other `derive(PostExpansion_xyz)` derives
-                    let rest: Vec<_> = nested.into_iter()
-                        .filter(|nested| {
-                            match *nested {
-                                MetaItem::Word(ref word) => {
-                                    !word.as_ref().starts_with("PostExpansion_")
-                                }
-                                _ => true,
-                            }
-                        })
-                        .collect();
-                    if rest.is_empty() {
-                        // Omit empty `#[derive()]`
-                        None
-                    } else {
-                        // At least one remaining derive
-                        Some(Attribute {
-                            style: AttrStyle::Outer,
-                            value: MetaItem::List(name, rest),
-                            is_sugared_doc: false,
-                        })
-                    }
-                }
-                _ => {
-                    // Neither `#[derive(...)]` nor `#[post_expansion(...)]` but
-                    // the original attribute has been destructured so it needs
-                    // to be put back together
-                    Some(Attribute {
-                        style: AttrStyle::Outer,
-                        value: MetaItem::List(name, nested),
-                        is_sugared_doc: false,
-                    })
-                }
-            }
-        })
-        .collect();
-
-    strip_attrs_now(ast, &strip.iter().map(AsRef::as_ref).collect::<Vec<_>>())
-}
-
-/// Strip the specified attributes from the AST. Note that if it is possible
-/// those attributes may be needed by other custom derives, you should use
-/// `strip_attrs_later` instead which strips the attributes only after other
-/// custom derives have had a chance to see them.
-///
-/// ```ignore
-/// ast = post_expansion::strip_attrs_now(ast, &["serde"]);
-/// ```
-pub fn strip_attrs_now(ast: MacroInput, strip: &[&str]) -> MacroInput {
-    if strip.is_empty() {
-        return ast;
-    }
-
-    return MacroInput {
-        attrs: strip_attrs(ast.attrs, strip),
-        body: match ast.body {
-            Body::Enum(variants) => {
-                Body::Enum(variants.into_iter()
-                    .map(|variant| {
-                        Variant {
-                            attrs: strip_attrs(variant.attrs, strip),
-                            data: strip_variant_data(variant.data, strip),
-                            ..variant
-                        }
-                    })
-                    .collect())
-            }
-            Body::Struct(variant_data) => Body::Struct(strip_variant_data(variant_data, strip)),
-        },
-        ..ast
-    };
-
-    fn strip_variant_data(data: VariantData, strip: &[&str]) -> VariantData {
-        match data {
-            VariantData::Struct(fields) => {
-                VariantData::Struct(fields.into_iter()
-                    .map(|field| strip_field(field, strip))
-                    .collect())
-            }
-            VariantData::Tuple(fields) => {
-                VariantData::Tuple(fields.into_iter()
-                    .map(|field| strip_field(field, strip))
-                    .collect())
-            }
-            VariantData::Unit => VariantData::Unit,
-        }
-    }
-
-    fn strip_field(field: Field, strip: &[&str]) -> Field {
-        Field { attrs: strip_attrs(field.attrs, strip), ..field }
-    }
-
-    fn strip_attrs(attrs: Vec<Attribute>, strip: &[&str]) -> Vec<Attribute> {
-        attrs.into_iter()
-            .filter(|attr| {
-                match attr.value {
-                    MetaItem::List(ref ident, _) => !strip.into_iter().any(|n| ident == n),
-                    _ => true,
-                }
-            })
-            .collect()
-    }
-}
-
-/// Set up a post-expansion pass to strip the given attributes after other
-/// custom derives have had a chance to see them. Must be used together with the
-/// `register_post_expansion!` macro. The third argument is the unique
-/// identifier from the invocation of `register_post_expansion!`. Recommended to
-/// use the crate name of the current crate as the unique identifier.
-///
-/// ```ignore
-/// let ast = post_expansion::strip_attrs_later(ast, &["serde", "elastic"], "elastic_types");
-/// ```
-pub fn strip_attrs_later(mut ast: MacroInput, strip: &[&str], identifier: &str) -> MacroInput {
-    if strip.is_empty() {
-        return ast;
-    }
-
-    let run_now = can_run_post_expansion_now(&ast);
-
-    // #[derive(PostExpansion_$identifier)]
-    ast.attrs.push(Attribute {
-        style: AttrStyle::Outer,
-        value: MetaItem::List("derive".into(),
-                              vec![MetaItem::Word(format!("PostExpansion_{}", identifier).into())]),
-        is_sugared_doc: false,
-    });
-    // #[post_expansion(strip = "a", strip = "b")]
-    ast.attrs.push(Attribute {
-        style: AttrStyle::Outer,
-        value: MetaItem::List("post_expansion".into(),
-                              strip.into_iter()
-                                  .map(|&n| {
-                                      MetaItem::NameValue("strip".into(),
-                                                          Lit::Str(n.into(), StrStyle::Cooked))
-                                  })
-                                  .collect()),
-        is_sugared_doc: false,
-    });
-
-    if run_now { post_expansion(ast) } else { ast }
-}
-
-/// Can run now if the only remaining derives are builtin derives which do not
-/// look at attributes, or other `PostExpansion` passes.
-fn can_run_post_expansion_now(ast: &MacroInput) -> bool {
-    for attr in &ast.attrs {
-        if attr.is_sugared_doc || attr.style != AttrStyle::Outer {
-            // Not a `derive` attribute
-            continue;
-        }
-        let list = match attr.value {
-            MetaItem::List(ref name, ref list) if name == "derive" => list,
-            _ => {
-                // Not a `derive` attribute
-                continue;
-            }
-        };
-        for elem in list {
-            let word = match *elem {
-                MetaItem::Word(ref word) => word,
-                _ => {
-                    // Unexpected thing inside `derive(...)`, take the safe path
-                    // by not running post-expansion now
-                    return false;
-                }
-            };
-            match word.as_ref() {
-                "Clone" | "Hash" | "RustcEncodable" | "RustcDecodable" | "PartialEq" | "Eq" |
-                "PartialOrd" | "Ord" | "Debug" | "Default" | "Send" | "Sync" | "Copy" |
-                "Encodable" | "Decodable" => {
-                    // The built-in derives do not look at attributes so
-                    // shouldn't stop us from stripping attributes now
-                    continue;
-                }
-                custom if custom.starts_with("PostExpansion_") => {
-                    // Okay to run now if the only other custom derives are
-                    // PostExpansion
-                    continue;
-                }
-                _ => {
-                    // Cannot run post-expansion now because there is a custom
-                    // derive that may need the same attributes
-                    return false;
-                }
-            }
-        }
-    }
-    // The only remaining derives are builtin derives or other PostExpansion
-    // passes; nothing more will need the attributes so strip them now
-    true
-}
--- a/third_party/rust/serde/.cargo-checksum.json
+++ b/third_party/rust/serde/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"695fc20cd6b24feb533162cf75457bf36574f332ba2312ab0632af33ab385dec","src/bytes.rs":"ae25683c8b2833a3ba4c1d5c0e89a574df938aac99191de9b8910fff92fd47d3","src/de/from_primitive.rs":"b1bd165e343a4380965551709119ef9ed895e4b025045a810dabd671511ba3ab","src/de/impls.rs":"c0fbbfea4e65f6fef1126db1a3509c201b8ffe5c24a0bd58a1a3ff36e6992468","src/de/mod.rs":"62291b6b7c29d411b9ff212cab480982e535e7aee21c1729b4bb592d681ab807","src/de/value.rs":"6dd878ce762799048c0ebc8f834932871e1bdf24953ea69415a2b2148e0d3dbc","src/error.rs":"da31d3881930f0e787d75191984f71fe2e1419d9331c68baa0fc0ce2d561766b","src/iter.rs":"30090fe6ab49bb1d8c7fec362cace52981b2c4e1a1a8e3fad4117eab558cdde6","src/lib.rs":"67f62df097e3b55a90a566af56d6e3c641f719300db8bfd5603ed5a2bff1aa8e","src/macros.rs":"e81e421815fac10d6a7bfb727bbe7b4f24e99b03cd8739efc806e4b704ac7b4e","src/ser/impls.rs":"36d372af1dae11444f85e497eefb98449bae70260348cdfb098c508439be7952","src/ser/mod.rs":"626e8ef5b1ddaf00fe84905e936046c40217e31609d5a56ca658f4eb23983fd5","src/utils.rs":"b0d1a54af90e3620abd66479d757a2eb442449788c4ece93161916da0838affa"},"package":"784e249221c84265caeb1e2fe48aeada86f67f5acb151bd3903c4585969e43f6"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"d65d5b80c0369d94cc9ae28f0d661ed9923e049a088412bd14abca77081d8e5d","src/bytes.rs":"ae25683c8b2833a3ba4c1d5c0e89a574df938aac99191de9b8910fff92fd47d3","src/de/from_primitive.rs":"b1bd165e343a4380965551709119ef9ed895e4b025045a810dabd671511ba3ab","src/de/impls.rs":"c0fbbfea4e65f6fef1126db1a3509c201b8ffe5c24a0bd58a1a3ff36e6992468","src/de/mod.rs":"62291b6b7c29d411b9ff212cab480982e535e7aee21c1729b4bb592d681ab807","src/de/value.rs":"6dd878ce762799048c0ebc8f834932871e1bdf24953ea69415a2b2148e0d3dbc","src/error.rs":"da31d3881930f0e787d75191984f71fe2e1419d9331c68baa0fc0ce2d561766b","src/iter.rs":"30090fe6ab49bb1d8c7fec362cace52981b2c4e1a1a8e3fad4117eab558cdde6","src/lib.rs":"67f62df097e3b55a90a566af56d6e3c641f719300db8bfd5603ed5a2bff1aa8e","src/macros.rs":"e81e421815fac10d6a7bfb727bbe7b4f24e99b03cd8739efc806e4b704ac7b4e","src/ser/impls.rs":"36d372af1dae11444f85e497eefb98449bae70260348cdfb098c508439be7952","src/ser/mod.rs":"626e8ef5b1ddaf00fe84905e936046c40217e31609d5a56ca658f4eb23983fd5","src/utils.rs":"b0d1a54af90e3620abd66479d757a2eb442449788c4ece93161916da0838affa"},"package":"d9b524a2fac246f45c36a7f3a5742c19dcb0b2d1252d1ad5458ca07f26e04a57"}
\ No newline at end of file
--- a/third_party/rust/serde/Cargo.toml
+++ b/third_party/rust/serde/Cargo.toml
@@ -1,11 +1,11 @@
 [package]
 name = "serde"
-version = "0.8.17"
+version = "0.8.18"
 authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
 license = "MIT/Apache-2.0"
 description = "A generic serialization/deserialization framework"
 homepage = "https://serde.rs"
 repository = "https://github.com/serde-rs/serde"
 documentation = "https://docs.serde.rs/serde/"
 readme = "../README.md"
 keywords = ["serde", "serialization"]
--- a/third_party/rust/serde_codegen/.cargo-checksum.json
+++ b/third_party/rust/serde_codegen/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"dd882c766fdb4fa70bb7c71d8cd24cdb86a3ebff0ca747a9b769d9953d2df1f1","src/bound.rs":"d1f94299052acaeeae0c011c2304b072dec76c7c32469d2b8881c2e380346496","src/de.rs":"a429c39e75abc0c080d1bd9b22c164a3fa7f45c48ccdadd50c41e8f05bcbde1b","src/lib.rs":"c03583c3c92e386850aad5ab572304a193cb707e057fa5ba23340d48ebe6bd7b","src/ser.rs":"12a9b9a21a4d2b0671531fc3c7d13ff50a9b9f00515468b78d3c8eb606324c21"},"package":"c3b932a3bb4d729e39aa04cc5e2f2ac70ba239a5a151d2dc9a1956fd6a2f7c15"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"77734c96fb811aaffd874e68d4fcaed848187e22b210f42a3a7ef2334c2d0ec7","src/bound.rs":"d1f94299052acaeeae0c011c2304b072dec76c7c32469d2b8881c2e380346496","src/de.rs":"a429c39e75abc0c080d1bd9b22c164a3fa7f45c48ccdadd50c41e8f05bcbde1b","src/lib.rs":"50ae99f8110a625f071595048a82108c685d384e5f832f86a96ac789629d6bfb","src/ser.rs":"12a9b9a21a4d2b0671531fc3c7d13ff50a9b9f00515468b78d3c8eb606324c21"},"package":"d658b798b60791e72c4d518bed618b12318527c7a5adae41c23da61fa3656bd6"}
\ No newline at end of file
--- a/third_party/rust/serde_codegen/Cargo.toml
+++ b/third_party/rust/serde_codegen/Cargo.toml
@@ -1,11 +1,11 @@
 [package]
 name = "serde_codegen"
-version = "0.8.17"
+version = "0.8.18"
 authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
 license = "MIT/Apache-2.0"
 description = "Macros to auto-generate implementations for the serde framework"
 homepage = "https://serde.rs"
 repository = "https://github.com/serde-rs/serde"
 documentation = "https://serde.rs/codegen.html"
 keywords = ["serde", "serialization"]
 include = ["Cargo.toml", "src/**/*.rs"]
@@ -17,14 +17,13 @@ unstable-testing = ["clippy"]
 with-syntex = [
     "syntex",
     "syntex_syntax",
 ]
 with-syn = []
 
 [dependencies]
 clippy = { version = "^0.*", optional = true }
-post-expansion = "0.1.0"
 quote = "0.3"
-serde_codegen_internals = { version = "=0.10.0", default-features = false, path = "../serde_codegen_internals" }
-syn = { version = "0.9", features = ["aster", "visit"] }
-syntex = { version = "^0.48.0", optional = true }
-syntex_syntax = { version = "^0.48.0", optional = true }
+serde_codegen_internals = { version = "=0.11.1", default-features = false, path = "../serde_codegen_internals" }
+syn = { version = "0.10", features = ["aster", "visit"] }
+syntex = { version = "^0.50.0", optional = true }
+syntex_syntax = { version = "^0.50.0", optional = true }
--- a/third_party/rust/serde_codegen/src/lib.rs
+++ b/third_party/rust/serde_codegen/src/lib.rs
@@ -22,19 +22,16 @@ extern crate syntax;
 
 #[cfg(not(feature = "with-syntex"))]
 extern crate rustc_plugin;
 
 extern crate syn;
 #[macro_use]
 extern crate quote;
 
-#[cfg(feature = "with-syn")]
-extern crate post_expansion;
-
 #[cfg(feature = "with-syntex")]
 use std::path::Path;
 
 #[cfg(not(feature = "with-syntex"))]
 use syntax::feature_gate::AttributeType;
 
 mod bound;
 mod de;
@@ -68,18 +65,18 @@ fn syntex_registry() -> syntex::Registry
         fold::Folder::fold_crate(&mut StripAttributeFolder, krate)
     }
 
     let mut reg = syntex::Registry::new();
 
     reg.add_attr("feature(custom_derive)");
     reg.add_attr("feature(custom_attribute)");
 
-    reg.add_decorator("derive_Serialize", expand_derive_serialize);
-    reg.add_decorator("derive_Deserialize", expand_derive_deserialize);
+    reg.add_decorator("derive_Serialize", shim::expand_derive_serialize);
+    reg.add_decorator("derive_Deserialize", shim::expand_derive_deserialize);
 
     reg.add_post_expansion_pass(strip_attributes);
 
     reg
 }
 
 #[cfg(feature = "with-syntex")]
 pub fn expand_str(src: &str) -> Result<String, syntex::Error> {
@@ -107,29 +104,29 @@ pub fn expand<S, D>(src: S, dst: D) -> R
     syntex::with_extra_stack(expand_thread)
 }
 
 #[cfg(not(feature = "with-syntex"))]
 pub fn register(reg: &mut rustc_plugin::Registry) {
     reg.register_syntax_extension(
         syntax::parse::token::intern("derive_Serialize"),
         syntax::ext::base::MultiDecorator(
-            Box::new(expand_derive_serialize)));
+            Box::new(shim::expand_derive_serialize)));
 
     reg.register_syntax_extension(
         syntax::parse::token::intern("derive_Deserialize"),
         syntax::ext::base::MultiDecorator(
-            Box::new(expand_derive_deserialize)));
+            Box::new(shim::expand_derive_deserialize)));
 
     reg.register_attribute("serde".to_owned(), AttributeType::Normal);
 }
 
 macro_rules! shim {
     ($name:ident $pkg:ident :: $func:ident) => {
-        fn $func(
+        pub fn $func(
             cx: &mut ::syntax::ext::base::ExtCtxt,
             span: ::syntax::codemap::Span,
             meta_item: &::syntax::ast::MetaItem,
             annotatable: &::syntax::ext::base::Annotatable,
             push: &mut FnMut(::syntax::ext::base::Annotatable)
         ) {
             let item = match *annotatable {
                 ::syntax::ext::base::Annotatable::Item(ref item) => item,
@@ -155,16 +152,17 @@ macro_rules! shim {
                     }
                 }
             }
             visit::walk_item(&mut MarkSerdeAttributesUsed, item);
 
             use syntax::print::pprust;
             let s = pprust::item_to_string(item);
 
+            use {syn, $pkg};
             let syn_item = syn::parse_macro_input(&s).unwrap();
             let expanded = match $pkg::$func(&syn_item) {
                 Ok(expanded) => expanded.to_string(),
                 Err(msg) => {
                     cx.span_err(span, &msg);
                     return;
                 }
             };
@@ -173,75 +171,28 @@ macro_rules! shim {
             let name = stringify!($name).to_string();
             let sess = cx.parse_sess;
             let impl_item = parse::parse_item_from_source_str(name, expanded, sess);
             push(::syntax::ext::base::Annotatable::Item(impl_item.unwrap().unwrap()));
         }
     };
 }
 
-shim!(Serialize ser::expand_derive_serialize);
-shim!(Deserialize de::expand_derive_deserialize);
+mod shim {
+    shim!(Serialize ser::expand_derive_serialize);
+    shim!(Deserialize de::expand_derive_deserialize);
+}
 
 #[cfg(feature = "with-syn")]
-pub fn expand_single_item(item: &str) -> Result<String, String> {
+#[doc(hidden)]
+/// Not public API. Use the serde_derive crate.
+pub fn expand_derive_serialize(item: &str) -> Result<String, String> {
     let syn_item = syn::parse_macro_input(item).unwrap();
-    let (ser, de, syn_item) = strip_serde_derives(syn_item);
-    let expanded_ser = if ser {
-        Some(try!(ser::expand_derive_serialize(&syn_item)))
-    } else {
-        None
-    };
-    let expanded_de = if de {
-        Some(try!(de::expand_derive_deserialize(&syn_item)))
-    } else {
-        None
-    };
-    let syn_item = post_expansion::strip_attrs_later(syn_item, &["serde"], "serde");
-    return Ok(quote!(#expanded_ser #expanded_de #syn_item).to_string());
+    ser::expand_derive_serialize(&syn_item).map(|derive| derive.to_string())
+}
 
-    fn strip_serde_derives(item: syn::MacroInput) -> (bool, bool, syn::MacroInput) {
-        let mut ser = false;
-        let mut de = false;
-        let item = syn::MacroInput {
-            attrs: item.attrs.into_iter().flat_map(|attr| {
-                if attr.is_sugared_doc || attr.style != syn::AttrStyle::Outer {
-                    return Some(attr);
-                }
-                let (name, nested) = match attr.value {
-                    syn::MetaItem::List(name, nested) => (name, nested),
-                    _ => return Some(attr)
-                };
-                if name != "derive" {
-                    return Some(syn::Attribute {
-                        style: syn::AttrStyle::Outer,
-                        value: syn::MetaItem::List(name, nested),
-                        is_sugared_doc: false,
-                    });
-                }
-                let rest: Vec<_> = nested.into_iter().filter(|nested| {
-                    match *nested {
-                        syn::MetaItem::Word(ref word) if word == "Serialize" => {
-                            ser = true;
-                            false
-                        }
-                        syn::MetaItem::Word(ref word) if word == "Deserialize" => {
-                            de = true;
-                            false
-                        }
-                        _ => true,
-                    }
-                }).collect();
-                if rest.is_empty() {
-                    None
-                } else {
-                    Some(syn::Attribute {
-                        style: syn::AttrStyle::Outer,
-                        value: syn::MetaItem::List(name, rest),
-                        is_sugared_doc: false,
-                    })
-                }
-            }).collect(),
-            ..item
-        };
-        (ser, de, item)
-    }
+#[cfg(feature = "with-syn")]
+#[doc(hidden)]
+/// Not public API. Use the serde_derive crate.
+pub fn expand_derive_deserialize(item: &str) -> Result<String, String> {
+    let syn_item = syn::parse_macro_input(item).unwrap();
+    de::expand_derive_deserialize(&syn_item).map(|derive| derive.to_string())
 }
--- a/third_party/rust/serde_codegen_internals/.cargo-checksum.json
+++ b/third_party/rust/serde_codegen_internals/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"e8f061ee5de2d47fa0e930fed7d077263c8f5b8f4041f097bf6478e1d3dd641d","src/ast.rs":"0b96616b2becc71ac85ffb0efcf6c6d0b451c7e2e4934df19193962e7fc9316a","src/attr.rs":"6d5473c0dc3f76db0af33975fe64aa9487b5a20f1e52d9f9625a706b6d446e48","src/ctxt.rs":"80795ca96772fdef304584795966bbf28c24b788590c83e44efca3bb45a7d06a","src/lib.rs":"a5b9dae1488c7c50f5ed630bf473f5ca13d44f795faf380152fef10bfc7b9eee"},"package":"318f7e77aa5187391d74aaf4553d2189f56b0ce25e963414c951b97877ffdcec"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"86d97dd1ec6b95ab0c57f68bd15c24341ee7d12a3173ae3bf680479e0448f4d9","src/ast.rs":"0b96616b2becc71ac85ffb0efcf6c6d0b451c7e2e4934df19193962e7fc9316a","src/attr.rs":"3e3403243a3e0c9bcf086e6bb80763a5e8281848f7257bf121b03731610038b4","src/ctxt.rs":"80795ca96772fdef304584795966bbf28c24b788590c83e44efca3bb45a7d06a","src/lib.rs":"a5b9dae1488c7c50f5ed630bf473f5ca13d44f795faf380152fef10bfc7b9eee"},"package":"59933a62554548c690d2673c5164f0c4a46be7c5731edfd94b0ecb1048940732"}
\ No newline at end of file
--- a/third_party/rust/serde_codegen_internals/Cargo.toml
+++ b/third_party/rust/serde_codegen_internals/Cargo.toml
@@ -1,18 +1,18 @@
 [package]
 name = "serde_codegen_internals"
-version = "0.10.0"
+version = "0.11.1"
 authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
 license = "MIT/Apache-2.0"
 description = "AST representation used by Serde codegen. Unstable."
 homepage = "https://serde.rs"
 repository = "https://github.com/serde-rs/serde"
 documentation = "https://docs.serde.rs/serde_codegen_internals/"
 keywords = ["serde", "serialization"]
 include = ["Cargo.toml", "src/**/*.rs"]
 
 [features]
 unstable-testing = ["clippy"]
 
 [dependencies]
 clippy = { version = "^0.*", optional = true }
-syn = "0.9"
+syn = "0.10"
--- a/third_party/rust/serde_codegen_internals/src/attr.rs
+++ b/third_party/rust/serde_codegen_internals/src/attr.rs
@@ -1,10 +1,12 @@
 use Ctxt;
 use syn;
+use syn::MetaItem::{List, NameValue, Word};
+use syn::NestedMetaItem::{Literal, MetaItem};
 
 // This module handles parsing of `#[serde(...)]` attributes. The entrypoints
 // are `attr::Item::from_ast`, `attr::Variant::from_ast`, and
 // `attr::Field::from_ast`. Each returns an instance of the corresponding
 // struct. Note that none of them return a Result. Unrecognized, malformed, or
 // duplicated attributes result in a span_err but otherwise are ignored. The
 // user will see errors simultaneously for all bad attributes in the crate
 // rather than just the first.
@@ -100,56 +102,60 @@ impl Item {
         let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields");
         let mut ser_bound = Attr::none(cx, "bound");
         let mut de_bound = Attr::none(cx, "bound");
 
         for meta_items in item.attrs.iter().filter_map(get_serde_meta_items) {
             for meta_item in meta_items {
                 match meta_item {
                     // Parse `#[serde(rename="foo")]`
-                    syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => {
+                    MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
                         if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
                             ser_name.set(s.clone());
                             de_name.set(s);
                         }
                     }
 
                     // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
-                    syn::MetaItem::List(ref name, ref meta_items) if name == "rename" => {
+                    MetaItem(List(ref name, ref meta_items)) if name == "rename" => {
                         if let Ok((ser, de)) = get_renames(cx, meta_items) {
                             ser_name.set_opt(ser);
                             de_name.set_opt(de);
                         }
                     }
 
                     // Parse `#[serde(deny_unknown_fields)]`
-                    syn::MetaItem::Word(ref name) if name == "deny_unknown_fields" => {
+                    MetaItem(Word(ref name)) if name == "deny_unknown_fields" => {
                         deny_unknown_fields.set_true();
                     }
 
                     // Parse `#[serde(bound="D: Serialize")]`
-                    syn::MetaItem::NameValue(ref name, ref lit) if name == "bound" => {
+                    MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
                         if let Ok(where_predicates) = parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
                             ser_bound.set(where_predicates.clone());
                             de_bound.set(where_predicates);
                         }
                     }
 
                     // Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]`
-                    syn::MetaItem::List(ref name, ref meta_items) if name == "bound" => {
+                    MetaItem(List(ref name, ref meta_items)) if name == "bound" => {
                         if let Ok((ser, de)) = get_where_predicates(cx, meta_items) {
                             ser_bound.set_opt(ser);
                             de_bound.set_opt(de);
                         }
                     }
 
-                    _ => {
+                    MetaItem(ref meta_item) => {
                         cx.error(format!("unknown serde container attribute `{}`",
                                          meta_item.name()));
                     }
+
+                    Literal(_) => {
+                        cx.error(format!("unexpected literal in serde container attribute"));
+                    }
                 }
             }
         }
 
         Item {
             name: Name {
                 serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()),
                 deserialize: de_name.get().unwrap_or_else(|| item.ident.to_string()),
@@ -187,35 +193,39 @@ impl Variant {
     pub fn from_ast(cx: &Ctxt, variant: &syn::Variant) -> Self {
         let mut ser_name = Attr::none(cx, "rename");
         let mut de_name = Attr::none(cx, "rename");
 
         for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) {
             for meta_item in meta_items {
                 match meta_item {
                     // Parse `#[serde(rename="foo")]`
-                    syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => {
+                    MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
                         if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
                             ser_name.set(s.clone());
                             de_name.set(s);
                         }
                     }
 
                     // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
-                    syn::MetaItem::List(ref name, ref meta_items) if name == "rename" => {
+                    MetaItem(List(ref name, ref meta_items)) if name == "rename" => {
                         if let Ok((ser, de)) = get_renames(cx, meta_items) {
                             ser_name.set_opt(ser);
                             de_name.set_opt(de);
                         }
                     }
 
-                    _ => {
+                    MetaItem(ref meta_item) => {
                         cx.error(format!("unknown serde variant attribute `{}`",
                                          meta_item.name()));
                     }
+
+                    Literal(_) => {
+                        cx.error(format!("unexpected literal in serde variant attribute"));
+                    }
                 }
             }
         }
 
         Variant {
             name: Name {
                 serialize: ser_name.get().unwrap_or_else(|| variant.ident.to_string()),
                 deserialize: de_name.get().unwrap_or_else(|| variant.ident.to_string()),
@@ -273,94 +283,98 @@ impl Field {
             Some(ref ident) => ident.to_string(),
             None => index.to_string(),
         };
 
         for meta_items in field.attrs.iter().filter_map(get_serde_meta_items) {
             for meta_item in meta_items {
                 match meta_item {
                     // Parse `#[serde(rename="foo")]`
-                    syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => {
+                    MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
                         if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
                             ser_name.set(s.clone());
                             de_name.set(s);
                         }
                     }
 
                     // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
-                    syn::MetaItem::List(ref name, ref meta_items) if name == "rename" => {
+                    MetaItem(List(ref name, ref meta_items)) if name == "rename" => {
                         if let Ok((ser, de)) = get_renames(cx, meta_items) {
                             ser_name.set_opt(ser);
                             de_name.set_opt(de);
                         }
                     }
 
                     // Parse `#[serde(default)]`
-                    syn::MetaItem::Word(ref name) if name == "default" => {
+                    MetaItem(Word(ref name)) if name == "default" => {
                         default.set(FieldDefault::Default);
                     }
 
                     // Parse `#[serde(default="...")]`
-                    syn::MetaItem::NameValue(ref name, ref lit) if name == "default" => {
+                    MetaItem(NameValue(ref name, ref lit)) if name == "default" => {
                         if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
                             default.set(FieldDefault::Path(path));
                         }
                     }
 
                     // Parse `#[serde(skip_serializing)]`
-                    syn::MetaItem::Word(ref name) if name == "skip_serializing" => {
+                    MetaItem(Word(ref name)) if name == "skip_serializing" => {
                         skip_serializing.set_true();
                     }
 
                     // Parse `#[serde(skip_deserializing)]`
-                    syn::MetaItem::Word(ref name) if name == "skip_deserializing" => {
+                    MetaItem(Word(ref name)) if name == "skip_deserializing" => {
                         skip_deserializing.set_true();
                     }
 
                     // Parse `#[serde(skip_serializing_if="...")]`
-                    syn::MetaItem::NameValue(ref name, ref lit) if name == "skip_serializing_if" => {
+                    MetaItem(NameValue(ref name, ref lit)) if name == "skip_serializing_if" => {
                         if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
                             skip_serializing_if.set(path);
                         }
                     }
 
                     // Parse `#[serde(serialize_with="...")]`
-                    syn::MetaItem::NameValue(ref name, ref lit) if name == "serialize_with" => {
+                    MetaItem(NameValue(ref name, ref lit)) if name == "serialize_with" => {
                         if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
                             serialize_with.set(path);
                         }
                     }
 
                     // Parse `#[serde(deserialize_with="...")]`
-                    syn::MetaItem::NameValue(ref name, ref lit) if name == "deserialize_with" => {
+                    MetaItem(NameValue(ref name, ref lit)) if name == "deserialize_with" => {
                         if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
                             deserialize_with.set(path);
                         }
                     }
 
                     // Parse `#[serde(bound="D: Serialize")]`
-                    syn::MetaItem::NameValue(ref name, ref lit) if name == "bound" => {
+                    MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
                         if let Ok(where_predicates) = parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
                             ser_bound.set(where_predicates.clone());
                             de_bound.set(where_predicates);
                         }
                     }
 
                     // Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]`
-                    syn::MetaItem::List(ref name, ref meta_items) if name == "bound" => {
+                    MetaItem(List(ref name, ref meta_items)) if name == "bound" => {
                         if let Ok((ser, de)) = get_where_predicates(cx, meta_items) {
                             ser_bound.set_opt(ser);
                             de_bound.set_opt(de);
                         }
                     }
 
-                    _ => {
+                    MetaItem(ref meta_item) => {
                         cx.error(format!("unknown serde field attribute `{}`",
                                          meta_item.name()));
                     }
+
+                    Literal(_) => {
+                        cx.error(format!("unexpected literal in serde field attribute"));
+                    }
                 }
             }
         }
 
         // Is skip_deserializing, initialize the field to Default::default()
         // unless a different default is specified by `#[serde(default="...")]`
         if skip_deserializing.0.value.is_some() {
             default.set_if_none(FieldDefault::Default);
@@ -419,33 +433,33 @@ impl Field {
     }
 }
 
 type SerAndDe<T> = (Option<T>, Option<T>);
 
 fn get_ser_and_de<T, F>(
     cx: &Ctxt,
     attr_name: &'static str,
-    items: &[syn::MetaItem],
+    items: &[syn::NestedMetaItem],
     f: F
 ) -> Result<SerAndDe<T>, ()>
     where F: Fn(&Ctxt, &str, &str, &syn::Lit) -> Result<T, ()>,
 {
     let mut ser_item = Attr::none(cx, attr_name);
     let mut de_item = Attr::none(cx, attr_name);
 
     for item in items {
         match *item {
-            syn::MetaItem::NameValue(ref name, ref lit) if name == "serialize" => {
+            MetaItem(NameValue(ref name, ref lit)) if name == "serialize" => {
                 if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) {
                     ser_item.set(v);
                 }
             }
 
-            syn::MetaItem::NameValue(ref name, ref lit) if name == "deserialize" => {
+            MetaItem(NameValue(ref name, ref lit)) if name == "deserialize" => {
                 if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) {
                     de_item.set(v);
                 }
             }
 
             _ => {
                 cx.error(format!("malformed {0} attribute, expected `{0}(serialize = ..., deserialize = ...)`",
                                  attr_name));
@@ -454,31 +468,31 @@ fn get_ser_and_de<T, F>(
         }
     }
 
     Ok((ser_item.get(), de_item.get()))
 }
 
 fn get_renames(
     cx: &Ctxt,
-    items: &[syn::MetaItem],
+    items: &[syn::NestedMetaItem],
 ) -> Result<SerAndDe<String>, ()> {
     get_ser_and_de(cx, "rename", items, get_string_from_lit)
 }
 
 fn get_where_predicates(
     cx: &Ctxt,
-    items: &[syn::MetaItem],
+    items: &[syn::NestedMetaItem],
 ) -> Result<SerAndDe<Vec<syn::WherePredicate>>, ()> {
     get_ser_and_de(cx, "bound", items, parse_lit_into_where)
 }
 
-pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option<Vec<syn::MetaItem>> {
+pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option<Vec<syn::NestedMetaItem>> {
     match attr.value {
-        syn::MetaItem::List(ref name, ref items) if name == "serde" => {
+        List(ref name, ref items) if name == "serde" => {
             Some(items.iter().cloned().collect())
         }
         _ => None
     }
 }
 
 fn get_string_from_lit(cx: &Ctxt, attr_name: &str, meta_item_name: &str, lit: &syn::Lit) -> Result<String, ()> {
     if let syn::Lit::Str(ref s, _) = *lit {
--- a/third_party/rust/syn/.cargo-checksum.json
+++ b/third_party/rust/syn/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"696b44bc0bee1d4eed084ef0bfe82249f2d577da53345ffaf94c26813e979164","src/aster/generics.rs":"77eb19443af0dff5debb18d064733cc8721a42ad7e993a33352cdeff2b5f9f85","src/aster/ident.rs":"e9d082664f008a56bd854011310b4258ab072740ba82e57495b6e8a868a5f36b","src/aster/invoke.rs":"2b1b993973ab4f5c8fa6d6a286576b2542edce21fe9904f5133c470c072e6d3f","src/aster/lifetime.rs":"f647a9995b7d2a7f9388966f3f970b478955842fdaff650cf34d825603e9b193","src/aster/mod.rs":"12220f73b0021e72b4c50f6a513cff174b9c7267209aa23f183043d96ccc9ab7","src/aster/path.rs":"60865b0f952077307c1a66810a4b6dafde43e76a417a433a8343960e7de474e4","src/aster/qpath.rs":"5ba33af56ccf74f5c516ed542d117d1f6ca9f7dfd1a74d08b4ac50d95666c497","src/aster/ty.rs":"90649aad98617c09ffc43a38aeb823a3298c41bf5e10f0ef3500b71c81021c2f","src/aster/ty_param.rs":"bad01b57c65bc06692478e9113fd8b0c5bccde0a1016d8ea7c2ea3a38b2e6111","src/aster/where_predicate.rs":"5fb8ec3fcb67bcc1d9bb7b64cf2f5beb601aac6502d6db30c0cdf8641fa248d1","src/attr.rs":"72d841c41583423c5b8c571d5758ed3e0eeb798cc8c414af8c0865c2b3b00c5a","src/constant.rs":"eaaa4d4721ad0c0ec009765c221ae244e2cd1d1f1ff38a460b95edbc4f4c68dc","src/data.rs":"d54f6606c2e6000a2398925c9d0c57ae685ada7b0c31e836537b59fa69e7fb82","src/escape.rs":"7aaf343809e82eb535b7485f2612f9f3e4f84d55a6d14ea6606bdbe23f1385aa","src/expr.rs":"3d7376019bb1d60ce0a2383efb4b839f8f00d7c055673d804e29553a4567cb66","src/generics.rs":"0d92372ac954c03a3678ce8e7a1d3dd969290b3cb114399e941eecb3deaef0f9","src/helper.rs":"b89de284fc7fe0731e44be5cbfee41e0c55d1918683094d72b9ee70699716801","src/ident.rs":"7e547772d100d616c692d77ba29d3f432e247c2a89c7ee6530671c1f303adb54","src/item.rs":"35e9acb07bd1c02db60a3792d5a67773882633b8ef14e1e3b83f3f6ae1985296","src/krate.rs":"092755ab0440465f7873e8782002d372a9ba1bed40116d168e9457829c123a94","src/lib.rs":"41540629e690c8d2ced54b6774ce03a541e1e45ef5105de2788ee1c989c4e137","src/lit.rs":"1b447af42878b64d87007f028a23e8e22fd8a8bc5fd7d409644b4a38a9d82e70","src/mac.rs":"834cb39c016c99e2d6726d5c2758a5571f11e305c37a62fe2100d1c9fc423fab","src/macro_input.rs":"5f4702308e9c66dd635dff919880b6765dfce87d6587a2d7b8257b33850f1ec7","src/nom.rs":"01fbcb124cb23146162fb606bd6507752fa69e2813767ca7d844c6ceaeaff920","src/op.rs":"fc279120f9c370bfb74d2f11978211b5b4644c27b6bb82dc8c5691f0cde476f2","src/space.rs":"28b4175abfd38ee64223479f24fe48b1b7ff343e6100a0f3a3b51519754c4d28","src/ty.rs":"1341d006929746aed67cfe9e764a2f4f0566707e65fbfcdfb965d3ba8c1bd2c8","src/visit.rs":"a13dd7f017da67387b83b765a3de1d4b8e4d74e1232f86b8b6c06b7907519040"},"package":"76c2db66dc579998854d84ff0ff4a81cb73e69596764d144ce7cece4d04ce6b5"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"72b00821197a467a2672ea9c0d18ee29386299b4ce1afbd29a60b8bb5bba0438","src/aster/generics.rs":"77eb19443af0dff5debb18d064733cc8721a42ad7e993a33352cdeff2b5f9f85","src/aster/ident.rs":"e9d082664f008a56bd854011310b4258ab072740ba82e57495b6e8a868a5f36b","src/aster/invoke.rs":"2b1b993973ab4f5c8fa6d6a286576b2542edce21fe9904f5133c470c072e6d3f","src/aster/lifetime.rs":"d83f4c1a48e3580caa028cfabde6ace232efc95d70af6dc9cfcca48317db9ad7","src/aster/mod.rs":"12220f73b0021e72b4c50f6a513cff174b9c7267209aa23f183043d96ccc9ab7","src/aster/path.rs":"60865b0f952077307c1a66810a4b6dafde43e76a417a433a8343960e7de474e4","src/aster/qpath.rs":"885c94b29ab8ee45c72a682221e241d1f0dd09c659809fe77279b5dd8a4bc645","src/aster/ty.rs":"90649aad98617c09ffc43a38aeb823a3298c41bf5e10f0ef3500b71c81021c2f","src/aster/ty_param.rs":"7ced1e6ca0c98ef468d507d3f07bfcb1171395cd66ff5c3e1b091fe7e8b9a562","src/aster/where_predicate.rs":"5fb8ec3fcb67bcc1d9bb7b64cf2f5beb601aac6502d6db30c0cdf8641fa248d1","src/attr.rs":"c28c41c330c5cd07bbc38ba3ea03c09e2ed57a710a6b80113444fa99a3e4c53b","src/constant.rs":"e5f349fc245af3d4c83bc3133555efa4abdc54d8fcc94e27aee64b936d5dbfe2","src/data.rs":"d3f34ff4258ed0396b127420e92a64d165cd71182ca4b5c5016735cc5ea498ac","src/escape.rs":"e035b1f6ce3255e868fddb62ee90a95a2f3caf2db73786a2b179b92e9e337539","src/expr.rs":"9f8dc642ffa01581e97540732c5650049064b820e9d425225df7307caec06ce9","src/generics.rs":"4e08adea6bad45643dba9d17dccee473e1dd9837a27974265d192823b010baee","src/helper.rs":"9693d5c78f2d627a90d689a5d4bee1061eddcb646ae6dff3b2e4fd7cfbb33845","src/ident.rs":"e808ecb1d9213c2738388738d8fbe53639048da983814d44a7f45fff10e12a26","src/item.rs":"f332b7a679fd75870c0bb1309305ec620aca36e5db6da59dc1ad24a06f353e60","src/krate.rs":"f560f370261660f0b67d0e9b077f8c117f2d5c472e91d764ffcd987fd6d10941","src/lib.rs":"248b9f0a4979c8ebdc575f306a82fc29787934a9ccb6b14bfbb820bc98805757","src/lit.rs":"ac9a3a34b9d4793656a93a6a0bdeefc424e855695928d6dfdb67f6aa0e4b0c77","src/mac.rs":"4876c2658e38f99deb07f2f10b51de70472f09b8d49f5aebe154f1dd1627bc58","src/macro_input.rs":"3b675de94924296aaf5adac8112fb5732bb88aacd1ea61b729284b02351e094c","src/nom.rs":"642149bf322b762e02183ac1fed641df7f03ac53334c869a64707de4e9c5e68c","src/op.rs":"fc279120f9c370bfb74d2f11978211b5b4644c27b6bb82dc8c5691f0cde476f2","src/registry.rs":"c293e79c3f9b0d564c60e9115bc537e4e2a6958b47681fbe549b54f443d0071b","src/space.rs":"de9cb71e831c1d66f0bf2f3f219c3455d1979ca89f89b198d3b324e0cd50faf8","src/ty.rs":"98e6c3940b5db9158f54e9633a62cecfec8eaf17c1715222bc2bc761cc37333f","src/visit.rs":"d7dcf429cc1a05821a66a4b38e7856eec45a9b2215f625d95030c3688eda26ca"},"package":"94e7d81ecd16d39f16193af05b8d5a0111b9d8d2f3f78f31760f327a247da777"}
\ No newline at end of file
--- a/third_party/rust/syn/Cargo.toml
+++ b/third_party/rust/syn/Cargo.toml
@@ -1,28 +1,32 @@
 [package]
 name = "syn"
-version = "0.9.2" # don't forget to update version in readme
+version = "0.10.3" # don't forget to update version in readme
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 license = "MIT/Apache-2.0"
 description = "Nom parser for Rust items"
 repository = "https://github.com/dtolnay/syn"
 documentation = "https://dtolnay.github.io/syn/syn/"
 include = ["Cargo.toml", "src/**/*.rs"]
 
 [features]
 default = ["parsing", "printing"]
 aster = []
+expand = ["full", "parsing", "printing"]
 full = []
 parsing = ["unicode-xid"]
+pretty = ["syntex_syntax"]
 printing = ["quote"]
 visit = []
 
 [dependencies]
 clippy = { version = "0.*", optional = true }
 quote = { version = "0.3.0", optional = true }
+syntex_syntax = { version = "0.47.0", optional = true }
 unicode-xid = { version = "0.0.3", optional = true }
 
 [dev-dependencies]
-syntex_pos = "0.44.0"
-syntex_syntax = "0.44.0"
+syntex_pos = "0.47.0"
+syntex_syntax = "0.47.0"
+tempdir = "0.3.5"
 time = "0.1.35"
-walkdir = "0.1.8"
+walkdir = "1.0.1"
--- a/third_party/rust/syn/src/aster/lifetime.rs
+++ b/third_party/rust/syn/src/aster/lifetime.rs
@@ -29,16 +29,17 @@ impl IntoLifetimeDef for LifetimeDef {
     fn into_lifetime_def(self) -> LifetimeDef {
         self
     }
 }
 
 impl IntoLifetimeDef for Lifetime {
     fn into_lifetime_def(self) -> LifetimeDef {
         LifetimeDef {
+            attrs: vec![],
             lifetime: self,
             bounds: vec![],
         }
     }
 }
 
 impl<'a> IntoLifetimeDef for &'a str {
     fn into_lifetime_def(self) -> LifetimeDef {
@@ -89,13 +90,14 @@ impl<F> LifetimeDefBuilder<F>
         let lifetime = Lifetime { ident: name.into() };
 
         self.bounds.push(lifetime);
         self
     }
 
     pub fn build(self) -> F::Result {
         self.callback.invoke(LifetimeDef {
+            attrs: vec![],
             lifetime: self.lifetime,
             bounds: self.bounds,
         })
     }
 }
--- a/third_party/rust/syn/src/aster/qpath.rs
+++ b/third_party/rust/syn/src/aster/qpath.rs
@@ -60,16 +60,19 @@ pub struct QPathTyBuilder<F> {
     builder: QPathBuilder<F>,
     ty: Ty,
 }
 
 impl<F> QPathTyBuilder<F>
     where F: Invoke<(QSelf, Path)>
 {
     /// Build a qualified path with a path builder.
+    // Clippy false positive
+    // https://github.com/Manishearth/rust-clippy/issues/1285
+    #[cfg_attr(feature = "clippy", allow(wrong_self_convention))]
     pub fn as_(self) -> PathBuilder<Self> {
         PathBuilder::with_callback(self)
     }
 
     pub fn id<T>(self, id: T) -> F::Result
         where T: ToIdent
     {
         let path = Path {
--- a/third_party/rust/syn/src/aster/ty_param.rs
+++ b/third_party/rust/syn/src/aster/ty_param.rs
@@ -82,16 +82,17 @@ impl<F> TyParamBuilder<F>
         let lifetime = lifetime.into_lifetime();
 
         self.bounds.push(TyParamBound::Region(lifetime));
         self
     }
 
     pub fn build(self) -> F::Result {
         self.callback.invoke(TyParam {
+            attrs: vec![],
             ident: self.id,
             bounds: self.bounds,
             default: self.default,
         })
     }
 }
 
 impl<F> Invoke<Ty> for TyParamBuilder<F>
--- a/third_party/rust/syn/src/attr.rs
+++ b/third_party/rust/syn/src/attr.rs
@@ -32,33 +32,46 @@ pub enum AttrStyle {
 pub enum MetaItem {
     /// Word meta item.
     ///
     /// E.g. `test` as in `#[test]`
     Word(Ident),
     /// List meta item.
     ///
     /// E.g. `derive(..)` as in `#[derive(..)]`
-    List(Ident, Vec<MetaItem>),
+    List(Ident, Vec<NestedMetaItem>),
     /// Name value meta item.
     ///
     /// E.g. `feature = "foo"` as in `#[feature = "foo"]`
     NameValue(Ident, Lit),
 }
 
 impl MetaItem {
     pub fn name(&self) -> &str {
         match *self {
             MetaItem::Word(ref name) |
             MetaItem::List(ref name, _) |
             MetaItem::NameValue(ref name, _) => name.as_ref(),
         }
     }
 }
 
+/// Possible values inside of compile-time attribute lists.
+///
+/// E.g. the '..' in `#[name(..)]`.
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub enum NestedMetaItem {
+    /// A full MetaItem, for recursive meta items.
+    MetaItem(MetaItem),
+    /// A literal.
+    ///
+    /// E.g. "foo", 64, true
+    Literal(Lit),
+}
+
 pub trait FilterAttrs<'a> {
     type Ret: Iterator<Item = &'a Attribute>;
 
     fn outer(self) -> Self::Ret;
     fn inner(self) -> Self::Ret;
 }
 
 impl<'a, T> FilterAttrs<'a> for T
@@ -80,17 +93,16 @@ impl<'a, T> FilterAttrs<'a> for T
         self.into_iter().filter(is_inner)
     }
 }
 
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
     use ident::parsing::ident;
-    use lit::{Lit, StrStyle};
     use lit::parsing::lit;
     use space::{block_comment, whitespace};
 
     #[cfg(feature = "full")]
     named!(pub inner_attr -> Attribute, alt!(
         do_parse!(
             punct!("#") >>
             punct!("!") >>
@@ -106,34 +118,31 @@ pub mod parsing {
         |
         do_parse!(
             punct!("//!") >>
             content: take_until!("\n") >>
             (Attribute {
                 style: AttrStyle::Inner,
                 value: MetaItem::NameValue(
                     "doc".into(),
-                    Lit::Str(
-                        format!("//!{}", content),
-                        StrStyle::Cooked,
-                    ),
+                    format!("//!{}", content).into(),
                 ),
                 is_sugared_doc: true,
             })
         )
         |
         do_parse!(
             option!(whitespace) >>
             peek!(tag!("/*!")) >>
             com: block_comment >>
             (Attribute {
                 style: AttrStyle::Inner,
                 value: MetaItem::NameValue(
                     "doc".into(),
-                    Lit::Str(com.to_owned(), StrStyle::Cooked),
+                    com.into(),
                 ),
                 is_sugared_doc: true,
             })
         )
     ));
 
     named!(pub outer_attr -> Attribute, alt!(
         do_parse!(
@@ -151,58 +160,61 @@ pub mod parsing {
         do_parse!(
             punct!("///") >>
             not!(peek!(tag!("/"))) >>
             content: take_until!("\n") >>
             (Attribute {
                 style: AttrStyle::Outer,
                 value: MetaItem::NameValue(
                     "doc".into(),
-                    Lit::Str(
-                        format!("///{}", content),
-                        StrStyle::Cooked,
-                    ),
+                    format!("///{}", content).into(),
                 ),
                 is_sugared_doc: true,
             })
         )
         |
         do_parse!(
             option!(whitespace) >>
             peek!(tuple!(tag!("/**"), not!(tag!("*")))) >>
             com: block_comment >>
             (Attribute {
                 style: AttrStyle::Outer,
                 value: MetaItem::NameValue(
                     "doc".into(),
-                    Lit::Str(com.to_owned(), StrStyle::Cooked),
+                    com.into(),
                 ),
                 is_sugared_doc: true,
             })
         )
     ));
 
     named!(meta_item -> MetaItem, alt!(
         do_parse!(
             id: ident >>
             punct!("(") >>
-            inner: terminated_list!(punct!(","), meta_item) >>
+            inner: terminated_list!(punct!(","), nested_meta_item) >>
             punct!(")") >>
             (MetaItem::List(id, inner))
         )
         |
         do_parse!(
             name: ident >>
             punct!("=") >>
             value: lit >>
             (MetaItem::NameValue(name, value))
         )
         |
         map!(ident, MetaItem::Word)
     ));
+
+    named!(nested_meta_item -> NestedMetaItem, alt!(
+        meta_item => { NestedMetaItem::MetaItem }
+        |
+        lit => { NestedMetaItem::Literal }
+    ));
 }
 
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
     use lit::{Lit, StrStyle};
     use quote::{Tokens, ToTokens};
 
@@ -260,9 +272,22 @@ mod printing {
                 MetaItem::NameValue(ref name, ref value) => {
                     name.to_tokens(tokens);
                     tokens.append("=");
                     value.to_tokens(tokens);
                 }
             }
         }
     }
+
+    impl ToTokens for NestedMetaItem {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            match *self {
+                NestedMetaItem::MetaItem(ref nested) => {
+                    nested.to_tokens(tokens);
+                }
+                NestedMetaItem::Literal(ref lit) => {
+                    lit.to_tokens(tokens);
+                }
+            }
+        }
+    }
 }
--- a/third_party/rust/syn/src/constant.rs
+++ b/third_party/rust/syn/src/constant.rs
@@ -13,47 +13,69 @@ pub enum ConstExpr {
     Unary(UnOp, Box<ConstExpr>),
     /// A literal (For example: `1`, `"foo"`)
     Lit(Lit),
     /// A cast (`foo as f64`)
     Cast(Box<ConstExpr>, Box<Ty>),
     /// Variable reference, possibly containing `::` and/or type
     /// parameters, e.g. foo::bar::<baz>.
     Path(Path),
+    /// An indexing operation (`foo[2]`)
+    Index(Box<ConstExpr>, Box<ConstExpr>),
+    /// No-op: used solely so we can pretty-print faithfully
+    Paren(Box<ConstExpr>),
+    /// If compiling with full support for expression syntax, any expression is
+    /// allowed
+    Other(Other),
 }
 
+#[cfg(not(feature = "full"))]
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct Other {
+    _private: (),
+}
+
+#[cfg(feature = "full")]
+pub type Other = Expr;
+
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
     use {BinOp, Ty};
     use lit::parsing::lit;
     use op::parsing::{binop, unop};
     use ty::parsing::{path, ty};
 
     named!(pub const_expr -> ConstExpr, do_parse!(
         mut e: alt!(
+            expr_unary
+            |
             expr_lit
             |
-            expr_unary
+            expr_path
             |
-            path => { ConstExpr::Path }
+            expr_paren
         ) >>
         many0!(alt!(
             tap!(args: and_call => {
                 e = ConstExpr::Call(Box::new(e), args);
             })
             |
             tap!(more: and_binary => {
                 let (op, other) = more;
                 e = ConstExpr::Binary(op, Box::new(e), Box::new(other));
             })
             |
             tap!(ty: and_cast => {
                 e = ConstExpr::Cast(Box::new(e), Box::new(ty));
             })
+            |
+            tap!(i: and_index => {
+                e = ConstExpr::Index(Box::new(e), Box::new(i));
+            })
         )) >>
         (e)
     ));
 
     named!(and_call -> Vec<ConstExpr>, do_parse!(
         punct!("(") >>
         args: terminated_list!(punct!(","), const_expr) >>
         punct!(")") >>
@@ -65,16 +87,27 @@ pub mod parsing {
     named!(expr_unary -> ConstExpr, do_parse!(
         operator: unop >>
         operand: const_expr >>
         (ConstExpr::Unary(operator, Box::new(operand)))
     ));
 
     named!(expr_lit -> ConstExpr, map!(lit, ConstExpr::Lit));
 
+    named!(expr_path -> ConstExpr, map!(path, ConstExpr::Path));
+
+    named!(and_index -> ConstExpr, delimited!(punct!("["), const_expr, punct!("]")));
+
+    named!(expr_paren -> ConstExpr, do_parse!(
+        punct!("(") >>
+        e: const_expr >>
+        punct!(")") >>
+        (ConstExpr::Paren(Box::new(e)))
+    ));
+
     named!(and_cast -> Ty, do_parse!(
         keyword!("as") >>
         ty: ty >>
         (ty)
     ));
 }
 
 #[cfg(feature = "printing")]
@@ -102,12 +135,33 @@ mod printing {
                 }
                 ConstExpr::Lit(ref lit) => lit.to_tokens(tokens),
                 ConstExpr::Cast(ref expr, ref ty) => {
                     expr.to_tokens(tokens);
                     tokens.append("as");
                     ty.to_tokens(tokens);
                 }
                 ConstExpr::Path(ref path) => path.to_tokens(tokens),
+                ConstExpr::Index(ref expr, ref index) => {
+                    expr.to_tokens(tokens);
+                    tokens.append("[");
+                    index.to_tokens(tokens);
+                    tokens.append("]");
+                }
+                ConstExpr::Paren(ref expr) => {
+                    tokens.append("(");
+                    expr.to_tokens(tokens);
+                    tokens.append(")");
+                }
+                ConstExpr::Other(ref other) => {
+                    other.to_tokens(tokens);
+                }
             }
         }
     }
+
+    #[cfg(not(feature = "full"))]
+    impl ToTokens for Other {
+        fn to_tokens(&self, _tokens: &mut Tokens) {
+            unreachable!()
+        }
+    }
 }
--- a/third_party/rust/syn/src/data.rs
+++ b/third_party/rust/syn/src/data.rs
@@ -37,43 +37,61 @@ impl VariantData {
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct Field {
     pub ident: Option<Ident>,
     pub vis: Visibility,
     pub attrs: Vec<Attribute>,
     pub ty: Ty,
 }
 
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+#[derive(Debug, Clone, Eq, PartialEq)]
 pub enum Visibility {
     Public,
+    Crate,
+    Restricted(Box<Path>),
     Inherited,
 }
 
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
+    use WhereClause;
     use attr::parsing::outer_attr;
     use constant::parsing::const_expr;
+    use generics::parsing::where_clause;
     use ident::parsing::ident;
-    use ty::parsing::ty;
+    use ty::parsing::{path, ty};
 
-    named!(pub struct_body -> VariantData, alt!(
-        struct_like_body => { VariantData::Struct }
+    named!(pub struct_body -> (WhereClause, VariantData), alt!(
+        do_parse!(
+            wh: where_clause >>
+            body: struct_like_body >>
+            (wh, VariantData::Struct(body))
+        )
         |
-        terminated!(tuple_like_body, punct!(";")) => { VariantData::Tuple }
+        do_parse!(
+            body: tuple_like_body >>
+            wh: where_clause >>
+            punct!(";") >>
+            (wh, VariantData::Tuple(body))
+        )
         |
-        punct!(";") => { |_| VariantData::Unit }
+        do_parse!(
+            wh: where_clause >>
+            punct!(";") >>
+            (wh, VariantData::Unit)
+        )
     ));
 
-    named!(pub enum_body -> Vec<Variant>, do_parse!(
+    named!(pub enum_body -> (WhereClause, Vec<Variant>), do_parse!(
+        wh: where_clause >>
         punct!("{") >>
         variants: terminated_list!(punct!(","), variant) >>
         punct!("}") >>
-        (variants)
+        (wh, variants)
     ));
 
     named!(variant -> Variant, do_parse!(
         attrs: many0!(outer_attr) >>
         id: ident >>
         data: alt!(
             struct_like_body => { VariantData::Struct }
             |
@@ -126,16 +144,32 @@ pub mod parsing {
             ident: None,
             vis: vis,
             attrs: attrs,
             ty: ty,
         })
     ));
 
     named!(pub visibility -> Visibility, alt!(
+        do_parse!(
+            keyword!("pub") >>
+            punct!("(") >>
+            keyword!("crate") >>
+            punct!(")") >>
+            (Visibility::Crate)
+        )
+        |
+        do_parse!(
+            keyword!("pub") >>
+            punct!("(") >>
+            restricted: path >>
+            punct!(")") >>
+            (Visibility::Restricted(Box::new(restricted)))
+        )
+        |
         keyword!("pub") => { |_| Visibility::Public }
         |
         epsilon!() => { |_| Visibility::Inherited }
     ));
 }
 
 #[cfg(feature = "printing")]
 mod printing {
@@ -185,14 +219,27 @@ mod printing {
                 tokens.append(":");
             }
             self.ty.to_tokens(tokens);
         }
     }
 
     impl ToTokens for Visibility {
         fn to_tokens(&self, tokens: &mut Tokens) {
-            if let Visibility::Public = *self {
-                tokens.append("pub");
+            match *self {
+                Visibility::Public => tokens.append("pub"),
+                Visibility::Crate => {
+                    tokens.append("pub");
+                    tokens.append("(");
+                    tokens.append("crate");
+                    tokens.append(")");
+                }
+                Visibility::Restricted(ref path) => {
+                    tokens.append("pub");
+                    tokens.append("(");
+                    path.to_tokens(tokens);
+                    tokens.append(")");
+                }
+                Visibility::Inherited => {}
             }
         }
     }
 }
--- a/third_party/rust/syn/src/escape.rs
+++ b/third_party/rust/syn/src/escape.rs
@@ -1,23 +1,31 @@
 use std::{char, str};
+use std::num::ParseIntError;
 use nom::IResult;
 
 pub fn cooked_string(input: &str) -> IResult<&str, String> {
     let mut s = String::new();
     let mut chars = input.char_indices().peekable();
     while let Some((byte_offset, ch)) = chars.next() {
         match ch {
             '"' => {
                 return IResult::Done(&input[byte_offset..], s);
             }
+            '\r' => {
+                if let Some((_, '\n')) = chars.next() {
+                    s.push('\n');
+                } else {
+                    break;
+                }
+            }
             '\\' => {
                 match chars.next() {
                     Some((_, 'x')) => {
-                        match backslash_x(&mut chars) {
+                        match backslash_x_char(&mut chars) {
                             Some(ch) => s.push(ch),
                             None => break,
                         }
                     }
                     Some((_, 'n')) => s.push('\n'),
                     Some((_, 'r')) => s.push('\r'),
                     Some((_, 't')) => s.push('\t'),
                     Some((_, '\\')) => s.push('\\'),
@@ -25,17 +33,17 @@ pub fn cooked_string(input: &str) -> IRe
                     Some((_, 'u')) => {
                         match backslash_u(&mut chars) {
                             Some(ch) => s.push(ch),
                             None => break,
                         }
                     }
                     Some((_, '\'')) => s.push('\''),
                     Some((_, '"')) => s.push('"'),
-                    Some((_, '\n')) => {
+                    Some((_, '\n')) | Some((_, '\r')) => {
                         while let Some(&(_, ch)) = chars.peek() {
                             if ch.is_whitespace() {
                                 chars.next();
                             } else {
                                 break;
                             }
                         }
                     }
@@ -45,22 +53,76 @@ pub fn cooked_string(input: &str) -> IRe
             ch => {
                 s.push(ch);
             }
         }
     }
     IResult::Error
 }
 
+pub fn cooked_byte_string(mut input: &str) -> IResult<&str, Vec<u8>> {
+    let mut vec = Vec::new();
+    let mut bytes = input.bytes().enumerate();
+    'outer: while let Some((offset, b)) = bytes.next() {
+        match b {
+            b'"' => {
+                return IResult::Done(&input[offset..], vec);
+            }
+            b'\r' => {
+                if let Some((_, b'\n')) = bytes.next() {
+                    vec.push(b'\n');
+                } else {
+                    break;
+                }
+            }
+            b'\\' => {
+                match bytes.next() {
+                    Some((_, b'x')) => {
+                        match backslash_x_byte(&mut bytes) {
+                            Some(b) => vec.push(b),
+                            None => break,
+                        }
+                    }
+                    Some((_, b'n')) => vec.push(b'\n'),
+                    Some((_, b'r')) => vec.push(b'\r'),
+                    Some((_, b't')) => vec.push(b'\t'),
+                    Some((_, b'\\')) => vec.push(b'\\'),
+                    Some((_, b'0')) => vec.push(b'\0'),
+                    Some((_, b'\'')) => vec.push(b'\''),
+                    Some((_, b'"')) => vec.push(b'"'),
+                    Some((newline, b'\n')) |
+                    Some((newline, b'\r')) => {
+                        let rest = &input[newline + 1..];
+                        for (offset, ch) in rest.char_indices() {
+                            if !ch.is_whitespace() {
+                                input = &rest[offset..];
+                                bytes = input.bytes().enumerate();
+                                continue 'outer;
+                            }
+                        }
+                        break;
+                    }
+                    _ => break,
+                }
+            }
+            b if b < 0x80 => {
+                vec.push(b);
+            }
+            _ => break,
+        }
+    }
+    IResult::Error
+}
+
 pub fn cooked_char(input: &str) -> IResult<&str, char> {
     let mut chars = input.char_indices();
     let ch = match chars.next().map(|(_, ch)| ch) {
         Some('\\') => {
             match chars.next().map(|(_, ch)| ch) {
-                Some('x') => backslash_x(&mut chars),
+                Some('x') => backslash_x_char(&mut chars),
                 Some('n') => Some('\n'),
                 Some('r') => Some('\r'),
                 Some('t') => Some('\t'),
                 Some('\\') => Some('\\'),
                 Some('0') => Some('\0'),
                 Some('u') => backslash_u(&mut chars),
                 Some('\'') => Some('\''),
                 Some('"') => Some('"'),
@@ -70,94 +132,161 @@ pub fn cooked_char(input: &str) -> IResu
         ch => ch,
     };
     match ch {
         Some(ch) => IResult::Done(chars.as_str(), ch),
         None => IResult::Error,
     }
 }
 
+pub fn cooked_byte(input: &str) -> IResult<&str, u8> {
+    let mut bytes = input.bytes().enumerate();
+    let b = match bytes.next().map(|(_, b)| b) {
+        Some(b'\\') => {
+            match bytes.next().map(|(_, b)| b) {
+                Some(b'x') => backslash_x_byte(&mut bytes),
+                Some(b'n') => Some(b'\n'),
+                Some(b'r') => Some(b'\r'),
+                Some(b't') => Some(b'\t'),
+                Some(b'\\') => Some(b'\\'),
+                Some(b'0') => Some(b'\0'),
+                Some(b'\'') => Some(b'\''),
+                Some(b'"') => Some(b'"'),
+                _ => None,
+            }
+        }
+        b => b,
+    };
+    match b {
+        Some(b) => {
+            match bytes.next() {
+                Some((offset, _)) => IResult::Done(&input[offset..], b),
+                None => IResult::Done("", b),
+            }
+        }
+        None => IResult::Error,
+    }
+}
+
 pub fn raw_string(input: &str) -> IResult<&str, (String, usize)> {
     let mut chars = input.char_indices();
     let mut n = 0;
     while let Some((byte_offset, ch)) = chars.next() {
         match ch {
             '"' => {
                 n = byte_offset;
                 break;
             }
             '#' => {}
             _ => return IResult::Error,
         }
     }
+    let mut s = String::new();
     for (byte_offset, ch) in chars {
-        if ch == '"' && input[byte_offset + 1..].starts_with(&input[..n]) {
-            let rest = &input[byte_offset + 1 + n..];
-            let value = &input[n + 1..byte_offset];
-            return IResult::Done(rest, (value.to_owned(), n));
+        match ch {
+            '"' if input[byte_offset + 1..].starts_with(&input[..n]) => {
+                let rest = &input[byte_offset + 1 + n..];
+                return IResult::Done(rest, (s, n));
+            }
+            '\r' => {}
+            _ => s.push(ch),
         }
     }
     IResult::Error
 }
 
-macro_rules! next_char {
+macro_rules! next_ch {
     ($chars:ident @ $pat:pat $(| $rest:pat)*) => {
         match $chars.next() {
             Some((_, ch)) => match ch {
                 $pat $(| $rest)*  => ch,
                 _ => return None,
             },
             None => return None,
         }
     };
 }
 
+trait FromStrRadix: Sized {
+    fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError>;
+}
+
+impl FromStrRadix for u8 {
+    fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
+        u8::from_str_radix(src, radix)
+    }
+}
+
+impl FromStrRadix for u32 {
+    fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
+        u32::from_str_radix(src, radix)
+    }
+}
+
+macro_rules! from_hex {
+    ($($ch:ident)+) => {{
+        let hex_bytes = &[$($ch as u8),*];
+        let hex_str = str::from_utf8(hex_bytes).unwrap();
+        FromStrRadix::from_str_radix(hex_str, 16).unwrap()
+    }};
+}
+
 #[cfg_attr(feature = "clippy", allow(diverging_sub_expression))]
-fn backslash_x<I>(chars: &mut I) -> Option<char>
+fn backslash_x_char<I>(chars: &mut I) -> Option<char>
     where I: Iterator<Item = (usize, char)>
 {
-    let a = next_char!(chars @ '0'...'7');
-    let b = next_char!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F');
-    char_from_hex_bytes(&[a as u8, b as u8])
+    let a = next_ch!(chars @ '0'...'7');
+    let b = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F');
+    char::from_u32(from_hex!(a b))
+}
+
+#[cfg_attr(feature = "clippy", allow(diverging_sub_expression))]
+fn backslash_x_byte<I>(chars: &mut I) -> Option<u8>
+    where I: Iterator<Item = (usize, u8)>
+{
+    let a = next_ch!(chars @ b'0'...b'9' | b'a'...b'f' | b'A'...b'F');
+    let b = next_ch!(chars @ b'0'...b'9' | b'a'...b'f' | b'A'...b'F');
+    Some(from_hex!(a b))
 }
 
 #[cfg_attr(feature = "clippy", allow(diverging_sub_expression, many_single_char_names))]
 fn backslash_u<I>(chars: &mut I) -> Option<char>
     where I: Iterator<Item = (usize, char)>
 {
-    next_char!(chars @ '{');
-    let a = next_char!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F');
-    let b = next_char!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}');
+    next_ch!(chars @ '{');
+    let a = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F');
+    let b = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}');
     if b == '}' {
-        return char_from_hex_bytes(&[a as u8]);
+        return char::from_u32(from_hex!(a));
     }
-    let c = next_char!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}');
+    let c = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}');
     if c == '}' {
-        return char_from_hex_bytes(&[a as u8, b as u8]);
-    }
-    let d = next_char!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}');
-    if d == '}' {
-        return char_from_hex_bytes(&[a as u8, b as u8, c as u8]);
+        return char::from_u32(from_hex!(a b));
     }
-    let e = next_char!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}');
-    if e == '}' {
-        return char_from_hex_bytes(&[a as u8, b as u8, c as u8, d as u8]);
-    }
-    let f = next_char!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}');
-    if f == '}' {
-        return char_from_hex_bytes(&[a as u8, b as u8, c as u8, d as u8, e as u8]);
+    let d = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}');
+    if d == '}' {
+        return char::from_u32(from_hex!(a b c));
     }
-    next_char!(chars @ '}');
-    char_from_hex_bytes(&[a as u8, b as u8, c as u8, d as u8, e as u8, f as u8])
-}
-
-/// Assumes the bytes are all '0'...'9' | 'a'...'f' | 'A'...'F'.
-fn char_from_hex_bytes(hex_bytes: &[u8]) -> Option<char> {
-    let hex_str = unsafe { str::from_utf8_unchecked(hex_bytes) };
-    char::from_u32(u32::from_str_radix(hex_str, 16).unwrap())
+    let e = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}');
+    if e == '}' {
+        return char::from_u32(from_hex!(a b c d));
+    }
+    let f = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '}');
+    if f == '}' {
+        return char::from_u32(from_hex!(a b c d e));
+    }
+    next_ch!(chars @ '}');
+    char::from_u32(from_hex!(a b c d e f))
 }
 
 #[test]
 fn test_cooked_string() {
-    let input = r#"\x62 \u{7} \u{64} \u{bf5} \u{12ba} \u{1F395} \u{102345}""#;
+    let input = "\\x62 \\\n \\u{7} \\u{64} \\u{bf5} \\u{12ba} \\u{1F395} \\u{102345}\"";
     let expected = "\x62 \u{7} \u{64} \u{bf5} \u{12ba} \u{1F395} \u{102345}";
     assert_eq!(cooked_string(input), IResult::Done("\"", expected.to_string()));
 }
+
+#[test]
+fn test_cooked_byte_string() {
+    let input = "\\x62 \\\n \\xEF\"";
+    let expected = b"\x62 \xEF";
+    assert_eq!(cooked_byte_string(input), IResult::Done("\"", expected.to_vec()));
+}
--- a/third_party/rust/syn/src/expr.rs
+++ b/third_party/rust/syn/src/expr.rs
@@ -1,14 +1,31 @@
 use super::*;
 
 #[derive(Debug, Clone, Eq, PartialEq)]
-pub enum Expr {
+pub struct Expr {
+    pub node: ExprKind,
+    pub attrs: Vec<Attribute>,
+}
+
+impl From<ExprKind> for Expr {
+    fn from(node: ExprKind) -> Expr {
+        Expr {
+            node: node,
+            attrs: Vec::new(),
+        }
+    }
+}
+
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub enum ExprKind {
     /// A `box x` expression.
     Box(Box<Expr>),
+    /// First expr is the place; second expr is the value.
+    InPlace(Box<Expr>, Box<Expr>),
     /// An array (`[a, b, c, d]`)
     Vec(Vec<Expr>),
     /// A function call
     ///
     /// The first field resolves to the function itself,
     /// and the second field is the list of arguments
     Call(Box<Expr>, Vec<Expr>),
     /// A method call (`x.foo::<Bar, Baz>(a, b, c, d)`)
@@ -127,16 +144,17 @@ pub enum Expr {
     /// `expr?`
     Try(Box<Expr>),
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct FieldValue {
     pub ident: Ident,
     pub expr: Expr,
+    pub is_shorthand: bool,
 }
 
 /// A Block (`{ .. }`).
 ///
 /// E.g. `{ .. }` as in `fn foo() { .. }`
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct Block {
     /// Statements in a block
@@ -184,16 +202,19 @@ pub struct Local {
     pub pat: Box<Pat>,
     pub ty: Option<Box<Ty>>,
     /// Initializer expression to set the value, if any
     pub init: Option<Box<Expr>>,
     pub attrs: Vec<Attribute>,
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
+// Clippy false positive
+// https://github.com/Manishearth/rust-clippy/issues/1241
+#[cfg_attr(feature = "clippy", allow(enum_variant_names))]
 pub enum Pat {
     /// Represents a wildcard pattern (`_`)
     Wild,
 
     /// A `Pat::Ident` may either be a new bound variable (`ref mut binding @ OPT_SUBPATTERN`),
     /// or a unit struct/variant pattern, or a const pattern (in the last two cases the third
     /// field must be `None`). Disambiguation cannot be done with parser alone, so it happens
     /// during name resolution.
@@ -218,19 +239,19 @@ pub enum Pat {
     /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
     /// 0 <= position <= subpats.len()
     Tuple(Vec<Pat>, Option<usize>),
     /// A `box` pattern
     Box(Box<Pat>),
     /// A reference pattern, e.g. `&mut (a, b)`
     Ref(Box<Pat>, Mutability),
     /// A literal
-    Lit(Box<Lit>),
+    Lit(Box<Expr>),
     /// A range pattern, e.g. `1...2`
-    Range(Box<Lit>, Box<Lit>),
+    Range(Box<Expr>, Box<Expr>),
     /// `[a, b, ..i, y, z]` is represented as:
     ///     `Pat::Slice(box [a, b], Some(i), box [y, z])`
     Slice(Vec<Pat>, Option<Box<Pat>>, Vec<Pat>),
     /// A macro pattern; pre-expansion
     Mac(Mac),
 }
 
 /// An arm of a 'match'.
@@ -285,151 +306,190 @@ pub struct FieldPat {
 pub enum BindingMode {
     ByRef(Mutability),
     ByValue(Mutability),
 }
 
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use {BinOp, Delimited, DelimToken, FnArg, FnDecl, FunctionRetTy, Ident, Lifetime, TokenTree,
-         Ty};
+    use {BinOp, Delimited, DelimToken, FnArg, FnDecl, FunctionRetTy, Ident, Lifetime, Mac,
+         TokenTree, Ty, UnOp};
     use attr::parsing::outer_attr;
     use generics::parsing::lifetime;
-    use ident::parsing::ident;
+    use ident::parsing::{ident, wordlike};
     use item::parsing::item;
     use lit::parsing::{digits, lit};
-    use mac::parsing::mac;
-    use nom::IResult::Error;
+    use mac::parsing::{mac, token_trees};
+    use nom::IResult::{self, Error};
     use op::parsing::{assign_op, binop, unop};
     use ty::parsing::{mutability, path, qpath, ty};
 
-    named!(pub expr -> Expr, do_parse!(
-        mut e: alt!(
-            expr_lit // must be before expr_struct
-            |
-            expr_struct // must be before expr_path
-            |
-            expr_paren // must be before expr_tup
-            |
-            expr_mac // must be before expr_path
-            |
-            expr_break // must be before expr_path
-            |
-            expr_continue // must be before expr_path
-            |
-            expr_ret // must be before expr_path
-            |
-            expr_box
-            |
-            expr_vec
-            |
-            expr_tup
-            |
-            expr_unary
-            |
-            expr_if
-            |
-            expr_while
-            |
-            expr_for_loop
-            |
-            expr_loop
-            |
-            expr_match
-            |
-            expr_closure
-            |
-            expr_block
-            |
-            expr_range
-            |
-            expr_path
-            |
-            expr_addr_of
-            |
-            expr_repeat
-        ) >>
-        many0!(alt!(
-            tap!(args: and_call => {
-                e = Expr::Call(Box::new(e), args);
-            })
-            |
-            tap!(more: and_method_call => {
-                let (method, ascript, mut args) = more;
-                args.insert(0, e);
-                e = Expr::MethodCall(method, ascript, args);
-            })
-            |
-            tap!(more: and_binary => {
-                let (op, other) = more;
-                e = Expr::Binary(op, Box::new(e), Box::new(other));
-            })
-            |
-            tap!(ty: and_cast => {
-                e = Expr::Cast(Box::new(e), Box::new(ty));
-            })
-            |
-            tap!(ty: and_ascription => {
-                e = Expr::Type(Box::new(e), Box::new(ty));
-            })
-            |
-            tap!(v: and_assign => {
-                e = Expr::Assign(Box::new(e), Box::new(v));
-            })
-            |
-            tap!(more: and_assign_op => {
-                let (op, v) = more;
-                e = Expr::AssignOp(op, Box::new(e), Box::new(v));
-            })
-            |
-            tap!(field: and_field => {
-                e = Expr::Field(Box::new(e), field);
-            })
-            |
-            tap!(field: and_tup_field => {
-                e = Expr::TupField(Box::new(e), field as usize);
-            })
-            |
-            tap!(i: and_index => {
-                e = Expr::Index(Box::new(e), Box::new(i));
-            })
-            |
-            tap!(more: and_range => {
-                let (limits, hi) = more;
-                e = Expr::Range(Some(Box::new(e)), hi.map(Box::new), limits);
-            })
-            |
-            tap!(_try: punct!("?") => {
-                e = Expr::Try(Box::new(e));
-            })
-        )) >>
-        (e)
-    ));
+    // Struct literals are ambiguous in certain positions
+    // https://github.com/rust-lang/rfcs/pull/92
+    macro_rules! named_ambiguous_expr {
+        ($name:ident -> $o:ty, $allow_struct:ident, $submac:ident!( $($args:tt)* )) => {
+            fn $name(i: &str, $allow_struct: bool) -> $crate::nom::IResult<&str, $o> {
+                $submac!(i, $($args)*)
+            }
+        };
+    }
+
+    macro_rules! ambiguous_expr {
+        ($i:expr, $allow_struct:ident) => {
+            ambiguous_expr($i, $allow_struct, true)
+        };
+    }
+
+    named!(pub expr -> Expr, ambiguous_expr!(true));
+
+    named!(expr_no_struct -> Expr, ambiguous_expr!(false));
 
-    named!(expr_mac -> Expr, map!(mac, Expr::Mac));
+    fn ambiguous_expr(i: &str, allow_struct: bool, allow_block: bool) -> IResult<&str, Expr> {
+        do_parse!(
+            i,
+            mut e: alt!(
+                expr_lit // must be before expr_struct
+                |
+                cond_reduce!(allow_struct, expr_struct) // must be before expr_path
+                |
+                expr_paren // must be before expr_tup
+                |
+                expr_mac // must be before expr_path
+                |
+                expr_break // must be before expr_path
+                |
+                expr_continue // must be before expr_path
+                |
+                call!(expr_ret, allow_struct) // must be before expr_path
+                |
+                call!(expr_box, allow_struct)
+                |
+                expr_in_place
+                |
+                expr_vec
+                |
+                expr_tup
+                |
+                call!(expr_unary, allow_struct)
+                |
+                expr_if
+                |
+                expr_while
+                |
+                expr_for_loop
+                |
+                expr_loop
+                |
+                expr_match
+                |
+                call!(expr_closure, allow_struct)
+                |
+                cond_reduce!(allow_block, expr_block)
+                |
+                call!(expr_range, allow_struct)
+                |
+                expr_path
+                |
+                call!(expr_addr_of, allow_struct)
+                |
+                expr_repeat
+            ) >>
+            many0!(alt!(
+                tap!(args: and_call => {
+                    e = ExprKind::Call(Box::new(e.into()), args);
+                })
+                |
+                tap!(more: and_method_call => {
+                    let (method, ascript, mut args) = more;
+                    args.insert(0, e.into());
+                    e = ExprKind::MethodCall(method, ascript, args);
+                })
+                |
+                tap!(more: call!(and_binary, allow_struct) => {
+                    let (op, other) = more;
+                    e = ExprKind::Binary(op, Box::new(e.into()), Box::new(other));
+                })
+                |
+                tap!(ty: and_cast => {
+                    e = ExprKind::Cast(Box::new(e.into()), Box::new(ty));
+                })
+                |
+                tap!(ty: and_ascription => {
+                    e = ExprKind::Type(Box::new(e.into()), Box::new(ty));
+                })
+                |
+                tap!(v: call!(and_assign, allow_struct) => {
+                    e = ExprKind::Assign(Box::new(e.into()), Box::new(v));
+                })
+                |
+                tap!(more: call!(and_assign_op, allow_struct) => {
+                    let (op, v) = more;
+                    e = ExprKind::AssignOp(op, Box::new(e.into()), Box::new(v));
+                })
+                |
+                tap!(field: and_field => {
+                    e = ExprKind::Field(Box::new(e.into()), field);
+                })
+                |
+                tap!(field: and_tup_field => {
+                    e = ExprKind::TupField(Box::new(e.into()), field as usize);
+                })
+                |
+                tap!(i: and_index => {
+                    e = ExprKind::Index(Box::new(e.into()), Box::new(i));
+                })
+                |
+                tap!(more: call!(and_range, allow_struct) => {
+                    let (limits, hi) = more;
+                    e = ExprKind::Range(Some(Box::new(e.into())), hi.map(Box::new), limits);
+                })
+                |
+                tap!(_try: punct!("?") => {
+                    e = ExprKind::Try(Box::new(e.into()));
+                })
+            )) >>
+            (e.into())
+        )
+    }
 
-    named!(expr_paren -> Expr, do_parse!(
+    named!(expr_mac -> ExprKind, map!(mac, ExprKind::Mac));
+
+    named!(expr_paren -> ExprKind, do_parse!(
         punct!("(") >>
         e: expr >>
         punct!(")") >>
-        (Expr::Paren(Box::new(e)))
+        (ExprKind::Paren(Box::new(e)))
+    ));
+
+    named_ambiguous_expr!(expr_box -> ExprKind, allow_struct, do_parse!(
+        keyword!("box") >>
+        inner: ambiguous_expr!(allow_struct) >>
+        (ExprKind::Box(Box::new(inner)))
     ));
 
-    named!(expr_box -> Expr, do_parse!(
-        keyword!("box") >>
-        inner: expr >>
-        (Expr::Box(Box::new(inner)))
+    named!(expr_in_place -> ExprKind, do_parse!(
+        keyword!("in") >>
+        place: expr_no_struct >>
+        punct!("{") >>
+        value: within_block >>
+        punct!("}") >>
+        (ExprKind::InPlace(
+            Box::new(place),
+            Box::new(ExprKind::Block(BlockCheckMode::Default, Block {
+                stmts: value,
+            }).into()),
+        ))
     ));
 
-    named!(expr_vec -> Expr, do_parse!(
+    named!(expr_vec -> ExprKind, do_parse!(
         punct!("[") >>
         elems: terminated_list!(punct!(","), expr) >>
         punct!("]") >>
-        (Expr::Vec(elems))
+        (ExprKind::Vec(elems))
     ));
 
     named!(and_call -> Vec<Expr>, do_parse!(
         punct!("(") >>
         args: terminated_list!(punct!(","), expr) >>
         punct!(")") >>
         (args)
     ));
@@ -446,32 +506,35 @@ pub mod parsing {
             )
         )) >>
         punct!("(") >>
         args: terminated_list!(punct!(","), expr) >>
         punct!(")") >>
         (method, ascript, args)
     ));
 
-    named!(expr_tup -> Expr, do_parse!(
+    named!(expr_tup -> ExprKind, do_parse!(
         punct!("(") >>
         elems: terminated_list!(punct!(","), expr) >>
         punct!(")") >>
-        (Expr::Tup(elems))
+        (ExprKind::Tup(elems))
+    ));
+
+    named_ambiguous_expr!(and_binary -> (BinOp, Expr), allow_struct, tuple!(
+        binop,
+        ambiguous_expr!(allow_struct)
     ));
 
-    named!(and_binary -> (BinOp, Expr), tuple!(binop, expr));
-
-    named!(expr_unary -> Expr, do_parse!(
+    named_ambiguous_expr!(expr_unary -> ExprKind, allow_struct, do_parse!(
         operator: unop >>
-        operand: expr >>
-        (Expr::Unary(operator, Box::new(operand)))
+        operand: ambiguous_expr!(allow_struct) >>
+        (ExprKind::Unary(operator, Box::new(operand)))
     ));
 
-    named!(expr_lit -> Expr, map!(lit, Expr::Lit));
+    named!(expr_lit -> ExprKind, map!(lit, ExprKind::Lit));
 
     named!(and_cast -> Ty, do_parse!(
         keyword!("as") >>
         ty: ty >>
         (ty)
     ));
 
     named!(and_ascription -> Ty, preceded!(punct!(":"), ty));
@@ -481,271 +544,308 @@ pub mod parsing {
         Expr(Expr),
     }
 
     named!(cond -> Cond, alt!(
         do_parse!(
             keyword!("let") >>
             pat: pat >>
             punct!("=") >>
-            value: expr >>
+            value: expr_no_struct >>
             (Cond::Let(pat, value))
         )
         |
-        map!(expr, Cond::Expr)
+        map!(expr_no_struct, Cond::Expr)
     ));
 
-    named!(expr_if -> Expr, do_parse!(
+    named!(expr_if -> ExprKind, do_parse!(
         keyword!("if") >>
         cond: cond >>
         punct!("{") >>
         then_block: within_block >>
         punct!("}") >>
         else_block: option!(preceded!(
             keyword!("else"),
             alt!(
                 expr_if
                 |
                 do_parse!(
                     punct!("{") >>
                     else_block: within_block >>
                     punct!("}") >>
-                    (Expr::Block(BlockCheckMode::Default, Block {
+                    (ExprKind::Block(BlockCheckMode::Default, Block {
                         stmts: else_block,
-                    }))
+                    }).into())
                 )
             )
         )) >>
         (match cond {
-            Cond::Let(pat, expr) => Expr::IfLet(
+            Cond::Let(pat, expr) => ExprKind::IfLet(
                 Box::new(pat),
                 Box::new(expr),
                 Block {
                     stmts: then_block,
                 },
-                else_block.map(Box::new),
+                else_block.map(|els| Box::new(els.into())),
             ),
-            Cond::Expr(cond) => Expr::If(
+            Cond::Expr(cond) => ExprKind::If(
                 Box::new(cond),
                 Block {
                     stmts: then_block,
                 },
-                else_block.map(Box::new),
+                else_block.map(|els| Box::new(els.into())),
             ),
         })
     ));
 
-    named!(expr_for_loop -> Expr, do_parse!(
+    named!(expr_for_loop -> ExprKind, do_parse!(
         lbl: option!(terminated!(label, punct!(":"))) >>
         keyword!("for") >>
         pat: pat >>
         keyword!("in") >>
-        expr: expr >>
+        expr: expr_no_struct >>
         loop_block: block >>
-        (Expr::ForLoop(Box::new(pat), Box::new(expr), loop_block, lbl))
+        (ExprKind::ForLoop(Box::new(pat), Box::new(expr), loop_block, lbl))
     ));
 
-    named!(expr_loop -> Expr, do_parse!(
+    named!(expr_loop -> ExprKind, do_parse!(
         lbl: option!(terminated!(label, punct!(":"))) >>
         keyword!("loop") >>
         loop_block: block >>
-        (Expr::Loop(loop_block, lbl))
+        (ExprKind::Loop(loop_block, lbl))
+    ));
+
+    named!(expr_match -> ExprKind, do_parse!(
+        keyword!("match") >>
+        obj: expr_no_struct >>
+        punct!("{") >>
+        mut arms: many0!(do_parse!(
+            arm: match_arm >>
+            cond!(arm_requires_comma(&arm), punct!(",")) >>
+            cond!(!arm_requires_comma(&arm), option!(punct!(","))) >>
+            (arm)
+        )) >>
+        last_arm: option!(match_arm) >>
+        punct!("}") >>
+        (ExprKind::Match(Box::new(obj), {
+            arms.extend(last_arm);
+            arms
+        }))
     ));
 
-    named!(expr_match -> Expr, do_parse!(
-        keyword!("match") >>
-        obj: expr >>
-        punct!("{") >>
-        arms: many0!(do_parse!(
-            attrs: many0!(outer_attr) >>
-            pats: separated_nonempty_list!(punct!("|"), pat) >>
-            guard: option!(preceded!(keyword!("if"), expr)) >>
-            punct!("=>") >>
-            body: alt!(
-                map!(block, |blk| Expr::Block(BlockCheckMode::Default, blk))
-                |
-                expr
-            ) >>
-            option!(punct!(",")) >>
-            (Arm {
-                attrs: attrs,
-                pats: pats,
-                guard: guard.map(Box::new),
-                body: Box::new(body),
-            })
-        )) >>
-        punct!("}") >>
-        (Expr::Match(Box::new(obj), arms))
+    fn arm_requires_comma(arm: &Arm) -> bool {
+        if let ExprKind::Block(BlockCheckMode::Default, _) = arm.body.node {
+            false
+        } else {
+            true
+        }
+    }
+
+    named!(match_arm -> Arm, do_parse!(
+        attrs: many0!(outer_attr) >>
+        pats: separated_nonempty_list!(punct!("|"), pat) >>
+        guard: option!(preceded!(keyword!("if"), expr)) >>
+        punct!("=>") >>
+        body: alt!(
+            map!(block, |blk| ExprKind::Block(BlockCheckMode::Default, blk).into())
+            |
+            expr
+        ) >>
+        (Arm {
+            attrs: attrs,
+            pats: pats,
+            guard: guard.map(Box::new),
+            body: Box::new(body),
+        })
     ));
 
-    named!(expr_closure -> Expr, do_parse!(
+    named_ambiguous_expr!(expr_closure -> ExprKind, allow_struct, do_parse!(
         capture: capture_by >>
         punct!("|") >>
         inputs: terminated_list!(punct!(","), closure_arg) >>
         punct!("|") >>
         ret_and_body: alt!(
             do_parse!(
                 punct!("->") >>
                 ty: ty >>
                 body: block >>
                 ((FunctionRetTy::Ty(ty), body))
             )
             |
-            map!(expr, |e| (
+            map!(ambiguous_expr!(allow_struct), |e| (
                 FunctionRetTy::Default,
                 Block {
                     stmts: vec![Stmt::Expr(Box::new(e))],
                 },
             ))
         ) >>
-        (Expr::Closure(
+        (ExprKind::Closure(
             capture,
             Box::new(FnDecl {
                 inputs: inputs,
                 output: ret_and_body.0,
+                variadic: false,
             }),
             ret_and_body.1,
         ))
     ));
 
     named!(closure_arg -> FnArg, do_parse!(
         pat: pat >>
         ty: option!(preceded!(punct!(":"), ty)) >>
         (FnArg::Captured(pat, ty.unwrap_or(Ty::Infer)))
     ));
 
-    named!(expr_while -> Expr, do_parse!(
+    named!(expr_while -> ExprKind, do_parse!(
         lbl: option!(terminated!(label, punct!(":"))) >>
         keyword!("while") >>
         cond: cond >>
         while_block: block >>
         (match cond {
-            Cond::Let(pat, expr) => Expr::WhileLet(
+            Cond::Let(pat, expr) => ExprKind::WhileLet(
                 Box::new(pat),
                 Box::new(expr),
                 while_block,
                 lbl,
             ),
-            Cond::Expr(cond) => Expr::While(
+            Cond::Expr(cond) => ExprKind::While(
                 Box::new(cond),
                 while_block,
                 lbl,
             ),
         })
     ));
 
-    named!(expr_continue -> Expr, do_parse!(
+    named!(expr_continue -> ExprKind, do_parse!(
         keyword!("continue") >>
         lbl: option!(label) >>
-        (Expr::Continue(lbl))
+        (ExprKind::Continue(lbl))
     ));
 
-    named!(expr_break -> Expr, do_parse!(
+    named!(expr_break -> ExprKind, do_parse!(
         keyword!("break") >>
         lbl: option!(label) >>
-        (Expr::Break(lbl))
+        (ExprKind::Break(lbl))
     ));
 
-    named!(expr_ret -> Expr, do_parse!(
+    named_ambiguous_expr!(expr_ret -> ExprKind, allow_struct, do_parse!(
         keyword!("return") >>
-        ret_value: option!(expr) >>
-        (Expr::Ret(ret_value.map(Box::new)))
+        ret_value: option!(ambiguous_expr!(allow_struct)) >>
+        (ExprKind::Ret(ret_value.map(Box::new)))
     ));
 
-    named!(expr_struct -> Expr, do_parse!(
+    named!(expr_struct -> ExprKind, do_parse!(
         path: path >>
         punct!("{") >>
         fields: separated_list!(punct!(","), field_value) >>
         base: option!(do_parse!(
             cond!(!fields.is_empty(), punct!(",")) >>
             punct!("..") >>
             base: expr >>
             (base)
         )) >>
         cond!(!fields.is_empty() && base.is_none(), option!(punct!(","))) >>
         punct!("}") >>
-        (Expr::Struct(path, fields, base.map(Box::new)))
+        (ExprKind::Struct(path, fields, base.map(Box::new)))
     ));
 
-    named!(field_value -> FieldValue, do_parse!(
-        name: ident >>
-        punct!(":") >>
-        value: expr >>
-        (FieldValue {
-            ident: name,
-            expr: value,
+    named!(field_value -> FieldValue, alt!(
+        do_parse!(
+            name: wordlike >>
+            punct!(":") >>
+            value: expr >>
+            (FieldValue {
+                ident: name,
+                expr: value,
+                is_shorthand: false,
+            })
+        )
+        |
+        map!(ident, |name: Ident| FieldValue {
+            ident: name.clone(),
+            expr: ExprKind::Path(None, name.into()).into(),
+            is_shorthand: true,
         })
     ));
 
-    named!(expr_repeat -> Expr, do_parse!(
+    named!(expr_repeat -> ExprKind, do_parse!(
         punct!("[") >>
         value: expr >>
         punct!(";") >>
         times: expr >>
         punct!("]") >>
-        (Expr::Repeat(Box::new(value), Box::new(times)))
+        (ExprKind::Repeat(Box::new(value), Box::new(times)))
     ));
 
-    named!(expr_block -> Expr, do_parse!(
+    named!(expr_block -> ExprKind, do_parse!(
         rules: block_check_mode >>
         b: block >>
-        (Expr::Block(rules, Block {
+        (ExprKind::Block(rules, Block {
             stmts: b.stmts,
         }))
     ));
 
-    named!(expr_range -> Expr, do_parse!(
+    named_ambiguous_expr!(expr_range -> ExprKind, allow_struct, do_parse!(
         limits: range_limits >>
-        hi: option!(expr) >>
-        (Expr::Range(None, hi.map(Box::new), limits))
+        hi: option!(ambiguous_expr!(allow_struct)) >>
+        (ExprKind::Range(None, hi.map(Box::new), limits))
     ));
 
     named!(range_limits -> RangeLimits, alt!(
         punct!("...") => { |_| RangeLimits::Closed }
         |
         punct!("..") => { |_| RangeLimits::HalfOpen }
     ));
 
-    named!(expr_path -> Expr, map!(qpath, |(qself, path)| Expr::Path(qself, path)));
+    named!(expr_path -> ExprKind, map!(qpath, |(qself, path)| ExprKind::Path(qself, path)));
 
-    named!(expr_addr_of -> Expr, do_parse!(
+    named_ambiguous_expr!(expr_addr_of -> ExprKind, allow_struct, do_parse!(
         punct!("&") >>
         mutability: mutability >>
-        expr: expr >>
-        (Expr::AddrOf(mutability, Box::new(expr)))
+        expr: ambiguous_expr!(allow_struct) >>
+        (ExprKind::AddrOf(mutability, Box::new(expr)))
     ));
 
-    named!(and_assign -> Expr, preceded!(punct!("="), expr));
+    named_ambiguous_expr!(and_assign -> Expr, allow_struct, preceded!(
+        punct!("="),
+        ambiguous_expr!(allow_struct)
+    ));
 
-    named!(and_assign_op -> (BinOp, Expr), tuple!(assign_op, expr));
+    named_ambiguous_expr!(and_assign_op -> (BinOp, Expr), allow_struct, tuple!(
+        assign_op,
+        ambiguous_expr!(allow_struct)
+    ));
 
     named!(and_field -> Ident, preceded!(punct!("."), ident));
 
     named!(and_tup_field -> u64, preceded!(punct!("."), digits));
 
     named!(and_index -> Expr, delimited!(punct!("["), expr, punct!("]")));
 
-    named!(and_range -> (RangeLimits, Option<Expr>), tuple!(range_limits, option!(expr)));
+    named_ambiguous_expr!(and_range -> (RangeLimits, Option<Expr>), allow_struct, tuple!(
+        range_limits,
+        option!(call!(ambiguous_expr, allow_struct, false))
+    ));
 
     named!(pub block -> Block, do_parse!(
         punct!("{") >>
         stmts: within_block >>
         punct!("}") >>
         (Block {
             stmts: stmts,
         })
     ));
 
     named!(block_check_mode -> BlockCheckMode, alt!(
         keyword!("unsafe") => { |_| BlockCheckMode::Unsafe }
         |
         epsilon!() => { |_| BlockCheckMode::Default }
     ));
 
-    named!(within_block -> Vec<Stmt>, do_parse!(
+    named!(pub within_block -> Vec<Stmt>, do_parse!(
         many0!(punct!(";")) >>
         mut standalone: many0!(terminated!(standalone_stmt, many0!(punct!(";")))) >>
         last: option!(expr) >>
         (match last {
             None => standalone,
             Some(last) => {
                 standalone.push(Stmt::Expr(Box::new(last)));
                 standalone
@@ -760,31 +860,39 @@ pub mod parsing {
         |
         stmt_item
         |
         stmt_expr
     ));
 
     named!(stmt_mac -> Stmt, do_parse!(
         attrs: many0!(outer_attr) >>
-        mac: mac >>
+        name: ident >>
+        punct!("!") >>
+    // Only parse braces here; paren and bracket will get parsed as
+    // expression statements
+        punct!("{") >>
+        tts: token_trees >>
+        punct!("}") >>
         semi: option!(punct!(";")) >>
-        ({
-            let style = if semi.is_some() {
+        (Stmt::Mac(Box::new((
+            Mac {
+                path: name.into(),
+                tts: vec![TokenTree::Delimited(Delimited {
+                    delim: DelimToken::Brace,
+                    tts: tts,
+                })],
+            },
+            if semi.is_some() {
                 MacStmtStyle::Semicolon
-            } else if let Some(&TokenTree::Delimited(Delimited { delim, .. })) = mac.tts.last() {
-                match delim {
-                    DelimToken::Paren | DelimToken::Bracket => MacStmtStyle::NoBraces,
-                    DelimToken::Brace => MacStmtStyle::Braces,
-                }
             } else {
-                MacStmtStyle::NoBraces
-            };
-            Stmt::Mac(Box::new((mac, style, attrs)))
-        })
+                MacStmtStyle::Braces
+            },
+            attrs,
+        ))))
     ));
 
     named!(stmt_local -> Stmt, do_parse!(
         attrs: many0!(outer_attr) >>
         keyword!("let") >>
         pat: pat >>
         ty: option!(preceded!(punct!(":"), ty)) >>
         init: option!(preceded!(punct!("="), expr)) >>
@@ -795,81 +903,90 @@ pub mod parsing {
             init: init.map(Box::new),
             attrs: attrs,
         })))
     ));
 
     named!(stmt_item -> Stmt, map!(item, |i| Stmt::Item(Box::new(i))));
 
     fn requires_semi(e: &Expr) -> bool {
-        match *e {
-            Expr::If(_, _, _) |
-            Expr::IfLet(_, _, _, _) |
-            Expr::While(_, _, _) |
-            Expr::WhileLet(_, _, _, _) |
-            Expr::ForLoop(_, _, _, _) |
-            Expr::Loop(_, _) |
-            Expr::Match(_, _) |
-            Expr::Block(_, _) => false,
+        match e.node {
+            ExprKind::If(_, _, _) |
+            ExprKind::IfLet(_, _, _, _) |
+            ExprKind::While(_, _, _) |
+            ExprKind::WhileLet(_, _, _, _) |
+            ExprKind::ForLoop(_, _, _, _) |
+            ExprKind::Loop(_, _) |
+            ExprKind::Match(_, _) |
+            ExprKind::Block(_, _) => false,
 
             _ => true,
         }
     }
 
     named!(stmt_expr -> Stmt, do_parse!(
-        e: expr >>
+        attrs: many0!(outer_attr) >>
+        mut e: expr >>
         semi: option!(punct!(";")) >>
-        (if semi.is_some() {
-            Stmt::Semi(Box::new(e))
-        } else if requires_semi(&e) {
-            return Error;
-        } else {
-            Stmt::Expr(Box::new(e))
+        ({
+            e.attrs = attrs;
+            if semi.is_some() {
+                Stmt::Semi(Box::new(e))
+            } else if requires_semi(&e) {
+                return Error;
+            } else {
+                Stmt::Expr(Box::new(e))
+            }
         })
     ));
 
     named!(pub pat -> Pat, alt!(
         pat_wild // must be before pat_ident
         |
         pat_box // must be before pat_ident
         |
         pat_range // must be before pat_lit
         |
         pat_tuple_struct // must be before pat_ident
         |
         pat_struct // must be before pat_ident
         |
         pat_mac // must be before pat_ident
         |
+        pat_lit // must be before pat_ident
+        |
         pat_ident // must be before pat_path
         |
         pat_path
         |
         pat_tuple
         |
         pat_ref
         |
-        pat_lit
-    // TODO: Vec
+        pat_slice
     ));
 
     named!(pat_mac -> Pat, map!(mac, Pat::Mac));
 
     named!(pat_wild -> Pat, map!(keyword!("_"), |_| Pat::Wild));
 
     named!(pat_box -> Pat, do_parse!(
         keyword!("box") >>
         pat: pat >>
         (Pat::Box(Box::new(pat)))
     ));
 
     named!(pat_ident -> Pat, do_parse!(
         mode: option!(keyword!("ref")) >>
         mutability: mutability >>
-        name: ident >>
+        name: alt!(
+            ident
+            |
+            keyword!("self") => { Into::into }
+        ) >>
         not!(peek!(punct!("<"))) >>
         not!(peek!(punct!("::"))) >>
         subpat: option!(preceded!(punct!("@"), pat)) >>
         (Pat::Ident(
             if mode.is_some() {
                 BindingMode::ByRef(mutability)
             } else {
                 BindingMode::ByValue(mutability)
@@ -895,42 +1012,49 @@ pub mod parsing {
         )) >>
         cond!(!fields.is_empty() && more.is_none(), option!(punct!(","))) >>
         punct!("}") >>
         (Pat::Struct(path, fields, more.is_some()))
     ));
 
     named!(field_pat -> FieldPat, alt!(
         do_parse!(
-            ident: ident >>
+            ident: wordlike >>
             punct!(":") >>
             pat: pat >>
             (FieldPat {
                 ident: ident,
                 pat: Box::new(pat),
                 is_shorthand: false,
             })
         )
         |
         do_parse!(
+            boxed: option!(keyword!("box")) >>
             mode: option!(keyword!("ref")) >>
             mutability: mutability >>
             ident: ident >>
-            (FieldPat {
-                ident: ident.clone(),
-                pat: Box::new(Pat::Ident(
+            ({
+                let mut pat = Pat::Ident(
                     if mode.is_some() {
                         BindingMode::ByRef(mutability)
                     } else {
                         BindingMode::ByValue(mutability)
                     },
-                    ident,
+                    ident.clone(),
                     None,
-                )),
-                is_shorthand: true,
+                );
+                if boxed.is_some() {
+                    pat = Pat::Box(Box::new(pat));
+                }
+                FieldPat {
+                    ident: ident,
+                    pat: Box::new(pat),
+                    is_shorthand: true,
+                }
             })
         )
     ));
 
     named!(pat_path -> Pat, map!(qpath, |(qself, path)| Pat::Path(qself, path)));
 
     named!(pat_tuple -> Pat, map!(
         pat_tuple_helper,
@@ -961,25 +1085,73 @@ pub mod parsing {
 
     named!(pat_ref -> Pat, do_parse!(
         punct!("&") >>
         mutability: mutability >>
         pat: pat >>
         (Pat::Ref(Box::new(pat), mutability))
     ));
 
-    named!(pat_lit -> Pat, map!(lit, |lit| Pat::Lit(Box::new(lit))));
+    named!(pat_lit -> Pat, do_parse!(
+        lit: pat_lit_expr >>
+        (if let ExprKind::Path(_, _) = lit.node {
+            return IResult::Error; // these need to be parsed by pat_path
+        } else {
+            Pat::Lit(Box::new(lit))
+        })
+    ));
 
     named!(pat_range -> Pat, do_parse!(
-        lo: lit >>
+        lo: pat_lit_expr >>
         punct!("...") >>
-        hi: lit >>
+        hi: pat_lit_expr >>
         (Pat::Range(Box::new(lo), Box::new(hi)))
     ));
 
+    named!(pat_lit_expr -> Expr, do_parse!(
+        neg: option!(punct!("-")) >>
+        v: alt!(
+            lit => { ExprKind::Lit }
+            |
+            path => { |p| ExprKind::Path(None, p) }
+        ) >>
+        (if neg.is_some() {
+            ExprKind::Unary(UnOp::Neg, Box::new(v.into())).into()
+        } else {
+            v.into()
+        })
+    ));
+
+    named!(pat_slice -> Pat, do_parse!(
+        punct!("[") >>
+        mut before: separated_list!(punct!(","), pat) >>
+        after: option!(do_parse!(
+            comma_before_dots: option!(cond_reduce!(!before.is_empty(), punct!(","))) >>
+            punct!("..") >>
+            after: many0!(preceded!(punct!(","), pat)) >>
+            cond!(!after.is_empty(), option!(punct!(","))) >>
+            (comma_before_dots.is_some(), after)
+        )) >>
+        cond!(after.is_none(), option!(punct!(","))) >>
+        punct!("]") >>
+        (match after {
+            None => Pat::Slice(before, None, Vec::new()),
+            Some((true, after)) => {
+                if before.is_empty() {
+                    return IResult::Error;
+                }
+                Pat::Slice(before, Some(Box::new(Pat::Wild)), after)
+            }
+            Some((false, after)) => {
+                let rest = before.pop().unwrap_or(Pat::Wild);
+                Pat::Slice(before, Some(Box::new(rest)), after)
+            }
+        })
+    ));
+
     named!(capture_by -> CaptureBy, alt!(
         keyword!("move") => { |_| CaptureBy::Value }
         |
         epsilon!() => { |_| CaptureBy::Ref }
     ));
 
     named!(label -> Ident, map!(lifetime, |lt: Lifetime| lt.ident));
 }
@@ -988,143 +1160,149 @@ pub mod parsing {
 mod printing {
     use super::*;
     use {FnArg, FunctionRetTy, Mutability, Ty};
     use attr::FilterAttrs;
     use quote::{Tokens, ToTokens};
 
     impl ToTokens for Expr {
         fn to_tokens(&self, tokens: &mut Tokens) {
-            match *self {
-                Expr::Box(ref inner) => {
+            tokens.append_all(self.attrs.outer());
+            match self.node {
+                ExprKind::Box(ref inner) => {
                     tokens.append("box");
                     inner.to_tokens(tokens);
                 }
-                Expr::Vec(ref tys) => {
+                ExprKind::InPlace(ref place, ref value) => {
+                    tokens.append("in");
+                    place.to_tokens(tokens);
+                    value.to_tokens(tokens);
+                }
+                ExprKind::Vec(ref tys) => {
                     tokens.append("[");
                     tokens.append_separated(tys, ",");
                     tokens.append("]");
                 }
-                Expr::Call(ref func, ref args) => {
+                ExprKind::Call(ref func, ref args) => {
                     func.to_tokens(tokens);
                     tokens.append("(");
                     tokens.append_separated(args, ",");
                     tokens.append(")");
                 }
-                Expr::MethodCall(ref ident, ref ascript, ref args) => {
+                ExprKind::MethodCall(ref ident, ref ascript, ref args) => {
                     args[0].to_tokens(tokens);
                     tokens.append(".");
                     ident.to_tokens(tokens);
-                    if ascript.len() > 0 {
+                    if !ascript.is_empty() {
                         tokens.append("::");
                         tokens.append("<");
                         tokens.append_separated(ascript, ",");
                         tokens.append(">");
                     }
                     tokens.append("(");
                     tokens.append_separated(&args[1..], ",");
                     tokens.append(")");
                 }
-                Expr::Tup(ref fields) => {
+                ExprKind::Tup(ref fields) => {
                     tokens.append("(");
                     tokens.append_separated(fields, ",");
                     if fields.len() == 1 {
                         tokens.append(",");
                     }
                     tokens.append(")");
                 }
-                Expr::Binary(op, ref left, ref right) => {
+                ExprKind::Binary(op, ref left, ref right) => {
                     left.to_tokens(tokens);
                     op.to_tokens(tokens);
                     right.to_tokens(tokens);
                 }
-                Expr::Unary(op, ref expr) => {
+                ExprKind::Unary(op, ref expr) => {
                     op.to_tokens(tokens);
                     expr.to_tokens(tokens);
                 }
-                Expr::Lit(ref lit) => lit.to_tokens(tokens),
-                Expr::Cast(ref expr, ref ty) => {
+                ExprKind::Lit(ref lit) => lit.to_tokens(tokens),
+                ExprKind::Cast(ref expr, ref ty) => {
                     expr.to_tokens(tokens);
                     tokens.append("as");
                     ty.to_tokens(tokens);
                 }
-                Expr::Type(ref expr, ref ty) => {
+                ExprKind::Type(ref expr, ref ty) => {
                     expr.to_tokens(tokens);
                     tokens.append(":");
                     ty.to_tokens(tokens);
                 }
-                Expr::If(ref cond, ref then_block, ref else_block) => {
+                ExprKind::If(ref cond, ref then_block, ref else_block) => {
                     tokens.append("if");
                     cond.to_tokens(tokens);
                     then_block.to_tokens(tokens);
                     if let Some(ref else_block) = *else_block {
                         tokens.append("else");
                         else_block.to_tokens(tokens);
                     }
                 }
-                Expr::IfLet(ref pat, ref expr, ref then_block, ref else_block) => {
+                ExprKind::IfLet(ref pat, ref expr, ref then_block, ref else_block) => {
                     tokens.append("if");
                     tokens.append("let");
                     pat.to_tokens(tokens);
                     tokens.append("=");
                     expr.to_tokens(tokens);
                     then_block.to_tokens(tokens);
                     if let Some(ref else_block) = *else_block {
                         tokens.append("else");
                         else_block.to_tokens(tokens);
                     }
                 }
-                Expr::While(ref cond, ref body, ref label) => {
+                ExprKind::While(ref cond, ref body, ref label) => {
                     if let Some(ref label) = *label {
                         label.to_tokens(tokens);
                         tokens.append(":");
                     }
                     tokens.append("while");
                     cond.to_tokens(tokens);
                     body.to_tokens(tokens);
                 }
-                Expr::WhileLet(ref pat, ref expr, ref body, ref label) => {
+                ExprKind::WhileLet(ref pat, ref expr, ref body, ref label) => {
                     if let Some(ref label) = *label {
                         label.to_tokens(tokens);
                         tokens.append(":");
                     }
                     tokens.append("while");
                     tokens.append("let");
                     pat.to_tokens(tokens);
                     tokens.append("=");
                     expr.to_tokens(tokens);
                     body.to_tokens(tokens);
                 }
-                Expr::ForLoop(ref pat, ref expr, ref body, ref label) => {
+                ExprKind::ForLoop(ref pat, ref expr, ref body, ref label) => {
                     if let Some(ref label) = *label {
                         label.to_tokens(tokens);
                         tokens.append(":");
                     }
                     tokens.append("for");
                     pat.to_tokens(tokens);
                     tokens.append("in");
                     expr.to_tokens(tokens);
                     body.to_tokens(tokens);
                 }
-                Expr::Loop(ref body, ref label) => {
+                ExprKind::Loop(ref body, ref label) => {
                     if let Some(ref label) = *label {
                         label.to_tokens(tokens);
                         tokens.append(":");
                     }
                     tokens.append("loop");
                     body.to_tokens(tokens);
                 }
-                Expr::Match(ref expr, ref arms) => {
+                ExprKind::Match(ref expr, ref arms) => {
                     tokens.append("match");
                     expr.to_tokens(tokens);
                     tokens.append("{");
                     tokens.append_all(arms);
                     tokens.append("}");
                 }
-                Expr::Closure(capture, ref decl, ref body) => {
+                ExprKind::Closure(capture, ref decl, ref body) => {
                     capture.to_tokens(tokens);
                     tokens.append("|");
                     for (i, input) in decl.inputs.iter().enumerate() {
                         if i > 0 {
                             tokens.append(",");
                         }
                         match *input {
                             FnArg::Captured(ref pat, Ty::Infer) => {
@@ -1148,56 +1326,56 @@ mod printing {
                         }
                         FunctionRetTy::Ty(ref ty) => {
                             tokens.append("->");
                             ty.to_tokens(tokens);
                             body.to_tokens(tokens);
                         }
                     }
                 }
-                Expr::Block(rules, ref block) => {
+                ExprKind::Block(rules, ref block) => {
                     rules.to_tokens(tokens);
                     block.to_tokens(tokens);
                 }
-                Expr::Assign(ref var, ref expr) => {
+                ExprKind::Assign(ref var, ref expr) => {
                     var.to_tokens(tokens);
                     tokens.append("=");
                     expr.to_tokens(tokens);
                 }
-                Expr::AssignOp(op, ref var, ref expr) => {
+                ExprKind::AssignOp(op, ref var, ref expr) => {
                     var.to_tokens(tokens);
                     tokens.append(op.assign_op().unwrap());
                     expr.to_tokens(tokens);
                 }
-                Expr::Field(ref expr, ref field) => {
+                ExprKind::Field(ref expr, ref field) => {
                     expr.to_tokens(tokens);
                     tokens.append(".");
                     field.to_tokens(tokens);
                 }
-                Expr::TupField(ref expr, field) => {
+                ExprKind::TupField(ref expr, field) => {
                     expr.to_tokens(tokens);
                     tokens.append(".");
                     tokens.append(&field.to_string());
                 }
-                Expr::Index(ref expr, ref index) => {
+                ExprKind::Index(ref expr, ref index) => {
                     expr.to_tokens(tokens);
                     tokens.append("[");
                     index.to_tokens(tokens);
                     tokens.append("]");
                 }
-                Expr::Range(ref from, ref to, limits) => {
+                ExprKind::Range(ref from, ref to, limits) => {
                     from.to_tokens(tokens);
                     match limits {
                         RangeLimits::HalfOpen => tokens.append(".."),
                         RangeLimits::Closed => tokens.append("..."),
                     }
                     to.to_tokens(tokens);
                 }
-                Expr::Path(None, ref path) => path.to_tokens(tokens),
-                Expr::Path(Some(ref qself), ref path) => {
+                ExprKind::Path(None, ref path) => path.to_tokens(tokens),
+                ExprKind::Path(Some(ref qself), ref path) => {
                     tokens.append("<");
                     qself.ty.to_tokens(tokens);
                     if qself.position > 0 {
                         tokens.append("as");
                         for (i, segment) in path.segments
                             .iter()
                             .take(qself.position)
                             .enumerate() {
@@ -1208,89 +1386,91 @@ mod printing {
                         }
                     }
                     tokens.append(">");
                     for segment in path.segments.iter().skip(qself.position) {
                         tokens.append("::");
                         segment.to_tokens(tokens);
                     }
                 }
-                Expr::AddrOf(mutability, ref expr) => {
+                ExprKind::AddrOf(mutability, ref expr) => {
                     tokens.append("&");
                     mutability.to_tokens(tokens);
                     expr.to_tokens(tokens);
                 }
-                Expr::Break(ref opt_label) => {
+                ExprKind::Break(ref opt_label) => {
                     tokens.append("break");
                     opt_label.to_tokens(tokens);
                 }
-                Expr::Continue(ref opt_label) => {
+                ExprKind::Continue(ref opt_label) => {
                     tokens.append("continue");
                     opt_label.to_tokens(tokens);
                 }
-                Expr::Ret(ref opt_expr) => {
+                ExprKind::Ret(ref opt_expr) => {
                     tokens.append("return");
                     opt_expr.to_tokens(tokens);
                 }
-                Expr::Mac(ref mac) => mac.to_tokens(tokens),
-                Expr::Struct(ref path, ref fields, ref base) => {
+                ExprKind::Mac(ref mac) => mac.to_tokens(tokens),
+                ExprKind::Struct(ref path, ref fields, ref base) => {
                     path.to_tokens(tokens);
                     tokens.append("{");
                     tokens.append_separated(fields, ",");
                     if let Some(ref base) = *base {
                         if !fields.is_empty() {
                             tokens.append(",");
                         }
                         tokens.append("..");
                         base.to_tokens(tokens);
                     }
                     tokens.append("}");
                 }
-                Expr::Repeat(ref expr, ref times) => {
+                ExprKind::Repeat(ref expr, ref times) => {
                     tokens.append("[");
                     expr.to_tokens(tokens);
                     tokens.append(";");
                     times.to_tokens(tokens);
                     tokens.append("]");
                 }
-                Expr::Paren(ref expr) => {
+                ExprKind::Paren(ref expr) => {
                     tokens.append("(");
                     expr.to_tokens(tokens);
                     tokens.append(")");
                 }
-                Expr::Try(ref expr) => {
+                ExprKind::Try(ref expr) => {
                     expr.to_tokens(tokens);
                     tokens.append("?");
                 }
             }
         }
     }
 
     impl ToTokens for FieldValue {
         fn to_tokens(&self, tokens: &mut Tokens) {
             self.ident.to_tokens(tokens);
-            tokens.append(":");
-            self.expr.to_tokens(tokens);
+            if !self.is_shorthand {
+                tokens.append(":");
+                self.expr.to_tokens(tokens);
+            }
         }
     }
 
     impl ToTokens for Arm {
         fn to_tokens(&self, tokens: &mut Tokens) {
             for attr in &self.attrs {
                 attr.to_tokens(tokens);
             }
             tokens.append_separated(&self.pats, "|");
             if let Some(ref guard) = self.guard {
                 tokens.append("if");
                 guard.to_tokens(tokens);
             }
             tokens.append("=>");
             self.body.to_tokens(tokens);
-            match *self.body {
-                Expr::Block(_, _) => {
+            match self.body.node {
+                ExprKind::Block(BlockCheckMode::Default, _) => {
                     // no comma
                 }
                 _ => tokens.append(","),
             }
         }
     }
 
     impl ToTokens for Pat {
@@ -1367,17 +1547,22 @@ mod printing {
                                 tokens.append(",");
                             }
                             tokens.append("..");
                             if pos < pats.len() {
                                 tokens.append(",");
                                 tokens.append_separated(&pats[pos..], ",");
                             }
                         }
-                        None => tokens.append_separated(pats, ","),
+                        None => {
+                            tokens.append_separated(pats, ",");
+                            if pats.len() == 1 {
+                                tokens.append(",");
+                            }
+                        }
                     }
                     tokens.append(")");
                 }
                 Pat::Box(ref inner) => {
                     tokens.append("box");
                     inner.to_tokens(tokens);
                 }
                 Pat::Ref(ref target, mutability) => {
@@ -1386,17 +1571,34 @@ mod printing {
                     target.to_tokens(tokens);
                 }
                 Pat::Lit(ref lit) => lit.to_tokens(tokens),
                 Pat::Range(ref lo, ref hi) => {
                     lo.to_tokens(tokens);
                     tokens.append("...");
                     hi.to_tokens(tokens);
                 }
-                Pat::Slice(ref _before, ref _dots, ref _after) => unimplemented!(),
+                Pat::Slice(ref before, ref rest, ref after) => {
+                    tokens.append("[");
+                    tokens.append_separated(before, ",");
+                    if let Some(ref rest) = *rest {
+                        if !before.is_empty() {
+                            tokens.append(",");
+                        }
+                        if **rest != Pat::Wild {
+                            rest.to_tokens(tokens);
+                        }
+                        tokens.append("..");
+                        if !after.is_empty() {
+                            tokens.append(",");
+                        }
+                        tokens.append_separated(after, ",");
+                    }
+                    tokens.append("]");
+                }
                 Pat::Mac(ref mac) => mac.to_tokens(tokens),
             }
         }
     }
 
     impl ToTokens for FieldPat {
         fn to_tokens(&self, tokens: &mut Tokens) {
             if !self.is_shorthand {
@@ -1434,19 +1636,17 @@ mod printing {
                 }
             }
         }
     }
 
     impl ToTokens for Block {
         fn to_tokens(&self, tokens: &mut Tokens) {
             tokens.append("{");
-            for stmt in &self.stmts {
-                stmt.to_tokens(tokens);
-            }
+            tokens.append_all(&self.stmts);
             tokens.append("}");
         }
     }
 
     impl ToTokens for BlockCheckMode {
         fn to_tokens(&self, tokens: &mut Tokens) {
             match *self {
                 BlockCheckMode::Default => {
@@ -1464,33 +1664,32 @@ mod printing {
                 Stmt::Item(ref item) => item.to_tokens(tokens),
                 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
                 Stmt::Semi(ref expr) => {
                     expr.to_tokens(tokens);
                     tokens.append(";");
                 }
                 Stmt::Mac(ref mac) => {
                     let (ref mac, style, ref attrs) = **mac;
-                    for attr in attrs.outer() {
-                        attr.to_tokens(tokens);
-                    }
+                    tokens.append_all(attrs.outer());
                     mac.to_tokens(tokens);
                     match style {
                         MacStmtStyle::Semicolon => tokens.append(";"),
                         MacStmtStyle::Braces | MacStmtStyle::NoBraces => {
                             // no semicolon
                         }
                     }
                 }
             }
         }
     }
 
     impl ToTokens for Local {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             tokens.append("let");
             self.pat.to_tokens(tokens);
             if let Some(ref ty) = self.ty {
                 tokens.append(":");
                 ty.to_tokens(tokens);
             }
             if let Some(ref init) = self.init {
                 tokens.append("=");
--- a/third_party/rust/syn/src/generics.rs
+++ b/third_party/rust/syn/src/generics.rs
@@ -4,17 +4,28 @@ use super::*;
 /// of a function, enum, trait, etc.
 #[derive(Debug, Clone, Eq, PartialEq, Default)]
 pub struct Generics {
     pub lifetimes: Vec<LifetimeDef>,
     pub ty_params: Vec<TyParam>,
     pub where_clause: WhereClause,
 }
 
+#[cfg(feature = "printing")]
+/// Returned by `Generics::split_for_impl`.
+#[derive(Debug)]
+pub struct ImplGenerics<'a>(&'a Generics);
+
+#[cfg(feature = "printing")]
+/// Returned by `Generics::split_for_impl`.
+#[derive(Debug)]
+pub struct TyGenerics<'a>(&'a Generics);
+
 impl Generics {
+    #[cfg(feature = "printing")]
     /// Split a type's generics into the pieces required for impl'ing a trait
     /// for that type.
     ///
     /// ```
     /// # extern crate syn;
     /// # #[macro_use]
     /// # extern crate quote;
     /// # fn main() {
@@ -24,60 +35,18 @@ impl Generics {
     /// quote! {
     ///     impl #impl_generics MyTrait for #name #ty_generics #where_clause {
     ///         // ...
     ///     }
     /// }
     /// # ;
     /// # }
     /// ```
-    pub fn split_for_impl(&self) -> (Generics, Generics, WhereClause) {
-        // Remove where clause and type parameter defaults.
-        let impl_generics = Generics {
-            lifetimes: self.lifetimes.clone(),
-            ty_params: self.ty_params
-                .iter()
-                .map(|ty_param| {
-                    TyParam {
-                        ident: ty_param.ident.clone(),
-                        bounds: ty_param.bounds.clone(),
-                        default: None,
-                    }
-                })
-                .collect(),
-            where_clause: WhereClause::none(),
-        };
-
-        // Remove where clause, type parameter defaults, and bounds.
-        let ty_generics = Generics {
-            lifetimes: self.lifetimes
-                .iter()
-                .map(|lifetime_def| {
-                    LifetimeDef {
-                        lifetime: lifetime_def.lifetime.clone(),
-                        bounds: Vec::new(),
-                    }
-                })
-                .collect(),
-            ty_params: self.ty_params
-                .iter()
-                .map(|ty_param| {
-                    TyParam {
-                        ident: ty_param.ident.clone(),
-                        bounds: Vec::new(),
-                        default: None,
-                    }
-                })
-                .collect(),
-            where_clause: WhereClause::none(),
-        };
-
-        let where_clause = self.where_clause.clone();
-
-        (impl_generics, ty_generics, where_clause)
+    pub fn split_for_impl(&self) -> (ImplGenerics, TyGenerics, &WhereClause) {
+        (ImplGenerics(self), TyGenerics(self), &self.where_clause)
     }
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct Lifetime {
     pub ident: Ident,
 }
 
@@ -91,31 +60,34 @@ impl Lifetime {
         }
         Lifetime { ident: id }
     }
 }
 
 /// A lifetime definition, e.g. `'a: 'b+'c+'d`
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct LifetimeDef {
+    pub attrs: Vec<Attribute>,
     pub lifetime: Lifetime,
     pub bounds: Vec<Lifetime>,
 }
 
 impl LifetimeDef {
     pub fn new<T: Into<Ident>>(t: T) -> Self {
         LifetimeDef {
+            attrs: Vec::new(),
             lifetime: Lifetime::new(t),
             bounds: Vec::new(),
         }
     }
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct TyParam {
+    pub attrs: Vec<Attribute>,
     pub ident: Ident,
     pub bounds: Vec<TyParamBound>,
     pub default: Option<Ty>,
 }
 
 /// The AST represents all type param bounds as types.
 /// `typeck::collect::compute_bounds` matches these against
 /// the "special" built-in traits (see `middle::lang_items`) and
@@ -175,79 +147,91 @@ pub struct WhereBoundPredicate {
 pub struct WhereRegionPredicate {
     pub lifetime: Lifetime,
     pub bounds: Vec<Lifetime>,
 }
 
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
+    use attr::parsing::outer_attr;
     use ident::parsing::ident;
     use ty::parsing::{ty, poly_trait_ref};
 
     named!(pub generics -> Generics, map!(
         alt!(
             do_parse!(
                 punct!("<") >>
                 lifetimes: separated_list!(punct!(","), lifetime_def) >>
                 ty_params: opt_vec!(preceded!(
                     cond!(!lifetimes.is_empty(), punct!(",")),
                     separated_nonempty_list!(punct!(","), ty_param)
                 )) >>
+                cond!(!lifetimes.is_empty() || !ty_params.is_empty(), option!(punct!(","))) >>
                 punct!(">") >>
                 (lifetimes, ty_params)
             )
             |
             epsilon!() => { |_| (Vec::new(), Vec::new()) }
         ),
         |(lifetimes, ty_params)| Generics {
             lifetimes: lifetimes,
             ty_params: ty_params,
             where_clause: Default::default(),
         }
     ));
 
     named!(pub lifetime -> Lifetime, preceded!(
         punct!("'"),
-        map!(ident, |id| Lifetime {
-            ident: format!("'{}", id).into(),
-        })
+        alt!(
+            map!(ident, |id| Lifetime {
+                ident: format!("'{}", id).into(),
+            })
+            |
+            map!(keyword!("static"), |_| Lifetime {
+                ident: "'static".into(),
+            })
+        )
     ));
 
     named!(pub lifetime_def -> LifetimeDef, do_parse!(
+        attrs: many0!(outer_attr) >>
         life: lifetime >>
         bounds: opt_vec!(preceded!(
             punct!(":"),
-            separated_nonempty_list!(punct!("+"), lifetime)
+            separated_list!(punct!("+"), lifetime)
         )) >>
         (LifetimeDef {
+            attrs: attrs,
             lifetime: life,
             bounds: bounds,
         })
     ));
 
     named!(pub bound_lifetimes -> Vec<LifetimeDef>, opt_vec!(do_parse!(
         keyword!("for") >>
         punct!("<") >>
         lifetimes: terminated_list!(punct!(","), lifetime_def) >>
         punct!(">") >>
         (lifetimes)
     )));
 
     named!(ty_param -> TyParam, do_parse!(
+        attrs: many0!(outer_attr) >>
         id: ident >>
         bounds: opt_vec!(preceded!(
             punct!(":"),
             separated_nonempty_list!(punct!("+"), ty_param_bound)
         )) >>
         default: option!(preceded!(
             punct!("="),
             ty
         )) >>
         (TyParam {
+            attrs: attrs,
             ident: id,
             bounds: bounds,
             default: default,
         })
     ));
 
     named!(pub ty_param_bound -> TyParamBound, alt!(
         preceded!(punct!("?"), poly_trait_ref) => {
@@ -270,18 +254,20 @@ pub mod parsing {
         )
         |
         epsilon!() => { |_| Default::default() }
     ));
 
     named!(where_predicate -> WherePredicate, alt!(
         do_parse!(
             ident: lifetime >>
-            punct!(":") >>
-            bounds: separated_nonempty_list!(punct!("+"), lifetime) >>
+            bounds: opt_vec!(preceded!(
+                punct!(":"),
+                separated_list!(punct!("+"), lifetime)
+            )) >>
             (WherePredicate::RegionPredicate(WhereRegionPredicate {
                 lifetime: ident,
                 bounds: bounds,
             }))
         )
         |
         do_parse!(
             bound_lifetimes: bound_lifetimes >>
@@ -295,16 +281,17 @@ pub mod parsing {
             }))
         )
     ));
 }
 
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
+    use attr::FilterAttrs;
     use quote::{Tokens, ToTokens};
 
     impl ToTokens for Generics {
         fn to_tokens(&self, tokens: &mut Tokens) {
             let has_lifetimes = !self.lifetimes.is_empty();
             let has_ty_params = !self.ty_params.is_empty();
             if has_lifetimes || has_ty_params {
                 tokens.append("<");
@@ -313,34 +300,80 @@ mod printing {
                     tokens.append(",");
                 }
                 tokens.append_separated(&self.ty_params, ",");
                 tokens.append(">");
             }
         }
     }
 
+    impl<'a> ToTokens for ImplGenerics<'a> {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            let has_lifetimes = !self.0.lifetimes.is_empty();
+            let has_ty_params = !self.0.ty_params.is_empty();
+            if has_lifetimes || has_ty_params {
+                tokens.append("<");
+                tokens.append_separated(&self.0.lifetimes, ",");
+                // Leave off the type parameter defaults
+                for (i, ty_param) in self.0.ty_params.iter().enumerate() {
+                    if i > 0 || has_lifetimes {
+                        tokens.append(",");
+                    }
+                    tokens.append_all(ty_param.attrs.outer());
+                    ty_param.ident.to_tokens(tokens);
+                    if !ty_param.bounds.is_empty() {
+                        tokens.append(":");
+                        tokens.append_separated(&ty_param.bounds, "+");
+                    }
+                }
+                tokens.append(">");
+            }
+        }
+    }
+
+    impl<'a> ToTokens for TyGenerics<'a> {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            let has_lifetimes = !self.0.lifetimes.is_empty();
+            let has_ty_params = !self.0.ty_params.is_empty();
+            if has_lifetimes || has_ty_params {
+                tokens.append("<");
+                // Leave off the lifetime bounds and attributes
+                let lifetimes = self.0.lifetimes.iter().map(|ld| &ld.lifetime);
+                tokens.append_separated(lifetimes, ",");
+                if has_lifetimes && has_ty_params {
+                    tokens.append(",");
+                }
+                // Leave off the type parameter bounds, defaults, and attributes
+                let ty_params = self.0.ty_params.iter().map(|tp| &tp.ident);
+                tokens.append_separated(ty_params, ",");
+                tokens.append(">");
+            }
+        }
+    }
+
     impl ToTokens for Lifetime {
         fn to_tokens(&self, tokens: &mut Tokens) {
             self.ident.to_tokens(tokens);
         }
     }
 
     impl ToTokens for LifetimeDef {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.lifetime.to_tokens(tokens);
             if !self.bounds.is_empty() {
                 tokens.append(":");
                 tokens.append_separated(&self.bounds, "+");
             }
         }
     }
 
     impl ToTokens for TyParam {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.ident.to_tokens(tokens);
             if !self.bounds.is_empty() {
                 tokens.append(":");
                 tokens.append_separated(&self.bounds, "+");
             }
             if let Some(ref default) = self.default {
                 tokens.append("=");
                 default.to_tokens(tokens);
--- a/third_party/rust/syn/src/helper.rs
+++ b/third_party/rust/syn/src/helper.rs
@@ -1,22 +1,19 @@
 use nom::IResult;
-use space::{whitespace, word_break};
+use space::{skip_whitespace, word_break};
 
 macro_rules! punct {
     ($i:expr, $punct:expr) => {
         $crate::helper::punct($i, $punct)
     };
 }
 
 pub fn punct<'a>(input: &'a str, token: &'static str) -> IResult<&'a str, &'a str> {
-    let input = match whitespace(input) {
-        IResult::Done(rest, _) => rest,
-        IResult::Error => input,
-    };
+    let input = skip_whitespace(input);
     if input.starts_with(token) {
         IResult::Done(&input[token.len()..], token)
     } else {
         IResult::Error
     }
 }
 
 macro_rules! keyword {
@@ -89,22 +86,21 @@ macro_rules! separated_list {
 }
 
 macro_rules! terminated_list {
     ($i:expr, punct!($sep:expr), $f:expr) => {
         $crate::helper::separated_list($i, $sep, $f, true)
     };
 }
 
-pub fn separated_list<'a, T>(
-    mut input: &'a str,
-    sep: &'static str,
-    f: fn(&'a str) -> IResult<&'a str, T>,
-    terminated: bool,
-) -> IResult<&'a str, Vec<T>> {
+pub fn separated_list<'a, T>(mut input: &'a str,
+                             sep: &'static str,
+                             f: fn(&'a str) -> IResult<&'a str, T>,
+                             terminated: bool)
+                             -> IResult<&'a str, Vec<T>> {
     let mut res = Vec::new();
 
     // get the first element
     match f(input) {
         IResult::Error => IResult::Done(input, Vec::new()),
         IResult::Done(i, o) => {
             if i.len() == input.len() {
                 IResult::Error
--- a/third_party/rust/syn/src/ident.rs
+++ b/third_party/rust/syn/src/ident.rs
@@ -45,26 +45,73 @@ impl<T: ?Sized> PartialEq<T> for Ident
     fn eq(&self, other: &T) -> bool {
         self.0 == other.as_ref()
     }
 }
 
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use space::whitespace;
+    use nom::IResult;
+    use space::skip_whitespace;
+    use unicode_xid::UnicodeXID;
+
+    pub fn ident(input: &str) -> IResult<&str, Ident> {
+        let (rest, id) = match word(input) {
+            IResult::Done(rest, id) => (rest, id),
+            IResult::Error => return IResult::Error,
+        };
 
-    fn ident_ch(ch: char) -> bool {
-        ch.is_alphanumeric() || ch == '_'
+        match id.as_ref() {
+            // From https://doc.rust-lang.org/grammar.html#keywords
+            "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const" | "continue" |
+            "crate" | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" |
+            "if" | "impl" | "in" | "let" | "loop" | "macro" | "match" | "mod" | "move" |
+            "mut" | "offsetof" | "override" | "priv" | "proc" | "pub" | "pure" | "ref" |
+            "return" | "Self" | "self" | "sizeof" | "static" | "struct" | "super" | "trait" |
+            "true" | "type" | "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" |
+            "while" | "yield" => IResult::Error,
+            _ => IResult::Done(rest, id),
+        }
     }
 
-    named!(pub ident -> Ident, preceded!(
-        option!(whitespace),
-        map!(take_while1!(ident_ch), Into::into)
-    ));
+    pub fn word(mut input: &str) -> IResult<&str, Ident> {
+        input = skip_whitespace(input);
+
+        let mut chars = input.char_indices();
+        match chars.next() {
+            Some((_, ch)) if UnicodeXID::is_xid_start(ch) || ch == '_' => {}
+            _ => return IResult::Error,
+        }
+
+        while let Some((i, ch)) = chars.next() {
+            if !UnicodeXID::is_xid_continue(ch) {
+                return IResult::Done(&input[i..], input[..i].into());
+            }
+        }
+
+        IResult::Done("", input.into())
+    }
+
+    #[cfg(feature = "full")]
+    pub fn wordlike(mut input: &str) -> IResult<&str, Ident> {
+        input = skip_whitespace(input);
+
+        for (i, ch) in input.char_indices() {
+            if !UnicodeXID::is_xid_start(ch) && !UnicodeXID::is_xid_continue(ch) {
+                return if i == 0 {
+                    IResult::Error
+                } else {
+                    IResult::Done(&input[i..], input[..i].into())
+                };
+            }
+        }
+
+        IResult::Done("", input.into())
+    }
 }
 
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
     use quote::{Tokens, ToTokens};
 
     impl ToTokens for Ident {
--- a/third_party/rust/syn/src/item.rs
+++ b/third_party/rust/syn/src/item.rs
@@ -31,17 +31,17 @@ pub enum ItemKind {
     Const(Box<Ty>, Box<Expr>),
     /// A function declaration (`fn` or `pub fn`).
     ///
     /// E.g. `fn foo(bar: usize) -> usize { .. }`
     Fn(Box<FnDecl>, Unsafety, Constness, Option<Abi>, Generics, Box<Block>),
     /// A module declaration (`mod` or `pub mod`).
     ///
     /// E.g. `mod foo;` or `mod foo { .. }`
-    Mod(Vec<Item>),
+    Mod(Option<Vec<Item>>),
     /// An external module (`extern` or `pub extern`).
     ///
     /// E.g. `extern {}` or `extern "C" {}`
     ForeignMod(ForeignMod),
     /// A type alias (`type` or `pub type`).
     ///
     /// E.g. `type Foo = Bar<u8>;`
     Ty(Box<Ty>, Generics),
@@ -75,16 +75,30 @@ pub enum ItemKind {
          Box<Ty>, // self
          Vec<ImplItem>),
     /// A macro invocation (which includes macro definition).
     ///
     /// E.g. `macro_rules! foo { .. }` or `foo!(..)`
     Mac(Mac),
 }
 
+impl From<MacroInput> for Item {
+    fn from(input: MacroInput) -> Item {
+        Item {
+            ident: input.ident,
+            vis: input.vis,
+            attrs: input.attrs,
+            node: match input.body {
+                Body::Enum(variants) => ItemKind::Enum(variants, input.generics),
+                Body::Struct(variant_data) => ItemKind::Struct(variant_data, input.generics),
+            },
+        }
+    }
+}
+
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub enum ViewPath {
     /// `foo::bar::baz as quux`
     ///
     /// or just
     ///
     /// `foo::bar::baz` (with `as baz` implicitly on the right)
     Simple(Path, Option<Ident>),
@@ -99,42 +113,33 @@ pub enum ViewPath {
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct PathListItem {
     pub name: Ident,
     /// renamed in list, e.g. `use foo::{bar as baz};`
     pub rename: Option<Ident>,
 }
 
 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
-pub enum Unsafety {
-    Unsafe,
-    Normal,
-}
-
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
 pub enum Constness {
     Const,
     NotConst,
 }
 
 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
 pub enum Defaultness {
     Default,
     Final,
 }
 
-#[derive(Debug, Clone, Eq, PartialEq)]
-pub struct Abi(pub String);
-
 /// Foreign module declaration.
 ///
 /// E.g. `extern { .. }` or `extern "C" { .. }`
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct ForeignMod {
-    pub abi: Option<Abi>,
+    pub abi: Abi,
     pub items: Vec<ForeignItem>,
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct ForeignItem {
     pub ident: Ident,
     pub attrs: Vec<Attribute>,
     pub node: ForeignItemKind,
@@ -207,43 +212,44 @@ pub struct MethodSig {
 
 /// Header (not the body) of a function declaration.
 ///
 /// E.g. `fn foo(bar: baz)`
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct FnDecl {
     pub inputs: Vec<FnArg>,
     pub output: FunctionRetTy,
+    pub variadic: bool,
 }
 
 /// An argument in a function header.
 ///
 /// E.g. `bar: usize` as in `fn foo(bar: usize)`
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub enum FnArg {
     SelfRef(Option<Lifetime>, Mutability),
     SelfValue(Mutability),
     Captured(Pat, Ty),
     Ignored(Ty),
 }
 
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use {DelimToken, FunctionRetTy, Generics, Ident, Mac, Path, TokenTree, VariantData, Visibility};
-    use attr::parsing::outer_attr;
+    use {Block, DelimToken, FunctionRetTy, Generics, Ident, Mac, Path, TokenTree, VariantData,
+         Visibility};
+    use attr::parsing::{inner_attr, outer_attr};
     use data::parsing::{struct_like_body, visibility};
-    use expr::parsing::{block, expr, pat};
+    use expr::parsing::{expr, pat, within_block};
     use generics::parsing::{generics, lifetime, ty_param_bound, where_clause};
     use ident::parsing::ident;
-    use lit::parsing::quoted_string;
     use mac::parsing::delimited;
     use macro_input::{Body, MacroInput};
     use macro_input::parsing::macro_input;
-    use ty::parsing::{mutability, path, ty};
+    use ty::parsing::{abi, mutability, path, ty, unsafety};
 
     named!(pub item -> Item, alt!(
         item_extern_crate
         |
         item_use
         |
         item_static
         |
@@ -265,16 +271,18 @@ pub mod parsing {
         |
         item_default_impl
         |
         item_impl
         |
         item_mac
     ));
 
+    named!(pub items -> Vec<Item>, many0!(item));
+
     named!(item_mac -> Item, do_parse!(
         attrs: many0!(outer_attr) >>
         path: ident >>
         punct!("!") >>
         name: option!(ident) >>
         body: delimited >>
         cond!(match body.delim {
             DelimToken::Paren | DelimToken::Bracket => true,
@@ -353,34 +361,38 @@ pub mod parsing {
         punct!("*") >>
         (ViewPath::Glob(path))
     ));
 
     named!(view_path_list -> ViewPath, do_parse!(
         path: path >>
         punct!("::") >>
         punct!("{") >>
-        items: separated_nonempty_list!(punct!(","), path_list_item) >>
+        items: terminated_list!(punct!(","), path_list_item) >>
         punct!("}") >>
         (ViewPath::List(path, items))
     ));
 
     named!(view_path_list_root -> ViewPath, do_parse!(
         global: option!(punct!("::")) >>
         punct!("{") >>
-        items: separated_nonempty_list!(punct!(","), path_list_item) >>
+        items: terminated_list!(punct!(","), path_list_item) >>
         punct!("}") >>
         (ViewPath::List(Path {
             global: global.is_some(),
             segments: Vec::new(),
         }, items))
     ));
 
     named!(path_list_item -> PathListItem, do_parse!(
-        name: ident >>
+        name: alt!(
+            ident
+            |
+            map!(keyword!("self"), Into::into)
+        ) >>
         rename: option!(preceded!(keyword!("as"), ident)) >>
         (PathListItem {
             name: name,
             rename: rename,
         })
     ));
 
     named!(item_static -> Item, do_parse!(
@@ -416,105 +428,137 @@ pub mod parsing {
             ident: id,
             vis: vis,
             attrs: attrs,
             node: ItemKind::Const(Box::new(ty), Box::new(value)),
         })
     ));
 
     named!(item_fn -> Item, do_parse!(
-        attrs: many0!(outer_attr) >>
+        outer_attrs: many0!(outer_attr) >>
         vis: visibility >>
         constness: constness >>
         unsafety: unsafety >>
-        abi: option!(preceded!(keyword!("extern"), quoted_string)) >>
+        abi: option!(abi) >>
         keyword!("fn") >>
         name: ident >>
         generics: generics >>
         punct!("(") >>
         inputs: terminated_list!(punct!(","), fn_arg) >>
         punct!(")") >>
         ret: option!(preceded!(punct!("->"), ty)) >>
         where_clause: where_clause >>
-        body: block >>
+        punct!("{") >>
+        inner_attrs: many0!(inner_attr) >>
+        stmts: within_block >>
+        punct!("}") >>
         (Item {
             ident: name,
             vis: vis,
-            attrs: attrs,
+            attrs: {
+                let mut attrs = outer_attrs;
+                attrs.extend(inner_attrs);
+                attrs
+            },
             node: ItemKind::Fn(
                 Box::new(FnDecl {
                     inputs: inputs,
                     output: ret.map(FunctionRetTy::Ty).unwrap_or(FunctionRetTy::Default),
+                    variadic: false,
                 }),
                 unsafety,
                 constness,
-                abi.map(Abi),
+                abi,
                 Generics {
                     where_clause: where_clause,
                     .. generics
                 },
-                Box::new(body),
+                Box::new(Block {
+                    stmts: stmts,
+                }),
             ),
         })
     ));
 
     named!(fn_arg -> FnArg, alt!(
         do_parse!(
             punct!("&") >>
             lt: option!(lifetime) >>
             mutability: mutability >>
             keyword!("self") >>
+            not!(peek!(punct!(":"))) >>
             (FnArg::SelfRef(lt, mutability))
         )
         |
         do_parse!(
             mutability: mutability >>
             keyword!("self") >>
+            not!(peek!(punct!(":"))) >>
             (FnArg::SelfValue(mutability))
         )
         |
         do_parse!(
             pat: pat >>
             punct!(":") >>
             ty: ty >>
             (FnArg::Captured(pat, ty))
         )
         |
         ty => { FnArg::Ignored }
     ));
 
     named!(item_mod -> Item, do_parse!(
-        attrs: many0!(outer_attr) >>
+        outer_attrs: many0!(outer_attr) >>
         vis: visibility >>
         keyword!("mod") >>
         id: ident >>
-        punct!("{") >>
-        items: many0!(item) >>
-        punct!("}") >>
-        (Item {
-            ident: id,
-            vis: vis,
-            attrs: attrs,
-            node: ItemKind::Mod(items),
+        content: alt!(
+            punct!(";") => { |_| None }
+            |
+            delimited!(
+                punct!("{"),
+                tuple!(
+                    many0!(inner_attr),
+                    items
+                ),
+                punct!("}")
+            ) => { Some }
+        ) >>
+        (match content {
+            Some((inner_attrs, items)) => Item {
+                ident: id,
+                vis: vis,
+                attrs: {
+                    let mut attrs = outer_attrs;
+                    attrs.extend(inner_attrs);
+                    attrs
+                },
+                node: ItemKind::Mod(Some(items)),
+            },
+            None => Item {
+                ident: id,
+                vis: vis,
+                attrs: outer_attrs,
+                node: ItemKind::Mod(None),
+            },
         })
     ));
 
     named!(item_foreign_mod -> Item, do_parse!(
         attrs: many0!(outer_attr) >>
-        keyword!("extern") >>
-        abi: option!(quoted_string) >>
+        abi: abi >>
         punct!("{") >>
         items: many0!(foreign_item) >>
         punct!("}") >>
         (Item {
             ident: "".into(),
             vis: Visibility::Inherited,
             attrs: attrs,
             node: ItemKind::ForeignMod(ForeignMod {
-                abi: abi.map(Abi),
+                abi: abi,
                 items: items,
             }),
         })
     ));
 
     named!(foreign_item -> ForeignItem, alt!(
         foreign_fn
         |
@@ -523,28 +567,31 @@ pub mod parsing {
 
     named!(foreign_fn -> ForeignItem, do_parse!(
         attrs: many0!(outer_attr) >>
         vis: visibility >>
         keyword!("fn") >>
         name: ident >>
         generics: generics >>
         punct!("(") >>
-        inputs: terminated_list!(punct!(","), fn_arg) >>
+        inputs: separated_list!(punct!(","), fn_arg) >>
+        trailing_comma: option!(punct!(",")) >>
+        variadic: option!(cond_reduce!(trailing_comma.is_some(), punct!("..."))) >>
         punct!(")") >>
         ret: option!(preceded!(punct!("->"), ty)) >>
         where_clause: where_clause >>
         punct!(";") >>
         (ForeignItem {
             ident: name,
             attrs: attrs,
             node: ForeignItemKind::Fn(
                 Box::new(FnDecl {
                     inputs: inputs,
                     output: ret.map(FunctionRetTy::Ty).unwrap_or(FunctionRetTy::Default),
+                    variadic: variadic.is_some(),
                 }),
                 Generics {
                     where_clause: where_clause,
                     .. generics
                 },
             ),
             vis: vis,
         })
@@ -568,24 +615,31 @@ pub mod parsing {
     ));
 
     named!(item_ty -> Item, do_parse!(
         attrs: many0!(outer_attr) >>
         vis: visibility >>
         keyword!("type") >>
         id: ident >>
         generics: generics >>
+        where_clause: where_clause >>
         punct!("=") >>
         ty: ty >>
         punct!(";") >>
         (Item {
             ident: id,
             vis: vis,
             attrs: attrs,
-            node: ItemKind::Ty(Box::new(ty), generics),
+            node: ItemKind::Ty(
+                Box::new(ty),
+                Generics {
+                    where_clause: where_clause,
+                    ..generics
+                },
+            ),
         })
     ));
 
     named!(item_struct_or_enum -> Item, map!(
         macro_input,
         |def: MacroInput| Item {
             ident: def.ident,
             vis: def.vis,
@@ -692,49 +746,64 @@ pub mod parsing {
         (TraitItem {
             ident: id,
             attrs: attrs,
             node: TraitItemKind::Const(ty, value),
         })
     ));
 
     named!(trait_item_method -> TraitItem, do_parse!(
-        attrs: many0!(outer_attr) >>
+        outer_attrs: many0!(outer_attr) >>
         constness: constness >>
         unsafety: unsafety >>
-        abi: option!(preceded!(keyword!("extern"), quoted_string)) >>
+        abi: option!(abi) >>
         keyword!("fn") >>
         name: ident >>
         generics: generics >>
         punct!("(") >>
         inputs: terminated_list!(punct!(","), fn_arg) >>
         punct!(")") >>
         ret: option!(preceded!(punct!("->"), ty)) >>
         where_clause: where_clause >>
-        body: option!(block) >>
+        body: option!(delimited!(
+            punct!("{"),
+            tuple!(many0!(inner_attr), within_block),
+            punct!("}")
+        )) >>
         cond!(body.is_none(), punct!(";")) >>
-        (TraitItem {
-            ident: name,
-            attrs: attrs,
-            node: TraitItemKind::Method(
-                MethodSig {
-                    unsafety: unsafety,
-                    constness: constness,
-                    abi: abi.map(Abi),
-                    decl: FnDecl {
-                        inputs: inputs,
-                        output: ret.map(FunctionRetTy::Ty).unwrap_or(FunctionRetTy::Default),
+        ({
+            let (inner_attrs, stmts) = match body {
+                Some((inner_attrs, stmts)) => (inner_attrs, Some(stmts)),
+                None => (Vec::new(), None),
+            };
+            TraitItem {
+                ident: name,
+                attrs: {
+                    let mut attrs = outer_attrs;
+                    attrs.extend(inner_attrs);
+                    attrs
+                },
+                node: TraitItemKind::Method(
+                    MethodSig {
+                        unsafety: unsafety,
+                        constness: constness,
+                        abi: abi,
+                        decl: FnDecl {
+                            inputs: inputs,
+                            output: ret.map(FunctionRetTy::Ty).unwrap_or(FunctionRetTy::Default),
+                            variadic: false,
+                        },
+                        generics: Generics {
+                            where_clause: where_clause,
+                            .. generics
+                        },
                     },
-                    generics: Generics {
-                        where_clause: where_clause,
-                        .. generics
-                    },
-                },
-                body,
-            ),
+                    stmts.map(|stmts| Block { stmts: stmts }),
+                ),
+            }
         })
     ));
 
     named!(trait_item_type -> TraitItem, do_parse!(
         attrs: many0!(outer_attr) >>
         keyword!("type") >>
         id: ident >>
         bounds: opt_vec!(preceded!(
@@ -833,51 +902,61 @@ pub mod parsing {
             vis: vis,
             defaultness: defaultness,
             attrs: attrs,
             node: ImplItemKind::Const(ty, value),
         })
     ));
 
     named!(impl_item_method -> ImplItem, do_parse!(
-        attrs: many0!(outer_attr) >>
+        outer_attrs: many0!(outer_attr) >>
         vis: visibility >>
         defaultness: defaultness >>
         constness: constness >>
         unsafety: unsafety >>
-        abi: option!(preceded!(keyword!("extern"), quoted_string)) >>
+        abi: option!(abi) >>
         keyword!("fn") >>
         name: ident >>
         generics: generics >>
         punct!("(") >>
         inputs: terminated_list!(punct!(","), fn_arg) >>
         punct!(")") >>
         ret: option!(preceded!(punct!("->"), ty)) >>
         where_clause: where_clause >>
-        body: block >>
+        punct!("{") >>
+        inner_attrs: many0!(inner_attr) >>
+        stmts: within_block >>
+        punct!("}") >>
         (ImplItem {
             ident: name,
             vis: vis,
             defaultness: defaultness,
-            attrs: attrs,
+            attrs: {
+                let mut attrs = outer_attrs;
+                attrs.extend(inner_attrs);
+                attrs
+            },
             node: ImplItemKind::Method(
                 MethodSig {
                     unsafety: unsafety,
                     constness: constness,
-                    abi: abi.map(Abi),
+                    abi: abi,
                     decl: FnDecl {
                         inputs: inputs,
                         output: ret.map(FunctionRetTy::Ty).unwrap_or(FunctionRetTy::Default),
+                        variadic: false,
                     },
                     generics: Generics {
                         where_clause: where_clause,
                         .. generics
                     },
                 },
-                body,
+                Block {
+                    stmts: stmts,
+                },
             ),
         })
     ));
 
     named!(impl_item_type -> ImplItem, do_parse!(
         attrs: many0!(outer_attr) >>
         vis: visibility >>
         defaultness: defaultness >>
@@ -923,22 +1002,16 @@ pub mod parsing {
     ));
 
     named!(constness -> Constness, alt!(
         keyword!("const") => { |_| Constness::Const }
         |
         epsilon!() => { |_| Constness::NotConst }
     ));
 
-    named!(unsafety -> Unsafety, alt!(
-        keyword!("unsafe") => { |_| Unsafety::Unsafe }
-        |
-        epsilon!() => { |_| Unsafety::Normal }
-    ));
-
     named!(defaultness -> Defaultness, alt!(
         keyword!("default") => { |_| Defaultness::Default }
         |
         epsilon!() => { |_| Defaultness::Final }
     ));
 }
 
 #[cfg(feature = "printing")]
@@ -949,16 +1022,17 @@ mod printing {
     use data::VariantData;
     use quote::{Tokens, ToTokens};
 
     impl ToTokens for Item {
         fn to_tokens(&self, tokens: &mut Tokens) {
             tokens.append_all(self.attrs.outer());
             match self.node {
                 ItemKind::ExternCrate(ref original) => {
+                    self.vis.to_tokens(tokens);
                     tokens.append("extern");
                     tokens.append("crate");
                     if let Some(ref original) = *original {
                         original.to_tokens(tokens);
                         tokens.append("as");
                     }
                     self.ident.to_tokens(tokens);
                     tokens.append(";");
@@ -1001,41 +1075,48 @@ mod printing {
                     tokens.append("(");
                     tokens.append_separated(&decl.inputs, ",");
                     tokens.append(")");
                     if let FunctionRetTy::Ty(ref ty) = decl.output {
                         tokens.append("->");
                         ty.to_tokens(tokens);
                     }
                     generics.where_clause.to_tokens(tokens);
-                    block.to_tokens(tokens);
+                    tokens.append("{");
+                    tokens.append_all(self.attrs.inner());
+                    tokens.append_all(&block.stmts);
+                    tokens.append("}");
                 }
                 ItemKind::Mod(ref items) => {
                     self.vis.to_tokens(tokens);
                     tokens.append("mod");
                     self.ident.to_tokens(tokens);
-                    tokens.append("{");
-                    tokens.append_all(items);
-                    tokens.append("}");
+                    match *items {
+                        Some(ref items) => {
+                            tokens.append("{");
+                            tokens.append_all(self.attrs.inner());
+                            tokens.append_all(items);
+                            tokens.append("}");
+                        }
+                        None => tokens.append(";"),
+                    }
                 }
                 ItemKind::ForeignMod(ref foreign_mod) => {
                     self.vis.to_tokens(tokens);
-                    match foreign_mod.abi {
-                        Some(ref abi) => abi.to_tokens(tokens),
-                        None => tokens.append("extern"),
-                    }
+                    foreign_mod.abi.to_tokens(tokens);
                     tokens.append("{");
                     tokens.append_all(&foreign_mod.items);
                     tokens.append("}");
                 }
                 ItemKind::Ty(ref ty, ref generics) => {
                     self.vis.to_tokens(tokens);
                     tokens.append("type");
                     self.ident.to_tokens(tokens);
                     generics.to_tokens(tokens);
+                    generics.where_clause.to_tokens(tokens);
                     tokens.append("=");
                     ty.to_tokens(tokens);
                     tokens.append(";");
                 }
                 ItemKind::Enum(ref variants, ref generics) => {
                     self.vis.to_tokens(tokens);
                     tokens.append("enum");
                     self.ident.to_tokens(tokens);
@@ -1048,44 +1129,51 @@ mod printing {
                     }
                     tokens.append("}");
                 }
                 ItemKind::Struct(ref variant_data, ref generics) => {
                     self.vis.to_tokens(tokens);
                     tokens.append("struct");
                     self.ident.to_tokens(tokens);
                     generics.to_tokens(tokens);
-                    generics.where_clause.to_tokens(tokens);
-                    variant_data.to_tokens(tokens);
                     match *variant_data {
                         VariantData::Struct(_) => {
+                            generics.where_clause.to_tokens(tokens);
+                            variant_data.to_tokens(tokens);
                             // no semicolon
                         }
-                        VariantData::Tuple(_) |
-                        VariantData::Unit => tokens.append(";"),
+                        VariantData::Tuple(_) => {
+                            variant_data.to_tokens(tokens);
+                            generics.where_clause.to_tokens(tokens);
+                            tokens.append(";");
+                        }
+                        VariantData::Unit => {
+                            generics.where_clause.to_tokens(tokens);
+                            tokens.append(";");
+                        }
                     }
                 }
                 ItemKind::Union(ref variant_data, ref generics) => {
                     self.vis.to_tokens(tokens);
                     tokens.append("union");
                     self.ident.to_tokens(tokens);
                     generics.to_tokens(tokens);
                     generics.where_clause.to_tokens(tokens);
                     variant_data.to_tokens(tokens);
                 }
                 ItemKind::Trait(unsafety, ref generics, ref bound, ref items) => {
                     self.vis.to_tokens(tokens);
                     unsafety.to_tokens(tokens);
                     tokens.append("trait");
                     self.ident.to_tokens(tokens);
+                    generics.to_tokens(tokens);
                     if !bound.is_empty() {
                         tokens.append(":");
                         tokens.append_separated(bound, "+");
                     }
-                    generics.to_tokens(tokens);
                     generics.where_clause.to_tokens(tokens);
                     tokens.append("{");
                     tokens.append_all(items);
                     tokens.append("}");
                 }
                 ItemKind::DefaultImpl(unsafety, ref path) => {
                     unsafety.to_tokens(tokens);
                     tokens.append("impl");
@@ -1177,31 +1265,37 @@ mod printing {
                     ty.to_tokens(tokens);
                     if let Some(ref expr) = *expr {
                         tokens.append("=");
                         expr.to_tokens(tokens);
                     }
                     tokens.append(";");
                 }
                 TraitItemKind::Method(ref sig, ref block) => {
+                    sig.constness.to_tokens(tokens);
                     sig.unsafety.to_tokens(tokens);
                     sig.abi.to_tokens(tokens);
                     tokens.append("fn");
                     self.ident.to_tokens(tokens);
                     sig.generics.to_tokens(tokens);
                     tokens.append("(");
                     tokens.append_separated(&sig.decl.inputs, ",");
                     tokens.append(")");
                     if let FunctionRetTy::Ty(ref ty) = sig.decl.output {
                         tokens.append("->");
                         ty.to_tokens(tokens);
                     }
                     sig.generics.where_clause.to_tokens(tokens);
                     match *block {
-                        Some(ref block) => block.to_tokens(tokens),
+                        Some(ref block) => {
+                            tokens.append("{");
+                            tokens.append_all(self.attrs.inner());
+                            tokens.append_all(&block.stmts);
+                            tokens.append("}");
+                        }
                         None => tokens.append(";"),
                     }
                 }
                 TraitItemKind::Type(ref bound, ref default) => {
                     tokens.append("type");
                     self.ident.to_tokens(tokens);
                     if !bound.is_empty() {
                         tokens.append(":");
@@ -1239,30 +1333,34 @@ mod printing {
                     ty.to_tokens(tokens);
                     tokens.append("=");
                     expr.to_tokens(tokens);
                     tokens.append(";");
                 }
                 ImplItemKind::Method(ref sig, ref block) => {
                     self.vis.to_tokens(tokens);
                     self.defaultness.to_tokens(tokens);
+                    sig.constness.to_tokens(tokens);
                     sig.unsafety.to_tokens(tokens);
                     sig.abi.to_tokens(tokens);
                     tokens.append("fn");
                     self.ident.to_tokens(tokens);
                     sig.generics.to_tokens(tokens);
                     tokens.append("(");
                     tokens.append_separated(&sig.decl.inputs, ",");
                     tokens.append(")");
                     if let FunctionRetTy::Ty(ref ty) = sig.decl.output {
                         tokens.append("->");
                         ty.to_tokens(tokens);
                     }
                     sig.generics.where_clause.to_tokens(tokens);
-                    block.to_tokens(tokens);
+                    tokens.append("{");
+                    tokens.append_all(self.attrs.inner());
+                    tokens.append_all(&block.stmts);
+                    tokens.append("}");
                 }
                 ImplItemKind::Type(ref ty) => {
                     self.vis.to_tokens(tokens);
                     self.defaultness.to_tokens(tokens);
                     tokens.append("type");
                     self.ident.to_tokens(tokens);
                     tokens.append("=");
                     ty.to_tokens(tokens);
@@ -1287,16 +1385,22 @@ mod printing {
             match self.node {
                 ForeignItemKind::Fn(ref decl, ref generics) => {
                     self.vis.to_tokens(tokens);
                     tokens.append("fn");
                     self.ident.to_tokens(tokens);
                     generics.to_tokens(tokens);
                     tokens.append("(");
                     tokens.append_separated(&decl.inputs, ",");
+                    if decl.variadic {
+                        if !decl.inputs.is_empty() {
+                            tokens.append(",");
+                        }
+                        tokens.append("...");
+                    }
                     tokens.append(")");
                     if let FunctionRetTy::Ty(ref ty) = decl.output {
                         tokens.append("->");
                         ty.to_tokens(tokens);
                     }
                     generics.where_clause.to_tokens(tokens);
                     tokens.append(";");
                 }
@@ -1333,27 +1437,16 @@ mod printing {
                 }
                 FnArg::Ignored(ref ty) => {
                     ty.to_tokens(tokens);
                 }
             }
         }
     }
 
-    impl ToTokens for Unsafety {
-        fn to_tokens(&self, tokens: &mut Tokens) {
-            match *self {
-                Unsafety::Unsafe => tokens.append("unsafe"),
-                Unsafety::Normal => {
-                    // nothing
-                }
-            }
-        }
-    }
-
     impl ToTokens for Constness {
         fn to_tokens(&self, tokens: &mut Tokens) {
             match *self {
                 Constness::Const => tokens.append("const"),
                 Constness::NotConst => {
                     // nothing
                 }
             }
@@ -1376,16 +1469,9 @@ mod printing {
             match *self {
                 ImplPolarity::Negative => tokens.append("!"),
                 ImplPolarity::Positive => {
                     // nothing
                 }
             }
         }
     }
-
-    impl ToTokens for Abi {
-        fn to_tokens(&self, tokens: &mut Tokens) {
-            tokens.append("extern");
-            self.0.to_tokens(tokens);
-        }
-    }
 }
--- a/third_party/rust/syn/src/krate.rs
+++ b/third_party/rust/syn/src/krate.rs
@@ -6,39 +6,51 @@ pub struct Crate {
     pub attrs: Vec<Attribute>,
     pub items: Vec<Item>,
 }
 
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
     use attr::parsing::inner_attr;
-    use space::whitespace;
-    use item::parsing::item;
+    use item::parsing::items;
 
     named!(pub krate -> Crate, do_parse!(
+        option!(byte_order_mark) >>
+        shebang: option!(shebang) >>
         attrs: many0!(inner_attr) >>
-        items: many0!(item) >>
-        option!(whitespace) >>
+        items: items >>
         (Crate {
-            shebang: None,
+            shebang: shebang,
             attrs: attrs,
             items: items,
         })
     ));
+
+    named!(byte_order_mark -> &str, tag!("\u{feff}"));
+
+    named!(shebang -> String, do_parse!(
+        tag!("#!") >>
+        not!(peek!(tag!("["))) >>
+        content: take_until!("\n") >>
+        (format!("#!{}", content))
+    ));
 }
 
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
     use attr::FilterAttrs;
     use quote::{Tokens, ToTokens};
 
     impl ToTokens for Crate {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            if let Some(ref shebang) = self.shebang {
+                tokens.append(&format!("{}\n", shebang));
+            }
             for attr in self.attrs.inner() {
                 attr.to_tokens(tokens);
             }
             for item in &self.items {
                 item.to_tokens(tokens);
             }
         }
     }
--- a/third_party/rust/syn/src/lib.rs
+++ b/third_party/rust/syn/src/lib.rs
@@ -1,97 +1,108 @@
 #![cfg_attr(feature = "clippy", feature(plugin))]
 #![cfg_attr(feature = "clippy", plugin(clippy))]
 
 #[cfg(feature = "printing")]
+#[macro_use]
 extern crate quote;
 
+#[cfg(feature = "pretty")]
+extern crate syntex_syntax as syntax;
+
 #[cfg(feature = "parsing")]
 extern crate unicode_xid;
 
 #[cfg(feature = "parsing")]
 #[macro_use]
 mod nom;
 
 #[cfg(feature = "parsing")]
 #[macro_use]
 mod helper;
 
-#[cfg(feature = "parsing")]
-mod escape;
+#[cfg(feature = "aster")]
+pub mod aster;
 
 mod attr;
-pub use attr::{Attribute, AttrStyle, MetaItem};
+pub use attr::{Attribute, AttrStyle, MetaItem, NestedMetaItem};
 
 mod constant;
 pub use constant::ConstExpr;
 
 mod data;
 pub use data::{Field, Variant, VariantData, Visibility};
 
+#[cfg(feature = "parsing")]
+mod escape;
+
 #[cfg(feature = "full")]
 mod expr;
 #[cfg(feature = "full")]
-pub use expr::{Arm, BindingMode, Block, BlockCheckMode, CaptureBy, Expr, FieldPat, Local,
-               MacStmtStyle, Pat, RangeLimits, Stmt};
+pub use expr::{Arm, BindingMode, Block, BlockCheckMode, CaptureBy, Expr, ExprKind, FieldPat,
+               FieldValue, Local, MacStmtStyle, Pat, RangeLimits, Stmt};
 
 mod generics;
 pub use generics::{Generics, Lifetime, LifetimeDef, TraitBoundModifier, TyParam, TyParamBound,
                    WhereBoundPredicate, WhereClause, WherePredicate, WhereRegionPredicate};
-
-#[cfg(feature = "full")]
-mod krate;
-#[cfg(feature = "full")]
-pub use krate::Crate;
+#[cfg(feature = "printing")]
+pub use generics::{ImplGenerics, TyGenerics};
 
 mod ident;
 pub use ident::Ident;
 
 #[cfg(feature = "full")]
 mod item;
 #[cfg(feature = "full")]
-pub use item::{Abi, Constness, Defaultness, FnArg, FnDecl, ForeignItemKind, ForeignItem,
-               ForeignMod, ImplItem, ImplItemKind, ImplPolarity, Item, ItemKind, MethodSig,
-               PathListItem, TraitItem, TraitItemKind, Unsafety, ViewPath};
+pub use item::{Constness, Defaultness, FnArg, FnDecl, ForeignItemKind, ForeignItem, ForeignMod,
+               ImplItem, ImplItemKind, ImplPolarity, Item, ItemKind, MethodSig, PathListItem,
+               TraitItem, TraitItemKind, ViewPath};
+
+#[cfg(feature = "full")]
+mod krate;
+#[cfg(feature = "full")]
+pub use krate::Crate;
 
 mod lit;
 pub use lit::{FloatTy, IntTy, Lit, StrStyle};
 
 #[cfg(feature = "full")]
 mod mac;
 #[cfg(feature = "full")]
 pub use mac::{BinOpToken, DelimToken, Delimited, Mac, Token, TokenTree};
 
 mod macro_input;
 pub use macro_input::{Body, MacroInput};
 
 mod op;
 pub use op::{BinOp, UnOp};
 
+#[cfg(feature = "expand")]
+mod registry;
+#[cfg(feature = "expand")]
+pub use registry::{CustomDerive, Expanded, Registry};
+
 #[cfg(feature = "parsing")]
 mod space;
 
 mod ty;
-pub use ty::{AngleBracketedParameterData, BareFnArg, BareFnTy, FunctionRetTy, MutTy, Mutability,
-             ParenthesizedParameterData, Path, PathParameters, PathSegment, PolyTraitRef, QSelf,
-             Ty, TypeBinding};
-
-#[cfg(feature = "aster")]
-pub mod aster;
+pub use ty::{Abi, AngleBracketedParameterData, BareFnArg, BareFnTy, FunctionRetTy, MutTy,
+             Mutability, ParenthesizedParameterData, Path, PathParameters, PathSegment,
+             PolyTraitRef, QSelf, Ty, TypeBinding, Unsafety};
 
 #[cfg(feature = "visit")]
 pub mod visit;
 
 #[cfg(feature = "parsing")]
 pub use parsing::*;
 
 #[cfg(feature = "parsing")]
 mod parsing {
     use super::*;
-    use {generics, macro_input, ty};
+    use {generics, macro_input, space, ty};
     use nom::IResult;
 
     #[cfg(feature = "full")]
     use {expr, item, krate, mac};
 
     pub fn parse_macro_input(input: &str) -> Result<MacroInput, String> {
         unwrap("macro input", macro_input::parsing::macro_input, input)
     }
@@ -102,16 +113,21 @@ mod parsing {
     }
 
     #[cfg(feature = "full")]
     pub fn parse_item(input: &str) -> Result<Item, String> {
         unwrap("item", item::parsing::item, input)
     }
 
     #[cfg(feature = "full")]
+    pub fn parse_items(input: &str) -> Result<Vec<Item>, String> {
+        unwrap("items", item::parsing::items, input)
+    }
+
+    #[cfg(feature = "full")]
     pub fn parse_expr(input: &str) -> Result<Expr, String> {
         unwrap("expression", expr::parsing::expr, input)
     }
 
     pub fn parse_type(input: &str) -> Result<Ty, String> {
         unwrap("type", ty::parsing::ty, input)
     }
 
@@ -128,17 +144,18 @@ mod parsing {
         unwrap("token trees", mac::parsing::token_trees, input)
     }
 
     fn unwrap<T>(name: &'static str,
                  f: fn(&str) -> IResult<&str, T>,
                  input: &str)
                  -> Result<T, String> {
         match f(input) {
-            IResult::Done(rest, t) => {
+            IResult::Done(mut rest, t) => {
+                rest = space::skip_whitespace(rest);
                 if rest.is_empty() {
                     Ok(t)
                 } else if rest.len() == input.len() {
                     // parsed nothing
                     Err(format!("failed to parse {}: {:?}", name, rest))
                 } else {
                     Err(format!("failed to parse tokens after {}: {:?}", name, rest))
                 }
--- a/third_party/rust/syn/src/lit.rs
+++ b/third_party/rust/syn/src/lit.rs
@@ -1,17 +1,17 @@
 /// Literal kind.
 ///
 /// E.g. `"foo"`, `42`, `12.34` or `bool`
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub enum Lit {
     /// A string literal (`"foo"`)
     Str(String, StrStyle),
     /// A byte string (`b"foo"`)
-    ByteStr(Vec<u8>),
+    ByteStr(Vec<u8>, StrStyle),
     /// A byte char (`b'f'`)
     Byte(u8),
     /// A character literal (`'a'`)
     Char(char),
     /// An integer literal (`1`)
     Int(u64, IntTy),
     /// A float literal (`1f64` or `1E10f64` or `1.0E10`)
     Float(String, FloatTy),
@@ -24,16 +24,52 @@ pub enum StrStyle {
     /// A regular string, like `"foo"`
     Cooked,
     /// A raw string, like `r##"foo"##`
     ///
     /// The uint is the number of `#` symbols used
     Raw(usize),
 }
 
+impl From<String> for Lit {
+    fn from(input: String) -> Lit {
+        Lit::Str(input, StrStyle::Cooked)
+    }
+}
+
+impl<'a> From<&'a str> for Lit {
+    fn from(input: &str) -> Lit {
+        Lit::Str(input.into(), StrStyle::Cooked)
+    }
+}
+
+impl From<Vec<u8>> for Lit {
+    fn from(input: Vec<u8>) -> Lit {
+        Lit::ByteStr(input, StrStyle::Cooked)
+    }
+}
+
+impl<'a> From<&'a [u8]> for Lit {
+    fn from(input: &[u8]) -> Lit {
+        Lit::ByteStr(input.into(), StrStyle::Cooked)
+    }
+}
+
+impl From<char> for Lit {
+    fn from(input: char) -> Lit {
+        Lit::Char(input)
+    }
+}
+
+impl From<bool> for Lit {
+    fn from(input: bool) -> Lit {
+        Lit::Bool(input)
+    }
+}
+
 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
 pub enum IntTy {
     Isize,
     I8,
     I16,
     I32,
     I64,
     Usize,
@@ -46,38 +82,77 @@ pub enum IntTy {
 
 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
 pub enum FloatTy {
     F32,
     F64,
     Unsuffixed,
 }
 
+macro_rules! impl_from_for_lit {
+    (Int, [$($rust_type:ty => $syn_type:expr),+]) => {
+        $(
+            impl From<$rust_type> for Lit {
+                fn from(input: $rust_type) -> Lit {
+                    Lit::Int(input as u64, $syn_type)
+                }
+            }
+        )+
+    };
+    (Float, [$($rust_type:ty => $syn_type:expr),+]) => {
+        $(
+            impl From<$rust_type> for Lit {
+                fn from(input: $rust_type) -> Lit {
+                    Lit::Float(format!("{}", input), $syn_type)
+                }
+            }
+        )+
+    };
+}
+
+impl_from_for_lit! {Int, [
+    isize => IntTy::Isize,
+    i8 => IntTy::I8,
+    i16 => IntTy::I16,
+    i32 => IntTy::I32,
+    i64 => IntTy::I64,
+    usize => IntTy::Usize,
+    u8 => IntTy::U8,
+    u16 => IntTy::U16,
+    u32 => IntTy::U32,
+    u64 => IntTy::U64
+]}
+
+impl_from_for_lit! {Float, [
+    f32 => FloatTy::F32,
+    f64 => FloatTy::F64
+]}
+
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use escape::{cooked_char, cooked_string, raw_string};
-    use space::whitespace;
+    use escape::{cooked_byte, cooked_byte_string, cooked_char, cooked_string, raw_string};
+    use space::skip_whitespace;
     use nom::IResult;
+    use unicode_xid::UnicodeXID;
 
     named!(pub lit -> Lit, alt!(
         string
         |
         byte_string
         |
         byte
         |
         character
         |
-        int => { |(value, ty)| Lit::Int(value, ty) }
-    // TODO: Float
+        float // must be before int
         |
-        keyword!("true") => { |_| Lit::Bool(true) }
+        int => { |(value, ty)| Lit::Int(value, ty) }
         |
-        keyword!("false") => { |_| Lit::Bool(false) }
+        boolean
     ));
 
     named!(string -> Lit, alt!(
         quoted_string => { |s| Lit::Str(s, StrStyle::Cooked) }
         |
         preceded!(
             punct!("r"),
             raw_string
@@ -88,46 +163,55 @@ pub mod parsing {
         punct!("\""),
         cooked_string,
         tag!("\"")
     ));
 
     named!(byte_string -> Lit, alt!(
         delimited!(
             punct!("b\""),
-            cooked_string,
+            cooked_byte_string,
             tag!("\"")
-        ) => { |s: String| Lit::ByteStr(s.into_bytes()) }
+        ) => { |vec| Lit::ByteStr(vec, StrStyle::Cooked) }
         |
         preceded!(
             punct!("br"),
             raw_string
-        ) => { |(s, _): (String, _)| Lit::ByteStr(s.into_bytes()) }
+        ) => { |(s, n): (String, _)| Lit::ByteStr(s.into_bytes(), StrStyle::Raw(n)) }
     ));
 
     named!(byte -> Lit, do_parse!(
         punct!("b") >>
         tag!("'") >>
-        ch: cooked_char >>
+        b: cooked_byte >>
         tag!("'") >>
-        (Lit::Byte(ch as u8))
+        (Lit::Byte(b))
     ));
 
     named!(character -> Lit, do_parse!(
         punct!("'") >>
         ch: cooked_char >>
         tag!("'") >>
         (Lit::Char(ch))
     ));
 
+    named!(float -> Lit, do_parse!(
+        value: float_string >>
+        suffix: alt!(
+            tag!("f32") => { |_| FloatTy::F32 }
+            |
+            tag!("f64") => { |_| FloatTy::F64 }
+            |
+            epsilon!() => { |_| FloatTy::Unsuffixed }
+        ) >>
+        (Lit::Float(value, suffix))
+    ));
+
     named!(pub int -> (u64, IntTy), tuple!(
-        preceded!(
-            option!(whitespace),
-            digits
-        ),
+        digits,
         alt!(
             tag!("isize") => { |_| IntTy::Isize }
             |
             tag!("i8") => { |_| IntTy::I8 }
             |
             tag!("i16") => { |_| IntTy::I16 }
             |
             tag!("i32") => { |_| IntTy::I32 }
@@ -143,70 +227,200 @@ pub mod parsing {
             tag!("u32") => { |_| IntTy::U32 }
             |
             tag!("u64") => { |_| IntTy::U64 }
             |
             epsilon!() => { |_| IntTy::Unsuffixed }
         )
     ));
 
-    pub fn digits(input: &str) -> IResult<&str, u64> {
-        let mut value = 0u64;
-        let mut len = 0;
-        let mut bytes = input.bytes().peekable();
-        while let Some(&b) = bytes.peek() {
-            match b {
-                b'0'...b'9' => {
-                    value = match value.checked_mul(10) {
-                        Some(value) => value,
-                        None => return IResult::Error,
-                    };
-                    value = match value.checked_add((b - b'0') as u64) {
-                        Some(value) => value,
-                        None => return IResult::Error,
-                    };
-                    bytes.next();
+    named!(boolean -> Lit, alt!(
+        keyword!("true") => { |_| Lit::Bool(true) }
+        |
+        keyword!("false") => { |_| Lit::Bool(false) }
+    ));
+
+    fn float_string(mut input: &str) -> IResult<&str, String> {
+        input = skip_whitespace(input);
+
+        let mut chars = input.chars().peekable();
+        match chars.next() {
+            Some(ch) if ch >= '0' && ch <= '9' => {}
+            _ => return IResult::Error,
+        }
+
+        let mut len = 1;
+        let mut has_dot = false;
+        let mut has_exp = false;
+        while let Some(&ch) = chars.peek() {
+            match ch {
+                '0'...'9' | '_' => {
+                    chars.next();
                     len += 1;
                 }
+                '.' => {
+                    if has_dot {
+                        break;
+                    }
+                    chars.next();
+                    if chars.peek()
+                        .map(|&ch| ch == '.' || UnicodeXID::is_xid_start(ch))
+                        .unwrap_or(false) {
+                        return IResult::Error;
+                    }
+                    len += 1;
+                    has_dot = true;
+                }
+                'e' | 'E' => {
+                    chars.next();
+                    len += 1;
+                    has_exp = true;
+                    break;
+                }
                 _ => break,
             }
         }
-        if len > 0 {
+
+        let rest = &input[len..];
+        if !(has_dot || has_exp || rest.starts_with("f32") || rest.starts_with("f64")) {
+            return IResult::Error;
+        }
+
+        if has_exp {
+            let mut has_exp_value = false;
+            while let Some(&ch) = chars.peek() {
+                match ch {
+                    '+' | '-' => {
+                        if has_exp_value {
+                            break;
+                        }
+                        chars.next();
+                        len += 1;
+                    }
+                    '0'...'9' => {
+                        chars.next();
+                        len += 1;
+                        has_exp_value = true;
+                    }
+                    '_' => {
+                        chars.next();
+                        len += 1;
+                    }
+                    _ => break,
+                }
+            }
+            if !has_exp_value {
+                return IResult::Error;
+            }
+        }
+
+        IResult::Done(&input[len..], input[..len].replace("_", ""))
+    }
+
+    pub fn digits(mut input: &str) -> IResult<&str, u64> {
+        input = skip_whitespace(input);
+
+        let base = if input.starts_with("0x") {
+            input = &input[2..];
+            16
+        } else if input.starts_with("0o") {
+            input = &input[2..];
+            8
+        } else if input.starts_with("0b") {
+            input = &input[2..];
+            2
+        } else {
+            10
+        };
+
+        let mut value = 0u64;
+        let mut len = 0;
+        let mut empty = true;
+        for b in input.bytes() {
+            let digit = match b {
+                b'0'...b'9' => (b - b'0') as u64,
+                b'a'...b'f' => 10 + (b - b'a') as u64,
+                b'A'...b'F' => 10 + (b - b'A') as u64,
+                b'_' => {
+                    if empty && base == 10 {
+                        return IResult::Error;
+                    }
+                    len += 1;
+                    continue;
+                }
+                _ => break,
+            };
+            if digit >= base {
+                return IResult::Error;
+            }
+            value = match value.checked_mul(base) {
+                Some(value) => value,
+                None => return IResult::Error,
+            };
+            value = match value.checked_add(digit) {
+                Some(value) => value,
+                None => return IResult::Error,
+            };
+            len += 1;
+            empty = false;
+        }
+        if empty {
+            IResult::Error
+        } else {
             IResult::Done(&input[len..], value)
-        } else {
-            IResult::Error
         }
     }
 }
 
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
     use quote::{Tokens, ToTokens};
     use std::{ascii, iter};
     use std::fmt::{self, Display};
+    use std::str;
 
     impl ToTokens for Lit {
         fn to_tokens(&self, tokens: &mut Tokens) {
             match *self {
                 Lit::Str(ref s, StrStyle::Cooked) => s.to_tokens(tokens),
                 Lit::Str(ref s, StrStyle::Raw(n)) => {
                     tokens.append(&format!("r{delim}\"{string}\"{delim}",
                         delim = iter::repeat("#").take(n).collect::<String>(),
                         string = s));
                 }
-                Lit::ByteStr(ref v) => {
+                Lit::ByteStr(ref v, StrStyle::Cooked) => {
                     let mut escaped = "b\"".to_string();
                     for &ch in v.iter() {
-                        escaped.extend(ascii::escape_default(ch).map(|c| c as char));
+                        match ch {
+                            0 => escaped.push_str(r"\0"),
+                            b'\'' => escaped.push('\''),
+                            _ => escaped.extend(ascii::escape_default(ch).map(|c| c as char)),
+                        }
                     }
                     escaped.push('"');
                     tokens.append(&escaped);
                 }
-                Lit::Byte(b) => tokens.append(&format!("b{:?}", b as char)),
+                Lit::ByteStr(ref vec, StrStyle::Raw(n)) => {
+                    tokens.append(&format!("br{delim}\"{string}\"{delim}",
+                        delim = iter::repeat("#").take(n).collect::<String>(),
+                        string = str::from_utf8(vec).unwrap()));
+                }
+                Lit::Byte(b) => {
+                    match b {
+                        0 => tokens.append(r"b'\0'"),
+                        b'\"' => tokens.append("b'\"'"),
+                        _ => {
+                            let mut escaped = "b'".to_string();
+                            escaped.extend(ascii::escape_default(b).map(|c| c as char));
+                            escaped.push('\'');
+                            tokens.append(&escaped);
+                        }
+                    }
+                }
                 Lit::Char(ch) => ch.to_tokens(tokens),
                 Lit::Int(value, ty) => tokens.append(&format!("{}{}", value, ty)),
                 Lit::Float(ref value, ty) => tokens.append(&format!("{}{}", value, ty)),
                 Lit::Bool(true) => tokens.append("true"),
                 Lit::Bool(false) => tokens.append("false"),
             }
         }
     }
--- a/third_party/rust/syn/src/mac.rs
+++ b/third_party/rust/syn/src/mac.rs
@@ -109,52 +109,48 @@ pub enum DelimToken {
     Brace,
 }
 
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
     use Lifetime;
     use generics::parsing::lifetime;
-    use ident::parsing::ident;
+    use ident::parsing::{ident, word};
     use lit::parsing::lit;
     use space::{block_comment, whitespace};
 
     named!(pub mac -> Mac, do_parse!(
         name: ident >>
         punct!("!") >>
         body: delimited >>
         (Mac {
             path: name.into(),
             tts: vec![TokenTree::Delimited(body)],
         })
     ));
 
-    named!(pub token_trees -> Vec<TokenTree>, do_parse!(
-        tts: many0!(token_tree) >>
-        option!(whitespace) >>
-        (tts)
-    ));
+    named!(pub token_trees -> Vec<TokenTree>, many0!(token_tree));
 
     named!(pub delimited -> Delimited, alt!(
         delimited!(
             punct!("("),
-            many0!(token_tree),
+            token_trees,
             punct!(")")
         ) => { |tts| Delimited { delim: DelimToken::Paren, tts: tts } }
         |
         delimited!(
             punct!("["),
-            many0!(token_tree),
+            token_trees,
             punct!("]")
         ) => { |tts| Delimited { delim: DelimToken::Bracket, tts: tts } }
         |
         delimited!(
             punct!("{"),
-            many0!(token_tree),
+            token_trees,
             punct!("}")
         ) => { |tts| Delimited { delim: DelimToken::Brace, tts: tts } }
     ));
 
     named!(token_tree -> TokenTree, alt!(
         map!(token, TokenTree::Token)
         |
         map!(delimited, TokenTree::Delimited)
@@ -174,28 +170,28 @@ pub mod parsing {
         punct!("=>") => { |_| Token::FatArrow } // must be before Eq
         |
         punct!("...") => { |_| Token::DotDotDot } // must be before DotDot
         |
         punct!("..") => { |_| Token::DotDot } // must be before Dot
         |
         punct!(".") => { |_| Token::Dot }
         |
-        map!(bin_op_eq, Token::BinOpEq)
+        map!(doc_comment, Token::DocComment) // must be before bin_op
+        |
+        map!(bin_op_eq, Token::BinOpEq) // must be before bin_op
         |
         map!(bin_op, Token::BinOp)
         |
         map!(lit, Token::Literal)
         |
-        map!(ident, Token::Ident)
+        map!(word, Token::Ident)
         |
         map!(lifetime, |lt: Lifetime| Token::Lifetime(lt.ident))
         |
-        map!(doc_comment, Token::DocComment)
-        |
         punct!("<=") => { |_| Token::Le }
         |
         punct!("==") => { |_| Token::EqEq }
         |
         punct!("!=") => { |_| Token::Ne }
         |
         punct!(">=") => { |_| Token::Ge }
         |
@@ -378,19 +374,19 @@ mod printing {
                 Token::ModSep => tokens.append("::"),
                 Token::RArrow => tokens.append("->"),
                 Token::LArrow => tokens.append("<-"),
                 Token::FatArrow => tokens.append("=>"),
                 Token::Pound => tokens.append("#"),
                 Token::Dollar => tokens.append("$"),
                 Token::Question => tokens.append("?"),
                 Token::Literal(ref lit) => lit.to_tokens(tokens),
-                Token::Ident(ref ident) => ident.to_tokens(tokens),
+                Token::Ident(ref ident) |
+                Token::Lifetime(ref ident) => ident.to_tokens(tokens),
                 Token::Underscore => tokens.append("_"),
-                Token::Lifetime(ref ident) => ident.to_tokens(tokens),
                 Token::DocComment(ref com) => {
                     tokens.append(&format!("{}\n", com));
                 }
             }
         }
     }
 
     impl BinOpToken {
--- a/third_party/rust/syn/src/macro_input.rs
+++ b/third_party/rust/syn/src/macro_input.rs
@@ -16,51 +16,48 @@ pub enum Body {
 }
 
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
     use Generics;
     use attr::parsing::outer_attr;
     use data::parsing::{visibility, struct_body, enum_body};
-    use generics::parsing::{generics, where_clause};
-    use space::whitespace;
+    use generics::parsing::generics;
     use ident::parsing::ident;
 
     named!(pub macro_input -> MacroInput, do_parse!(
         attrs: many0!(outer_attr) >>
         vis: visibility >>
         which: alt!(keyword!("struct") | keyword!("enum")) >>
         id: ident >>
         generics: generics >>
-        where_clause: where_clause >>
         item: switch!(value!(which),
-            "struct" => map!(struct_body, move |body| MacroInput {
+            "struct" => map!(struct_body, move |(wh, body)| MacroInput {
                 ident: id,
                 vis: vis,
                 attrs: attrs,
                 generics: Generics {
-                    where_clause: where_clause,
+                    where_clause: wh,
                     .. generics
                 },
                 body: Body::Struct(body),
             })
             |
-            "enum" => map!(enum_body, move |body| MacroInput {
+            "enum" => map!(enum_body, move |(wh, body)| MacroInput {
                 ident: id,
                 vis: vis,
                 attrs: attrs,
                 generics: Generics {
-                    where_clause: where_clause,
+                    where_clause: wh,
                     .. generics
                 },
                 body: Body::Enum(body),
             })
         ) >>
-        option!(whitespace) >>
         (item)
     ));
 }
 
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
     use attr::FilterAttrs;
@@ -74,38 +71,40 @@ mod printing {
             }
             self.vis.to_tokens(tokens);
             match self.body {
                 Body::Enum(_) => tokens.append("enum"),
                 Body::Struct(_) => tokens.append("struct"),
             }
             self.ident.to_tokens(tokens);
             self.generics.to_tokens(tokens);
-            self.generics.where_clause.to_tokens(tokens);
-            self.body.to_tokens(tokens);
-        }
-    }
-
-    impl ToTokens for Body {
-        fn to_tokens(&self, tokens: &mut Tokens) {
-            match *self {
+            match self.body {
                 Body::Enum(ref variants) => {
+                    self.generics.where_clause.to_tokens(tokens);
                     tokens.append("{");
                     for variant in variants {
                         variant.to_tokens(tokens);
                         tokens.append(",");
                     }
                     tokens.append("}");
                 }
                 Body::Struct(ref variant_data) => {
-                    variant_data.to_tokens(tokens);
                     match *variant_data {
                         VariantData::Struct(_) => {
+                            self.generics.where_clause.to_tokens(tokens);
+                            variant_data.to_tokens(tokens);
                             // no semicolon
                         }
-                        VariantData::Tuple(_) |
-                        VariantData::Unit => tokens.append(";"),
+                        VariantData::Tuple(_) => {
+                            variant_data.to_tokens(tokens);
+                            self.generics.where_clause.to_tokens(tokens);
+                            tokens.append(";");
+                        }
+                        VariantData::Unit => {
+                            self.generics.where_clause.to_tokens(tokens);
+                            tokens.append(";");
+                        }
                     }
                 }
             }
         }
     }
 }
--- a/third_party/rust/syn/src/nom.rs
+++ b/third_party/rust/syn/src/nom.rs
@@ -20,28 +20,28 @@ macro_rules! named {
     (pub $name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
         pub fn $name(i: &str) -> $crate::nom::IResult<&str, $o> {
             $submac!(i, $($args)*)
         }
     };
 }
 
 macro_rules! call {
-    ($i:expr, $fun:expr) => {
-        $fun($i)
+    ($i:expr, $fun:expr $(, $args:expr)*) => {
+        $fun($i $(, $args)*)
     };
 }
 
 macro_rules! map {
     ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
-        map_impl!($i, $submac!($($args)*), call!($g));
+        map_impl!($i, $submac!($($args)*), call!($g))
     };
 
     ($i:expr, $f:expr, $g:expr) => {
-        map_impl!($i, call!($f), call!($g));
+        map_impl!($i, call!($f), call!($g))
     };
 }
 
 /// Internal parser, do not use directly
 macro_rules! map_impl {
     ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => {
         match $submac!($i, $($args)*) {
             $crate::nom::IResult::Error => $crate::nom::IResult::Error,
@@ -56,72 +56,87 @@ macro_rules! not {
     ($i:expr, $submac:ident!( $($args:tt)* )) => {
         match $submac!($i, $($args)*) {
             $crate::nom::IResult::Done(_, _) => $crate::nom::IResult::Error,
             $crate::nom::IResult::Error => $crate::nom::IResult::Done($i, ""),
         }
     };
 }
 
+// This is actually nom's cond_with_error.
 macro_rules! cond {
     ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
         if $cond {
             match $submac!($i, $($args)*) {
                 $crate::nom::IResult::Done(i, o) => $crate::nom::IResult::Done(i, ::std::option::Option::Some(o)),
-                $crate::nom::IResult::Error => $crate::nom::IResult::Done($i, ::std::option::Option::None),
+                $crate::nom::IResult::Error => $crate::nom::IResult::Error,
             }
         } else {
             $crate::nom::IResult::Done($i, ::std::option::Option::None)
         }
     };
 
     ($i:expr, $cond:expr, $f:expr) => {
-        cond!($i, $cond, call!($f));
+        cond!($i, $cond, call!($f))
+    };
+}
+
+macro_rules! cond_reduce {
+    ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
+        if $cond {
+            $submac!($i, $($args)*)
+        } else {
+            $crate::nom::IResult::Error
+        }
+    };
+
+    ($i:expr, $cond:expr, $f:expr) => {
+        cond_reduce!($i, $cond, call!($f))
     };
 }
 
 macro_rules! preceded {
     ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => {
         match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) {
             $crate::nom::IResult::Done(remaining, (_, o)) => $crate::nom::IResult::Done(remaining, o),
             $crate::nom::IResult::Error => $crate::nom::IResult::Error,
         }
     };
 
     ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
-        preceded!($i, $submac!($($args)*), call!($g));
+        preceded!($i, $submac!($($args)*), call!($g))
     };
 
     ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
-        preceded!($i, call!($f), $submac!($($args)*));
+        preceded!($i, call!($f), $submac!($($args)*))
     };
 
     ($i:expr, $f:expr, $g:expr) => {
-        preceded!($i, call!($f), call!($g));
+        preceded!($i, call!($f), call!($g))
     };
 }
 
 macro_rules! terminated {
     ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => {
         match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) {
             $crate::nom::IResult::Done(remaining, (o, _)) => $crate::nom::IResult::Done(remaining, o),
             $crate::nom::IResult::Error => $crate::nom::IResult::Error,
         }
     };
 
     ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
-        terminated!($i, $submac!($($args)*), call!($g));
+        terminated!($i, $submac!($($args)*), call!($g))
     };
 
     ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
-        terminated!($i, call!($f), $submac!($($args)*));
+        terminated!($i, call!($f), $submac!($($args)*))
     };
 
     ($i:expr, $f:expr, $g:expr) => {
-        terminated!($i, call!($f), call!($g));
+        terminated!($i, call!($f), call!($g))
     };
 }
 
 macro_rules! many0 {
     ($i:expr, $submac:ident!( $($args:tt)* )) => {{
         let ret;
         let mut res   = ::std::vec::Vec::new();
         let mut input = $i;
@@ -153,17 +168,19 @@ macro_rules! many0 {
         ret
     }};
 
     ($i:expr, $f:expr) => {
         $crate::nom::many0($i, $f)
     };
 }
 
-pub fn many0<'a, T>(mut input: &'a str, f: fn(&'a str) -> IResult<&'a str, T>) -> IResult<&'a str, Vec<T>> {
+pub fn many0<'a, T>(mut input: &'a str,
+                    f: fn(&'a str) -> IResult<&'a str, T>)
+                    -> IResult<&'a str, Vec<T>> {
     let mut res = Vec::new();
 
     loop {
         if input.is_empty() {
             return IResult::Done(input, res);
         }
 
         match f(input) {
@@ -292,17 +309,17 @@ macro_rules! delimited {
     ($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)+) => {
         match tuple_parser!($i, (), $submac!($($args)*), $($rest)*) {
             $crate::nom::IResult::Error => $crate::nom::IResult::Error,
             $crate::nom::IResult::Done(i1, (_, o, _)) => $crate::nom::IResult::Done(i1, o)
         }
     };
 
     ($i:expr, $f:expr, $($rest:tt)+) => {
-        delimited!($i, call!($f), $($rest)*);
+        delimited!($i, call!($f), $($rest)*)
     };
 }
 
 macro_rules! separated_nonempty_list {
     ($i:expr, $sep:ident!( $($args:tt)* ), $submac:ident!( $($args2:tt)* )) => {{
         let mut res   = ::std::vec::Vec::new();
         let mut input = $i;
 
@@ -333,38 +350,38 @@ macro_rules! separated_nonempty_list {
                     }
                     $crate::nom::IResult::Done(input, res)
                 }
             }
         }
     }};
 
     ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
-        separated_nonempty_list!($i, $submac!($($args)*), call!($g));
+        separated_nonempty_list!($i, $submac!($($args)*), call!($g))
     };
 
     ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
-        separated_nonempty_list!($i, call!($f), $submac!($($args)*));
+        separated_nonempty_list!($i, call!($f), $submac!($($args)*))
     };
 
     ($i:expr, $f:expr, $g:expr) => {
-        separated_nonempty_list!($i, call!($f), call!($g));
+        separated_nonempty_list!($i, call!($f), call!($g))
     };
 }
 
 macro_rules! tuple {
     ($i:expr, $($rest:tt)*) => {
         tuple_parser!($i, (), $($rest)*)
     };
 }
 
 /// Internal parser, do not use directly
 macro_rules! tuple_parser {
     ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => {
-        tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*);
+        tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*)
     };
 
     ($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
         match $submac!($i, $($args)*) {
             $crate::nom::IResult::Error => $crate::nom::IResult::Error,
             $crate::nom::IResult::Done(i, o) =>
                 tuple_parser!(i, (o), $($rest)*),
         }
@@ -374,17 +391,17 @@ macro_rules! tuple_parser {
         match $submac!($i, $($args)*) {
             $crate::nom::IResult::Error => $crate::nom::IResult::Error,
             $crate::nom::IResult::Done(i, o) =>
                 tuple_parser!(i, ($($parsed)* , o), $($rest)*),
         }
     };
 
     ($i:expr, ($($parsed:tt),*), $e:ident) => {
-        tuple_parser!($i, ($($parsed),*), call!($e));
+        tuple_parser!($i, ($($parsed),*), call!($e))
     };
 
     ($i:expr, (), $submac:ident!( $($args:tt)* )) => {
         $submac!($i, $($args)*)
     };
 
     ($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => {
         match $submac!($i, $($args)*) {
@@ -395,17 +412,17 @@ macro_rules! tuple_parser {
 
     ($i:expr, ($($parsed:expr),*)) => {
         $crate::nom::IResult::Done($i, ($($parsed),*))
     };
 }
 
 macro_rules! alt {
     ($i:expr, $e:ident | $($rest:tt)*) => {
-        alt!($i, call!($e) | $($rest)*);
+        alt!($i, call!($e) | $($rest)*)
     };
 
     ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => {
         match $subrule!($i, $($args)*) {
             res @ $crate::nom::IResult::Done(_, _) => res,
             _ => alt!($i, $($rest)*)
         }
     };
@@ -413,79 +430,72 @@ macro_rules! alt {
     ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => {
         match $subrule!($i, $($args)*) {
             $crate::nom::IResult::Done(i, o) => $crate::nom::IResult::Done(i, $gen(o)),
             $crate::nom::IResult::Error => alt!($i, $($rest)*)
         }
     };
 
     ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => {
-        alt!($i, call!($e) => { $gen } | $($rest)*);
+        alt!($i, call!($e) => { $gen } | $($rest)*)
     };
 
     ($i:expr, $e:ident => { $gen:expr }) => {
-        alt!($i, call!($e) => { $gen });
+        alt!($i, call!($e) => { $gen })
     };
 
     ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => {
         match $subrule!($i, $($args)*) {
             $crate::nom::IResult::Done(i, o) => $crate::nom::IResult::Done(i, $gen(o)),
-            $crate::nom::IResult::Error => alt!($i)
+            $crate::nom::IResult::Error => $crate::nom::IResult::Error,
         }
     };
 
     ($i:expr, $e:ident) => {
-        alt!($i, call!($e));
+        alt!($i, call!($e))
     };
 
     ($i:expr, $subrule:ident!( $($args:tt)*)) => {
-        match $subrule!( $i, $($args)* ) {
-            $crate::nom::IResult::Done(i, o) => $crate::nom::IResult::Done(i, o),
-            $crate::nom::IResult::Error => alt!($i),
-        }
-    };
-
-    ($i:expr) => {
-        $crate::nom::IResult::Error
+        $subrule!($i, $($args)*)
     };
 }
 
 macro_rules! do_parse {
     ($i:expr, ( $($rest:expr),* )) => {
         $crate::nom::IResult::Done($i, ( $($rest),* ))
     };
 
     ($i:expr, $e:ident >> $($rest:tt)*) => {
-        do_parse!($i, call!($e) >> $($rest)*);
+        do_parse!($i, call!($e) >> $($rest)*)
     };
 
     ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
         match $submac!($i, $($args)*) {
             $crate::nom::IResult::Error => $crate::nom::IResult::Error,
             $crate::nom::IResult::Done(i, _) =>
                 do_parse!(i, $($rest)*),
         }
     };
 
     ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => {
-        do_parse!($i, $field: call!($e) >> $($rest)*);
+        do_parse!($i, $field: call!($e) >> $($rest)*)
     };
 
     ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
         match $submac!($i, $($args)*) {
             $crate::nom::IResult::Error => $crate::nom::IResult::Error,
             $crate::nom::IResult::Done(i, o) => {
                 let $field = o;
                 do_parse!(i, $($rest)*)
             },
         }
     };
 
     ($i:expr, mut $field:ident : $e:ident >> $($rest:tt)*) => {
-        do_parse!($i, $field: call!($e) >> $($rest)*);
+        do_parse!($i, mut $field: call!($e) >> $($rest)*)
     };
 
     ($i:expr, mut $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
         match $submac!($i, $($args)*) {
             $crate::nom::IResult::Error => $crate::nom::IResult::Error,
             $crate::nom::IResult::Done(i, o) => {
                 let mut $field = o;
                 do_parse!(i, $($rest)*)
new file mode 100644
--- /dev/null
+++ b/third_party/rust/syn/src/registry.rs
@@ -0,0 +1,393 @@
+use super::{Attribute, AttrStyle, Body, Crate, Ident, Item, ItemKind, MacroInput, MetaItem,
+            NestedMetaItem};
+use quote::Tokens;
+
+use std::collections::BTreeMap as Map;
+use std::fs::File;
+use std::io::{Read, Write};
+use std::path::Path;
+
+/// Implementation of a custom derive. Custom derives take a struct or enum and
+/// expand it into zero or more items, typically `impl` items.
+pub trait CustomDerive {
+    /// Expand the given struct or enum. If this custom derive modifies the
+    /// input item or preserves it unmodified, it must be returned back in the
+    /// `original` field of Expanded. The custom derive may discard the input
+    /// item by setting `original` to None.
+    fn expand(&self, input: MacroInput) -> Result<Expanded, String>;
+}
+
+/// Produced by expanding a custom derive.
+pub struct Expanded {
+    /// The items (typically `impl` items) constructed by the custom derive.
+    pub new_items: Vec<Item>,
+    /// The input to the custom derive, whether modified or unmodified. If the
+    /// custom derive discards the input item it may do so by setting `original`
+    /// to None.
+    pub original: Option<MacroInput>,
+}
+
+/// Registry of custom derives. Callers add custom derives to a registry, then
+/// use the registry to expand those derives in a source file.
+#[derive(Default)]
+pub struct Registry<'a> {
+    derives: Map<String, Box<CustomDerive + 'a>>,
+}
+
+impl<T> CustomDerive for T
+    where T: Fn(MacroInput) -> Result<Expanded, String>
+{
+    fn expand(&self, input: MacroInput) -> Result<Expanded, String> {
+        self(input)
+    }
+}
+
+impl<'a> Registry<'a> {
+    pub fn new() -> Self {
+        Default::default()
+    }
+
+    /// Register a custom derive. A `fn(MacroInput) -> Result<Expanded, String>`
+    /// may be used as a custom derive.
+    ///
+    /// ```ignore
+    /// registry.add_derive("Serialize", expand_serialize);
+    /// ```
+    pub fn add_derive<T>(&mut self, name: &str, derive: T)
+        where T: CustomDerive + 'a
+    {
+        self.derives.insert(name.into(), Box::new(derive));
+    }
+
+    /// Read Rust source code from the `src` file, expand the custom derives
+    /// that have been registered, and write the result to the `dst` file.
+    pub fn expand_file<S, D>(&self, src: S, dst: D) -> Result<(), String>
+        where S: AsRef<Path>,
+              D: AsRef<Path>
+    {
+        // Open the src file
+        let mut src = match File::open(src) {
+            Ok(open) => open,
+            Err(err) => return Err(err.to_string()),
+        };
+
+        // Read the contents of the src file to a String
+        let mut content = String::new();
+        if let Err(err) = src.read_to_string(&mut content) {
+            return Err(err.to_string());
+        }
+
+        // Parse the contents
+        let krate = try!(super::parse_crate(&content));
+
+        // Expand
+        let expanded = try!(expand_crate(self, krate));
+
+        // Print the expanded code to a String
+        let out = try!(pretty(quote!(#expanded)));
+
+        // Create or truncate the dst file, opening in write-only mode
+        let mut dst = match File::create(dst) {
+            Ok(create) => create,
+            Err(err) => return Err(err.to_string()),
+        };
+
+        // Write expanded code to the dst file
+        if let Err(err) = dst.write_all(out.as_bytes()) {
+            return Err(err.to_string());
+        }
+
+        Ok(())
+    }
+}
+
+fn expand_crate(reg: &Registry, krate: Crate) -> Result<Crate, String> {
+    let mut items = Vec::new();
+    for item in krate.items {
+        try!(expand_item(reg, item, Vec::new(), &mut items));
+    }
+    Ok(Crate { items: items, ..krate })
+}
+
+fn expand_item(reg: &Registry,
+               mut item: Item,
+               cfg: Vec<NestedMetaItem>,
+               out: &mut Vec<Item>)
+               -> Result<(), String> {
+    let (body, generics) = match item.node {
+        ItemKind::Enum(variants, generics) => (Body::Enum(variants), generics),
+        ItemKind::Struct(variant_data, generics) => (Body::Struct(variant_data), generics),
+        _ => {
+            // Custom derives cannot apply to this item, preserve it unmodified
+            item.attrs.extend(combine_cfgs(cfg));
+            out.push(item);
+            return Ok(());
+        }
+    };
+    let macro_input = MacroInput {
+        ident: item.ident,
+        vis: item.vis,
+        attrs: item.attrs,
+        generics: generics,
+        body: body,
+    };
+    expand_macro_input(reg, macro_input, cfg, out)
+}
+
+fn expand_macro_input(reg: &Registry,
+                      mut input: MacroInput,
+                      inherited_cfg: Vec<NestedMetaItem>,
+                      out: &mut Vec<Item>)
+                      -> Result<(), String> {
+    let mut derives = Vec::new();
+    let mut all_cfg = inherited_cfg;
+
+    // Find custom derives on this item, removing them from the input
+    input.attrs = input.attrs
+        .into_iter()
+        .flat_map(|attr| {
+            let (new_derives, cfg, attr) = parse_attr(reg, attr);
+            derives.extend(new_derives);
+            all_cfg.extend(cfg);
+            attr
+        })
+        .collect();
+
+    // Expand each custom derive
+    for derive in derives {
+        let expanded = try!(reg.derives[derive.name.as_ref()].expand(input));
+
+        for new_item in expanded.new_items {
+            let mut extended_cfg = all_cfg.clone();
+            extended_cfg.extend(derive.cfg.clone());
+            try!(expand_item(reg, new_item, extended_cfg, out));
+        }
+
+        input = match expanded.original {
+            Some(input) => input,
+            None => return Ok(()),
+        };
+    }
+
+    input.attrs.extend(combine_cfgs(all_cfg));
+    out.push(input.into());
+    Ok(())
+}
+
+struct Derive {
+    name: Ident,
+    /// If the custom derive was behind a cfg_attr
+    cfg: Option<NestedMetaItem>,
+}
+
+/// Pull custom derives and cfgs out of the given Attribute.
+fn parse_attr(reg: &Registry,
+              attr: Attribute)
+              -> (Vec<Derive>, Vec<NestedMetaItem>, Option<Attribute>) {
+    if attr.style != AttrStyle::Outer || attr.is_sugared_doc {
+        return (Vec::new(), Vec::new(), Some(attr));
+    }
+
+    let (name, nested) = match attr.value {
+        MetaItem::List(name, nested) => (name, nested),
+        _ => return (Vec::new(), Vec::new(), Some(attr)),
+    };
+
+    match name.as_ref() {
+        "derive" => {
+            let (derives, attr) = parse_derive_attr(reg, nested);
+            let derives = derives.into_iter()
+                .map(|d| {
+                    Derive {
+                        name: d,
+                        cfg: None,
+                    }
+                })
+                .collect();
+            (derives, Vec::new(), attr)
+        }
+        "cfg_attr" => {
+            let (derives, attr) = parse_cfg_attr(reg, nested);
+            (derives, Vec::new(), attr)
+        }
+        "cfg" => (Vec::new(), nested, None),
+        _ => {
+            // Rebuild the original attribute because it was destructured above
+            let attr = Attribute {
+                style: AttrStyle::Outer,
+                value: MetaItem::List(name, nested),
+                is_sugared_doc: false,
+            };
+            (Vec::new(), Vec::new(), Some(attr))
+        }
+    }
+}
+
+/// Assuming the given nested meta-items came from a #[derive(...)] attribute,
+/// pull out the ones that are custom derives.
+fn parse_derive_attr(reg: &Registry,
+                     nested: Vec<NestedMetaItem>)
+                     -> (Vec<Ident>, Option<Attribute>) {
+    let mut derives = Vec::new();
+
+    let remaining: Vec<_> = nested.into_iter()
+        .flat_map(|meta| {
+            let word = match meta {
+                NestedMetaItem::MetaItem(MetaItem::Word(word)) => word,
+                _ => return Some(meta),
+            };
+            if reg.derives.contains_key(word.as_ref()) {
+                derives.push(word);
+                None
+            } else {
+                Some(NestedMetaItem::MetaItem(MetaItem::Word(word)))
+            }
+        })
+        .collect();
+
+    let attr = if remaining.is_empty() {
+        // Elide an empty #[derive()]
+        None
+    } else {
+        Some(Attribute {
+            style: AttrStyle::Outer,
+            value: MetaItem::List("derive".into(), remaining),
+            is_sugared_doc: false,
+        })
+    };
+
+    (derives, attr)
+}
+
+/// Assuming the given nested meta-items came from a #[cfg_attr(...)] attribute,
+/// pull out any custom derives contained within.
+fn parse_cfg_attr(reg: &Registry, nested: Vec<NestedMetaItem>) -> (Vec<Derive>, Option<Attribute>) {
+    if nested.len() != 2 {
+        let attr = Attribute {
+            style: AttrStyle::Outer,
+            value: MetaItem::List("cfg_attr".into(), nested),
+            is_sugared_doc: false,
+        };
+        return (Vec::new(), Some(attr));
+    }
+
+    let mut iter = nested.into_iter();
+    let cfg = iter.next().unwrap();
+    let arg = iter.next().unwrap();
+
+    let (name, nested) = match arg {
+        NestedMetaItem::MetaItem(MetaItem::List(name, nested)) => (name, nested),
+        _ => {
+            let attr = Attribute {
+                style: AttrStyle::Outer,
+                value: MetaItem::List("cfg_attr".into(), vec![cfg, arg]),
+                is_sugared_doc: false,
+            };
+            return (Vec::new(), Some(attr));
+        }
+    };
+
+    if name == "derive" {
+        let (derives, attr) = parse_derive_attr(reg, nested);
+        let derives = derives.into_iter()
+            .map(|d| {
+                Derive {
+                    name: d,
+                    cfg: Some(cfg.clone()),
+                }
+            })
+            .collect();
+        let attr = attr.map(|attr| {
+            Attribute {
+                style: AttrStyle::Outer,
+                value: MetaItem::List("cfg_attr".into(),
+                                      vec![cfg, NestedMetaItem::MetaItem(attr.value)]),
+                is_sugared_doc: false,
+            }
+        });
+        (derives, attr)
+    } else {
+        let attr = Attribute {
+            style: AttrStyle::Outer,
+            value:
+                MetaItem::List("cfg_attr".into(),
+                               vec![cfg, NestedMetaItem::MetaItem(MetaItem::List(name, nested))]),
+            is_sugared_doc: false,
+        };
+        (Vec::new(), Some(attr))
+    }
+}
+
+/// Combine a list of cfg expressions into an attribute like `#[cfg(a)]` or
+/// `#[cfg(all(a, b, c))]`, or nothing if there are no cfg expressions.
+fn combine_cfgs(cfg: Vec<NestedMetaItem>) -> Option<Attribute> {
+    // Flatten `all` cfgs so we don't nest `all` inside of `all`.
+    let cfg: Vec<_> = cfg.into_iter()
+        .flat_map(|cfg| {
+            let (name, nested) = match cfg {
+                NestedMetaItem::MetaItem(MetaItem::List(name, nested)) => (name, nested),
+                _ => return vec![cfg],
+            };
+            if name == "all" {
+                nested
+            } else {
+                vec![NestedMetaItem::MetaItem(MetaItem::List(name, nested))]
+            }
+        })
+        .collect();
+
+    let value = match cfg.len() {
+        0 => return None,
+        1 => cfg,
+        _ => vec![NestedMetaItem::MetaItem(MetaItem::List("all".into(), cfg))],
+    };
+
+    Some(Attribute {
+        style: AttrStyle::Outer,
+        value: MetaItem::List("cfg".into(), value),
+        is_sugared_doc: false,
+    })
+}
+
+#[cfg(not(feature = "pretty"))]
+fn pretty(tokens: Tokens) -> Result<String, String> {
+    Ok(tokens.to_string())
+}
+
+#[cfg(feature = "pretty")]
+fn pretty(tokens: Tokens) -> Result<String, String> {
+    use syntax::parse::{self, ParseSess};
+    use syntax::print::pprust;
+
+    let name = "syn".to_string();
+    let source = tokens.to_string();
+    let cfg = Vec::new();
+    let sess = ParseSess::new();
+    let krate = match parse::parse_crate_from_source_str(name, source, cfg, &sess) {
+        Ok(krate) => krate,
+        Err(mut err) => {
+            err.emit();
+            return Err("pretty printer failed to parse expanded code".into());
+        }
+    };
+
+    if sess.span_diagnostic.has_errors() {
+        return Err("pretty printer failed to parse expanded code".into());
+    }
+
+    let mut reader = &tokens.to_string().into_bytes()[..];
+    let mut writer = Vec::new();
+    let ann = pprust::NoAnn;
+
+    try!(pprust::print_crate(
+        sess.codemap(),
+        &sess.span_diagnostic,
+        &krate,
+        "".to_string(),
+        &mut reader,
+        Box::new(&mut writer),
+        &ann,
+        false).map_err(|err| err.to_string()));
+
+    String::from_utf8(writer).map_err(|err| err.to_string())
+}
--- a/third_party/rust/syn/src/space.rs
+++ b/third_party/rust/syn/src/space.rs
@@ -13,17 +13,18 @@ pub fn whitespace(input: &str) -> IResul
         if bytes[i] == b'/' {
             if s.starts_with("//") && (!s.starts_with("///") || s.starts_with("////")) &&
                !s.starts_with("//!") {
                 if let Some(len) = s.find('\n') {
                     i += len + 1;
                     continue;
                 }
                 break;
-            } else if s.starts_with("/*") && !s.starts_with("/**") && !s.starts_with("/*!") {
+            } else if s.starts_with("/*") && (!s.starts_with("/**") || s.starts_with("/***")) &&
+                      !s.starts_with("/*!") {
                 match block_comment(s) {
                     IResult::Done(_, com) => {
                         i += com.len();
                         continue;
                     }
                     IResult::Error => {
                         return IResult::Error;
                     }
@@ -33,17 +34,17 @@ pub fn whitespace(input: &str) -> IResul
         match bytes[i] {
             b' ' | 0x09...0x0d => {
                 i += 1;
                 continue;
             }
             b if b <= 0x7f => {}
             _ => {
                 let ch = s.chars().next().unwrap();
-                if ch.is_whitespace() {
+                if is_whitespace(ch) {
                     i += ch.len_utf8();
                     continue;
                 }
             }
         }
         return if i > 0 {
             IResult::Done(s, ())
         } else {
@@ -79,8 +80,20 @@ pub fn block_comment(input: &str) -> IRe
 }
 
 pub fn word_break(input: &str) -> IResult<&str, ()> {
     match input.chars().next() {
         Some(ch) if UnicodeXID::is_xid_continue(ch) => IResult::Error,
         Some(_) | None => IResult::Done(input, ()),
     }
 }
+
+pub fn skip_whitespace(input: &str) -> &str {
+    match whitespace(input) {
+        IResult::Done(rest, _) => rest,
+        IResult::Error => input,
+    }
+}
+
+fn is_whitespace(ch: char) -> bool {
+    // Rust treats left-to-right mark and right-to-left mark as whitespace
+    ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}'
+}
--- a/third_party/rust/syn/src/ty.rs
+++ b/third_party/rust/syn/src/ty.rs
@@ -100,16 +100,26 @@ pub enum PathParameters {
     /// The `(A, B)` and `C` in `Foo(A, B) -> C`
     Parenthesized(ParenthesizedParameterData),
 }
 
 impl PathParameters {
     pub fn none() -> Self {
         PathParameters::AngleBracketed(AngleBracketedParameterData::default())
     }
+
+    pub fn is_empty(&self) -> bool {
+        match *self {
+            PathParameters::AngleBracketed(ref bracketed) => {
+                bracketed.lifetimes.is_empty() && bracketed.types.is_empty() &&
+                bracketed.bindings.is_empty()
+            }
+            PathParameters::Parenthesized(_) => false,
+        }
+    }
 }
 
 /// A path like `Foo<'a, T>`
 #[derive(Debug, Clone, Eq, PartialEq, Default)]
 pub struct AngleBracketedParameterData {
     /// The lifetime parameters for this path segment.
     pub lifetimes: Vec<Lifetime>,
     /// The type parameters for this path segment, if present.
@@ -161,19 +171,34 @@ pub struct PolyTraitRef {
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct QSelf {
     pub ty: Box<Ty>,
     pub position: usize,
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct BareFnTy {
+    pub unsafety: Unsafety,
+    pub abi: Option<Abi>,
     pub lifetimes: Vec<LifetimeDef>,
     pub inputs: Vec<BareFnArg>,
     pub output: FunctionRetTy,
+    pub variadic: bool,
+}
+
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum Unsafety {
+    Unsafe,
+    Normal,
+}
+
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub enum Abi {
+    Named(String),
+    Rust,
 }
 
 /// An argument in a function type.
 ///
 /// E.g. `bar: usize` as in `fn foo(bar: usize)`
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct BareFnArg {
     pub name: Option<Ident>,
@@ -190,62 +215,80 @@ pub enum FunctionRetTy {
     Default,
     /// Everything else
     Ty(Ty),
 }
 
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use {TraitBoundModifier, TyParamBound};
+    #[cfg(feature = "full")]
+    use ConstExpr;
     use constant::parsing::const_expr;
+    #[cfg(feature = "full")]
+    use expr::parsing::expr;
     use generics::parsing::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes};
     use ident::parsing::ident;
+    use lit::parsing::quoted_string;
     use std::str;
 
     named!(pub ty -> Ty, alt!(
-        ty_poly_trait_ref // must be before ty_path
+        ty_paren // must be before ty_tup
+        |
+        ty_path // must be before ty_poly_trait_ref
         |
         ty_vec
         |
         ty_array
         |
         ty_ptr
         |
         ty_rptr
         |
         ty_bare_fn
         |
         ty_never
         |
         ty_tup
         |
-        ty_path
+        ty_poly_trait_ref
         |
         ty_impl_trait
-        |
-        ty_paren
     ));
 
     named!(ty_vec -> Ty, do_parse!(
         punct!("[") >>
         elem: ty >>
         punct!("]") >>
         (Ty::Slice(Box::new(elem)))
     ));
 
+    #[cfg(not(feature = "full"))]
     named!(ty_array -> Ty, do_parse!(
         punct!("[") >>
         elem: ty >>
         punct!(";") >>
         len: const_expr >>
         punct!("]") >>
         (Ty::Array(Box::new(elem), len))
     ));
 
+    #[cfg(feature = "full")]
+    named!(ty_array -> Ty, do_parse!(
+        punct!("[") >>
+        elem: ty >>
+        punct!(";") >>
+        len: alt!(
+            terminated!(const_expr, punct!("]"))
+            |
+            terminated!(expr, punct!("]")) => { ConstExpr::Other }
+        ) >>
+        (Ty::Array(Box::new(elem), len))
+    ));
+
     named!(ty_ptr -> Ty, do_parse!(
         punct!("*") >>
         mutability: alt!(
             keyword!("const") => { |_| Mutability::Immutable }
             |
             keyword!("mut") => { |_| Mutability::Mutable }
         ) >>
         target: ty >>
@@ -262,36 +305,45 @@ pub mod parsing {
         target: ty >>
         (Ty::Rptr(life, Box::new(MutTy {
             ty: target,
             mutability: mutability,
         })))
     ));
 
     named!(ty_bare_fn -> Ty, do_parse!(
+        lifetimes: opt_vec!(do_parse!(
+            keyword!("for") >>
+            punct!("<") >>
+            lifetimes: terminated_list!(punct!(","), lifetime_def) >>
+            punct!(">") >>
+            (lifetimes)
+        )) >>
+        unsafety: unsafety >>
+        abi: option!(abi) >>
         keyword!("fn") >>
-        lifetimes: opt_vec!(delimited!(
-            punct!("<"),
-            terminated_list!(punct!(","), lifetime_def),
-            punct!(">")
-        )) >>
         punct!("(") >>
-        inputs: terminated_list!(punct!(","), fn_arg) >>
+        inputs: separated_list!(punct!(","), fn_arg) >>
+        trailing_comma: option!(punct!(",")) >>
+        variadic: option!(cond_reduce!(trailing_comma.is_some(), punct!("..."))) >>
         punct!(")") >>
         output: option!(preceded!(
             punct!("->"),
             ty
         )) >>
         (Ty::BareFn(Box::new(BareFnTy {
+            unsafety: unsafety,
+            abi: abi,
             lifetimes: lifetimes,
             inputs: inputs,
             output: match output {
                 Some(ty) => FunctionRetTy::Ty(ty),
                 None => FunctionRetTy::Default,
             },
+            variadic: variadic.is_some(),
         })))
     ));
 
     named!(ty_never -> Ty, map!(punct!("!"), |_| Ty::Never));
 
     named!(ty_tup -> Ty, do_parse!(
         punct!("(") >>
         elems: terminated_list!(punct!(","), ty) >>
@@ -360,33 +412,23 @@ pub mod parsing {
                         (Some(QSelf { ty: this, position: 0 }), Path {
                             global: false,
                             segments: rest,
                         })
                     }
                 }
             })
         )
+        |
+        map!(keyword!("self"), |_| (None, "self".into()))
     ));
 
-    named!(ty_poly_trait_ref -> Ty, do_parse!(
-        keyword!("for") >>
-        punct!("<") >>
-        lifetimes: terminated_list!(punct!(","), lifetime_def) >>
-        punct!(">") >>
-        trait_ref: path >>
-        (Ty::PolyTraitRef(vec![
-            TyParamBound::Trait(
-                PolyTraitRef {
-                    bound_lifetimes: lifetimes,
-                    trait_ref: trait_ref,
-                },
-                TraitBoundModifier::None,
-            ),
-        ]))
+    named!(ty_poly_trait_ref -> Ty, map!(
+        separated_nonempty_list!(punct!("+"), ty_param_bound),
+        Ty::PolyTraitRef
     ));
 
     named!(ty_impl_trait -> Ty, do_parse!(
         keyword!("impl") >>
         elem: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
         (Ty::ImplTrait(elem))
     ));
 
@@ -423,69 +465,98 @@ pub mod parsing {
                     punct!(","),
                     terminated!(ty, not!(peek!(punct!("="))))
                 )
             )) >>
             bindings: opt_vec!(preceded!(
                 cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")),
                 separated_nonempty_list!(punct!(","), type_binding)
             )) >>
+            cond!(!lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty(), option!(punct!(","))) >>
             punct!(">") >>
             (PathSegment {
                 ident: id.unwrap_or_else(|| "".into()),
                 parameters: PathParameters::AngleBracketed(
                     AngleBracketedParameterData {
                         lifetimes: lifetimes,
                         types: types,
                         bindings: bindings,
                     }
                 ),
             })
         )
         |
         map!(ident, Into::into)
+        |
+        map!(alt!(
+            keyword!("super")
+            |
+            keyword!("self")
+            |
+            keyword!("Self")
+        ), Into::into)
     ));
 
     named!(type_binding -> TypeBinding, do_parse!(
         id: ident >>
         punct!("=") >>
         ty: ty >>
         (TypeBinding {
             ident: id,
             ty: ty,
         })
     ));
 
     named!(pub poly_trait_ref -> PolyTraitRef, do_parse!(
         bound_lifetimes: bound_lifetimes >>
         trait_ref: path >>
-        parenthesized: cond!(
+        parenthesized: option!(cond_reduce!(
             trait_ref.segments.last().unwrap().parameters == PathParameters::none(),
-            option!(parenthesized_parameter_data)
-        ) >>
+            parenthesized_parameter_data
+        )) >>
         ({
             let mut trait_ref = trait_ref;
-            if let Some(Some(parenthesized)) = parenthesized {
+            if let Some(parenthesized) = parenthesized {
                 trait_ref.segments.last_mut().unwrap().parameters = parenthesized;
             }
             PolyTraitRef {
                 bound_lifetimes: bound_lifetimes,
                 trait_ref: trait_ref,
             }
         })
     ));
 
     named!(pub fn_arg -> BareFnArg, do_parse!(
-        name: option!(terminated!(ident, punct!(":"))) >>
+        name: option!(do_parse!(
+            name: ident >>
+            punct!(":") >>
+            not!(peek!(tag!(":"))) >> // not ::
+            (name)
+        )) >>
         ty: ty >>
         (BareFnArg {
             name: name,
             ty: ty,
         })
     ));
+
+    named!(pub unsafety -> Unsafety, alt!(
+        keyword!("unsafe") => { |_| Unsafety::Unsafe }
+        |
+        epsilon!() => { |_| Unsafety::Normal }
+    ));
+
+    named!(pub abi -> Abi, do_parse!(
+        keyword!("extern") >>
+        name: option!(quoted_string) >>
+        (match name {
+            Some(name) => Abi::Named(name),
+            None => Abi::Rust,
+        })
+    ));
 }
 
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
     use quote::{Tokens, ToTokens};
 
     impl ToTokens for Ty {
@@ -598,17 +669,22 @@ mod printing {
                 segment.to_tokens(tokens);
             }
         }
     }
 
     impl ToTokens for PathSegment {
         fn to_tokens(&self, tokens: &mut Tokens) {
             self.ident.to_tokens(tokens);
-            self.parameters.to_tokens(tokens);
+            if self.ident.as_ref().is_empty() && self.parameters.is_empty() {
+                tokens.append("<");
+                tokens.append(">");
+            } else {
+                self.parameters.to_tokens(tokens);
+            }
         }
     }
 
     impl ToTokens for PathParameters {
         fn to_tokens(&self, tokens: &mut Tokens) {
             match *self {
                 PathParameters::AngleBracketed(ref parameters) => {
                     parameters.to_tokens(tokens);
@@ -687,24 +763,33 @@ mod printing {
                 tokens.append(">");
             }
             self.trait_ref.to_tokens(tokens);
         }
     }
 
     impl ToTokens for BareFnTy {
         fn to_tokens(&self, tokens: &mut Tokens) {
-            tokens.append("fn");
             if !self.lifetimes.is_empty() {
+                tokens.append("for");
                 tokens.append("<");
                 tokens.append_separated(&self.lifetimes, ",");
                 tokens.append(">");
             }
+            self.unsafety.to_tokens(tokens);
+            self.abi.to_tokens(tokens);
+            tokens.append("fn");
             tokens.append("(");
             tokens.append_separated(&self.inputs, ",");
+            if self.variadic {
+                if !self.inputs.is_empty() {
+                    tokens.append(",");
+                }
+                tokens.append("...");
+            }
             tokens.append(")");
             if let FunctionRetTy::Ty(ref ty) = self.output {
                 tokens.append("->");
                 ty.to_tokens(tokens);
             }
         }
     }
 
@@ -712,9 +797,30 @@ mod printing {
         fn to_tokens(&self, tokens: &mut Tokens) {
             if let Some(ref name) = self.name {
                 name.to_tokens(tokens);
                 tokens.append(":");
             }
             self.ty.to_tokens(tokens);
         }
     }
+
+    impl ToTokens for Unsafety {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            match *self {
+                Unsafety::Unsafe => tokens.append("unsafe"),
+                Unsafety::Normal => {
+                    // nothing
+                }
+            }
+        }
+    }
+
+    impl ToTokens for Abi {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append("extern");
+            match *self {
+                Abi::Named(ref named) => named.to_tokens(tokens),
+                Abi::Rust => {}
+            }
+        }
+    }
 }
--- a/third_party/rust/syn/src/visit.rs
+++ b/third_party/rust/syn/src/visit.rs
@@ -136,17 +136,17 @@ pub fn walk_ty<V: Visitor>(visitor: &mut
     match *ty {
         Ty::Slice(ref inner) |
         Ty::Paren(ref inner) => visitor.visit_ty(inner),
         Ty::Ptr(ref mutable_type) => visitor.visit_ty(&mutable_type.ty),
         Ty::Rptr(ref opt_lifetime, ref mutable_type) => {
             walk_list!(visitor, visit_lifetime, opt_lifetime);
             visitor.visit_ty(&mutable_type.ty)
         }
-        Ty::Never => {}
+        Ty::Never | Ty::Infer => {}
         Ty::Tup(ref tuple_element_types) => {
             walk_list!(visitor, visit_ty, tuple_element_types);
         }
         Ty::BareFn(ref bare_fn) => {
             walk_list!(visitor, visit_lifetime_def, &bare_fn.lifetimes);
             for argument in &bare_fn.inputs {
                 walk_opt_ident(visitor, &argument.name);
                 visitor.visit_ty(&argument.ty)
@@ -162,23 +162,20 @@ pub fn walk_ty<V: Visitor>(visitor: &mut
         Ty::ObjectSum(ref inner, ref bounds) => {
             visitor.visit_ty(inner);
             walk_list!(visitor, visit_ty_param_bound, bounds);
         }
         Ty::Array(ref inner, ref len) => {
             visitor.visit_ty(inner);
             visitor.visit_const_expr(len);
         }
-        Ty::PolyTraitRef(ref bounds) => {
-            walk_list!(visitor, visit_ty_param_bound, bounds);
-        }
+        Ty::PolyTraitRef(ref bounds) |
         Ty::ImplTrait(ref bounds) => {
             walk_list!(visitor, visit_ty_param_bound, bounds);
         }
-        Ty::Infer => {}
     }
 }
 
 pub fn walk_path<V: Visitor>(visitor: &mut V, path: &Path) {
     for segment in &path.segments {
         visitor.visit_path_segment(segment);
     }
 }
@@ -261,17 +258,17 @@ pub fn walk_field<V: Visitor>(visitor: &
     walk_opt_ident(visitor, &field.ident);
     visitor.visit_ty(&field.ty);
     walk_list!(visitor, visit_attribute, &field.attrs);
 }
 
 pub fn walk_const_expr<V: Visitor>(visitor: &mut V, len: &ConstExpr) {
     match *len {
         ConstExpr::Call(ref function, ref args) => {
-            visitor.visit_const_expr(&function);
+            visitor.visit_const_expr(function);
             walk_list!(visitor, visit_const_expr, args);
         }
         ConstExpr::Binary(_op, ref left, ref right) => {
             visitor.visit_const_expr(left);
             visitor.visit_const_expr(right);
         }
         ConstExpr::Unary(_op, ref v) => {
             visitor.visit_const_expr(v);
@@ -281,10 +278,18 @@ pub fn walk_const_expr<V: Visitor>(visit
         }
         ConstExpr::Cast(ref expr, ref ty) => {
             visitor.visit_const_expr(expr);
             visitor.visit_ty(ty);
         }
         ConstExpr::Path(ref path) => {
             visitor.visit_path(path);
         }
+        ConstExpr::Index(ref expr, ref index) => {
+            visitor.visit_const_expr(expr);
+            visitor.visit_const_expr(index);
+        }
+        ConstExpr::Paren(ref expr) => {
+            visitor.visit_const_expr(expr);
+        }
+        ConstExpr::Other(_) => {}
     }
 }
--- a/third_party/rust/syntex/.cargo-checksum.json
+++ b/third_party/rust/syntex/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"8403571b422ecef7f0d499be0c187f584e3eb008d50b5d9df7f77622b2bd917d","src/error.rs":"c99d5582e76ca9f9b06989517e866d0078834b3db3d4e51b3b193cae06b55526","src/lib.rs":"1679bbd38be948783e508648cf075fe27174ed2e717efa80609befcf6d772f55","src/registry.rs":"6ef31957e2a5d3662df8d82fa87071d1ca130c2887856ed4b2a8e28976e24975","src/resolver.rs":"46ed3368df59ce4df276af3c29f612f3cd713b715eeb3493e2b6ea0731063996","src/stack.rs":"130dc7ff3851288a0e8e701f69af99f8f52f203a1419976d09ebc0075abe97e7"},"package":"17e2e2ad78f4942d011750c304e9a9874717b6986c8fa2f6072f58fbd0835dcb"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"0223de2f0ead630441b623d93d8c66b92268e11ffc42c1c731dd5e4bde4f4c08","src/error.rs":"c99d5582e76ca9f9b06989517e866d0078834b3db3d4e51b3b193cae06b55526","src/lib.rs":"1679bbd38be948783e508648cf075fe27174ed2e717efa80609befcf6d772f55","src/registry.rs":"6ef31957e2a5d3662df8d82fa87071d1ca130c2887856ed4b2a8e28976e24975","src/resolver.rs":"a5a77dccd705ebd2a470d4905a57c5b818eb46887bd0f04a94e65b3ec241008c","src/stack.rs":"130dc7ff3851288a0e8e701f69af99f8f52f203a1419976d09ebc0075abe97e7"},"package":"3bd253b0d7d787723a33384d426f0ebec7f8edccfaeb2022d0177162bb134da0"}
\ No newline at end of file
--- a/third_party/rust/syntex/Cargo.toml
+++ b/third_party/rust/syntex/Cargo.toml
@@ -1,13 +1,13 @@
 [package]
 name = "syntex"
-version = "0.48.0"
+version = "0.50.0"
 authors = [ "erick.tryzelaar@gmail.com" ]
 license = "MIT/Apache-2.0"
 description = "A library that enables compile time syntax extension expansion"
 repository = "https://github.com/erickt/rust-syntex"
 readme = "../README.md"
 include = ["Cargo.toml", "src/**/*.rs"]
 
 [dependencies]
-syntex_errors = { version = "^0.48.0", path = "../syntex_errors" }
-syntex_syntax = { version = "^0.48.0", path = "../syntex_syntax" }
+syntex_errors = { version = "^0.50.0", path = "../syntex_errors" }
+syntex_syntax = { version = "^0.50.0", path = "../syntex_syntax" }
--- a/third_party/rust/syntex/src/resolver.rs
+++ b/third_party/rust/syntex/src/resolver.rs
@@ -8,16 +8,17 @@ use syntex_syntax::ext::base::{
     MultiDecorator,
     MultiModifier,
     SyntaxExtension,
 };
 use syntex_syntax::ext::expand::Expansion;
 use syntex_syntax::ext::hygiene::Mark;
 use syntex_syntax::parse::token::intern;
 use syntex_syntax::parse::ParseSess;
+use syntex_syntax::ptr::P;
 
 pub struct Resolver<'a> {
     session: &'a ParseSess,
     extensions: HashMap<ast::Name, Rc<SyntaxExtension>>,
 }
 
 impl<'a> Resolver<'a> {
     pub fn new(session: &'a ParseSess) -> Self {
@@ -28,28 +29,30 @@ impl<'a> Resolver<'a> {
     }
 }
 
 impl<'a> base::Resolver for Resolver<'a> {
     fn next_node_id(&mut self) -> ast::NodeId {
         ast::DUMMY_NODE_ID
     }
     fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() }
+    fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
 
     fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {}
     fn add_macro(&mut self, _scope: Mark, def: ast::MacroDef, _export: bool) {
         self.session.span_diagnostic.span_bug(
             def.span,
             "add_macro is not supported yet");
     }
     fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
         self.extensions.insert(ident.name, ext);
     }
     fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}
 
+    fn resolve_imports(&mut self) {}
     fn find_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute> {
         for i in 0..attrs.len() {
             let name = intern(&attrs[i].name());
 
             if let Some(ext) = self.extensions.get(&name) {
                 match **ext {
                     MultiModifier(..) | MultiDecorator(..) => return Some(attrs.remove(i)),
                     _ => {}
--- a/third_party/rust/syntex_errors/.cargo-checksum.json
+++ b/third_party/rust/syntex_errors/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"60308594f04273935624ba9a941fb2935be0f28b1f607ef9360e0c182977317e","src/emitter.rs":"03e348851ccd7586610e2a44c0b310d3c8199343afa1d62fcd354fcfd9153e97","src/lib.rs":"5ae8bb1151e812753ffd37d42e4d6324989c80956484eb31895e48bba0551527","src/lock.rs":"77e185b48b20509596d9778d7dcca02b92e09be061ed57a9ef37ccfb9fa781ae","src/registry.rs":"ab229b7c6d3016917638d15e754df421be8f4b88b95518773c5c33a07a005274","src/snippet.rs":"6e7fa339014fc33511e23bcdc8ad4ddf5f5f5e4f71dfe12b1f9b580e9f8eca50","src/styled_buffer.rs":"a00d37a0c57b0c16cafa28dff936c1689e0d64a0002570b731f9f34a8ecdc61c"},"package":"0b2784ff2ca385a451f1f835dcb3926e5c61461c6468aac1e35edcbc4cd33808"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"96ab8e31312c9001d83d066cc407c8555cb56d98bd3813c36191fca5a8db8991","src/diagnostic.rs":"c469bbeb9bc0bff1dc7da90f12fbf686de53b7920e8a8ec509171d7ee7939f9e","src/diagnostic_builder.rs":"535a903c0961e85d8ad9eb88a08e3095fbc251c6f032f84cb48a1f1d36c1b716","src/emitter.rs":"03e348851ccd7586610e2a44c0b310d3c8199343afa1d62fcd354fcfd9153e97","src/lib.rs":"54a337b9925688773622b5fb520e51d12b92a8e1f1fc22c6e760bc26527698c5","src/lock.rs":"77e185b48b20509596d9778d7dcca02b92e09be061ed57a9ef37ccfb9fa781ae","src/registry.rs":"ab229b7c6d3016917638d15e754df421be8f4b88b95518773c5c33a07a005274","src/snippet.rs":"6e7fa339014fc33511e23bcdc8ad4ddf5f5f5e4f71dfe12b1f9b580e9f8eca50","src/styled_buffer.rs":"a00d37a0c57b0c16cafa28dff936c1689e0d64a0002570b731f9f34a8ecdc61c"},"package":"84822a1178204a191239ad844599f8c85c128cf9f4173397def4eb46b55b0aa1"}
\ No newline at end of file
--- a/third_party/rust/syntex_errors/Cargo.toml
+++ b/third_party/rust/syntex_errors/Cargo.toml
@@ -1,16 +1,16 @@
 [package]
 name = "syntex_errors"
-version = "0.48.0"
+version = "0.50.0"
 authors = [ "erick.tryzelaar@gmail.com" ]
 license = "MIT/Apache-2.0"
 description = "Export of librustc_errors for code generation"
 repository = "https://github.com/serde-rs/syntex"
 include = ["Cargo.toml", "src/**/*.rs"]
 
 [dependencies]
 libc = "^0.2.13"
 log = "^0.3.3"
 rustc-serialize = "^0.3.16"
-syntex_pos = { version = "^0.48.0", path = "../syntex_pos" }
+syntex_pos = { version = "^0.50.0", path = "../syntex_pos" }
 term = "^0.4.4"
 unicode-xid = "^0.0.3"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/syntex_errors/src/diagnostic.rs
@@ -0,0 +1,202 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <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 CodeSuggestion;
+use Level;
+use RenderSpan;
+use RenderSpan::Suggestion;
+use std::fmt;
+use syntax_pos::{MultiSpan, Span};
+
+#[must_use]
+#[derive(Clone, Debug, PartialEq)]
+pub struct Diagnostic {
+    pub level: Level,
+    pub message: String,
+    pub code: Option<String>,
+    pub span: MultiSpan,
+    pub children: Vec<SubDiagnostic>,
+}
+
+/// For example a note attached to an error.
+#[derive(Clone, Debug, PartialEq)]
+pub struct SubDiagnostic {
+    pub level: Level,
+    pub message: String,
+    pub span: MultiSpan,
+    pub render_span: Option<RenderSpan>,
+}
+
+impl Diagnostic {
+    pub fn new(level: Level, message: &str) -> Self {
+        Diagnostic::new_with_code(level, None, message)
+    }
+
+    pub fn new_with_code(level: Level, code: Option<String>, message: &str) -> Self {
+        Diagnostic {
+            level: level,
+            message: message.to_owned(),
+            code: code,
+            span: MultiSpan::new(),
+            children: vec![],
+        }
+    }
+
+    /// Cancel the diagnostic (a structured diagnostic must either be emitted or
+    /// cancelled or it will panic when dropped).
+    /// BEWARE: if this DiagnosticBuilder is an error, then creating it will
+    /// bump the error count on the Handler and cancelling it won't undo that.
+    /// If you want to decrement the error count you should use `Handler::cancel`.
+    pub fn cancel(&mut self) {
+        self.level = Level::Cancelled;
+    }
+
+    pub fn cancelled(&self) -> bool {
+        self.level == Level::Cancelled
+    }
+
+    pub fn is_fatal(&self) -> bool {
+        self.level == Level::Fatal
+    }
+
+    /// Add a span/label to be included in the resulting snippet.
+    /// This is pushed onto the `MultiSpan` that was created when the
+    /// diagnostic was first built. If you don't call this function at
+    /// all, and you just supplied a `Span` to create the diagnostic,
+    /// then the snippet will just include that `Span`, which is
+    /// called the primary span.
+    pub fn span_label(&mut self, span: Span, label: &fmt::Display)
+                      -> &mut Self {
+        self.span.push_span_label(span, format!("{}", label));
+        self
+    }
+
+    pub fn note_expected_found(&mut self,
+                               label: &fmt::Display,
+                               expected: &fmt::Display,
+                               found: &fmt::Display)
+                               -> &mut Self
+    {
+        self.note_expected_found_extra(label, expected, found, &"", &"")
+    }
+
+    pub fn note_expected_found_extra(&mut self,
+                                     label: &fmt::Display,
+                                     expected: &fmt::Display,
+                                     found: &fmt::Display,
+                                     expected_extra: &fmt::Display,
+                                     found_extra: &fmt::Display)
+                                     -> &mut Self
+    {
+        // For now, just attach these as notes
+        self.note(&format!("expected {} `{}`{}", label, expected, expected_extra));
+        self.note(&format!("   found {} `{}`{}", label, found, found_extra));
+        self
+    }
+
+    pub fn note(&mut self, msg: &str) -> &mut Self {
+        self.sub(Level::Note, msg, MultiSpan::new(), None);
+        self
+    }
+
+    pub fn span_note<S: Into<MultiSpan>>(&mut self,
+                                         sp: S,
+                                         msg: &str)
+                                         -> &mut Self {
+        self.sub(Level::Note, msg, sp.into(), None);
+        self
+    }
+
+    pub fn warn(&mut self, msg: &str) -> &mut Self {
+        self.sub(Level::Warning, msg, MultiSpan::new(), None);
+        self
+    }
+
+    pub fn span_warn<S: Into<MultiSpan>>(&mut self,
+                                         sp: S,
+                                         msg: &str)
+                                         -> &mut Self {
+        self.sub(Level::Warning, msg, sp.into(), None);
+        self
+    }
+
+    pub fn help(&mut self , msg: &str) -> &mut Self {
+        self.sub(Level::Help, msg, MultiSpan::new(), None);
+        self
+    }
+
+    pub fn span_help<S: Into<MultiSpan>>(&mut self,
+                                         sp: S,
+                                         msg: &str)
+                                         -> &mut Self {
+        self.sub(Level::Help, msg, sp.into(), None);
+        self
+    }
+
+    /// Prints out a message with a suggested edit of the code.
+    ///
+    /// See `diagnostic::RenderSpan::Suggestion` for more information.
+    pub fn span_suggestion<S: Into<MultiSpan>>(&mut self,
+                                               sp: S,
+                                               msg: &str,
+                                               suggestion: String)
+                                               -> &mut Self {
+        self.sub(Level::Help,
+                 msg,
+                 MultiSpan::new(),
+                 Some(Suggestion(CodeSuggestion {
+                     msp: sp.into(),
+                     substitutes: vec![suggestion],
+                 })));
+        self
+    }
+
+    pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self {
+        self.span = sp.into();
+        self
+    }
+
+    pub fn code(&mut self, s: String) -> &mut Self {
+        self.code = Some(s);
+        self
+    }
+
+    pub fn message(&self) -> &str {
+        &self.message
+    }
+
+    pub fn level(&self) -> Level {
+        self.level
+    }
+
+    /// Used by a lint. Copies over all details *but* the "main
+    /// message".
+    pub fn copy_details_not_message(&mut self, from: &Diagnostic) {
+        self.span = from.span.clone();
+        self.code = from.code.clone();
+        self.children.extend(from.children.iter().cloned())
+    }
+
+    /// Convenience function for internal use, clients should use one of the
+    /// public methods above.
+    fn sub(&mut self,
+           level: Level,
+           message: &str,
+           span: MultiSpan,
+           render_span: Option<RenderSpan>) {
+        let sub = SubDiagnostic {
+            level: level,
+            message: message.to_owned(),
+            span: span,
+            render_span: render_span,
+        };
+        self.children.push(sub);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/syntex_errors/src/diagnostic_builder.rs
@@ -0,0 +1,196 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <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 Diagnostic;
+use Level;
+use Handler;
+use std::fmt::{self, Debug};
+use std::ops::{Deref, DerefMut};
+use std::thread::panicking;
+use syntax_pos::{MultiSpan, Span};
+
+/// Used for emitting structured error messages and other diagnostic information.
+#[must_use]
+#[derive(Clone)]
+pub struct DiagnosticBuilder<'a> {
+    handler: &'a Handler,
+    diagnostic: Diagnostic,
+}
+
+/// In general, the `DiagnosticBuilder` uses deref to allow access to
+/// the fields and methods of the embedded `diagnostic` in a
+/// transparent way.  *However,* many of the methods are intended to
+/// be used in a chained way, and hence ought to return `self`. In
+/// that case, we can't just naively forward to the method on the
+/// `diagnostic`, because the return type would be a `&Diagnostic`
+/// instead of a `&DiagnosticBuilder<'a>`. This `forward!` macro makes
+/// it easy to declare such methods on the builder.
+macro_rules! forward {
+    // Forward pattern for &self -> &Self
+    (pub fn $n:ident(&self, $($name:ident: $ty:ty),*) -> &Self) => {
+        pub fn $n(&self, $($name: $ty),*) -> &Self {
+            self.diagnostic.$n($($name),*);
+            self
+        }
+    };
+
+    // Forward pattern for &mut self -> &mut Self
+    (pub fn $n:ident(&mut self, $($name:ident: $ty:ty),*) -> &mut Self) => {
+        pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
+            self.diagnostic.$n($($name),*);
+            self
+        }
+    };
+
+    // Forward pattern for &mut self -> &mut Self, with S: Into<MultiSpan>
+    // type parameter. No obvious way to make this more generic.
+    (pub fn $n:ident<S: Into<MultiSpan>>(&mut self, $($name:ident: $ty:ty),*) -> &mut Self) => {
+        pub fn $n<S: Into<MultiSpan>>(&mut self, $($name: $ty),*) -> &mut Self {
+            self.diagnostic.$n($($name),*);
+            self
+        }
+    };
+}
+
+impl<'a> Deref for DiagnosticBuilder<'a> {
+    type Target = Diagnostic;
+
+    fn deref(&self) -> &Diagnostic {
+        &self.diagnostic
+    }
+}
+
+impl<'a> DerefMut for DiagnosticBuilder<'a> {
+    fn deref_mut(&mut self) -> &mut Diagnostic {
+        &mut self.diagnostic
+    }
+}
+
+impl<'a> DiagnosticBuilder<'a> {
+    /// Emit the diagnostic.
+    pub fn emit(&mut self) {
+        if self.cancelled() {
+            return;
+        }
+
+        match self.level {
+            Level::Bug |
+            Level::Fatal |
+            Level::PhaseFatal |
+            Level::Error => {
+                self.handler.bump_err_count();
+            }
+
+            Level::Warning |
+            Level::Note |
+            Level::Help |
+            Level::Cancelled => {
+            }
+        }
+
+        self.handler.emitter.borrow_mut().emit(&self);
+        self.cancel();
+        self.handler.panic_if_treat_err_as_bug();
+
+        // if self.is_fatal() {
+        //     panic!(FatalError);
+        // }
+    }
+
+    /// Add a span/label to be included in the resulting snippet.
+    /// This is pushed onto the `MultiSpan` that was created when the
+    /// diagnostic was first built. If you don't call this function at
+    /// all, and you just supplied a `Span` to create the diagnostic,
+    /// then the snippet will just include that `Span`, which is
+    /// called the primary span.
+    forward!(pub fn span_label(&mut self, span: Span, label: &fmt::Display)
+                               -> &mut Self);
+
+    forward!(pub fn note_expected_found(&mut self,
+                                        label: &fmt::Display,
+                                        expected: &fmt::Display,
+                                        found: &fmt::Display)
+                                        -> &mut Self);
+
+    forward!(pub fn note_expected_found_extra(&mut self,
+                                              label: &fmt::Display,
+                                              expected: &fmt::Display,
+                                              found: &fmt::Display,
+                                              expected_extra: &fmt::Display,
+                                              found_extra: &fmt::Display)
+                                              -> &mut Self);
+
+    forward!(pub fn note(&mut self, msg: &str) -> &mut Self);
+    forward!(pub fn span_note<S: Into<MultiSpan>>(&mut self,
+                                                  sp: S,
+                                                  msg: &str)
+                                                  -> &mut Self);
+    forward!(pub fn warn(&mut self, msg: &str) -> &mut Self);
+    forward!(pub fn span_warn<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> &mut Self);
+    forward!(pub fn help(&mut self , msg: &str) -> &mut Self);
+    forward!(pub fn span_help<S: Into<MultiSpan>>(&mut self,
+                                                  sp: S,
+                                                  msg: &str)
+                                                  -> &mut Self);
+    forward!(pub fn span_suggestion<S: Into<MultiSpan>>(&mut self,
+                                                        sp: S,
+                                                        msg: &str,
+                                                        suggestion: String)
+                                                        -> &mut Self);
+    forward!(pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self);
+    forward!(pub fn code(&mut self, s: String) -> &mut Self);
+
+    /// Convenience function for internal use, clients should use one of the
+    /// struct_* methods on Handler.
+    pub fn new(handler: &'a Handler, level: Level, message: &str) -> DiagnosticBuilder<'a> {
+        DiagnosticBuilder::new_with_code(handler, level, None, message)
+    }
+
+    /// Convenience function for internal use, clients should use one of the
+    /// struct_* methods on Handler.
+    pub fn new_with_code(handler: &'a Handler,
+                         level: Level,
+                         code: Option<String>,
+                         message: &str)
+                         -> DiagnosticBuilder<'a> {
+        DiagnosticBuilder {
+            handler: handler,
+            diagnostic: Diagnostic::new_with_code(level, code, message)
+        }
+    }
+
+    pub fn into_diagnostic(mut self) -> Diagnostic {
+        // annoyingly, the Drop impl means we can't actually move
+        let result = self.diagnostic.clone();
+        self.cancel();
+        result
+    }
+}
+
+impl<'a> Debug for DiagnosticBuilder<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.diagnostic.fmt(f)
+    }
+}
+
+/// Destructor bomb - a DiagnosticBuilder must be either emitted or cancelled or
+/// we emit a bug.
+impl<'a> Drop for DiagnosticBuilder<'a> {
+    fn drop(&mut self) {
+        if !panicking() && !self.cancelled() {
+            let mut db = DiagnosticBuilder::new(self.handler,
+                                                Level::Bug,
+                                                "Error constructed but not emitted");
+            db.emit();
+            panic!();
+        }
+    }
+}
+
--- a/third_party/rust/syntex_errors/src/lib.rs
+++ b/third_party/rust/syntex_errors/src/lib.rs
@@ -23,49 +23,49 @@ extern crate log;
 extern crate libc;
 extern crate unicode_xid;
 extern crate rustc_serialize;
 extern crate syntex_pos as syntax_pos;
 
 pub use emitter::ColorConfig;
 
 use self::Level::*;
-use self::RenderSpan::*;
 
 use emitter::{Emitter, EmitterWriter};
 
 use std::cell::{RefCell, Cell};
 use std::{error, fmt};
 use std::rc::Rc;
-use std::thread::panicking;
 
+pub mod diagnostic;
+pub mod diagnostic_builder;
 pub mod emitter;
 pub mod snippet;
 pub mod registry;
 pub mod styled_buffer;
 mod lock;
 
 use syntax_pos::{BytePos, Loc, FileLinesResult, FileName, MultiSpan, Span, NO_EXPANSION};
 use syntax_pos::MacroBacktrace;
 
-#[derive(Clone)]
+#[derive(Clone, Debug, PartialEq)]
 pub enum RenderSpan {
     /// A FullSpan renders with both with an initial line for the
     /// message, prefixed by file:linenum, followed by a summary of
     /// the source code covered by the span.
     FullSpan(MultiSpan),
 
     /// A suggestion renders with both with an initial line for the
     /// message, prefixed by file:linenum, followed by a summary
     /// of hypothetical source code, where each `String` is spliced
     /// into the lines in place of the code covered by each span.
     Suggestion(CodeSuggestion),
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug, PartialEq)]
 pub struct CodeSuggestion {
     pub msp: MultiSpan,
     pub substitutes: Vec<String>,
 }
 
 pub trait CodeMapper {
     fn lookup_char_pos(&self, pos: BytePos) -> Loc;
     fn span_to_lines(&self, sp: Span) -> FileLinesResult;
@@ -195,229 +195,18 @@ impl fmt::Display for ExplicitBug {
 }
 
 impl error::Error for ExplicitBug {
     fn description(&self) -> &str {
         "The parser has encountered an internal bug"
     }
 }
 
-/// Used for emitting structured error messages and other diagnostic information.
-#[must_use]
-#[derive(Clone)]
-pub struct DiagnosticBuilder<'a> {
-    handler: &'a Handler,
-    pub level: Level,
-    pub message: String,
-    pub code: Option<String>,
-    pub span: MultiSpan,
-    pub children: Vec<SubDiagnostic>,
-}
-
-/// For example a note attached to an error.
-#[derive(Clone)]
-pub struct SubDiagnostic {
-    pub level: Level,
-    pub message: String,
-    pub span: MultiSpan,
-    pub render_span: Option<RenderSpan>,
-}
-
-impl<'a> DiagnosticBuilder<'a> {
-    /// Emit the diagnostic.
-    pub fn emit(&mut self) {
-        if self.cancelled() {
-            return;
-        }
-
-        self.handler.emitter.borrow_mut().emit(&self);
-        self.cancel();
-        self.handler.panic_if_treat_err_as_bug();
-
-        // if self.is_fatal() {
-        //     panic!(FatalError);
-        // }
-    }
-
-    /// Cancel the diagnostic (a structured diagnostic must either be emitted or
-    /// cancelled or it will panic when dropped).
-    /// BEWARE: if this DiagnosticBuilder is an error, then creating it will
-    /// bump the error count on the Handler and cancelling it won't undo that.
-    /// If you want to decrement the error count you should use `Handler::cancel`.
-    pub fn cancel(&mut self) {
-        self.level = Level::Cancelled;
-    }
-
-    pub fn cancelled(&self) -> bool {
-        self.level == Level::Cancelled
-    }
-
-    pub fn is_fatal(&self) -> bool {
-        self.level == Level::Fatal
-    }
-
-    /// Add a span/label to be included in the resulting snippet.
-    /// This is pushed onto the `MultiSpan` that was created when the
-    /// diagnostic was first built. If you don't call this function at
-    /// all, and you just supplied a `Span` to create the diagnostic,
-    /// then the snippet will just include that `Span`, which is
-    /// called the primary span.
-    pub fn span_label(&mut self, span: Span, label: &fmt::Display) -> &mut DiagnosticBuilder<'a> {
-        self.span.push_span_label(span, format!("{}", label));
-        self
-    }
-
-    pub fn note_expected_found(&mut self,
-                               label: &fmt::Display,
-                               expected: &fmt::Display,
-                               found: &fmt::Display)
-                               -> &mut DiagnosticBuilder<'a> {
-        self.note_expected_found_extra(label, expected, found, &"", &"")
-    }
-
-    pub fn note_expected_found_extra(&mut self,
-                                     label: &fmt::Display,
-                                     expected: &fmt::Display,
-                                     found: &fmt::Display,
-                                     expected_extra: &fmt::Display,
-                                     found_extra: &fmt::Display)
-                                     -> &mut DiagnosticBuilder<'a> {
-        // For now, just attach these as notes
-        self.note(&format!("expected {} `{}`{}", label, expected, expected_extra));
-        self.note(&format!("   found {} `{}`{}", label, found, found_extra));
-        self
-    }
-
-    pub fn note(&mut self, msg: &str) -> &mut DiagnosticBuilder<'a> {
-        self.sub(Level::Note, msg, MultiSpan::new(), None);
-        self
-    }
-    pub fn span_note<S: Into<MultiSpan>>(&mut self,
-                                         sp: S,
-                                         msg: &str)
-                                         -> &mut DiagnosticBuilder<'a> {
-        self.sub(Level::Note, msg, sp.into(), None);
-        self
-    }
-    pub fn warn(&mut self, msg: &str) -> &mut DiagnosticBuilder<'a> {
-        self.sub(Level::Warning, msg, MultiSpan::new(), None);
-        self
-    }
-    pub fn span_warn<S: Into<MultiSpan>>(&mut self,
-                                         sp: S,
-                                         msg: &str)
-                                         -> &mut DiagnosticBuilder<'a> {
-        self.sub(Level::Warning, msg, sp.into(), None);
-        self
-    }
-    pub fn help(&mut self, msg: &str) -> &mut DiagnosticBuilder<'a> {
-        self.sub(Level::Help, msg, MultiSpan::new(), None);
-        self
-    }
-    pub fn span_help<S: Into<MultiSpan>>(&mut self,
-                                         sp: S,
-                                         msg: &str)
-                                         -> &mut DiagnosticBuilder<'a> {
-        self.sub(Level::Help, msg, sp.into(), None);
-        self
-    }
-    /// Prints out a message with a suggested edit of the code.
-    ///
-    /// See `diagnostic::RenderSpan::Suggestion` for more information.
-    pub fn span_suggestion<S: Into<MultiSpan>>(&mut self,
-                                               sp: S,
-                                               msg: &str,
-                                               suggestion: String)
-                                               -> &mut DiagnosticBuilder<'a> {
-        self.sub(Level::Help,
-                 msg,
-                 MultiSpan::new(),
-                 Some(Suggestion(CodeSuggestion {
-                     msp: sp.into(),
-                     substitutes: vec![suggestion],
-                 })));
-        self
-    }
-
-    pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self {
-        self.span = sp.into();
-        self
-    }
-
-    pub fn code(&mut self, s: String) -> &mut Self {
-        self.code = Some(s);
-        self
-    }
-
-    pub fn message(&self) -> &str {
-        &self.message
-    }
-
-    pub fn level(&self) -> Level {
-        self.level
-    }
-
-    /// Convenience function for internal use, clients should use one of the
-    /// struct_* methods on Handler.
-    fn new(handler: &'a Handler, level: Level, message: &str) -> DiagnosticBuilder<'a> {
-        DiagnosticBuilder::new_with_code(handler, level, None, message)
-    }
-
-    /// Convenience function for internal use, clients should use one of the
-    /// struct_* methods on Handler.
-    fn new_with_code(handler: &'a Handler,
-                     level: Level,
-                     code: Option<String>,
-                     message: &str)
-                     -> DiagnosticBuilder<'a> {
-        DiagnosticBuilder {
-            handler: handler,
-            level: level,
-            message: message.to_owned(),
-            code: code,
-            span: MultiSpan::new(),
-            children: vec![],
-        }
-    }
-
-    /// Convenience function for internal use, clients should use one of the
-    /// public methods above.
-    fn sub(&mut self,
-           level: Level,
-           message: &str,
-           span: MultiSpan,
-           render_span: Option<RenderSpan>) {
-        let sub = SubDiagnostic {
-            level: level,
-            message: message.to_owned(),
-            span: span,
-            render_span: render_span,
-        };
-        self.children.push(sub);
-    }
-}
-
-impl<'a> fmt::Debug for DiagnosticBuilder<'a> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.message.fmt(f)
-    }
-}
-
-/// Destructor bomb - a DiagnosticBuilder must be either emitted or cancelled or
-/// we emit a bug.
-impl<'a> Drop for DiagnosticBuilder<'a> {
-    fn drop(&mut self) {
-        if !panicking() && !self.cancelled() {
-            let mut db =
-                DiagnosticBuilder::new(self.handler, Bug, "Error constructed but not emitted");
-            db.emit();
-            panic!();
-        }
-    }
-}
+pub use diagnostic::{Diagnostic, SubDiagnostic};
+pub use diagnostic_builder::DiagnosticBuilder;
 
 /// A handler deals with errors; certain errors
 /// (fatal, bug, unimpl) may cause immediate exit,
 /// others log errors for later reporting.
 pub struct Handler {
     err_count: Cell<usize>,
     emitter: RefCell<Box<Emitter>>,
     pub can_emit_warnings: bool,
@@ -488,110 +277,93 @@ impl Handler {
             result.cancel();
         }
         result
     }
     pub fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
                                                    sp: S,
                                                    msg: &str)
                                                    -> DiagnosticBuilder<'a> {
-        self.bump_err_count();
         let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
         result.set_span(sp);
         result
     }
     pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                              sp: S,
                                                              msg: &str,
                                                              code: &str)
                                                              -> DiagnosticBuilder<'a> {
-        self.bump_err_count();
         let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
         result.set_span(sp);
         result.code(code.to_owned());
         result
     }
     pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
-        self.bump_err_count();
         DiagnosticBuilder::new(self, Level::Error, msg)
     }
     pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(&'a self,
                                                      sp: S,
                                                      msg: &str)
                                                      -> DiagnosticBuilder<'a> {
-        self.bump_err_count();
         let mut result = DiagnosticBuilder::new(self, Level::Fatal, msg);
         result.set_span(sp);
         result
     }
     pub fn struct_span_fatal_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                                sp: S,
                                                                msg: &str,
                                                                code: &str)
                                                                -> DiagnosticBuilder<'a> {
-        self.bump_err_count();
         let mut result = DiagnosticBuilder::new(self, Level::Fatal, msg);
         result.set_span(sp);
         result.code(code.to_owned());
         result
     }
     pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
-        self.bump_err_count();
         DiagnosticBuilder::new(self, Level::Fatal, msg)
     }
 
     pub fn cancel(&self, err: &mut DiagnosticBuilder) {
-        if err.level == Level::Error || err.level == Level::Fatal {
-            self.err_count.set(self.err_count
-                .get()
-                .checked_sub(1)
-                .expect("cancelled an error but err_count is 0"));
-        }
         err.cancel();
     }
 
     fn panic_if_treat_err_as_bug(&self) {
         if self.treat_err_as_bug {
             panic!("encountered error with `-Z treat_err_as_bug");
         }
     }
 
     pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> FatalError {
         self.emit(&sp.into(), msg, Fatal);
-        self.bump_err_count();
         self.panic_if_treat_err_as_bug();
         return FatalError;
     }
     pub fn span_fatal_with_code<S: Into<MultiSpan>>(&self,
                                                     sp: S,
                                                     msg: &str,
                                                     code: &str)
                                                     -> FatalError {
         self.emit_with_code(&sp.into(), msg, code, Fatal);
-        self.bump_err_count();
         self.panic_if_treat_err_as_bug();
         return FatalError;
     }
     pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.emit(&sp.into(), msg, Error);
-        self.bump_err_count();
         self.panic_if_treat_err_as_bug();
     }
     pub fn mut_span_err<'a, S: Into<MultiSpan>>(&'a self,
                                                 sp: S,
                                                 msg: &str)
                                                 -> DiagnosticBuilder<'a> {
         let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
         result.set_span(sp);
-        self.bump_err_count();
         result
     }
     pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) {
         self.emit_with_code(&sp.into(), msg, code, Error);
-        self.bump_err_count();
         self.panic_if_treat_err_as_bug();
     }
     pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.emit(&sp.into(), msg, Warning);
     }
     pub fn span_warn_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) {
         self.emit_with_code(&sp.into(), msg, code, Warning);
     }
@@ -600,40 +372,37 @@ impl Handler {
         panic!(ExplicitBug);
     }
     pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         let mut delayed = self.delayed_span_bug.borrow_mut();
         *delayed = Some((sp.into(), msg.to_string()));
     }
     pub fn span_bug_no_panic<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.emit(&sp.into(), msg, Bug);
-        self.bump_err_count();
     }
     pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.emit(&sp.into(), msg, Note);
     }
     pub fn span_unimpl<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
         self.span_bug(sp, &format!("unimplemented {}", msg));
     }
     pub fn fatal(&self, msg: &str) -> FatalError {
         if self.treat_err_as_bug {
             self.bug(msg);
         }
         let mut db = DiagnosticBuilder::new(self, Fatal, msg);
         db.emit();
-        self.bump_err_count();
         FatalError
     }
     pub fn err(&self, msg: &str) {
         if self.treat_err_as_bug {
             self.bug(msg);
         }
         let mut db = DiagnosticBuilder::new(self, Error, msg);
         db.emit();
-        self.bump_err_count();
     }
     pub fn warn(&self, msg: &str) {
         let mut db = DiagnosticBuilder::new(self, Warning, msg);
         db.emit();
     }
     pub fn note_without_error(&self, msg: &str) {
         let mut db = DiagnosticBuilder::new(self, Note, msg);
         db.emit();
--- a/third_party/rust/syntex_pos/.cargo-checksum.json
+++ b/third_party/rust/syntex_pos/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"184ea1b1cc8da9f51aecfa908a2c914972c0f825a9e5240744b7a82d3088bbd1","src/lib.rs":"39256672c6a2510505d4a970ece5eb11ae6a2badfc3cb13e369b638f026609a2"},"package":"25fadff25e4db9336cd715dea4bc7d4bf51d08cc39a1463b689661f1dea6893c"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"c5fc83ac158c863c4e9f7ee4d98d94e748ae204c5338322dbc93fb46cbb65057","src/lib.rs":"5bcf6170629a9afb40f06028d4708bb2cd9d278988e57f7269abcefc437f4616"},"package":"a43abded5057c75bac8555e46ec913ce502efb418267b1ab8e9783897470c7db"}
\ No newline at end of file
--- a/third_party/rust/syntex_pos/Cargo.toml
+++ b/third_party/rust/syntex_pos/Cargo.toml
@@ -1,11 +1,11 @@
 [package]
 name = "syntex_pos"
-version = "0.48.0"
+version = "0.50.0"
 authors = [ "erick.tryzelaar@gmail.com" ]
 license = "MIT/Apache-2.0"
 description = "Export of libsyntax_pos for code generation"
 repository = "https://github.com/serde-rs/syntex"
 include = ["Cargo.toml", "src/**/*.rs"]
 
 [dependencies]
 rustc-serialize = "^0.3.16"
--- a/third_party/rust/syntex_pos/src/lib.rs
+++ b/third_party/rust/syntex_pos/src/lib.rs
@@ -38,32 +38,32 @@ pub type FileName = String;
 /// Spans represent a region of code, used for error reporting. Positions in spans
 /// are *absolute* positions from the beginning of the codemap, not positions
 /// relative to FileMaps. Methods on the CodeMap can be used to relate spans back
 /// to the original source.
 /// You must be careful if the span crosses more than one file - you will not be
 /// able to use many of the functions on spans in codemap and you cannot assume
 /// that the length of the span = hi - lo; there may be space in the BytePos
 /// range between files.
-#[derive(Clone, Copy, Hash, PartialEq, Eq)]
+#[derive(Clone, Copy, Hash, PartialEq, Eq, Ord, PartialOrd)]
 pub struct Span {
     pub lo: BytePos,
     pub hi: BytePos,
     /// Information about where the macro came from, if this piece of
     /// code was created by a macro expansion.
     pub expn_id: ExpnId
 }
 
 /// A collection of spans. Spans have two orthogonal attributes:
 ///
 /// - they can be *primary spans*. In this case they are the locus of
 ///   the error, and would be rendered with `^^^`.
 /// - they can have a *label*. In this case, the label is written next
 ///   to the mark in the snippet when we render.
-#[derive(Clone)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
 pub struct MultiSpan {
     primary_spans: Vec<Span>,
     span_labels: Vec<(Span, String)>,
 }
 
 impl Span {
     /// Returns a new span representing just the end-point of this span
     pub fn end_point(self) -> Span {
@@ -240,17 +240,17 @@ impl MultiSpan {
 }
 
 impl From<Span> for MultiSpan {
     fn from(span: Span) -> MultiSpan {
         MultiSpan::from_span(span)
     }
 }
 
-#[derive(PartialEq, Eq, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Copy)]
+#[derive(PartialEq, Eq, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Copy, Ord, PartialOrd)]
 pub struct ExpnId(pub u32);
 
 pub const NO_EXPANSION: ExpnId = ExpnId(!0);
 // For code appearing from the command line
 pub const COMMAND_LINE_EXPN: ExpnId = ExpnId(!1);
 
 // For code generated by a procedural macro, without knowing which
 // Used in `qquote!`
--- a/third_party/rust/syntex_syntax/.cargo-checksum.json
+++ b/third_party/rust/syntex_syntax/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"255a9a11b2712a08d0f106e11b43d3dcb5ddcdbeb04a6098f49e9355e51f4f7b","src/abi.rs":"4ffa6e8069b78ec34c73435636072ba84ae352c22f1b91dde1b397efcdab4654","src/ast.rs":"1bac57a43e6d45fdddccb1962a25f1fd5d061df96f83abfd96f7f8f59baae1f9","src/attr.rs":"aebc56e4aa2cdeca243cc99e95ab17ba02fe6c84e550e05e89b60e62f3cbf7f7","src/codemap.rs":"dfd217155355fd0c3723dd2bd84a3353ebb476be757c58a23022f137ad00e1e0","src/config.rs":"9428a0ca89316579256d1a0892b3e498ba92ea8f70ce556ec6b0d5778a07533f","src/diagnostic_list.rs":"69240654107a937e38d030907323cfd7fa9542f5af5e1a77af03c47022ceb3ac","src/diagnostics/macros.rs":"81c36c9164ef238407540f7b026ae12117eb551630ae522c55a90ff9d01fff62","src/diagnostics/metadata.rs":"55570cb118892c25d98f1c120903caa88b212d83eee846594bf32d30245a00aa","src/diagnostics/plugin.rs":"610b2f8b2bcf33aec454a565edcbd4d6c5685f7b1250f71d3ed5a0b16b8ff8dc","src/entry.rs":"8e4c557e3f0c8e040d65a523fe4c97831869f4d5dcc7c6311c9a5363b36a5139","src/ext/base.rs":"7d7675adf5a872a997c65f7db7b9a44a66613441a9b47f376fef98446c99573a","src/ext/build.rs":"b8d9ee4095a4feee98b1e83ffc34329969dd31738b3d73e9ae3654272b0de4e0","src/ext/decorator.rs":"8213d7afa18ad112abfc0a3e224544053956eac1ffa98b4ec0a0f8391157057d","src/ext/env.rs":"7fc8430e069290fc25112a0feaca4a51f1d11b0ebad65f1b3cac733ca469d587","src/ext/expand.rs":"1c48576226e1baab4be53cadef146ba6799d9b61b9fcb6fbbea1ea45a3853605","src/ext/hygiene.rs":"c37b34a4f37c04bf0abb365e0dc15f8558bc1ce25508d62b61e1044f05c608ad","src/ext/placeholders.rs":"68fb160945cf6ed0ffee4e908ff15521f0cb2a8ccc6c6eebbe2e98bdc5f3a775","src/ext/proc_macro_shim.rs":"617c588d0565706096a56b11f191b635c86a5156d6d816071e30a54b6ddfc81d","src/ext/quote.rs":"2626661019f3e033696140dc6dc465cf0d9d41656e3891c984c6e4de78c31826","src/ext/source_util.rs":"3b8d73943767fcf4b953f91c9854f8abbd47ded18cff8b2c63606074ef23d275","src/ext/tt/macro_parser.rs":"f78bbefb6c8387bf9fa4014faf64e5131e263628e89d7b0a678db8ac0502f499","src/ext/tt/macro_rules.rs":"f5641a0dbf6224f6196f1eda7d480343154f4f0ccc8562b896a98033db898ef2","src/ext/tt/transcribe.rs":"c1063fc6b188fc3dc68cefb969581a2e12caaf8da0cfb48f3d864b0b4a15df9d","src/feature_gate.rs":"3df981ec69ed2a3fd4f7686a5356ca17cdbb8bd3814d48cd29575f72e74e9cec","src/fold.rs":"1925529e08731fb3b84869ecf9e9babf89babfd424f79d9dda3cef5736133d26","src/json.rs":"8c93c81515a127c8f780d27bded4968ed17f5b6fcc909319cac8d6b098e24bd9","src/lib.rs":"04f1b95a8f2369f87796703e35587e9c073aabdae7f73afc881e31adc4dc9b14","src/parse/attr.rs":"51aa288b435eac106e179b44a6e21daf31cc00f3e852858a60e56ae0fc626d09","src/parse/classify.rs":"4e859c566e98bc11e7cc05f3b5f7f7a67caa6c53b8b10366eaf32e58bcfdc7ca","src/parse/common.rs":"f231aece27f62694d1146c5b40b24daf8e0e2e0152b159ca6693a8f583679f43","src/parse/lexer/comments.rs":"d6b1b4a723032a27d65128df823d8e97d1512dbbdb363dc7556c1abe01cce0fc","src/parse/lexer/mod.rs":"7fbd92a0477cb2a9ef85ae4c12082203c055063968473e4d06fbf6fe39e58a95","src/parse/lexer/unicode_chars.rs":"92bdf17f281215b5b98e5d7ec8528142e7c04eaa7dba87c3b87b189a39161c63","src/parse/mod.rs":"4fc001e5e9ab7e87f64db0018fdec07d3bc22bd42322f2f3a9aeed3008149872","src/parse/obsolete.rs":"cd83ee6f4a01086b736594638492969c6cec9522527fc576886186b9ad6cff03","src/parse/parser.rs":"c1c060754a3a85a8688cb16403ef3319f431273da35eedb5f7be0f1a2bc5ab7b","src/parse/token.rs":"f1dd414fe5e1e6500defc4d23b53d7101abf4ce28c317d668852e1476f8ff5c7","src/print/pp.rs":"ef6752db3a36c7a614d43d767c788985a78f33e120b39a85e2156a576630afd4","src/print/pprust.rs":"7165e7d39ee964bda7c30fa8b92bc8f11b494a869a2baaea3301738e33432968","src/ptr.rs":"2f0ecadd1d19b1e11bb067cee99ac6fff7c48dd33222ed67fb61f240e1ca820e","src/show_span.rs":"586edbc823ef20137df8ee0ecc5b862bd5d0a9569089b873494ef691c860a1ea","src/std_inject.rs":"7a41a6843e7fe2f27abcdcff3b17626d6cacb3398a1e3969059531151283ce7a","src/str.rs":"023289c93979354cf6074e94327e5c71b5144e0d12042304c0c91b9dd974b26f","src/test.rs":"6e0e79a0aacf6ba1b49ff15afcfc98d48edba91e13618c2f9d921b771aca5f44","src/tokenstream.rs":"e52435751fedfc60c0833459bddffbe7f0634325efa099ea3aec51da7f7342a2","src/util/interner.rs":"474dd6dcab5430f0a28178f3383491539f69ef397865d7ac25aee9ab88761605","src/util/lev_distance.rs":"6ae1c19e373d6af5dfc1cef994648412e12223c7dce711f839b81e545473ff7c","src/util/move_map.rs":"8bf1a3546325872892ca5d4f04771af01566913d84fa678df7c862fda75fa16c","src/util/node_count.rs":"a1445e71285299e124e33dddd497879b9cbe2f2b658c4e16bce27c92bd0e5c54","src/util/parser.rs":"7e9af52677757e30cd4cad6d35caa32889e6e4012335cf31711dd4c079bee9d5","src/util/parser_testing.rs":"828bac41595054c643305ef2e39873baf33ecac30de6b76e87c7e3ea1c5532d1","src/util/small_vector.rs":"b8a61ab524dd5cda0bc9344d1863bb93063055445f66a8074e2839531e6a7fd2","src/util/thin_vec.rs":"eda6e0ab93dce5e45bb7a2ddeae9120fdb0df3c1d6a5d4e0c8ca3648d404177e","src/visit.rs":"42ca3fc7e38c928d915d310579fe22ce7d7bfa333e9f91a02b940cbf636e5a3b"},"package":"0c3c7d1082d30f7042d1e7b00bd2ab0466daa84529fa13891e9312d8a32fd97e"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"a1f38ca69e698467acd8b2bf19d2d6a7503983f11f9270e96abf767ef465b345","src/abi.rs":"4ffa6e8069b78ec34c73435636072ba84ae352c22f1b91dde1b397efcdab4654","src/ast.rs":"4ffb10ec1b3bc4adafdb3905cb9c7329799fcc7e25b3e393ced8858c56d0927e","src/attr.rs":"f0fe5eed02f132ed12647d26ef4e15afd1fa8d917195a04236eea35093362fc5","src/codemap.rs":"dfd217155355fd0c3723dd2bd84a3353ebb476be757c58a23022f137ad00e1e0","src/config.rs":"94294a4c9a9df62a9f98641b07987fcc5d9cb5f59accea3ef72c114f1b1533a1","src/diagnostic_list.rs":"69240654107a937e38d030907323cfd7fa9542f5af5e1a77af03c47022ceb3ac","src/diagnostics/macros.rs":"81c36c9164ef238407540f7b026ae12117eb551630ae522c55a90ff9d01fff62","src/diagnostics/metadata.rs":"55570cb118892c25d98f1c120903caa88b212d83eee846594bf32d30245a00aa","src/diagnostics/plugin.rs":"610b2f8b2bcf33aec454a565edcbd4d6c5685f7b1250f71d3ed5a0b16b8ff8dc","src/entry.rs":"8e4c557e3f0c8e040d65a523fe4c97831869f4d5dcc7c6311c9a5363b36a5139","src/ext/base.rs":"3d2a79ad417ee3e5470fd6047e356e9fe816a18534f5968a2e66e533126f9e54","src/ext/build.rs":"8cf50e3190797bdcdad1d77d59ce328d810ce64fb404a4d798a5a5a0df350fa2","src/ext/decorator.rs":"8213d7afa18ad112abfc0a3e224544053956eac1ffa98b4ec0a0f8391157057d","src/ext/env.rs":"7fc8430e069290fc25112a0feaca4a51f1d11b0ebad65f1b3cac733ca469d587","src/ext/expand.rs":"fafd944773160e8132ab709b237787cddcfca10b4505c0524c57b30b69154826","src/ext/hygiene.rs":"c37b34a4f37c04bf0abb365e0dc15f8558bc1ce25508d62b61e1044f05c608ad","src/ext/placeholders.rs":"68fb160945cf6ed0ffee4e908ff15521f0cb2a8ccc6c6eebbe2e98bdc5f3a775","src/ext/proc_macro_shim.rs":"617c588d0565706096a56b11f191b635c86a5156d6d816071e30a54b6ddfc81d","src/ext/quote.rs":"4754fb012fbefa61932d74cb53fad26f89b8cc629d950b6246e8564e4fcefb55","src/ext/source_util.rs":"e0d7e35657f0e1652eb1cace97b4d0a9fba133d69095abea0e299d6ef05ae093","src/ext/tt/macro_parser.rs":"0860c0ff09b7750e8007257cd4f201e094842dbfc9da2237f050c436582c6a8d","src/ext/tt/macro_rules.rs":"9479dda157e5e3926e49175e2ebd77fa900499da5ceff4ec84bf6f5e27e8d34d","src/ext/tt/transcribe.rs":"9b1a3248b38b205661502bb93397dfe2f15b1620d865fc4d5720dae6e5a1e7e3","src/feature_gate.rs":"7aab0cd9771d63747140845047fff68f43b2326469af9a70d58d5def1094d201","src/fold.rs":"b599accbb807c514e4f1de4d8df7359bb0598a71299678a75d192710b3209011","src/json.rs":"8c93c81515a127c8f780d27bded4968ed17f5b6fcc909319cac8d6b098e24bd9","src/lib.rs":"04f1b95a8f2369f87796703e35587e9c073aabdae7f73afc881e31adc4dc9b14","src/parse/attr.rs":"138719a525252da14df52ca2133277e92f8fd134f250ee439e795837bbfbec9d","src/parse/classify.rs":"4e859c566e98bc11e7cc05f3b5f7f7a67caa6c53b8b10366eaf32e58bcfdc7ca","src/parse/common.rs":"f231aece27f62694d1146c5b40b24daf8e0e2e0152b159ca6693a8f583679f43","src/parse/lexer/comments.rs":"d6b1b4a723032a27d65128df823d8e97d1512dbbdb363dc7556c1abe01cce0fc","src/parse/lexer/mod.rs":"9dd81cbd32ec994b1114afe7a7932657e4d5fd3ede574d8e097d6d6291c1868a","src/parse/lexer/unicode_chars.rs":"92bdf17f281215b5b98e5d7ec8528142e7c04eaa7dba87c3b87b189a39161c63","src/parse/mod.rs":"4fc001e5e9ab7e87f64db0018fdec07d3bc22bd42322f2f3a9aeed3008149872","src/parse/obsolete.rs":"cd83ee6f4a01086b736594638492969c6cec9522527fc576886186b9ad6cff03","src/parse/parser.rs":"d91f70a0ac82369a67a445eedaad2df0f829283c348bb10ae03c175e059a41e0","src/parse/token.rs":"2b9513ee9cbf949d5b111cf5866de619b5d63b5fa9e2ced99fd9d8f0bf1102d8","src/print/pp.rs":"ef6752db3a36c7a614d43d767c788985a78f33e120b39a85e2156a576630afd4","src/print/pprust.rs":"a77409b37009827b311fac353eda822b8263fdff087bcdb341343fd58072995d","src/ptr.rs":"2f0ecadd1d19b1e11bb067cee99ac6fff7c48dd33222ed67fb61f240e1ca820e","src/show_span.rs":"586edbc823ef20137df8ee0ecc5b862bd5d0a9569089b873494ef691c860a1ea","src/std_inject.rs":"7a41a6843e7fe2f27abcdcff3b17626d6cacb3398a1e3969059531151283ce7a","src/str.rs":"023289c93979354cf6074e94327e5c71b5144e0d12042304c0c91b9dd974b26f","src/test.rs":"ee36704f65b8622983039a74a700a93b5620be70c61f84ea5fad30363cdac2a8","src/tokenstream.rs":"0759ecdf1d24796fb587de4bbbc0b8d5e3b70632d57eb40eb210c2d302901883","src/util/interner.rs":"474dd6dcab5430f0a28178f3383491539f69ef397865d7ac25aee9ab88761605","src/util/lev_distance.rs":"6ae1c19e373d6af5dfc1cef994648412e12223c7dce711f839b81e545473ff7c","src/util/move_map.rs":"8bf1a3546325872892ca5d4f04771af01566913d84fa678df7c862fda75fa16c","src/util/node_count.rs":"1fe6cdcc457b2b10125553db8282396e26396876824732767ebd087abf167e40","src/util/parser.rs":"7e9af52677757e30cd4cad6d35caa32889e6e4012335cf31711dd4c079bee9d5","src/util/parser_testing.rs":"828bac41595054c643305ef2e39873baf33ecac30de6b76e87c7e3ea1c5532d1","src/util/small_vector.rs":"5f3de1a28196c60ff2efdbf0f61056de30aafc64b827531c3bb735b0bebed52f","src/util/thin_vec.rs":"eda6e0ab93dce5e45bb7a2ddeae9120fdb0df3c1d6a5d4e0c8ca3648d404177e","src/visit.rs":"7f9fcb15eac535ddc760c22503979293828421b3cdea5b2369d7ce9ff199125d"},"package":"6ef781e4b60f03431f1b5b59843546ce60ae029a787770cf8e0969ac1fd063a5"}
\ No newline at end of file
--- a/third_party/rust/syntex_syntax/Cargo.toml
+++ b/third_party/rust/syntex_syntax/Cargo.toml
@@ -1,18 +1,18 @@
 [package]
 name = "syntex_syntax"
-version = "0.48.0"
+version = "0.50.0"
 authors = [ "erick.tryzelaar@gmail.com" ]
 license = "MIT/Apache-2.0"
 description = "Export of libsyntax for code generation"
 repository = "https://github.com/serde-rs/syntex"
 include = ["Cargo.toml", "src/**/*.rs"]
 
 [dependencies]
 bitflags = "^0.7.0"
 libc = "^0.2.13"
 log = "^0.3.6"
 rustc-serialize = "^0.3.16"
-syntex_errors = { version = "^0.48.0", path = "../syntex_errors" }
-syntex_pos = { version = "^0.48.0", path = "../syntex_pos" }
+syntex_errors = { version = "^0.50.0", path = "../syntex_errors" }
+syntex_pos = { version = "^0.50.0", path = "../syntex_pos" }
 term = "^0.4.4"
 unicode-xid = "^0.0.3"
--- a/third_party/rust/syntex_syntax/src/ast.rs
+++ b/third_party/rust/syntex_syntax/src/ast.rs
@@ -394,16 +394,24 @@ impl Generics {
         !self.lifetimes.is_empty()
     }
     pub fn is_type_parameterized(&self) -> bool {
         !self.ty_params.is_empty()
     }
     pub fn is_parameterized(&self) -> bool {
         self.is_lt_parameterized() || self.is_type_parameterized()
     }
+    pub fn span_for_name(&self, name: &str) -> Option<Span> {
+        for t in &self.ty_params {
+            if t.ident.name.as_str() == name {
+                return Some(t.span);
+            }
+        }
+        None
+    }
 }
 
 impl Default for Generics {
     /// Creates an instance of `Generics`.
     fn default() ->  Generics {
         Generics {
             lifetimes: Vec::new(),
             ty_params: P::new(),
@@ -1004,20 +1012,20 @@ pub enum ExprKind {
     /// This is desugared to a combination of `loop` and `match` expressions.
     ForLoop(P<Pat>, P<Expr>, P<Block>, Option<SpannedIdent>),
     /// Conditionless loop (can be exited with break, continue, or return)
     ///
     /// `'label: loop { block }`
     Loop(P<Block>, Option<SpannedIdent>),
     /// A `match` block.
     Match(P<Expr>, Vec<Arm>),
-    /// A closure (for example, `move |a, b, c| {a + b + c}`)
+    /// A closure (for example, `move |a, b, c| a + b + c`)
     ///
     /// The final span is the span of the argument block `|...|`
-    Closure(CaptureBy, P<FnDecl>, P<Block>, Span),
+    Closure(CaptureBy, P<FnDecl>, P<Expr>, Span),
     /// A block (`{ ... }`)
     Block(P<Block>),
 
     /// An assignment (`a = foo()`)
     Assign(P<Expr>, P<Expr>),
     /// An assignment with an operator
     ///
     /// For example, `a += 1`.
@@ -1045,17 +1053,17 @@ pub enum ExprKind {
     /// A `break`, with an optional label to break
     Break(Option<SpannedIdent>),
     /// A `continue`, with an optional label
     Continue(Option<SpannedIdent>),
     /// A `return`, with an optional value to be returned
     Ret(Option<P<Expr>>),
 
     /// Output of the `asm!()` macro
-    InlineAsm(InlineAsm),
+    InlineAsm(P<InlineAsm>),
 
     /// A macro invocation; pre-expansion
     Mac(Mac),
 
     /// A struct literal expression.
     ///
     /// For example, `Foo {x: 1, y: 2}`, or
     /// `Foo {x: 1, .. base}`, where `base` is the `Option<Expr>`.
--- a/third_party/rust/syntex_syntax/src/attr.rs
+++ b/third_party/rust/syntex_syntax/src/attr.rs
@@ -27,17 +27,18 @@ use parse::token::InternedString;
 use parse::{ParseSess, token};
 use ptr::P;
 use util::ThinVec;
 
 use std::cell::{RefCell, Cell};
 use std::collections::HashSet;
 
 thread_local! {
-    static USED_ATTRS: RefCell<Vec<u64>> = RefCell::new(Vec::new())
+    static USED_ATTRS: RefCell<Vec<u64>> = RefCell::new(Vec::new());
+    static KNOWN_ATTRS: RefCell<Vec<u64>> = RefCell::new(Vec::new());
 }
 
 enum AttrError {
     MultipleItem(InternedString),
     UnknownMetaItem(InternedString),
     MissingSince,
     MissingFeature,
     MultipleStabilityLevels,
@@ -76,16 +77,39 @@ pub fn is_used(attr: &Attribute) -> bool
     USED_ATTRS.with(|slot| {
         let idx = (id / 64) as usize;
         let shift = id % 64;
         slot.borrow().get(idx).map(|bits| bits & (1 << shift) != 0)
             .unwrap_or(false)
     })
 }
 
+pub fn mark_known(attr: &Attribute) {
+    debug!("Marking {:?} as known.", attr);
+    let AttrId(id) = attr.node.id;
+    KNOWN_ATTRS.with(|slot| {
+        let idx = (id / 64) as usize;
+        let shift = id % 64;
+        if slot.borrow().len() <= idx {
+            slot.borrow_mut().resize(idx + 1, 0);
+        }
+        slot.borrow_mut()[idx] |= 1 << shift;
+    });
+}
+
+pub fn is_known(attr: &Attribute) -> bool {
+    let AttrId(id) = attr.node.id;
+    KNOWN_ATTRS.with(|slot| {
+        let idx = (id / 64) as usize;
+        let shift = id % 64;
+        slot.borrow().get(idx).map(|bits| bits & (1 << shift) != 0)
+            .unwrap_or(false)
+    })
+}
+
 impl NestedMetaItem {
     /// Returns the MetaItem if self is a NestedMetaItemKind::MetaItem.
     pub fn meta_item(&self) -> Option<&P<MetaItem>> {
         match self.node {
             NestedMetaItemKind::MetaItem(ref item) => Some(&item),
             _ => None
         }
     }
@@ -760,19 +784,16 @@ fn find_stability_generic<'a, I>(diagnos
             span_err!(diagnostic, attr.span(), E0548, "incorrect stability attribute type");
             continue
         }
     }
 
     // Merge the deprecation info into the stability info
     if let Some(rustc_depr) = rustc_depr {
         if let Some(ref mut stab) = stab {
-            if let Unstable {reason: ref mut reason @ None, ..} = stab.level {
-                *reason = Some(rustc_depr.reason.clone())
-            }
             stab.rustc_depr = Some(rustc_depr);
         } else {
             span_err!(diagnostic, item_sp, E0549,
                       "rustc_deprecated attribute must be paired with \
                        either stable or unstable attribute");
         }
     }
 
--- a/third_party/rust/syntex_syntax/src/config.rs
+++ b/third_party/rust/syntex_syntax/src/config.rs
@@ -274,17 +274,17 @@ impl<'a> fold::Folder for StripUnconfigu
         let mut expr = configure!(self, expr).unwrap();
         expr.node = self.configure_expr_kind(expr.node);
         Some(P(fold::noop_fold_expr(expr, self)))
     }
 
     fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
         match self.configure_stmt(stmt) {
             Some(stmt) => fold::noop_fold_stmt(stmt, self),
-            None => return SmallVector::zero(),
+            None => return SmallVector::new(),
         }
     }
 
     fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
         fold::noop_fold_item(configure!(self, item), self)
     }
 
     fn fold_impl_item(&mut self, item: ast::ImplItem) -> SmallVector<ast::ImplItem> {
--- a/third_party/rust/syntex_syntax/src/ext/base.rs
+++ b/third_party/rust/syntex_syntax/src/ext/base.rs
@@ -435,33 +435,33 @@ impl MacResult for DummyResult {
         Some(P(DummyResult::raw_pat(self.span)))
     }
 
     fn make_items(self: Box<DummyResult>) -> Option<SmallVector<P<ast::Item>>> {
         // this code needs a comment... why not always just return the Some() ?
         if self.expr_only {
             None
         } else {
-            Some(SmallVector::zero())
+            Some(SmallVector::new())
         }
     }
 
     fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVector<ast::ImplItem>> {
         if self.expr_only {
             None
         } else {
-            Some(SmallVector::zero())
+            Some(SmallVector::new())
         }
     }
 
     fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVector<ast::TraitItem>> {
         if self.expr_only {
             None
         } else {
-            Some(SmallVector::zero())
+            Some(SmallVector::new())
         }
     }
 
     fn make_stmts(self: Box<DummyResult>) -> Option<SmallVector<ast::Stmt>> {
         Some(SmallVector::one(ast::Stmt {
             id: ast::DUMMY_NODE_ID,
             node: ast::StmtKind::Expr(DummyResult::raw_expr(self.span)),
             span: self.span,
@@ -512,22 +512,24 @@ pub enum SyntaxExtension {
     CustomDerive(Box<MultiItemModifier>),
 }
 
 pub type NamedSyntaxExtension = (Name, SyntaxExtension);
 
 pub trait Resolver {
     fn next_node_id(&mut self) -> ast::NodeId;
     fn get_module_scope(&mut self, id: ast::NodeId) -> Mark;
+    fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item>;
 
     fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion);
     fn add_macro(&mut self, scope: Mark, def: ast::MacroDef, export: bool);
     fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>);
     fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>);
 
+    fn resolve_imports(&mut self);
     fn find_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute>;
     // FIXME(syntax): ignore unknown macros
     fn find_extension(&mut self, scope: Mark, name: ast::Name) -> Option<Rc<SyntaxExtension>>;
     // FIXME(syntax): ignore unknown macros
     fn find_mac(&mut self, scope: Mark, mac: &ast::Mac) -> Option<Rc<SyntaxExtension>>;
     fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
                      -> Result<Rc<SyntaxExtension>, Determinacy>;
 }
@@ -538,22 +540,24 @@ pub enum Determinacy {
     Undetermined,
 }
 
 pub struct DummyResolver;
 
 impl Resolver for DummyResolver {
     fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID }
     fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() }
+    fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
 
     fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {}
     fn add_macro(&mut self, _scope: Mark, _def: ast::MacroDef, _export: bool) {}
     fn add_ext(&mut self, _ident: ast::Ident, _ext: Rc<SyntaxExtension>) {}
     fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}
 
+    fn resolve_imports(&mut self) {}
     fn find_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>) -> Option<Attribute> { None }
     fn find_extension(&mut self, _scope: Mark, _name: ast::Name) -> Option<Rc<SyntaxExtension>> {
         None
     }
     fn find_mac(&mut self, _scope: Mark, _mac: &ast::Mac) -> Option<Rc<SyntaxExtension>> { None }
     fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool)
                      -> Result<Rc<SyntaxExtension>, Determinacy> {
         Err(Determinacy::Determined)
@@ -618,17 +622,19 @@ impl<'a> ExtCtxt<'a> {
     /// Returns a `Folder` that deeply expands all macros and assigns all node ids in an AST node.
     /// Once node ids are assigned, the node may not be expanded, removed, or otherwise modified.
     pub fn monotonic_expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
         expand::MacroExpander::new(self, true)
     }
 
     pub fn new_parser_from_tts(&self, tts: &[tokenstream::TokenTree])
         -> parser::Parser<'a> {
-        parse::tts_to_parser(self.parse_sess, tts.to_vec())
+        let mut parser = parse::tts_to_parser(self.parse_sess, tts.to_vec());
+        parser.allow_interpolated_tts = false; // FIXME(jseyfried) `quote!` can't handle these yet
+        parser
     }
     pub fn codemap(&self) -> &'a CodeMap { self.parse_sess.codemap() }
     pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess }
     pub fn cfg(&self) -> &ast::CrateConfig { &self.parse_sess.config }
     pub fn call_site(&self) -> Span {
         self.codemap().with_expn_info(self.backtrace(), |ei| match ei {
             Some(expn_info) => expn_info.call_site,
             None => self.bug("missing top span")
--- a/third_party/rust/syntex_syntax/src/ext/build.rs
+++ b/third_party/rust/syntex_syntax/src/ext/build.rs
@@ -193,27 +193,23 @@ pub trait AstBuilder {
     fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: Vec<ast::Arm> ) -> P<ast::Expr>;
     fn expr_if(&self, span: Span,
                cond: P<ast::Expr>, then: P<ast::Expr>, els: Option<P<ast::Expr>>) -> P<ast::Expr>;
     fn expr_loop(&self, span: Span, block: P<ast::Block>) -> P<ast::Expr>;
 
     fn lambda_fn_decl(&self,
                       span: Span,
                       fn_decl: P<ast::FnDecl>,
-                      blk: P<ast::Block>,
+                      body: P<ast::Expr>,
                       fn_decl_span: Span)
                       -> P<ast::Expr>;
 
-    fn lambda(&self, span: Span, ids: Vec<ast::Ident>, blk: P<ast::Block>) -> P<ast::Expr>;
-    fn lambda0(&self, span: Span, blk: P<ast::Block>) -> P<ast::Expr>;
-    fn lambda1(&self, span: Span, blk: P<ast::Block>, ident: ast::Ident) -> P<ast::Expr>;
-
-    fn lambda_expr(&self, span: Span, ids: Vec<ast::Ident> , blk: P<ast::Expr>) -> P<ast::Expr>;
-    fn lambda_expr_0(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Expr>;
-    fn lambda_expr_1(&self, span: Span, expr: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr>;
+    fn lambda(&self, span: Span, ids: Vec<ast::Ident>, body: P<ast::Expr>) -> P<ast::Expr>;
+    fn lambda0(&self, span: Span, body: P<ast::Expr>) -> P<ast::Expr>;
+    fn lambda1(&self, span: Span, body: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr>;
 
     fn lambda_stmts(&self, span: Span, ids: Vec<ast::Ident>,
                     blk: Vec<ast::Stmt>) -> P<ast::Expr>;
     fn lambda_stmts_0(&self, span: Span, stmts: Vec<ast::Stmt>) -> P<ast::Expr>;
     fn lambda_stmts_1(&self, span: Span, stmts: Vec<ast::Stmt>,
                       ident: ast::Ident) -> P<ast::Expr>;
 
     // items
@@ -935,73 +931,62 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
 
     fn expr_loop(&self, span: Span, block: P<ast::Block>) -> P<ast::Expr> {
         self.expr(span, ast::ExprKind::Loop(block, None))
     }
 
     fn lambda_fn_decl(&self,
                       span: Span,
                       fn_decl: P<ast::FnDecl>,
-                      blk: P<ast::Block>,
+                      body: P<ast::Expr>,
                       fn_decl_span: Span) // span of the `|...|` part
                       -> P<ast::Expr> {
         self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref,
                                                fn_decl,
-                                               blk,
+                                               body,
                                                fn_decl_span))
     }
 
     fn lambda(&self,
               span: Span,
               ids: Vec<ast::Ident>,
-              blk: P<ast::Block>)
+              body: P<ast::Expr>)
               -> P<ast::Expr> {
         let fn_decl = self.fn_decl(
             ids.iter().map(|id| self.arg(span, *id, self.ty_infer(span))).collect(),
             self.ty_infer(span));
 
         // FIXME -- We are using `span` as the span of the `|...|`
         // part of the lambda, but it probably (maybe?) corresponds to
         // the entire lambda body. Probably we should extend the API
         // here, but that's not entirely clear.
-        self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref, fn_decl, blk, span))
-    }
-
-    fn lambda0(&self, span: Span, blk: P<ast::Block>) -> P<ast::Expr> {
-        self.lambda(span, Vec::new(), blk)
+        self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref, fn_decl, body, span))
     }
 
-    fn lambda1(&self, span: Span, blk: P<ast::Block>, ident: ast::Ident) -> P<ast::Expr> {
-        self.lambda(span, vec![ident], blk)
+    fn lambda0(&self, span: Span, body: P<ast::Expr>) -> P<ast::Expr> {
+        self.lambda(span, Vec::new(), body)
     }
 
-    fn lambda_expr(&self, span: Span, ids: Vec<ast::Ident>,
-                   expr: P<ast::Expr>) -> P<ast::Expr> {
-        self.lambda(span, ids, self.block_expr(expr))
-    }
-    fn lambda_expr_0(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Expr> {
-        self.lambda0(span, self.block_expr(expr))
-    }
-    fn lambda_expr_1(&self, span: Span, expr: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr> {
-        self.lambda1(span, self.block_expr(expr), ident)
+    fn lambda1(&self, span: Span, body: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr> {
+        self.lambda(span, vec![ident], body)
     }
 
     fn lambda_stmts(&self,
                     span: Span,
                     ids: Vec<ast::Ident>,
                     stmts: Vec<ast::Stmt>)
                     -> P<ast::Expr> {
-        self.lambda(span, ids, self.block(span, stmts))
+        self.lambda(span, ids, self.expr_block(self.block(span, stmts)))
     }
     fn lambda_stmts_0(&self, span: Span, stmts: Vec<ast::Stmt>) -> P<ast::Expr> {
-        self.lambda0(span, self.block(span, stmts))
+        self.lambda0(span, self.expr_block(self.block(span, stmts)))
     }
     fn lambda_stmts_1(&self, span: Span, stmts: Vec<ast::Stmt>,
                       ident: ast::Ident) -> P<ast::Expr> {
-        self.lambda1(span, self.block(span, stmts), ident)
+        self.lambda1(span, self.expr_block(self.block(span, stmts)), ident)
     }
 
     fn arg(&self, span: Span, ident: ast::Ident, ty: P<ast::Ty>) -> ast::Arg {
         let arg_pat = self.pat_ident(span, ident);
         ast::Arg {
             ty: ty,
             pat: arg_pat,
             id: ast::DUMMY_NODE_ID
--- a/third_party/rust/syntex_syntax/src/ext/expand.rs
+++ b/third_party/rust/syntex_syntax/src/ext/expand.rs
@@ -85,17 +85,17 @@ macro_rules! expansions {
                 }
             }
 
             pub fn visit_with<V: Visitor>(&self, visitor: &mut V) {
                 match *self {
                     Expansion::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
                     Expansion::OptExpr(None) => {}
                     $($( Expansion::$kind(ref ast) => visitor.$visit(ast), )*)*
-                    $($( Expansion::$kind(ref ast) => for ast in ast.as_slice() {
+                    $($( Expansion::$kind(ref ast) => for ast in &ast[..] {
                         visitor.$visit_elt(ast);
                     }, )*)*
                 }
             }
         }
 
         impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
             fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
@@ -221,27 +221,28 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
     }
 
     // Fully expand all the invocations in `expansion`.
     fn expand(&mut self, expansion: Expansion) -> Expansion {
         let orig_expansion_data = self.cx.current_expansion.clone();
         self.cx.current_expansion.depth = 0;
 
         let (expansion, mut invocations) = self.collect_invocations(expansion);
+        self.resolve_imports();
         invocations.reverse();
 
         let mut expansions = Vec::new();
         let mut undetermined_invocations = Vec::new();
         let (mut progress, mut force) = (false, !self.monotonic);
         loop {
             let invoc = if let Some(invoc) = invocations.pop() {
                 invoc
-            } else if undetermined_invocations.is_empty() {
-                break
             } else {
+                self.resolve_imports();
+                if undetermined_invocations.is_empty() { break }
                 invocations = mem::replace(&mut undetermined_invocations, Vec::new());
                 force = !mem::replace(&mut progress, false);
                 continue
             };
 
             let scope =
                 if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark };
             let resolution = match invoc.kind {
@@ -291,16 +292,24 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             for (mark, expansion) in expansions.into_iter().rev() {
                 placeholder_expander.add(ast::NodeId::from_u32(mark), expansion);
             }
         }
 
         expansion.fold_with(&mut placeholder_expander)
     }
 
+    fn resolve_imports(&mut self) {
+        if self.monotonic {
+            let err_count = self.cx.parse_sess.span_diagnostic.err_count();
+            self.cx.resolver.resolve_imports();
+            self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
+        }
+    }
+
     fn collect_invocations(&mut self, expansion: Expansion) -> (Expansion, Vec<Invocation>) {
         let result = {
             let mut collector = InvocationCollector {
                 cfg: StripUnconfigured {
                     should_test: self.cx.ecfg.should_test,
                     sess: self.cx.parse_sess,
                     features: self.cx.ecfg.features,
                 },
@@ -510,39 +519,41 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
     }
 }
 
 impl<'a> Parser<'a> {
     pub fn parse_expansion(&mut self, kind: ExpansionKind, macro_legacy_warnings: bool)
                            -> PResult<'a, Expansion> {
         Ok(match kind {
             ExpansionKind::Items => {
-                let mut items = SmallVector::zero();
+                let mut items = SmallVector::new();
                 while let Some(item) = try!(self.parse_item()) {
                     items.push(item);
                 }
                 Expansion::Items(items)
             }
             ExpansionKind::TraitItems => {
-                let mut items = SmallVector::zero();
+                let mut items = SmallVector::new();
                 while self.token != token::Eof {
                     items.push(try!(self.parse_trait_item()));
                 }
                 Expansion::TraitItems(items)
             }
             ExpansionKind::ImplItems => {
-                let mut items = SmallVector::zero();
+                let mut items = SmallVector::new();
                 while self.token != token::Eof {
                     items.push(try!(self.parse_impl_item()));
                 }
                 Expansion::ImplItems(items)
             }
             ExpansionKind::Stmts => {
-                let mut stmts = SmallVector::zero();
-                while self.token != token::Eof {
+                let mut stmts = SmallVector::new();
+                while self.token != token::Eof &&
+                      // won't make progress on a `}`
+                      self.token != token::CloseDelim(token::Brace) {
                     if let Some(stmt) = try!(self.parse_full_stmt(macro_legacy_warnings)) {
                         stmts.push(stmt);
                     }
                 }
                 Expansion::Stmts(stmts)
             }
             ExpansionKind::Expr => Expansion::Expr(try!(self.parse_expr())),
             ExpansionKind::OptExpr => Expansion::OptExpr(Some(try!(self.parse_expr()))),
@@ -570,17 +581,17 @@ struct InvocationCollector<'a, 'b: 'a> {
     invocations: Vec<Invocation>,
     monotonic: bool,
 }
 
 macro_rules! fully_configure {
     ($this:ident, $node:ident, $noop_fold:ident) => {
         match $noop_fold($node, &mut $this.cfg).pop() {
             Some(node) => node,
-            None => return SmallVector::zero(),
+            None => return SmallVector::new(),
         }
     }
 }
 
 impl<'a, 'b> InvocationCollector<'a, 'b> {
     fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Expansion {
         let mark = Mark::fresh();
         self.invocations.push(Invocation {
@@ -702,17 +713,17 @@ impl<'a, 'b> Folder for InvocationCollec
             }
             _ => unreachable!(),
         })
     }
 
     fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
         let stmt = match self.cfg.configure_stmt(stmt) {
             Some(stmt) => stmt,
-            None => return SmallVector::zero(),
+            None => return SmallVector::new(),
         };
 
         let (mac, style, attrs) = if let StmtKind::Mac(mac) = stmt.node {
             // FIXME(syntex): ignore unknown macros.
             if self.cx.resolver.find_mac(self.cx.current_expansion.mark, &mac.0).is_none() {
                 let stmt = ast::Stmt { node: StmtKind::Mac(mac), .. stmt };
                 return SmallVector::one(stmt);
             }
--- a/third_party/rust/syntex_syntax/src/ext/quote.rs
+++ b/third_party/rust/syntex_syntax/src/ext/quote.rs
@@ -75,114 +75,123 @@ pub mod rt {
     impl ToTokens for ast::Ident {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
             vec![TokenTree::Token(DUMMY_SP, token::Ident(*self))]
         }
     }
 
     impl ToTokens for ast::Path {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(DUMMY_SP,
-                                  token::Interpolated(token::NtPath(Box::new(self.clone()))))]
+            let nt = token::NtPath(self.clone());
+            vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))]
         }
     }
 
     impl ToTokens for ast::Ty {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(self.span, token::Interpolated(token::NtTy(P(self.clone()))))]
+            let nt = token::NtTy(P(self.clone()));
+            vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]
         }
     }
 
     impl ToTokens for ast::Block {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(self.span, token::Interpolated(token::NtBlock(P(self.clone()))))]
+            let nt = token::NtBlock(P(self.clone()));
+            vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]
         }
     }
 
     impl ToTokens for ast::Generics {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtGenerics(self.clone())))]
+            let nt = token::NtGenerics(self.clone());
+            vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))]
         }
     }
 
     impl ToTokens for ast::WhereClause {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(DUMMY_SP,
-                                  token::Interpolated(token::NtWhereClause(self.clone())))]
+            let nt = token::NtWhereClause(self.clone());
+            vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))]
         }
     }
 
     impl ToTokens for P<ast::Item> {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(self.span, token::Interpolated(token::NtItem(self.clone())))]
+            let nt = token::NtItem(self.clone());
+            vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]
         }
     }
 
     impl ToTokens for ast::ImplItem {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(self.span,
-                                  token::Interpolated(token::NtImplItem(P(self.clone()))))]
+            let nt = token::NtImplItem(self.clone());
+            vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]
         }
     }
 
     impl ToTokens for P<ast::ImplItem> {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(self.span, token::Interpolated(token::NtImplItem(self.clone())))]
+            let nt = token::NtImplItem((**self).clone());
+            vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]
         }
     }
 
     impl ToTokens for ast::TraitItem {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(self.span,
-                                  token::Interpolated(token::NtTraitItem(P(self.clone()))))]
+            let nt = token::NtTraitItem(self.clone());
+            vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]
         }
     }
 
     impl ToTokens for ast::Stmt {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            let mut tts = vec![
-                TokenTree::Token(self.span, token::Interpolated(token::NtStmt(P(self.clone()))))
-            ];
+            let nt = token::NtStmt(self.clone());
+            let mut tts = vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))];
 
             // Some statements require a trailing semicolon.
             if classify::stmt_ends_with_semi(&self.node) {
                 tts.push(TokenTree::Token(self.span, token::Semi));
             }
 
             tts
         }
     }
 
     impl ToTokens for P<ast::Expr> {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(self.span, token::Interpolated(token::NtExpr(self.clone())))]
+            let nt = token::NtExpr(self.clone());
+            vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]
         }
     }
 
     impl ToTokens for P<ast::Pat> {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(self.span, token::Interpolated(token::NtPat(self.clone())))]
+            let nt = token::NtPat(self.clone());
+            vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]
         }
     }
 
     impl ToTokens for ast::Arm {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtArm(self.clone())))]
+            let nt = token::NtArm(self.clone());
+            vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))]
         }
     }
 
     impl ToTokens for ast::Arg {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtArg(self.clone())))]
+            let nt = token::NtArg(self.clone());
+            vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))]
         }
     }
 
     impl ToTokens for P<ast::Block> {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtBlock(self.clone())))]
+            let nt = token::NtBlock(self.clone());
+            vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))]
         }
     }
 
     macro_rules! impl_to_tokens_slice {
         ($t: ty, $sep: expr) => {
             impl ToTokens for [$t] {
                 fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
                     let mut v = vec![];
@@ -199,17 +208,18 @@ pub mod rt {
     }
 
     impl_to_tokens_slice! { ast::Ty, [TokenTree::Token(DUMMY_SP, token::Comma)] }
     impl_to_tokens_slice! { P<ast::Item>, [] }
     impl_to_tokens_slice! { ast::Arg, [TokenTree::Token(DUMMY_SP, token::Comma)] }
 
     impl ToTokens for P<ast::MetaItem> {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtMeta(self.clone())))]
+            let nt = token::NtMeta(self.clone());
+            vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))]
         }
     }
 
     impl ToTokens for ast::Attribute {
         fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
             let mut r = vec![];
             // FIXME: The spans could be better
             r.push(TokenTree::Token(self.span, token::Pound));
--- a/third_party/rust/syntex_syntax/src/ext/source_util.rs
+++ b/third_party/rust/syntex_syntax/src/ext/source_util.rs
@@ -99,17 +99,17 @@ pub fn expand_include<'cx>(cx: &'cx mut 
         p: parse::parser::Parser<'a>,
     }
     impl<'a> base::MacResult for ExpandResult<'a> {
         fn make_expr(mut self: Box<ExpandResult<'a>>) -> Option<P<ast::Expr>> {
             Some(panictry!(self.p.parse_expr()))
         }
         fn make_items(mut self: Box<ExpandResult<'a>>)
                       -> Option<SmallVector<P<ast::Item>>> {
-            let mut ret = SmallVector::zero();
+            let mut ret = SmallVector::new();
             while self.p.token != token::Eof {
                 match panictry!(self.p.parse_item()) {
                     Some(item) => ret.push(item),
                     None => panic!(self.p.diagnostic().span_fatal(self.p.span,
                                                            &format!("expected item, found `{}`",
                                                                     self.p.this_token_to_string())))
                 }
             }
--- a/third_party/rust/syntex_syntax/src/ext/tt/macro_parser.rs
+++ b/third_party/rust/syntex_syntax/src/ext/tt/macro_parser.rs
@@ -84,17 +84,16 @@ use codemap::Spanned;
 use errors::FatalError;
 use parse::lexer::*; //resolve bug?
 use parse::ParseSess;
 use parse::parser::{PathStyle, Parser};
 use parse::token::{DocComment, MatchNt, SubstNt};
 use parse::token::{Token, Nonterminal};
 use parse::token;
 use print::pprust;
-use ptr::P;
 use tokenstream::{self, TokenTree};
 use util::small_vector::SmallVector;
 
 use std::mem;
 use std::rc::Rc;
 use std::collections::HashMap;
 use std::collections::hash_map::Entry::{Vacant, Occupied};
 
@@ -126,29 +125,31 @@ impl TokenTreeOrTokenTreeVec {
 /// an unzipping of `TokenTree`s
 #[derive(Clone)]
 struct MatcherTtFrame {
     elts: TokenTreeOrTokenTreeVec,
     idx: usize,
 }
 
 #[derive(Clone)]
-pub struct MatcherPos {
+struct MatcherPos {
     stack: Vec<MatcherTtFrame>,
     top_elts: TokenTreeOrTokenTreeVec,
     sep: Option<Token>,
     idx: usize,
     up: Option<Box<MatcherPos>>,
     matches: Vec<Vec<Rc<NamedMatch>>>,
     match_lo: usize,
     match_cur: usize,
     match_hi: usize,
     sp_lo: BytePos,
 }
 
+pub type NamedParseResult = ParseResult<HashMap<Ident, Rc<NamedMatch>>>;
+
 pub fn count_names(ms: &[TokenTree]) -> usize {
     ms.iter().fold(0, |count, elt| {
         count + match *elt {
             TokenTree::Sequence(_, ref seq) => {
                 seq.num_captures
             }
             TokenTree::Delimited(_, ref delim) => {
                 count_names(&delim.tts)
@@ -156,24 +157,23 @@ pub fn count_names(ms: &[TokenTree]) -> 
             TokenTree::Token(_, MatchNt(..)) => {
                 1
             }
             TokenTree::Token(..) => 0,
         }
     })
 }
 
-pub fn initial_matcher_pos(ms: Vec<TokenTree>, sep: Option<Token>, lo: BytePos)
-                           -> Box<MatcherPos> {
+fn initial_matcher_pos(ms: Vec<TokenTree>, lo: BytePos) -> Box<MatcherPos> {
     let match_idx_hi = count_names(&ms[..]);
-    let matches: Vec<_> = (0..match_idx_hi).map(|_| Vec::new()).collect();
+    let matches = create_matches(match_idx_hi);
     Box::new(MatcherPos {
         stack: vec![],
         top_elts: TtSeq(ms),
-        sep: sep,
+        sep: None,
         idx: 0,
         up: None,
         matches: matches,
         match_lo: 0,
         match_cur: 0,
         match_hi: match_idx_hi,
         sp_lo: lo
     })
@@ -193,59 +193,56 @@ pub fn initial_matcher_pos(ms: Vec<Token
 /// `MatchedNonterminal`s, will depend on the token tree it was applied to:
 /// each MatchedSeq corresponds to a single TTSeq in the originating
 /// token tree. The depth of the NamedMatch structure will therefore depend
 /// only on the nesting depth of `ast::TTSeq`s in the originating
 /// token tree it was derived from.
 
 pub enum NamedMatch {
     MatchedSeq(Vec<Rc<NamedMatch>>, syntax_pos::Span),
-    MatchedNonterminal(Nonterminal)
+    MatchedNonterminal(Rc<Nonterminal>)
 }
 
-pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc<NamedMatch>])
-            -> ParseResult<HashMap<Ident, Rc<NamedMatch>>> {
-    fn n_rec(p_s: &ParseSess, m: &TokenTree, res: &[Rc<NamedMatch>],
-             ret_val: &mut HashMap<Ident, Rc<NamedMatch>>, idx: &mut usize)
+fn nameize<I: Iterator<Item=Rc<NamedMatch>>>(ms: &[TokenTree], mut res: I) -> NamedParseResult {
+    fn n_rec<I: Iterator<Item=Rc<NamedMatch>>>(m: &TokenTree, mut res: &mut I,
+             ret_val: &mut HashMap<Ident, Rc<NamedMatch>>)
              -> Result<(), (syntax_pos::Span, String)> {
         match *m {
             TokenTree::Sequence(_, ref seq) => {
                 for next_m in &seq.tts {
-                    try!(n_rec(p_s, next_m, res, ret_val, idx))
+                    try!(n_rec(next_m, res.by_ref(), ret_val))
                 }
             }
             TokenTree::Delimited(_, ref delim) => {
                 for next_m in &delim.tts {
-                    try!(n_rec(p_s, next_m, res, ret_val, idx));
+                    try!(n_rec(next_m, res.by_ref(), ret_val));
                 }
             }
             TokenTree::Token(sp, MatchNt(bind_name, _)) => {
                 match ret_val.entry(bind_name) {
                     Vacant(spot) => {
-                        spot.insert(res[*idx].clone());
-                        *idx += 1;
+                        spot.insert(res.next().unwrap());
                     }
                     Occupied(..) => {
                         return Err((sp, format!("duplicated bind name: {}", bind_name)))
                     }
                 }
             }
             TokenTree::Token(sp, SubstNt(..)) => {
                 return Err((sp, "missing fragment specifier".to_string()))
             }
             TokenTree::Token(..) => (),
         }
 
         Ok(())
     }
 
     let mut ret_val = HashMap::new();
-    let mut idx = 0;
     for m in ms {
-        match n_rec(p_s, m, res, &mut ret_val, &mut idx) {
+        match n_rec(m, res.by_ref(), &mut ret_val) {
             Ok(_) => {},
             Err((sp, msg)) => return Error(sp, msg),
         }
     }
 
     Success(ret_val)
 }
 
@@ -261,294 +258,289 @@ pub enum ParseResult<T> {
 
 pub fn parse_failure_msg(tok: Token) -> String {
     match tok {
         token::Eof => "unexpected end of macro invocation".to_string(),
         _ => format!("no rules expected the token `{}`", pprust::token_to_string(&tok)),
     }
 }
 
-pub type NamedParseResult = ParseResult<HashMap<Ident, Rc<NamedMatch>>>;
-
-/// Perform a token equality check, ignoring syntax context (that is, an
-/// unhygienic comparison)
-pub fn token_name_eq(t1 : &Token, t2 : &Token) -> bool {
+/// Perform a token equality check, ignoring syntax context (that is, an unhygienic comparison)
+fn token_name_eq(t1 : &Token, t2 : &Token) -> bool {
     match (t1,t2) {
         (&token::Ident(id1),&token::Ident(id2))
         | (&token::Lifetime(id1),&token::Lifetime(id2)) =>
             id1.name == id2.name,
         _ => *t1 == *t2
     }
 }
 
-pub fn parse(sess: &ParseSess, mut rdr: TtReader, ms: &[TokenTree]) -> NamedParseResult {
-    let mut cur_eis = SmallVector::one(initial_matcher_pos(ms.to_owned(),
-                                                           None,
-                                                           rdr.peek().sp.lo));
-
-    loop {
-        let mut bb_eis = Vec::new(); // black-box parsed by parser.rs
-        let mut next_eis = Vec::new(); // or proceed normally
-        let mut eof_eis = Vec::new();
-
-        let TokenAndSpan { tok, sp } = rdr.peek();
+fn create_matches(len: usize) -> Vec<Vec<Rc<NamedMatch>>> {
+    (0..len).into_iter().map(|_| Vec::new()).collect()
+}
 
-        /* we append new items to this while we go */
-        loop {
-            let mut ei = match cur_eis.pop() {
-                None => break, /* for each Earley Item */
-                Some(ei) => ei,
-            };
+fn inner_parse_loop(cur_eis: &mut SmallVector<Box<MatcherPos>>,
+                    next_eis: &mut Vec<Box<MatcherPos>>,
+                    eof_eis: &mut SmallVector<Box<MatcherPos>>,
+                    bb_eis: &mut SmallVector<Box<MatcherPos>>,
+                    token: &Token, span: &syntax_pos::Span) -> ParseResult<()> {
+    while let Some(mut ei) = cur_eis.pop() {
+        // When unzipped trees end, remove them
+        while ei.idx >= ei.top_elts.len() {
+            match ei.stack.pop() {
+                Some(MatcherTtFrame { elts, idx }) => {
+                    ei.top_elts = elts;
+                    ei.idx = idx + 1;
+                }
+                None => break
+            }
+        }
 
-            // When unzipped trees end, remove them
-            while ei.idx >= ei.top_elts.len() {
-                match ei.stack.pop() {
-                    Some(MatcherTtFrame { elts, idx }) => {
-                        ei.top_elts = elts;
-                        ei.idx = idx + 1;
-                    }
-                    None => break
-                }
-            }
-
-            let idx = ei.idx;
-            let len = ei.top_elts.len();
+        let idx = ei.idx;
+        let len = ei.top_elts.len();
 
-            /* at end of sequence */
-            if idx >= len {
-                // can't move out of `match`es, so:
-                if ei.up.is_some() {
-                    // hack: a matcher sequence is repeating iff it has a
-                    // parent (the top level is just a container)
-
-
-                    // disregard separator, try to go up
-                    // (remove this condition to make trailing seps ok)
-                    if idx == len {
-                        // pop from the matcher position
-
-                        let mut new_pos = ei.up.clone().unwrap();
+        // at end of sequence
+        if idx >= len {
+            // We are repeating iff there is a parent
+            if ei.up.is_some() {
+                // Disregarding the separator, add the "up" case to the tokens that should be
+                // examined.
+                // (remove this condition to make trailing seps ok)
+                if idx == len {
+                    let mut new_pos = ei.up.clone().unwrap();
 
-                        // update matches (the MBE "parse tree") by appending
-                        // each tree as a subtree.
+                    // update matches (the MBE "parse tree") by appending
+                    // each tree as a subtree.
 
-                        // I bet this is a perf problem: we're preemptively
-                        // doing a lot of array work that will get thrown away
-                        // most of the time.
+                    // I bet this is a perf problem: we're preemptively
+                    // doing a lot of array work that will get thrown away
+                    // most of the time.
 
-                        // Only touch the binders we have actually bound
-                        for idx in ei.match_lo..ei.match_hi {
-                            let sub = (ei.matches[idx]).clone();
-                            (&mut new_pos.matches[idx])
-                                   .push(Rc::new(MatchedSeq(sub, mk_sp(ei.sp_lo,
-                                                                       sp.hi))));
-                        }
-
-                        new_pos.match_cur = ei.match_hi;
-                        new_pos.idx += 1;
-                        cur_eis.push(new_pos);
+                    // Only touch the binders we have actually bound
+                    for idx in ei.match_lo..ei.match_hi {
+                        let sub = ei.matches[idx].clone();
+                        new_pos.matches[idx]
+                            .push(Rc::new(MatchedSeq(sub, mk_sp(ei.sp_lo,
+                                                                span.hi))));
                     }
 
-                    // can we go around again?
+                    new_pos.match_cur = ei.match_hi;
+                    new_pos.idx += 1;
+                    cur_eis.push(new_pos);
+                }
 
-                    // the *_t vars are workarounds for the lack of unary move
-                    match ei.sep {
-                        Some(ref t) if idx == len => { // we need a separator
-                            // i'm conflicted about whether this should be hygienic....
-                            // though in this case, if the separators are never legal
-                            // idents, it shouldn't matter.
-                            if token_name_eq(&tok, t) { //pass the separator
-                                let mut ei_t = ei.clone();
-                                // ei_t.match_cur = ei_t.match_lo;
-                                ei_t.idx += 1;
-                                next_eis.push(ei_t);
-                            }
-                        }
-                        _ => { // we don't need a separator
-                            let mut ei_t = ei;
-                            ei_t.match_cur = ei_t.match_lo;
-                            ei_t.idx = 0;
-                            cur_eis.push(ei_t);
-                        }
+                // Check if we need a separator
+                if idx == len && ei.sep.is_some() {
+                    // We have a separator, and it is the current token.
+                    if ei.sep.as_ref().map(|ref sep| token_name_eq(&token, sep)).unwrap_or(false) {
+                        ei.idx += 1;
+                        next_eis.push(ei);
                     }
-                } else {
-                    eof_eis.push(ei);
+                } else { // we don't need a separator
+                    ei.match_cur = ei.match_lo;
+                    ei.idx = 0;
+                    cur_eis.push(ei);
                 }
             } else {
-                match ei.top_elts.get_tt(idx) {
-                    /* need to descend into sequence */
-                    TokenTree::Sequence(sp, seq) => {
-                        if seq.op == tokenstream::KleeneOp::ZeroOrMore {
-                            let mut new_ei = ei.clone();
-                            new_ei.match_cur += seq.num_captures;
-                            new_ei.idx += 1;
-                            //we specifically matched zero repeats.
-                            for idx in ei.match_cur..ei.match_cur + seq.num_captures {
-                                (&mut new_ei.matches[idx]).push(Rc::new(MatchedSeq(vec![], sp)));
-                            }
-
-                            cur_eis.push(new_ei);
+                // We aren't repeating, so we must be potentially at the end of the input.
+                eof_eis.push(ei);
+            }
+        } else {
+            match ei.top_elts.get_tt(idx) {
+                /* need to descend into sequence */
+                TokenTree::Sequence(sp, seq) => {
+                    if seq.op == tokenstream::KleeneOp::ZeroOrMore {
+                        // Examine the case where there are 0 matches of this sequence
+                        let mut new_ei = ei.clone();
+                        new_ei.match_cur += seq.num_captures;
+                        new_ei.idx += 1;
+                        for idx in ei.match_cur..ei.match_cur + seq.num_captures {
+                            new_ei.matches[idx].push(Rc::new(MatchedSeq(vec![], sp)));
                         }
+                        cur_eis.push(new_ei);
+                    }
 
-                        let matches: Vec<_> = (0..ei.matches.len())
-                            .map(|_| Vec::new()).collect();
-                        let ei_t = ei;
-                        cur_eis.push(Box::new(MatcherPos {
-                            stack: vec![],
-                            sep: seq.separator.clone(),
-                            idx: 0,
-                            matches: matches,
-                            match_lo: ei_t.match_cur,
-                            match_cur: ei_t.match_cur,
-                            match_hi: ei_t.match_cur + seq.num_captures,
-                            up: Some(ei_t),
-                            sp_lo: sp.lo,
-                            top_elts: Tt(TokenTree::Sequence(sp, seq)),
-                        }));
+                    // Examine the case where there is at least one match of this sequence
+                    let matches = create_matches(ei.matches.len());
+                    cur_eis.push(Box::new(MatcherPos {
+                        stack: vec![],
+                        sep: seq.separator.clone(),
+                        idx: 0,
+                        matches: matches,
+                        match_lo: ei.match_cur,
+                        match_cur: ei.match_cur,
+                        match_hi: ei.match_cur + seq.num_captures,
+                        up: Some(ei),
+                        sp_lo: sp.lo,
+                        top_elts: Tt(TokenTree::Sequence(sp, seq)),
+                    }));
+                }
+                TokenTree::Token(_, MatchNt(..)) => {
+                    // Built-in nonterminals never start with these tokens,
+                    // so we can eliminate them from consideration.
+                    match *token {
+                        token::CloseDelim(_) => {},
+                        _ => bb_eis.push(ei),
                     }
-                    TokenTree::Token(_, MatchNt(..)) => {
-                        // Built-in nonterminals never start with these tokens,
-                        // so we can eliminate them from consideration.
-                        match tok {
-                            token::CloseDelim(_) => {},
-                            _ => bb_eis.push(ei),
-                        }
-                    }
-                    TokenTree::Token(sp, SubstNt(..)) => {
-                        return Error(sp, "missing fragment specifier".to_string())
-                    }
-                    seq @ TokenTree::Delimited(..) | seq @ TokenTree::Token(_, DocComment(..)) => {
-                        let lower_elts = mem::replace(&mut ei.top_elts, Tt(seq));
-                        let idx = ei.idx;
-                        ei.stack.push(MatcherTtFrame {
-                            elts: lower_elts,
-                            idx: idx,
-                        });
-                        ei.idx = 0;
-                        cur_eis.push(ei);
-                    }
-                    TokenTree::Token(_, ref t) => {
-                        if token_name_eq(t,&tok) {
-                            let mut ei_t = ei.clone();
-                            ei_t.idx += 1;
-                            next_eis.push(ei_t);
-                        }
+                }
+                TokenTree::Token(sp, SubstNt(..)) => {
+                    return Error(sp, "missing fragment specifier".to_string())
+                }
+                seq @ TokenTree::Delimited(..) | seq @ TokenTree::Token(_, DocComment(..)) => {
+                    let lower_elts = mem::replace(&mut ei.top_elts, Tt(seq));
+                    let idx = ei.idx;
+                    ei.stack.push(MatcherTtFrame {
+                        elts: lower_elts,