about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-05-30 08:13:08 -0700
committerbors <bors@rust-lang.org>2016-05-30 08:13:08 -0700
commitf3bfa313ecf557b9684568f6a2acd42cd67cc1bc (patch)
tree4d000fa349659239a36d57c9215b400e5cdc9ef4
parent5da602bda3f30a8943dd4d10383bae6d8a77575c (diff)
parent26c209897f4ae230828898551725cceced59e329 (diff)
downloadrust-f3bfa313ecf557b9684568f6a2acd42cd67cc1bc.tar.gz
rust-f3bfa313ecf557b9684568f6a2acd42cd67cc1bc.zip
Auto merge of #33965 - Manishearth:rollup, r=Manishearth
Rollup of 5 pull requests

- Successful merges: #33867, #33926, #33942, #33958, #33964
- Failed merges:
-rw-r--r--src/etc/htmldocck.py1
-rw-r--r--src/librustc_driver/driver.rs10
-rw-r--r--src/librustc_driver/test.rs5
-rw-r--r--src/librustc_llvm/archive_ro.rs29
-rw-r--r--src/librustc_llvm/build.rs61
-rw-r--r--src/librustc_llvm/diagnostic.rs49
-rw-r--r--src/librustdoc/html/format.rs16
-rw-r--r--src/librustdoc/html/render.rs69
-rw-r--r--src/librustdoc/html/static/rustdoc.css19
-rw-r--r--src/libstd/fs.rs4
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs24
-rw-r--r--src/libsyntax_ext/deriving/mod.rs60
-rw-r--r--src/test/compile-fail/issue-33571.rs14
13 files changed, 196 insertions, 165 deletions
diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py
index a930a0d0833..a5449b748dd 100644
--- a/src/etc/htmldocck.py
+++ b/src/etc/htmldocck.py
@@ -117,6 +117,7 @@ from xml.etree import cElementTree as ET
 from htmlentitydefs import entitydefs
 entitydefs['larrb'] = u'\u21e4'
 entitydefs['rarrb'] = u'\u21e5'
