about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-07-16 02:11:14 +0000
committerbors <bors@rust-lang.org>2014-07-16 02:11:14 +0000
commitc523d86552d6797ad52acece4e2e65cb319ee4f2 (patch)
tree2fc16da524e27fcdbe9434b300bf535ad775155c /src
parentafbcbbc77ffc6b10053bc543daf7d2e05d68cc01 (diff)
parent446f9373c05900125f30f244441c5833ce64e146 (diff)
downloadrust-c523d86552d6797ad52acece4e2e65cb319ee4f2.tar.gz
rust-c523d86552d6797ad52acece4e2e65cb319ee4f2.zip
auto merge of #15585 : bgamari/rust/subst-bug, r=pnkfelix
This branch has a fix for #15557 (a2bcef9) as well as a variety of patches I found useful while debugging this issue. These include adding `Show` impls to a variety of types, including the majority of `syntax::ast` and some of `middle::ty`.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/def.rs4
-rw-r--r--src/librustc/middle/kind.rs5
-rw-r--r--src/librustc/middle/subst.rs32
-rw-r--r--src/librustc/middle/ty.rs31
-rw-r--r--src/librustc/middle/typeck/astconv.rs5
-rw-r--r--src/librustc/middle/typeck/check/_match.rs22
-rw-r--r--src/librustc/middle/typeck/collect.rs13
-rw-r--r--src/librustc/middle/typeck/infer/region_inference/mod.rs2
-rw-r--r--src/libsyntax/ast.rs140
-rw-r--r--src/libsyntax/owned_slice.rs12
-rw-r--r--src/test/compile-fail/unsafe-destructor-check-crash.rs23
11 files changed, 181 insertions, 108 deletions
diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs
index 7ee8b33b1fa..914cf451ebe 100644
--- a/src/librustc/middle/def.rs
+++ b/src/librustc/middle/def.rs
@@ -14,7 +14,7 @@ use syntax::ast_util::local_def;
 
 use std::gc::Gc;
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum Def {
     DefFn(ast::DefId, ast::FnStyle),
     DefStaticMethod(/* method */ ast::DefId, MethodProvenance, ast::FnStyle),
@@ -51,7 +51,7 @@ pub enum Def {
     DefMethod(ast::DefId /* method */, Option<ast::DefId> /* trait */),
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum MethodProvenance {
     FromTrait(ast::DefId),
     FromImpl(ast::DefId),
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index d432ced5226..4f7cb742d8f 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -87,7 +87,8 @@ fn check_struct_safe_for_destructor(cx: &mut Context,
                                     span: Span,
                                     struct_did: DefId) {
     let struct_tpt = ty::lookup_item_type(cx.tcx, struct_did);
-    if !struct_tpt.generics.has_type_params(subst::TypeSpace) {
+    if !struct_tpt.generics.has_type_params(subst::TypeSpace)
+      && !struct_tpt.generics.has_region_params(subst::TypeSpace) {
         let struct_ty = ty::mk_struct(cx.tcx, struct_did,
                                       subst::Substs::empty());
         if !ty::type_is_sendable(cx.tcx, struct_ty) {
@@ -121,7 +122,7 @@ fn check_impl_of_trait(cx: &mut Context, it: &Item, trait_ref: &TraitRef, self_t
 
     // If this trait has builtin-kind supertraits, meet them.
     let self_ty: ty::t = ty::node_id_to_type(cx.tcx, it.id);
-    debug!("checking impl with self type {:?}", ty::get(self_ty).sty);
+    debug!("checking impl with self type {}", ty::get(self_ty).sty);
     check_builtin_bounds(cx, self_ty, trait_def.bounds, |missing| {
         cx.tcx.sess.span_err(self_type.span,
             format!("the type `{}', which does not fulfill `{}`, cannot implement this \
diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs
index 4684bd3532e..5c2a70a46fd 100644
--- a/src/librustc/middle/subst.rs
+++ b/src/librustc/middle/subst.rs
@@ -15,6 +15,7 @@ use middle::ty_fold;
 use middle::ty_fold::{TypeFoldable, TypeFolder};
 use util::ppaux::Repr;
 
+use std::fmt;
 use std::mem;
 use std::raw;
 use std::slice::{Items, MutItems};
@@ -83,7 +84,7 @@ impl<T> HomogeneousTuple3<T> for (T, T, T) {
  * space* (which indices where the parameter is defined; see
  * `ParamSpace`).
  */
-#[deriving(Clone, PartialEq, Eq, Hash)]
+#[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub struct Substs {
     pub types: VecPerParamSpace<ty::t>,
     pub regions: RegionSubsts,
@@ -93,7 +94,7 @@ pub struct Substs {
  * Represents the values to use when substituting lifetime parameters.
  * If the value is `ErasedRegions`, then this subst is occurring during
  * trans, and all region parameters will be replaced with `ty::ReStatic`. */
-#[deriving(Clone, PartialEq, Eq, Hash)]
+#[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub enum RegionSubsts {
     ErasedRegions,
     NonerasedRegions(VecPerParamSpace<ty::Region>)
@@ -275,6 +276,17 @@ pub struct VecPerParamSpace<T> {
     content: Vec<T>,
 }
 
+impl<T:fmt::Show> fmt::Show for VecPerParamSpace<T> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        try!(write!(fmt, "VecPerParamSpace {{"));
+        for space in ParamSpace::all().iter() {
+            try!(write!(fmt, "{}: {}, ", *space, self.get_slice(*space)));
+        }
+        try!(write!(fmt, "}}"));
+        Ok(())
+    }
+}
+
 impl<T:Clone> VecPerParamSpace<T> {
     pub fn push_all(&mut self, space: ParamSpace, values: &[T]) {
         // FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n).
@@ -558,10 +570,22 @@ impl<'a> TypeFolder for SubstFolder<'a> {
         // the specialized routine
         // `middle::typeck::check::regionmanip::replace_late_regions_in_fn_sig()`.
         match r {
-            ty::ReEarlyBound(_, space, i, _) => {
+            ty::ReEarlyBound(_, space, i, region_name) => {
                 match self.substs.regions {
                     ErasedRegions => ty::ReStatic,
-                    NonerasedRegions(ref regions) => *regions.get(space, i),
+                    NonerasedRegions(ref regions) =>
+                        match regions.opt_get(space, i) {
+                            Some(t) => *t,
+                            None => {
+                                let span = self.span.unwrap_or(DUMMY_SP);
+                                self.tcx().sess.span_bug(
+                                    span,
+                                    format!("Type parameter out of range \
+                                     when substituting in region {} (root type={})",
+                                    region_name.as_str(),
+                                    self.root_ty.repr(self.tcx())).as_slice());
+                            }
+                        }
                 }
             }
             _ => r
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index eee53b79763..dc69e3fd639 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -124,7 +124,7 @@ impl Method {
     }
 }
 
-#[deriving(Clone, PartialEq, Eq, Hash)]
+#[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub struct mt {
     pub ty: t,
     pub mutbl: ast::Mutability,
@@ -138,7 +138,7 @@ pub enum TraitStore {
     RegionTraitStore(Region, ast::Mutability),
 }
 
-#[deriving(Clone)]
+#[deriving(Clone, Show)]
 pub struct field_ty {
     pub name: Name,
     pub id: DefId,
@@ -394,6 +394,7 @@ pub enum tbox_flag {
 
 pub type t_box = &'static t_box_;
 
+#[deriving(Show)]
 pub struct t_box_ {
     pub sty: sty,
     pub id: uint,
@@ -436,14 +437,14 @@ pub fn type_needs_infer(t: t) -> bool {
 }
 pub fn type_id(t: t) -> uint { get(t).id }
 
-#[deriving(Clone, PartialEq, Eq, Hash)]
+#[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub struct BareFnTy {
     pub fn_style: ast::FnStyle,
     pub abi: abi::Abi,
     pub sig: FnSig,
 }
 
-#[deriving(Clone, PartialEq, Eq, Hash)]
+#[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub struct ClosureTy {
     pub fn_style: ast::FnStyle,
     pub onceness: ast::Onceness,
@@ -472,7 +473,7 @@ pub struct FnSig {
     pub variadic: bool
 }
 
-#[deriving(Clone, PartialEq, Eq, Hash)]
+#[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub struct ParamTy {
     pub space: subst::ParamSpace,
     pub idx: uint,
@@ -712,7 +713,7 @@ mod primitives {
 
 // NB: If you change this, you'll probably want to change the corresponding
 // AST structure in libsyntax/ast.rs as well.
-#[deriving(Clone, PartialEq, Eq, Hash)]
+#[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub enum sty {
     ty_nil,
     ty_bot,
@@ -741,14 +742,14 @@ pub enum sty {
             // on non-useful type error messages)
 }
 
-#[deriving(Clone, PartialEq, Eq, Hash)]
+#[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub struct TyTrait {
     pub def_id: DefId,
     pub substs: Substs,
     pub bounds: BuiltinBounds
 }
 
-#[deriving(PartialEq, Eq, Hash)]
+#[deriving(PartialEq, Eq, Hash, Show)]
 pub struct TraitRef {
     pub def_id: DefId,
     pub substs: Substs,
@@ -808,7 +809,7 @@ pub enum type_err {
     terr_variadic_mismatch(expected_found<bool>)
 }
 
-#[deriving(PartialEq, Eq, Hash)]
+#[deriving(PartialEq, Eq, Hash, Show)]
 pub struct ParamBounds {
     pub builtin_bounds: BuiltinBounds,
     pub trait_bounds: Vec<Rc<TraitRef>>
@@ -948,7 +949,7 @@ impl fmt::Show for IntVarValue {
     }
 }
 
-#[deriving(Clone)]
+#[deriving(Clone, Show)]
 pub struct TypeParameterDef {
     pub ident: ast::Ident,
     pub def_id: ast::DefId,
@@ -958,7 +959,7 @@ pub struct TypeParameterDef {
     pub default: Option<ty::t>
 }
 
-#[deriving(Encodable, Decodable, Clone)]
+#[deriving(Encodable, Decodable, Clone, Show)]
 pub struct RegionParameterDef {
     pub name: ast::Name,
     pub def_id: ast::DefId,
@@ -968,7 +969,7 @@ pub struct RegionParameterDef {
 
 /// Information about the type/lifetime parameters associated with an
 /// item or method. Analogous to ast::Generics.
-#[deriving(Clone)]
+#[deriving(Clone, Show)]
 pub struct Generics {
     pub types: VecPerParamSpace<TypeParameterDef>,
     pub regions: VecPerParamSpace<RegionParameterDef>,
@@ -983,6 +984,10 @@ impl Generics {
     pub fn has_type_params(&self, space: subst::ParamSpace) -> bool {
         !self.types.is_empty_in(space)
     }
+
+    pub fn has_region_params(&self, space: subst::ParamSpace) -> bool {
+        !self.regions.is_empty_in(space)
+    }
 }
 
 /// When type checking, we use the `ParameterEnvironment` to track
@@ -1014,7 +1019,7 @@ pub struct ParameterEnvironment {
 /// - `generics`: the set of type parameters and their bounds
 /// - `ty`: the base types, which may reference the parameters defined
 ///   in `generics`
-#[deriving(Clone)]
+#[deriving(Clone, Show)]
 pub struct Polytype {
     pub generics: Generics,
     pub ty: t
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index 90331d8f434..5ed92b305be 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -141,7 +141,7 @@ pub fn opt_ast_region_to_region<AC:AstConv,RS:RegionScope>(
         }
     };
 
-    debug!("opt_ast_region_to_region(opt_lifetime={:?}) yields {}",
+    debug!("opt_ast_region_to_region(opt_lifetime={}) yields {}",
             opt_lifetime.as_ref().map(|e| lifetime_to_string(e)),
             r.repr(this.tcx()));
 
@@ -504,6 +504,7 @@ pub fn ast_ty_to_builtin_ty<AC:AstConv,
     }
 }
 
+#[deriving(Show)]
 enum PointerTy {
     Box,
     RPtr(ty::Region),
@@ -565,7 +566,7 @@ fn mk_pointer<AC:AstConv,
               constr: |ty::t| -> ty::t)
               -> ty::t {
     let tcx = this.tcx();
-    debug!("mk_pointer(ptr_ty={:?})", ptr_ty);
+    debug!("mk_pointer(ptr_ty={})", ptr_ty);
 
     match a_seq_ty.ty.node {
         ast::TyVec(ref ty) => {
diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs
index 170f850328e..be01643e22a 100644
--- a/src/librustc/middle/typeck/check/_match.rs
+++ b/src/librustc/middle/typeck/check/_match.rs
@@ -507,14 +507,20 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
             ty::ty_struct(cid, ref substs) => {
                 // Verify that the pattern named the right structure.
                 let item_did = tcx.def_map.borrow().get(&pat.id).def_id();
-                let struct_did =
-                    ty::ty_to_def_id(
-                        ty::lookup_item_type(tcx, item_did).ty).unwrap();
-                if struct_did != cid {
-                    span_err!(tcx.sess, pat.span, E0032,
-                        "`{}` does not name the structure `{}`",
-                        pprust::path_to_string(path),
-                        fcx.infcx().ty_to_string(expected));
+                match ty::ty_to_def_id(ty::lookup_item_type(tcx, item_did).ty) {
+                    Some(struct_did) if struct_did != cid => {
+                        span_err!(tcx.sess, path.span, E0032,
+                                  "`{}` does not name the structure `{}`",
+                                  pprust::path_to_string(path),
+                                  fcx.infcx().ty_to_string(expected));
+                    },
+                    Some(_) => {},
+                    None => {
+                        tcx.sess.span_bug(
+                            path.span,
+                            format!("This shouldn't happen: failed to lookup structure. \
+                                item_did = {}", item_did).as_slice())
+                    },
                 }
 
                 check_struct_pat(pcx, pat.id, pat.span, expected, path,
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index 9f08dc2c924..7a39dd5b5ab 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -1018,16 +1018,17 @@ fn ty_generics(ccx: &CrateCtxt,
     let mut result = base_generics;
 
     for (i, l) in lifetimes.iter().enumerate() {
-        result.regions.push(space,
-                            ty::RegionParameterDef { name: l.name,
-                                                     space: space,
-                                                     index: i,
-                                                     def_id: local_def(l.id) });
+        let def = ty::RegionParameterDef { name: l.name,
+                                           space: space,
+                                           index: i,
+                                           def_id: local_def(l.id) };
+        debug!("ty_generics: def for region param: {}", def);
+        result.regions.push(space, def);
     }
 
     for (i, param) in types.iter().enumerate() {
         let def = get_or_create_type_parameter_def(ccx, space, param, i);
-        debug!("def for param: {}", def.repr(ccx.tcx));
+        debug!("ty_generics: def for type param: {}", def.repr(ccx.tcx));
         result.types.push(space, def);
     }
 
diff --git a/src/librustc/middle/typeck/infer/region_inference/mod.rs b/src/librustc/middle/typeck/infer/region_inference/mod.rs
index 757b715ec93..28240686dc3 100644
--- a/src/librustc/middle/typeck/infer/region_inference/mod.rs
+++ b/src/librustc/middle/typeck/infer/region_inference/mod.rs
@@ -246,7 +246,7 @@ impl<'a> RegionVarBindings<'a> {
         if self.in_snapshot() {
             self.undo_log.borrow_mut().push(AddVar(vid));
         }
-        debug!("created new region variable {:?} with origin {:?}",
+        debug!("created new region variable {} with origin {}",
                vid, origin.repr(self.tcx));
         return vid;
     }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index c7154da494f..857cb4c0162 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -152,7 +152,7 @@ impl<D:Decoder<E>, E> Decodable<D, E> for Ident {
 /// Function name (not all functions have names)
 pub type FnIdent = Option<Ident>;
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Lifetime {
     pub id: NodeId,
     pub span: Span,
@@ -162,7 +162,7 @@ pub struct Lifetime {
 /// A "Path" is essentially Rust's notion of a name; for instance:
 /// std::cmp::PartialEq  .  It's represented as a sequence of identifiers,
 /// along with a bunch of supporting information.
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Path {
     pub span: Span,
     /// A `::foo` path, is relative to the crate root rather than current
@@ -174,7 +174,7 @@ pub struct Path {
 
 /// A segment of a path: an identifier, an optional lifetime, and a set of
 /// types.
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct PathSegment {
     /// The identifier portion of this path segment.
     pub identifier: Ident,
@@ -208,7 +208,7 @@ pub static DUMMY_NODE_ID: NodeId = -1;
 /// typeck::collect::compute_bounds matches these against
 /// the "special" built-in traits (see middle::lang_items) and
 /// detects Copy, Send and Share.
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum TyParamBound {
     TraitTyParamBound(TraitRef),
     StaticRegionTyParamBound,
@@ -216,7 +216,7 @@ pub enum TyParamBound {
     OtherRegionTyParamBound(Span) // FIXME -- just here until work for #5723 lands
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct TyParam {
     pub ident: Ident,
     pub id: NodeId,
@@ -228,7 +228,7 @@ pub struct TyParam {
 
 /// Represents lifetimes and type parameters attached to a declaration
 /// of a function, enum, trait, etc.
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Generics {
     pub lifetimes: Vec<Lifetime>,
     pub ty_params: OwnedSlice<TyParam>,
@@ -250,7 +250,7 @@ impl Generics {
 /// used to drive conditional compilation
 pub type CrateConfig = Vec<Gc<MetaItem>> ;
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Crate {
     pub module: Mod,
     pub attrs: Vec<Attribute>,
@@ -261,7 +261,7 @@ pub struct Crate {
 
 pub type MetaItem = Spanned<MetaItem_>;
 
-#[deriving(Clone, Encodable, Decodable, Eq, Hash)]
+#[deriving(Clone, Encodable, Decodable, Eq, Hash, Show)]
 pub enum MetaItem_ {
     MetaWord(InternedString),
     MetaList(InternedString, Vec<Gc<MetaItem>>),
@@ -293,7 +293,7 @@ impl PartialEq for MetaItem_ {
     }
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Block {
     pub view_items: Vec<ViewItem>,
     pub stmts: Vec<Gc<Stmt>>,
@@ -303,26 +303,26 @@ pub struct Block {
     pub span: Span,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Pat {
     pub id: NodeId,
     pub node: Pat_,
     pub span: Span,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct FieldPat {
     pub ident: Ident,
     pub pat: Gc<Pat>,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum BindingMode {
     BindByRef(Mutability),
     BindByValue(Mutability),
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum Pat_ {
     PatWild,
     PatWildMulti,
@@ -354,7 +354,7 @@ pub enum Mutability {
     MutImmutable,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum ExprVstore {
     /// ~[1, 2, 3, 4]
     ExprVstoreUniq,
@@ -364,7 +364,7 @@ pub enum ExprVstore {
     ExprVstoreMutSlice,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum BinOp {
     BiAdd,
     BiSub,
@@ -386,7 +386,7 @@ pub enum BinOp {
     BiGt,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum UnOp {
     UnBox,
     UnUniq,
@@ -397,7 +397,7 @@ pub enum UnOp {
 
 pub type Stmt = Spanned<Stmt_>;
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum Stmt_ {
     /// Could be an item or a local (let) binding:
     StmtDecl(Gc<Decl>, NodeId),
@@ -414,7 +414,7 @@ pub enum Stmt_ {
 
 /// Where a local declaration came from: either a true `let ... =
 /// ...;`, or one desugared from the pattern of a for loop.
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum LocalSource {
     LocalLet,
     LocalFor,
@@ -423,7 +423,7 @@ pub enum LocalSource {
 // FIXME (pending discussion of #1697, #2178...): local should really be
 // a refinement on pat.
 /// Local represents a `let` statement, e.g., `let <pat>:<ty> = <expr>;`
-#[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Local {
     pub ty: P<Ty>,
     pub pat: Gc<Pat>,
@@ -435,7 +435,7 @@ pub struct Local {
 
 pub type Decl = Spanned<Decl_>;
 
-#[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum Decl_ {
     /// A local (let) binding:
     DeclLocal(Gc<Local>),
@@ -444,7 +444,7 @@ pub enum Decl_ {
 }
 
 /// represents one arm of a 'match'
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Arm {
     pub attrs: Vec<Attribute>,
     pub pats: Vec<Gc<Pat>>,
@@ -452,7 +452,7 @@ pub struct Arm {
     pub body: Gc<Expr>,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Field {
     pub ident: SpannedIdent,
     pub expr: Gc<Expr>,
@@ -461,26 +461,26 @@ pub struct Field {
 
 pub type SpannedIdent = Spanned<Ident>;
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum BlockCheckMode {
     DefaultBlock,
     UnsafeBlock(UnsafeSource),
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum UnsafeSource {
     CompilerGenerated,
     UserProvided,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Expr {
     pub id: NodeId,
     pub node: Expr_,
     pub span: Span,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum Expr_ {
     ExprVstore(Gc<Expr>, ExprVstore),
     /// First expr is the place; second expr is the value.
@@ -547,7 +547,7 @@ pub enum Expr_ {
 /// makes any real sense. You could write them elsewhere but nothing
 /// else knows what to do with them, so you'll probably get a syntax
 /// error.
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 #[doc="For macro invocations; parsing is delegated to the macro"]
 pub enum TokenTree {
     /// A single token
@@ -621,7 +621,7 @@ pub enum TokenTree {
 // macro system. Congratulations.
 pub type Matcher = Spanned<Matcher_>;
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum Matcher_ {
     /// Match one token
     MatchTok(::parse::token::Token),
@@ -638,7 +638,7 @@ pub type Mac = Spanned<Mac_>;
 /// is being invoked, and the vector of token-trees contains the source
 /// of the macro invocation.
 /// There's only one flavor, now, so this could presumably be simplified.
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum Mac_ {
     // NB: the additional ident for a macro_rules-style macro is actually
     // stored in the enclosing item. Oog.
@@ -670,13 +670,13 @@ pub enum Lit_ {
 
 // NB: If you change this, you'll probably want to change the corresponding
 // type structure in middle/ty.rs as well.
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct MutTy {
     pub ty: P<Ty>,
     pub mutbl: Mutability,
 }
 
-#[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct TypeField {
     pub ident: Ident,
     pub mt: MutTy,
@@ -685,7 +685,7 @@ pub struct TypeField {
 
 /// Represents a required method in a trait declaration,
 /// one without a default implementation
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct TypeMethod {
     pub ident: Ident,
     pub attrs: Vec<Attribute>,
@@ -702,7 +702,7 @@ pub struct TypeMethod {
 /// a default implementation A trait method is either required (meaning it
 /// doesn't have an implementation, just a signature) or provided (meaning it
 /// has a default implementation).
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum TraitMethod {
     Required(TypeMethod),
     Provided(Gc<Method>),
@@ -779,7 +779,7 @@ impl FloatTy {
 }
 
 // NB PartialEq method appears below.
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Ty {
     pub id: NodeId,
     pub node: Ty_,
@@ -787,7 +787,7 @@ pub struct Ty {
 }
 
 /// Not represented directly in the AST, referred to by name through a ty_path.
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum PrimTy {
     TyInt(IntTy),
     TyUint(UintTy),
@@ -813,7 +813,7 @@ impl fmt::Show for Onceness {
 }
 
 /// Represents the type of a closure
-#[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct ClosureTy {
     pub lifetimes: Vec<Lifetime>,
     pub fn_style: FnStyle,
@@ -826,7 +826,7 @@ pub struct ClosureTy {
     pub bounds: Option<OwnedSlice<TyParamBound>>,
 }
 
-#[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct BareFnTy {
     pub fn_style: FnStyle,
     pub abi: Abi,
@@ -834,12 +834,12 @@ pub struct BareFnTy {
     pub decl: P<FnDecl>
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct UnboxedFnTy {
     pub decl: P<FnDecl>,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum Ty_ {
     TyNil,
     TyBot, /* bottom type */
@@ -863,13 +863,13 @@ pub enum Ty_ {
     TyInfer,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum AsmDialect {
     AsmAtt,
     AsmIntel
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct InlineAsm {
     pub asm: InternedString,
     pub asm_str_style: StrStyle,
@@ -882,7 +882,7 @@ pub struct InlineAsm {
 }
 
 /// represents an argument in a function header
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Arg {
     pub ty: P<Ty>,
     pub pat: Gc<Pat>,
@@ -910,7 +910,7 @@ impl Arg {
 }
 
 /// represents the header (not the body) of a function declaration
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct FnDecl {
     pub inputs: Vec<Arg>,
     pub output: P<Ty>,
@@ -935,7 +935,7 @@ impl fmt::Show for FnStyle {
     }
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum RetStyle {
     /// Functions with return type ! that always
     /// raise an error or exit (i.e. never return to the caller)
@@ -945,7 +945,7 @@ pub enum RetStyle {
 }
 
 /// Represents the kind of 'self' associated with a method
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum ExplicitSelf_ {
     /// No self
     SelfStatic,
@@ -959,7 +959,7 @@ pub enum ExplicitSelf_ {
 
 pub type ExplicitSelf = Spanned<ExplicitSelf_>;
 
-#[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Method {
     pub attrs: Vec<Attribute>,
     pub id: NodeId,
@@ -967,7 +967,7 @@ pub struct Method {
     pub node: Method_
 }
 
-#[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum Method_ {
     /// Represents a method declaration
     MethDecl(Ident, Generics, ExplicitSelf, FnStyle, P<FnDecl>, P<Block>, Visibility),
@@ -975,7 +975,7 @@ pub enum Method_ {
     MethMac(Mac),
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Mod {
     /// A span from the first token past `{` to the last token until `}`.
     /// For `mod foo;`, the inner span ranges from the first token
@@ -985,31 +985,31 @@ pub struct Mod {
     pub items: Vec<Gc<Item>>,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct ForeignMod {
     pub abi: Abi,
     pub view_items: Vec<ViewItem>,
     pub items: Vec<Gc<ForeignItem>>,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct VariantArg {
     pub ty: P<Ty>,
     pub id: NodeId,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum VariantKind {
     TupleVariantKind(Vec<VariantArg>),
     StructVariantKind(Gc<StructDef>),
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct EnumDef {
     pub variants: Vec<P<Variant>>,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Variant_ {
     pub name: Ident,
     pub attrs: Vec<Attribute>,
@@ -1021,7 +1021,7 @@ pub struct Variant_ {
 
 pub type Variant = Spanned<Variant_>;
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct PathListIdent_ {
     pub name: Ident,
     pub id: NodeId,
@@ -1031,7 +1031,7 @@ pub type PathListIdent = Spanned<PathListIdent_>;
 
 pub type ViewPath = Spanned<ViewPath_>;
 
-#[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum ViewPath_ {
 
     /// `quux = foo::bar::baz`
@@ -1048,7 +1048,7 @@ pub enum ViewPath_ {
     ViewPathList(Path, Vec<PathListIdent> , NodeId)
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct ViewItem {
     pub node: ViewItem_,
     pub attrs: Vec<Attribute>,
@@ -1056,7 +1056,7 @@ pub struct ViewItem {
     pub span: Span,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum ViewItem_ {
     /// Ident: name used to refer to this crate in the code
     /// optional (InternedString,StrStyle): if present, this is a location
@@ -1072,17 +1072,17 @@ pub type Attribute = Spanned<Attribute_>;
 /// Distinguishes between Attributes that decorate items and Attributes that
 /// are contained as statements within items. These two cases need to be
 /// distinguished for pretty-printing.
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum AttrStyle {
     AttrOuter,
     AttrInner,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct AttrId(pub uint);
 
 /// Doc-comments are promoted to attributes that have is_sugared_doc = true
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Attribute_ {
     pub id: AttrId,
     pub style: AttrStyle,
@@ -1096,13 +1096,13 @@ pub struct Attribute_ {
 /// that the ref_id is for. The impl_id maps to the "self type" of this impl.
 /// If this impl is an ItemImpl, the impl_id is redundant (it could be the
 /// same as the impl's node id).
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash,   Show)]
 pub struct TraitRef {
     pub path: Path,
     pub ref_id: NodeId,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum Visibility {
     Public,
     Inherited,
@@ -1117,7 +1117,7 @@ impl Visibility {
     }
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct StructField_ {
     pub kind: StructFieldKind,
     pub id: NodeId,
@@ -1136,7 +1136,7 @@ impl StructField_ {
 
 pub type StructField = Spanned<StructField_>;
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum StructFieldKind {
     NamedField(Ident, Visibility),
     /// Element of a tuple-like struct
@@ -1152,7 +1152,7 @@ impl StructFieldKind {
     }
 }
 
-#[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct StructDef {
     /// Fields, not including ctor
     pub fields: Vec<StructField>,
@@ -1169,7 +1169,7 @@ pub struct StructDef {
   FIXME (#3300): Should allow items to be anonymous. Right now
   we just use dummy names for anon items.
  */
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct Item {
     pub ident: Ident,
     pub attrs: Vec<Attribute>,
@@ -1179,7 +1179,7 @@ pub struct Item {
     pub span: Span,
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum Item_ {
     ItemStatic(P<Ty>, Mutability, Gc<Expr>),
     ItemFn(P<FnDecl>, FnStyle, Abi, Generics, P<Block>),
@@ -1202,7 +1202,7 @@ pub enum Item_ {
     ItemMac(Mac),
 }
 
-#[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct ForeignItem {
     pub ident: Ident,
     pub attrs: Vec<Attribute>,
@@ -1212,7 +1212,7 @@ pub struct ForeignItem {
     pub vis: Visibility,
 }
 
-#[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum ForeignItem_ {
     ForeignItemFn(P<FnDecl>, Generics),
     ForeignItemStatic(P<Ty>, /* is_mutbl */ bool),
@@ -1221,7 +1221,7 @@ pub enum ForeignItem_ {
 /// The data we save and restore about an inlined item or method.  This is not
 /// part of the AST that we parse from a file, but it becomes part of the tree
 /// that we trans.
-#[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
+#[deriving(PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum InlinedItem {
     IIItem(Gc<Item>),
     IIMethod(DefId /* impl id */, bool /* is provided */, Gc<Method>),
diff --git a/src/libsyntax/owned_slice.rs b/src/libsyntax/owned_slice.rs
index 530ea013112..7eb6709919a 100644
--- a/src/libsyntax/owned_slice.rs
+++ b/src/libsyntax/owned_slice.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::fmt;
 use std::default::Default;
 use std::hash;
 use std::{mem, raw, ptr, slice};
@@ -22,6 +23,17 @@ pub struct OwnedSlice<T> {
     len: uint,
 }
 
+impl<T:fmt::Show> fmt::Show for OwnedSlice<T> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        try!("OwnedSlice {{".fmt(fmt));
+        for i in self.iter() {
+            try!(i.fmt(fmt));
+        }
+        try!("}}".fmt(fmt));
+        Ok(())
+    }
+}
+
 #[unsafe_destructor]
 impl<T> Drop for OwnedSlice<T> {
     fn drop(&mut self) {
diff --git a/src/test/compile-fail/unsafe-destructor-check-crash.rs b/src/test/compile-fail/unsafe-destructor-check-crash.rs
new file mode 100644
index 00000000000..af675587728
--- /dev/null
+++ b/src/test/compile-fail/unsafe-destructor-check-crash.rs
@@ -0,0 +1,23 @@
+// Copyright 2014 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.
+
+
+
+// Regression test for issue #15557
+
+#![allow(dead_code)]
+struct AReg1<'a>(&'a u32);
+
+impl<'a> Drop for AReg1<'a> {
+//~^ ERROR: cannot implement a destructor on a structure with type parameters
+  fn drop(&mut self) {}
+}
+
+fn main() {}