+entitydefs['nbsp'] = ' '
 
 # "void elements" (no closing tag) from the HTML Standard section 12.1.2
 VOID_ELEMENTS = set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen',
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index a8ddc7e7bda..d6d944fde5f 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -63,7 +63,7 @@ use syntax_ext;
 
 #[derive(Clone)]
 pub struct Resolutions {
-    pub def_map: RefCell<DefMap>,
+    pub def_map: DefMap,
     pub freevars: FreevarMap,
     pub trait_map: TraitMap,
     pub maybe_unused_trait_imports: NodeSet,
@@ -818,7 +818,7 @@ pub fn lower_and_resolve<'a>(sess: &Session,
             name: &id,
             glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None },
         }, Resolutions {
-            def_map: RefCell::new(resolver.def_map),
+            def_map: resolver.def_map,
             freevars: resolver.freevars,
             trait_map: resolver.trait_map,
             maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
@@ -866,7 +866,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                                 "lifetime resolution",
                                 || middle::resolve_lifetime::krate(sess,
                                                                    &hir_map,
-                                                                   &resolutions.def_map.borrow()))?;
+                                                                   &resolutions.def_map))?;
 
     time(time_passes,
          "looking for entry point",
@@ -886,14 +886,14 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
     time(time_passes,
               "static item recursion checking",
-              || static_recursion::check_crate(sess, &resolutions.def_map.borrow(), &hir_map))?;
+              || static_recursion::check_crate(sess, &resolutions.def_map, &hir_map))?;
 
     let index = stability::Index::new(&hir_map);
 
     let trait_map = resolutions.trait_map;
     TyCtxt::create_and_enter(sess,
                              arenas,
-                             resolutions.def_map,
+                             RefCell::new(resolutions.def_map),
                              named_region_map,
                              hir_map,
                              resolutions.freevars,
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index e0d693c4230..b1df80403c0 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -29,6 +29,7 @@ use rustc_metadata::cstore::CStore;
 use rustc_metadata::creader::read_local_crates;
 use rustc::hir::map as hir_map;
 use rustc::session::{self, config};
+use std::cell::RefCell;
 use std::rc::Rc;
 use syntax::ast;
 use syntax::abi::Abi;
@@ -134,12 +135,12 @@ fn test_env<F>(source_string: &str,
 
     // run just enough stuff to build a tcx:
     let lang_items = lang_items::collect_language_items(&sess, &ast_map);
-    let named_region_map = resolve_lifetime::krate(&sess, &ast_map, &resolutions.def_map.borrow());
+    let named_region_map = resolve_lifetime::krate(&sess, &ast_map, &resolutions.def_map);
     let region_map = region::resolve_crate(&sess, &ast_map);
     let index = stability::Index::new(&ast_map);
     TyCtxt::create_and_enter(&sess,
                              &arenas,
-                             resolutions.def_map,
+                             RefCell::new(resolutions.def_map),
                              named_region_map.unwrap(),
                              ast_map,
                              resolutions.freevars,
diff --git a/src/librustc_llvm/archive_ro.rs b/src/librustc_llvm/archive_ro.rs
index be7f0ed6a02..b3f5f8e5360 100644
--- a/src/librustc_llvm/archive_ro.rs
+++ b/src/librustc_llvm/archive_ro.rs
@@ -18,7 +18,9 @@ use std::path::Path;
 use std::slice;
 use std::str;
 
-pub struct ArchiveRO { ptr: ArchiveRef }
+pub struct ArchiveRO {
+    ptr: ArchiveRef,
+}
 
 pub struct Iter<'a> {
     archive: &'a ArchiveRO,
@@ -61,11 +63,16 @@ impl ArchiveRO {
         }
     }
 
-    pub fn raw(&self) -> ArchiveRef { self.ptr }
+    pub fn raw(&self) -> ArchiveRef {
+        self.ptr
+    }
 
     pub fn iter(&self) -> Iter {
         unsafe {
-            Iter { ptr: ::LLVMRustArchiveIteratorNew(self.ptr), archive: self }
+            Iter {
+                ptr: ::LLVMRustArchiveIteratorNew(self.ptr),
+                archive: self,
+            }
         }
     }
 }
@@ -86,7 +93,10 @@ impl<'a> Iterator for Iter<'a> {
         if ptr.is_null() {
             ::last_error().map(Err)
         } else {
-            Some(Ok(Child { ptr: ptr, _data: marker::PhantomData }))
+            Some(Ok(Child {
+                ptr: ptr,
+                _data: marker::PhantomData,
+            }))
         }
     }
 }
@@ -107,8 +117,7 @@ impl<'a> Child<'a> {
             if name_ptr.is_null() {
                 None
             } else {
-                let name = slice::from_raw_parts(name_ptr as *const u8,
-                                                 name_len as usize);
+                let name = slice::from_raw_parts(name_ptr as *const u8, name_len as usize);
                 str::from_utf8(name).ok().map(|s| s.trim())
             }
         }
@@ -125,11 +134,15 @@ impl<'a> Child<'a> {
         }
     }
 
-    pub fn raw(&self) -> ::ArchiveChildRef { self.ptr }
+    pub fn raw(&self) -> ::ArchiveChildRef {
+        self.ptr
+    }
 }
 
 impl<'a> Drop for Child<'a> {
     fn drop(&mut self) {
-        unsafe { ::LLVMRustArchiveChildFree(self.ptr); }
+        unsafe {
+            ::LLVMRustArchiveChildFree(self.ptr);
+        }
     }
 }
diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
index 0c6db2cb8ba..250aafd77a8 100644
--- a/src/librustc_llvm/build.rs
+++ b/src/librustc_llvm/build.rs
@@ -21,20 +21,25 @@ fn main() {
     println!("cargo:rustc-cfg=cargobuild");
 
     let target = env::var("TARGET").unwrap();
-    let llvm_config = env::var_os("LLVM_CONFIG").map(PathBuf::from)
-                           .unwrap_or_else(|| {
-        match env::var_os("CARGO_TARGET_DIR").map(PathBuf::from) {
-            Some(dir) => {
-                let to_test = dir.parent().unwrap().parent().unwrap()
-                                 .join(&target).join("llvm/bin/llvm-config");
-                if Command::new(&to_test).output().is_ok() {
-                    return to_test
-                }
-            }
-            None => {}
-        }
-        PathBuf::from("llvm-config")
-    });
+    let llvm_config = env::var_os("LLVM_CONFIG")
+                          .map(PathBuf::from)
+                          .unwrap_or_else(|| {
+                              match env::var_os("CARGO_TARGET_DIR").map(PathBuf::from) {
+                                  Some(dir) => {
+                                      let to_test = dir.parent()
+                                                       .unwrap()
+                                                       .parent()
+                                                       .unwrap()
+                                                       .join(&target)
+                                                       .join("llvm/bin/llvm-config");
+                                      if Command::new(&to_test).output().is_ok() {
+                                          return to_test;
+                                      }
+                                  }
+                                  None => {}
+                              }
+                              PathBuf::from("llvm-config")
+                          });
 
     println!("cargo:rerun-if-changed={}", llvm_config.display());
 
@@ -63,20 +68,22 @@ fn main() {
     let host = env::var("HOST").unwrap();
     let is_crossed = target != host;
 
-    let optional_components = ["x86", "arm", "aarch64", "mips", "powerpc",
-                               "pnacl"];
+    let optional_components = ["x86", "arm", "aarch64", "mips", "powerpc", "pnacl"];
 
     // FIXME: surely we don't need all these components, right? Stuff like mcjit
     //        or interpreter the compiler itself never uses.
-    let required_components = &["ipo", "bitreader", "bitwriter", "linker",
-                                "asmparser", "mcjit", "interpreter",
+    let required_components = &["ipo",
+                                "bitreader",
+                                "bitwriter",
+                                "linker",
+                                "asmparser",
+                                "mcjit",
+                                "interpreter",
                                 "instrumentation"];
 
     let components = output(Command::new(&llvm_config).arg("--components"));
     let mut components = components.split_whitespace().collect::<Vec<_>>();
-    components.retain(|c| {
-        optional_components.contains(c) || required_components.contains(c)
-    });
+    components.retain(|c| optional_components.contains(c) || required_components.contains(c));
 
     for component in required_components {
         if !components.contains(component) {
@@ -96,7 +103,7 @@ fn main() {
     for flag in cxxflags.split_whitespace() {
         // Ignore flags like `-m64` when we're doing a cross build
         if is_crossed && flag.starts_with("-m") {
-            continue
+            continue;
         }
         cfg.flag(flag);
     }
@@ -131,7 +138,7 @@ fn main() {
         } else if lib.starts_with("-") {
             &lib[1..]
         } else {
-            continue
+            continue;
         };
 
         // Don't need or want this library, but LLVM's CMake build system
@@ -140,10 +147,14 @@ fn main() {
         // library and it otherwise may just pull in extra dependencies on
         // libedit which we don't want
         if name == "LLVMLineEditor" {
-            continue
+            continue;
         }
 
-        let kind = if name.starts_with("LLVM") {"static"} else {"dylib"};
+        let kind = if name.starts_with("LLVM") {
+            "static"
+        } else {
+            "dylib"
+        };
         println!("cargo:rustc-link-lib={}={}", kind, name);
     }
 
diff --git a/src/librustc_llvm/diagnostic.rs b/src/librustc_llvm/diagnostic.rs
index acb47516150..44e01561464 100644
--- a/src/librustc_llvm/diagnostic.rs
+++ b/src/librustc_llvm/diagnostic.rs
@@ -16,7 +16,7 @@ pub use self::Diagnostic::*;
 use libc::{c_char, c_uint};
 use std::ptr;
 
-use {ValueRef, TwineRef, DebugLocRef, DiagnosticInfoRef};
+use {DebugLocRef, DiagnosticInfoRef, TwineRef, ValueRef};
 
 #[derive(Copy, Clone)]
 pub enum OptimizationDiagnosticKind {
@@ -46,8 +46,9 @@ pub struct OptimizationDiagnostic {
 }
 
 impl OptimizationDiagnostic {
-    unsafe fn unpack(kind: OptimizationDiagnosticKind, di: DiagnosticInfoRef)
-            -> OptimizationDiagnostic {
+    unsafe fn unpack(kind: OptimizationDiagnosticKind,
+                     di: DiagnosticInfoRef)
+                     -> OptimizationDiagnostic {
 
         let mut opt = OptimizationDiagnostic {
             kind: kind,
@@ -58,10 +59,10 @@ impl OptimizationDiagnostic {
         };
 
         super::LLVMUnpackOptimizationDiagnostic(di,
-            &mut opt.pass_name,
-            &mut opt.function,
-            &mut opt.debug_loc,
-            &mut opt.message);
+                                                &mut opt.pass_name,
+                                                &mut opt.function,
+                                                &mut opt.debug_loc,
+                                                &mut opt.message);
 
         opt
     }
@@ -75,8 +76,7 @@ pub struct InlineAsmDiagnostic {
 }
 
 impl InlineAsmDiagnostic {
-    unsafe fn unpack(di: DiagnosticInfoRef)
-            -> InlineAsmDiagnostic {
+    unsafe fn unpack(di: DiagnosticInfoRef) -> InlineAsmDiagnostic {
 
         let mut opt = InlineAsmDiagnostic {
             cookie: 0,
@@ -85,9 +85,9 @@ impl InlineAsmDiagnostic {
         };
 
         super::LLVMUnpackInlineAsmDiagnostic(di,
-            &mut opt.cookie,
-            &mut opt.message,
-            &mut opt.instruction);
+                                             &mut opt.cookie,
+                                             &mut opt.message,
+                                             &mut opt.instruction);
 
         opt
     }
@@ -106,22 +106,25 @@ impl Diagnostic {
         let kind = super::LLVMGetDiagInfoKind(di);
 
         match kind {
-            super::DK_InlineAsm
-                => InlineAsm(InlineAsmDiagnostic::unpack(di)),
+            super::DK_InlineAsm => InlineAsm(InlineAsmDiagnostic::unpack(di)),
 
-            super::DK_OptimizationRemark
-                => Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di)),
+            super::DK_OptimizationRemark => {
+                Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di))
+            }
 
-            super::DK_OptimizationRemarkMissed
-                => Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di)),
+            super::DK_OptimizationRemarkMissed => {
+                Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di))
+            }
 
-            super::DK_OptimizationRemarkAnalysis
-                => Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di)),
+            super::DK_OptimizationRemarkAnalysis => {
+                Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di))
+            }
 
-            super::DK_OptimizationFailure
-                => Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di)),
+            super::DK_OptimizationFailure => {
+                Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di))
+            }
 
-            _ => UnknownDiagnostic(di)
+            _ => UnknownDiagnostic(di),
         }
     }
 }
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index d4fdafea88a..92401a5c55f 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -111,27 +111,27 @@ impl fmt::Display for clean::Generics {
 
         for (i, life) in self.lifetimes.iter().enumerate() {
             if i > 0 {
-                f.write_str(", ")?;
+                f.write_str(",&nbsp;")?;
             }
             write!(f, "{}", *life)?;
         }
 
         if !self.type_params.is_empty() {
             if !self.lifetimes.is_empty() {
-                f.write_str(", ")?;
+                f.write_str(",&nbsp;")?;
             }
             for (i, tp) in self.type_params.iter().enumerate() {
                 if i > 0 {
-                    f.write_str(", ")?
+                    f.write_str(",&nbsp;")?
                 }
                 f.write_str(&tp.name)?;
 
                 if !tp.bounds.is_empty() {
-                    write!(f, ": {}", TyParamBounds(&tp.bounds))?;
+                    write!(f, ":&nbsp;{}", TyParamBounds(&tp.bounds))?;
                 }
 
                 match tp.default {
-                    Some(ref ty) => { write!(f, " = {}", ty)?; },
+                    Some(ref ty) => { write!(f, "&nbsp;=&nbsp;{}", ty)?; },
                     None => {}
                 };
             }
@@ -229,21 +229,21 @@ impl fmt::Display for clean::PathParameters {
                     let mut comma = false;
                     for lifetime in lifetimes {
                         if comma {
-                            f.write_str(", ")?;
+                            f.write_str(",&nbsp;")?;
                         }
                         comma = true;
                         write!(f, "{}", *lifetime)?;
                     }
                     for ty in types {
                         if comma {
-                            f.write_str(", ")?;
+                            f.write_str(",&nbsp;")?;
                         }
                         comma = true;
                         write!(f, "{}", *ty)?;
                     }
                     for binding in bindings {
                         if comma {
-                            f.write_str(", ")?;
+                            f.write_str(",&nbsp;")?;
                         }
                         comma = true;
                         write!(f, "{}", *binding)?;
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 7357ff3abac..396f71173f8 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -2243,26 +2243,24 @@ fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
     write!(w, "</pre>")?;
 
     document(w, cx, it)?;
-    let mut fields = s.fields.iter().filter(|f| {
+    let mut fields = s.fields.iter().filter_map(|f| {
         match f.inner {
-            clean::StructFieldItem(..) => true,
-            _ => false,
+            clean::StructFieldItem(ref ty) => Some((f, ty)),
+            _ => None,
         }
     }).peekable();
     if let doctree::Plain = s.struct_type {
         if fields.peek().is_some() {
-            write!(w, "<h2 class='fields'>Fields</h2>\n<table>")?;
-            for field in fields {
-                write!(w, "<tr class='stab {stab}'>
-                             <td id='{shortty}.{name}'>\
-                               <code>{name}</code></td><td>",
+            write!(w, "<h2 class='fields'>Fields</h2>")?;
+            for (field, ty) in fields {
+                write!(w, "<span id='{shortty}.{name}'><code>{name}: {ty}</code></span>
+                           <span class='stab {stab}'></span>",
                        shortty = ItemType::StructField,
                        stab = field.stability_class(),
-                       name = field.name.as_ref().unwrap())?;
+                       name = field.name.as_ref().unwrap(),
+                       ty = ty)?;
                 document(w, cx, field)?;
-                write!(w, "</td></tr>")?;
             }
-            write!(w, "</table>")?;
         }
     }
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
@@ -2292,7 +2290,7 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                             write!(w, "{}(", name)?;
                             for (i, ty) in tys.iter().enumerate() {
                                 if i > 0 {
-                                    write!(w, ", ")?
+                                    write!(w, ",&nbsp;")?
                                 }
                                 write!(w, "{}", *ty)?;
                             }
@@ -2324,40 +2322,47 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
 
     document(w, cx, it)?;
     if !e.variants.is_empty() {
-        write!(w, "<h2 class='variants'>Variants</h2>\n<table class='variants_table'>")?;
+        write!(w, "<h2 class='variants'>Variants</h2>\n")?;
         for variant in &e.variants {
-            write!(w, "<tr><td id='{shortty}.{name}'><code>{name}</code></td><td>",
+            write!(w, "<span id='{shortty}.{name}' class='variant'><code>{name}",
                    shortty = ItemType::Variant,
                    name = variant.name.as_ref().unwrap())?;
+            if let clean::VariantItem(ref var) = variant.inner {
+                if let clean::TupleVariant(ref tys) = var.kind {
+                    write!(w, "(")?;
+                    for (i, ty) in tys.iter().enumerate() {
+                        if i > 0 {
+                            write!(w, ",&nbsp;")?;
+                        }
+                        write!(w, "{}", *ty)?;
+                    }
+                    write!(w, ")")?;
+                }
+            }
+            write!(w, "</code></span>")?;
             document(w, cx, variant)?;
 
             use clean::{Variant, StructVariant};
             if let clean::VariantItem( Variant { kind: StructVariant(ref s) } ) = variant.inner {
-                let fields = s.fields.iter().filter(|f| {
-                    match f.inner {
-                        clean::StructFieldItem(..) => true,
-                        _ => false,
-                    }
-                });
                 write!(w, "<h3 class='fields'>Fields</h3>\n
                            <table>")?;
-                for field in fields {
-                    write!(w, "<tr><td \
-                               id='{shortty}.{v}.field.{f}'>\
-                               <code>{f}</code></td><td>",
-                           shortty = ItemType::Variant,
-                           v = variant.name.as_ref().unwrap(),
-                           f = field.name.as_ref().unwrap())?;
-                    document(w, cx, field)?;
-                    write!(w, "</td></tr>")?;
+                for field in &s.fields {
+                    use clean::StructFieldItem;
+                    if let StructFieldItem(ref ty) = field.inner {
+                        write!(w, "<tr><td \
+                                   id='variant.{v}.field.{f}'>\
+                                   <code>{f}:&nbsp;{t}</code></td><td>",
+                               v = variant.name.as_ref().unwrap(),
+                               f = field.name.as_ref().unwrap(),
+                               t = *ty)?;
+                        document(w, cx, field)?;
+                        write!(w, "</td></tr>")?;
+                    }
                 }
                 write!(w, "</table>")?;
             }
-            write!(w, "</td><td>")?;
             render_stability_since(w, variant, it)?;
-            write!(w, "</td></tr>")?;
         }
-        write!(w, "</table>")?;
     }
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)?;
     Ok(())
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 8e4245d4ebf..bfe3f7b8dd6 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -265,6 +265,10 @@ nav.sub {
 .docblock h2 { font-size: 1.15em; }
 .docblock h3, .docblock h4, .docblock h5 { font-size: 1em; }
 
+.docblock {
+    margin-left: 24px;
+}
+
 .content .out-of-band {
     font-size: 23px;
     margin: 0px;
@@ -640,6 +644,21 @@ span.since {
     margin-right: 5px;
 }
 
+.enum > .toggle-wrapper > .collapse-toggle, .struct > .toggle-wrapper > .collapse-toggle {
+    left: 0;
+    margin-top: 5px;
+}
+
+.enum > .toggle-wrapper + .docblock, .struct > .toggle-wrapper + .docblock {
+    margin-left: 30px;
+    margin-bottom: 20px;
+    margin-top: 5px;
+}
+
+.enum > .collapsed, .struct > .collapsed {
+    margin-bottom: 25px;
+}
+
 :target > code {
    background: #FDFFD3;
 }
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 125170bd47b..734f774043d 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -1338,10 +1338,10 @@ pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
 ///
 /// // one possible implementation of walking a directory only visiting files
 /// fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> io::Result<()> {
-///     if try!(fs::metadata(dir)).is_dir() {
+///     if dir.is_dir() {
 ///         for entry in try!(fs::read_dir(dir)) {
 ///             let entry = try!(entry);
-///             if try!(fs::metadata(entry.path())).is_dir() {
+///             if try!(entry.file_type()).is_dir() {
 ///                 try!(visit_dirs(&entry.path(), cb));
 ///             } else {
 ///                 cb(&entry);
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 9095230df63..d6adec84e84 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -201,7 +201,7 @@ use syntax::codemap::{self, respan, DUMMY_SP};
 use syntax::codemap::Span;
 use syntax::errors::Handler;
 use syntax::util::move_map::MoveMap;
-use syntax::parse::token::{intern, keywords, InternedString};
+use syntax::parse::token::{keywords, InternedString};
 use syntax::ptr::P;
 
 use self::ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty};
@@ -1420,31 +1420,13 @@ impl<'a> MethodDef<'a> {
 
 // general helper methods.
 impl<'a> TraitDef<'a> {
-    fn set_expn_info(&self,
-                     cx: &mut ExtCtxt,
-                     mut to_set: Span) -> Span {
-        let trait_name = match self.path.path.last() {
-            None => cx.span_bug(self.span, "trait with empty path in generic `derive`"),
-            Some(name) => *name
-        };
-        to_set.expn_id = cx.codemap().record_expansion(codemap::ExpnInfo {
-            call_site: to_set,
-            callee: codemap::NameAndSpan {
-                format: codemap::MacroAttribute(intern(&format!("derive({})", trait_name))),
-                span: Some(self.span),
-                allow_internal_unstable: false,
-            }
-        });
-        to_set
-    }
-
     fn summarise_struct(&self,
                         cx: &mut ExtCtxt,
                         struct_def: &VariantData) -> StaticFields {
         let mut named_idents = Vec::new();
         let mut just_spans = Vec::new();
         for field in struct_def.fields(){
-            let sp = self.set_expn_info(cx, field.span);
+            let sp = Span { expn_id: self.span.expn_id, ..field.span };
             match field.ident {
                 Some(ident) => named_idents.push((ident, sp)),
                 _ => just_spans.push(sp),
@@ -1486,7 +1468,7 @@ impl<'a> TraitDef<'a> {
         let mut paths = Vec::new();
         let mut ident_exprs = Vec::new();
         for (i, struct_field) in struct_def.fields().iter().enumerate() {
-            let sp = self.set_expn_info(cx, struct_field.span);
+            let sp = Span { expn_id: self.span.expn_id, ..struct_field.span };
             let ident = cx.ident_of(&format!("{}_{}", prefix, i));
             paths.push(codemap::Spanned{span: sp, node: ident});
             let val = cx.expr_deref(sp, cx.expr_path(cx.path_ident(sp,ident)));
diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs
index 91c272c59c4..6fb6dee94ed 100644
--- a/src/libsyntax_ext/deriving/mod.rs
+++ b/src/libsyntax_ext/deriving/mod.rs
@@ -16,7 +16,7 @@ use syntax::ext::base::{ExtCtxt, SyntaxEnv, Annotatable};
 use syntax::ext::base::{MultiDecorator, MultiItemDecorator, MultiModifier};
 use syntax::ext::build::AstBuilder;
 use syntax::feature_gate;
-use syntax::codemap::Span;
+use syntax::codemap::{self, Span};
 use syntax::parse::token::{intern, intern_and_get_ident};
 use syntax::ptr::P;
 
@@ -94,37 +94,7 @@ fn expand_derive(cx: &mut ExtCtxt,
             }
 
             let mut found_partial_eq = false;
-            let mut found_eq = false;
-
-            // This span is **very** sensitive and crucial to
-            // getting the stability behavior we want. What we are
-            // doing is marking the generated `#[derive_*]` with the
-            // span of the `#[deriving(...)]` attribute (the
-            // entire attribute, not just the `PartialEq` or `Eq`
-            // part), but with the current backtrace. The current
-            // backtrace will contain a topmost entry that IS this
-            // `#[deriving(...)]` attribute and with the
-            // "allow-unstable" flag set to true.
-            //
-            // Note that we do NOT use the span of the `Eq`
-            // text itself. You might think this is
-            // equivalent, because the `Eq` appears within the
-            // `#[deriving(Eq)]` attribute, and hence we would
-            // inherit the "allows unstable" from the
-            // backtrace.  But in fact this is not always the
-            // case. The actual source text that led to
-            // deriving can be `#[$attr]`, for example, where
-            // `$attr == deriving(Eq)`. In that case, the
-            // "#[derive_*]" would be considered to
-            // originate not from the deriving call but from
-            // text outside the deriving call, and hence would
-            // be forbidden from using unstable
-            // content.
-            //
-            // See tests src/run-pass/rfc1445 for
-            // examples. --nmatsakis
-            let span = Span { expn_id: cx.backtrace(), .. span };
-            assert!(cx.parse_sess.codemap().span_allows_unstable(span));
+            let mut eq_span = None;
 
             for titem in traits.iter().rev() {
                 let tname = match titem.node {
@@ -144,8 +114,19 @@ fn expand_derive(cx: &mut ExtCtxt,
                     continue;
                 }
 
+                let span = Span {
+                    expn_id: cx.codemap().record_expansion(codemap::ExpnInfo {
+                        call_site: titem.span,
+                        callee: codemap::NameAndSpan {
+                            format: codemap::MacroAttribute(intern(&format!("derive({})", tname))),
+                            span: Some(titem.span),
+                            allow_internal_unstable: true,
+                        },
+                    }), ..titem.span
+                };
+
                 if &tname[..] == "Eq" {
-                    found_eq = true;
+                    eq_span = Some(span);
                 } else if &tname[..] == "PartialEq" {
                     found_partial_eq = true;
                 }
@@ -157,12 +138,13 @@ fn expand_derive(cx: &mut ExtCtxt,
 
             // RFC #1445. `#[derive(PartialEq, Eq)]` adds a (trusted)
             // `#[structural_match]` attribute.
-            if found_partial_eq && found_eq {
-                debug!("inserting structural_match with span {:?}", span);
-                let structural_match = intern_and_get_ident("structural_match");
-                item.attrs.push(cx.attribute(span,
-                                             cx.meta_word(span,
-                                                          structural_match)));
+            if let Some(eq_span) = eq_span {
+                if found_partial_eq {
+                    let structural_match = intern_and_get_ident("structural_match");
+                    item.attrs.push(cx.attribute(eq_span,
+                                                 cx.meta_word(eq_span,
+                                                              structural_match)));
+                }
             }
 
             item
diff --git a/src/test/compile-fail/issue-33571.rs b/src/test/compile-fail/issue-33571.rs
new file mode 100644
index 00000000000..5dfc41c8f4a
--- /dev/null
+++ b/src/test/compile-fail/issue-33571.rs
@@ -0,0 +1,14 @@
+// Copyright 2016 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.
+
+#[derive(Clone,
+         Sync, //~ ERROR this unsafe trait should be implemented explicitly
+         Copy)]
+enum Foo {}