]> git.proxmox.com Git - rustc.git/blobdiff - src/librustdoc/clean/mod.rs
Imported Upstream version 1.4.0+dfsg1
[rustc.git] / src / librustdoc / clean / mod.rs
index a44c73e8c4120f91d9b986673e6a68273003faf8..7ef359787e87e1b6438e9737f85af75785e0d069 100644 (file)
 //! This module contains the "cleaned" pieces of the AST, and the functions
 //! that clean them.
 
-pub use self::ImplMethod::*;
 pub use self::Type::*;
 pub use self::PrimitiveType::*;
 pub use self::TypeKind::*;
 pub use self::StructField::*;
 pub use self::VariantKind::*;
 pub use self::Mutability::*;
-pub use self::ViewItemInner::*;
-pub use self::ViewPath::*;
+pub use self::Import::*;
 pub use self::ItemEnum::*;
 pub use self::Attribute::*;
 pub use self::TyParamBound::*;
 pub use self::SelfTy::*;
 pub use self::FunctionRetTy::*;
-pub use self::TraitMethod::*;
 
 use syntax;
+use syntax::abi;
 use syntax::ast;
-use syntax::ast_util;
-use syntax::ast_util::PostExpansionMethod;
-use syntax::attr;
-use syntax::attr::{AttributeMethods, AttrMetaMethods};
+use syntax::codemap;
 use syntax::codemap::{DUMMY_SP, Pos, Spanned};
 use syntax::parse::token::{self, InternedString, special_idents};
 use syntax::ptr::P;
@@ -42,15 +37,20 @@ use rustc::metadata::cstore;
 use rustc::metadata::csearch;
 use rustc::metadata::decoder;
 use rustc::middle::def;
+use rustc::middle::def_id::{DefId, LOCAL_CRATE};
 use rustc::middle::subst::{self, ParamSpace, VecPerParamSpace};
 use rustc::middle::ty;
 use rustc::middle::stability;
-use rustc::session::config;
 
+use rustc_front::hir;
+use rustc_front::attr;
+use rustc_front::attr::{AttributeMethods, AttrMetaMethods};
+use rustc_front::lowering::unlower_attribute;
+
+use std::collections::HashMap;
+use std::path::PathBuf;
 use std::rc::Rc;
 use std::u32;
-use std::str::Str as StrTrait; // Conflicts with Str variant
-use std::path::Path as FsPath; // Conflicts with Path struct
 
 use core::DocContext;
 use doctree;
@@ -58,12 +58,13 @@ use visit_ast;
 
 /// A stable identifier to the particular version of JSON output.
 /// Increment this when the `Crate` and related structures change.
-pub static SCHEMA_VERSION: &'static str = "0.8.3";
+pub const SCHEMA_VERSION: &'static str = "0.8.3";
 
 mod inline;
+mod simplify;
 
 // extract the stability index for a node from tcx, if possible
-fn get_stability(cx: &DocContext, def_id: ast::DefId) -> Option<Stability> {
+fn get_stability(cx: &DocContext, def_id: DefId) -> Option<Stability> {
     cx.tcx_opt().and_then(|tcx| stability::lookup(tcx, def_id)).clean(cx)
 }
 
@@ -71,7 +72,7 @@ pub trait Clean<T> {
     fn clean(&self, cx: &DocContext) -> T;
 }
 
-impl<T: Clean<U>, U> Clean<Vec<U>> for Vec<T> {
+impl<T: Clean<U>, U> Clean<Vec<U>> for [T] {
     fn clean(&self, cx: &DocContext) -> Vec<U> {
         self.iter().map(|x| x.clean(cx)).collect()
     }
@@ -104,23 +105,36 @@ impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
     }
 }
 
+impl<T, U> Clean<U> for ty::Binder<T> where T: Clean<U> {
+    fn clean(&self, cx: &DocContext) -> U {
+        self.0.clean(cx)
+    }
+}
+
 impl<T: Clean<U>, U> Clean<Vec<U>> for syntax::owned_slice::OwnedSlice<T> {
     fn clean(&self, cx: &DocContext) -> Vec<U> {
         self.iter().map(|x| x.clean(cx)).collect()
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Crate {
     pub name: String,
-    pub src: FsPath,
+    pub src: PathBuf,
     pub module: Option<Item>,
     pub externs: Vec<(ast::CrateNum, ExternalCrate)>,
     pub primitives: Vec<PrimitiveType>,
+    pub external_traits: HashMap<DefId, Trait>,
 }
 
 impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
     fn clean(&self, cx: &DocContext) -> Crate {
+        use rustc::session::config::Input;
+
+        if let Some(t) = cx.tcx_opt() {
+            cx.deref_trait_did.set(t.lang_items.deref_trait());
+        }
+
         let mut externs = Vec::new();
         cx.sess().cstore.iter_crate_data(|n, meta| {
             externs.push((n, meta.clean(cx)));
@@ -128,8 +142,9 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
         externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
 
         // Figure out the name of this crate
-        let input = config::Input::File(cx.src.clone());
-        let name = link::find_crate_name(None, self.attrs.as_slice(), &input);
+        let input = &cx.input;
+        let attrs: Vec<_> = self.attrs.iter().map(|a| unlower_attribute(a)).collect();
+        let name = link::find_crate_name(None, &attrs, input);
 
         // Clean the crate, translating the entire libsyntax AST to one that is
         // understood by rustdoc.
@@ -159,12 +174,12 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
                 _ => unreachable!(),
             };
             let mut tmp = Vec::new();
-            for child in m.items.iter_mut() {
+            for child in &mut m.items {
                 match child.inner {
                     ModuleItem(..) => {}
                     _ => continue,
                 }
-                let prim = match PrimitiveType::find(child.attrs.as_slice()) {
+                let prim = match PrimitiveType::find(&child.attrs) {
                     Some(prim) => prim,
                     None => continue,
                 };
@@ -173,26 +188,33 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
                     source: Span::empty(),
                     name: Some(prim.to_url_str().to_string()),
                     attrs: child.attrs.clone(),
-                    visibility: Some(ast::Public),
+                    visibility: Some(hir::Public),
                     stability: None,
-                    def_id: ast_util::local_def(prim.to_node_id()),
+                    def_id: DefId::local(prim.to_node_id()),
                     inner: PrimitiveItem(prim),
                 });
             }
-            m.items.extend(tmp.into_iter());
+            m.items.extend(tmp);
         }
 
+        let src = match cx.input {
+            Input::File(ref path) => path.clone(),
+            Input::Str(_) => PathBuf::new() // FIXME: this is wrong
+        };
+
         Crate {
             name: name.to_string(),
-            src: cx.src.clone(),
+            src: src,
             module: Some(module),
             externs: externs,
             primitives: primitives,
+            external_traits: cx.external_traits.borrow_mut().take()
+                               .unwrap_or(HashMap::new()),
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct ExternalCrate {
     pub name: String,
     pub attrs: Vec<Attribute>,
@@ -211,7 +233,7 @@ impl Clean<ExternalCrate> for cstore::crate_metadata {
                     _ => return
                 };
                 let attrs = inline::load_attrs(cx, tcx, did);
-                PrimitiveType::find(attrs.as_slice()).map(|prim| primitives.push(prim));
+                PrimitiveType::find(&attrs).map(|prim| primitives.push(prim));
             })
         });
         ExternalCrate {
@@ -225,7 +247,7 @@ impl Clean<ExternalCrate> for cstore::crate_metadata {
 /// Anything with a source location and set of attributes and, optionally, a
 /// name. That is, anything that can be documented. This doesn't correspond
 /// directly to the AST's concept of an item; it's a strict superset.
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Item {
     /// Stringified span
     pub source: Span,
@@ -234,7 +256,7 @@ pub struct Item {
     pub attrs: Vec<Attribute> ,
     pub inner: ItemEnum,
     pub visibility: Option<Visibility>,
-    pub def_id: ast::DefId,
+    pub def_id: DefId,
     pub stability: Option<Stability>,
 }
 
@@ -242,10 +264,10 @@ impl Item {
     /// Finds the `doc` attribute as a List and returns the list of attributes
     /// nested inside.
     pub fn doc_list<'a>(&'a self) -> Option<&'a [Attribute]> {
-        for attr in self.attrs.iter() {
+        for attr in &self.attrs {
             match *attr {
                 List(ref x, ref list) if "doc" == *x => {
-                    return Some(list.as_slice());
+                    return Some(list);
                 }
                 _ => {}
             }
@@ -256,10 +278,10 @@ impl Item {
     /// Finds the `doc` attribute as a NameValue and returns the corresponding
     /// value found.
     pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
-        for attr in self.attrs.iter() {
+        for attr in &self.attrs {
             match *attr {
                 NameValue(ref x, ref v) if "doc" == *x => {
-                    return Some(v.as_slice());
+                    return Some(v);
                 }
                 _ => {}
             }
@@ -269,8 +291,8 @@ impl Item {
 
     pub fn is_hidden_from_doc(&self) -> bool {
         match self.doc_list() {
-            Some(ref l) => {
-                for innerattr in l.iter() {
+            Some(l) => {
+                for innerattr in l {
                     match *innerattr {
                         Word(ref s) if "hidden" == *s => {
                             return true
@@ -299,21 +321,37 @@ impl Item {
     pub fn is_fn(&self) -> bool {
         match self.inner { FunctionItem(..) => true, _ => false }
     }
+
+    pub fn stability_class(&self) -> String {
+        match self.stability {
+            Some(ref s) => {
+                let mut base = match s.level {
+                    attr::Unstable => "unstable".to_string(),
+                    attr::Stable => String::new(),
+                };
+                if !s.deprecated_since.is_empty() {
+                    base.push_str(" deprecated");
+                }
+                base
+            }
+            _ => String::new(),
+        }
+    }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub enum ItemEnum {
+    ExternCrateItem(String, Option<String>),
+    ImportItem(Import),
     StructItem(Struct),
     EnumItem(Enum),
     FunctionItem(Function),
     ModuleItem(Module),
-    TypedefItem(Typedef),
+    TypedefItem(Typedef, bool /* is associated type */),
     StaticItem(Static),
     ConstantItem(Constant),
     TraitItem(Trait),
     ImplItem(Impl),
-    /// `use` and `extern crate`
-    ViewItemItem(ViewItem),
     /// A method signature only. Used for required methods in traits (ie,
     /// non-default-methods).
     TyMethodItem(TyMethod),
@@ -327,10 +365,12 @@ pub enum ItemEnum {
     ForeignStaticItem(Static),
     MacroItem(Macro),
     PrimitiveItem(PrimitiveType),
-    AssociatedTypeItem(TyParam),
+    AssociatedConstItem(Type, Option<String>),
+    AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
+    DefaultImplItem(DefaultImpl),
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Module {
     pub items: Vec<Item>,
     pub is_crate: bool,
@@ -343,27 +383,22 @@ impl Clean<Item> for doctree::Module {
         } else {
             "".to_string()
         };
-        let mut foreigns = Vec::new();
-        for subforeigns in self.foreigns.clean(cx).into_iter() {
-            for foreign in subforeigns.into_iter() {
-                foreigns.push(foreign)
-            }
-        }
-        let items: Vec<Vec<Item> > = vec!(
-            self.structs.clean(cx),
-            self.enums.clean(cx),
-            self.fns.clean(cx),
-            foreigns,
-            self.mods.clean(cx),
-            self.typedefs.clean(cx),
-            self.statics.clean(cx),
-            self.constants.clean(cx),
-            self.traits.clean(cx),
-            self.impls.clean(cx),
-            self.view_items.clean(cx).into_iter()
-                           .flat_map(|s| s.into_iter()).collect(),
-            self.macros.clean(cx),
-        );
+
+        let mut items: Vec<Item> = vec![];
+        items.extend(self.extern_crates.iter().map(|x| x.clean(cx)));
+        items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
+        items.extend(self.structs.iter().map(|x| x.clean(cx)));
+        items.extend(self.enums.iter().map(|x| x.clean(cx)));
+        items.extend(self.fns.iter().map(|x| x.clean(cx)));
+        items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx)));
+        items.extend(self.mods.iter().map(|x| x.clean(cx)));
+        items.extend(self.typedefs.iter().map(|x| x.clean(cx)));
+        items.extend(self.statics.iter().map(|x| x.clean(cx)));
+        items.extend(self.constants.iter().map(|x| x.clean(cx)));
+        items.extend(self.traits.iter().map(|x| x.clean(cx)));
+        items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
+        items.extend(self.macros.iter().map(|x| x.clean(cx)));
+        items.extend(self.def_traits.iter().map(|x| x.clean(cx)));
 
         // determine if we should display the inner contents or
         // the outer `mod` item for the source code.
@@ -386,39 +421,37 @@ impl Clean<Item> for doctree::Module {
             source: whence.clean(cx),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
-            def_id: ast_util::local_def(self.id),
+            def_id: DefId::local(self.id),
             inner: ModuleItem(Module {
                is_crate: self.is_crate,
-               items: items.iter()
-                           .flat_map(|x| x.iter().map(|x| (*x).clone()))
-                           .collect(),
+               items: items
             })
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub enum Attribute {
     Word(String),
     List(String, Vec<Attribute> ),
     NameValue(String, String)
 }
 
-impl Clean<Attribute> for ast::MetaItem {
+impl Clean<Attribute> for hir::MetaItem {
     fn clean(&self, cx: &DocContext) -> Attribute {
         match self.node {
-            ast::MetaWord(ref s) => Word(s.get().to_string()),
-            ast::MetaList(ref s, ref l) => {
-                List(s.get().to_string(), l.clean(cx))
+            hir::MetaWord(ref s) => Word(s.to_string()),
+            hir::MetaList(ref s, ref l) => {
+                List(s.to_string(), l.clean(cx))
             }
-            ast::MetaNameValue(ref s, ref v) => {
-                NameValue(s.get().to_string(), lit_to_string(v))
+            hir::MetaNameValue(ref s, ref v) => {
+                NameValue(s.to_string(), lit_to_string(v))
             }
         }
     }
 }
 
-impl Clean<Attribute> for ast::Attribute {
+impl Clean<Attribute> for hir::Attribute {
     fn clean(&self, cx: &DocContext) -> Attribute {
         self.with_desugared_doc(|a| a.node.value.clean(cx))
     }
@@ -429,7 +462,7 @@ impl attr::AttrMetaMethods for Attribute {
     fn name(&self) -> InternedString {
         match *self {
             Word(ref n) | List(ref n, _) | NameValue(ref n, _) => {
-                token::intern_and_get_ident(n.as_slice())
+                token::intern_and_get_ident(n)
             }
         }
     }
@@ -437,32 +470,34 @@ impl attr::AttrMetaMethods for Attribute {
     fn value_str(&self) -> Option<InternedString> {
         match *self {
             NameValue(_, ref v) => {
-                Some(token::intern_and_get_ident(v.as_slice()))
+                Some(token::intern_and_get_ident(v))
             }
             _ => None,
         }
     }
-    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<ast::MetaItem>]> { None }
+    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<hir::MetaItem>]> { None }
+    fn span(&self) -> codemap::Span { unimplemented!() }
 }
 impl<'a> attr::AttrMetaMethods for &'a Attribute {
     fn name(&self) -> InternedString { (**self).name() }
     fn value_str(&self) -> Option<InternedString> { (**self).value_str() }
-    fn meta_item_list(&self) -> Option<&[P<ast::MetaItem>]> { None }
+    fn meta_item_list(&self) -> Option<&[P<hir::MetaItem>]> { None }
+    fn span(&self) -> codemap::Span { unimplemented!() }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub struct TyParam {
     pub name: String,
-    pub did: ast::DefId,
+    pub did: DefId,
     pub bounds: Vec<TyParamBound>,
     pub default: Option<Type>,
 }
 
-impl Clean<TyParam> for ast::TyParam {
+impl Clean<TyParam> for hir::TyParam {
     fn clean(&self, cx: &DocContext) -> TyParam {
         TyParam {
             name: self.ident.clean(cx),
-            did: ast::DefId { krate: ast::LOCAL_CRATE, node: self.id },
+            did: DefId { krate: LOCAL_CRATE, node: self.id },
             bounds: self.bounds.clean(cx),
             default: self.default.clean(cx),
         }
@@ -473,48 +508,81 @@ impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
     fn clean(&self, cx: &DocContext) -> TyParam {
         cx.external_typarams.borrow_mut().as_mut().unwrap()
           .insert(self.def_id, self.name.clean(cx));
-        let bounds = self.bounds.clean(cx);
         TyParam {
             name: self.name.clean(cx),
             did: self.def_id,
-            bounds: bounds,
+            bounds: vec![], // these are filled in from the where-clauses
             default: self.default.clean(cx),
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub enum TyParamBound {
     RegionBound(Lifetime),
-    TraitBound(PolyTrait, ast::TraitBoundModifier)
+    TraitBound(PolyTrait, hir::TraitBoundModifier)
 }
 
-impl Clean<TyParamBound> for ast::TyParamBound {
+impl TyParamBound {
+    fn maybe_sized(cx: &DocContext) -> TyParamBound {
+        use rustc_front::hir::TraitBoundModifier as TBM;
+        let mut sized_bound = ty::BoundSized.clean(cx);
+        if let TyParamBound::TraitBound(_, ref mut tbm) = sized_bound {
+            *tbm = TBM::Maybe
+        };
+        sized_bound
+    }
+
+    fn is_sized_bound(&self, cx: &DocContext) -> bool {
+        use rustc_front::hir::TraitBoundModifier as TBM;
+        if let Some(tcx) = cx.tcx_opt() {
+            let sized_did = match tcx.lang_items.sized_trait() {
+                Some(did) => did,
+                None => return false
+            };
+            if let TyParamBound::TraitBound(PolyTrait {
+                trait_: Type::ResolvedPath { did, .. }, ..
+            }, TBM::None) = *self {
+                if did == sized_did {
+                    return true
+                }
+            }
+        }
+        false
+    }
+}
+
+impl Clean<TyParamBound> for hir::TyParamBound {
     fn clean(&self, cx: &DocContext) -> TyParamBound {
         match *self {
-            ast::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)),
-            ast::TraitTyParamBound(ref t, modifier) => TraitBound(t.clean(cx), modifier),
+            hir::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)),
+            hir::TraitTyParamBound(ref t, modifier) => TraitBound(t.clean(cx), modifier),
         }
     }
 }
 
-impl<'tcx> Clean<Vec<TyParamBound>> for ty::ExistentialBounds<'tcx> {
-    fn clean(&self, cx: &DocContext) -> Vec<TyParamBound> {
-        let mut vec = vec![];
-        self.region_bound.clean(cx).map(|b| vec.push(RegionBound(b)));
-        for bb in self.builtin_bounds.iter() {
-            vec.push(bb.clean(cx));
+impl<'tcx> Clean<(Vec<TyParamBound>, Vec<TypeBinding>)> for ty::ExistentialBounds<'tcx> {
+    fn clean(&self, cx: &DocContext) -> (Vec<TyParamBound>, Vec<TypeBinding>) {
+        let mut tp_bounds = vec![];
+        self.region_bound.clean(cx).map(|b| tp_bounds.push(RegionBound(b)));
+        for bb in &self.builtin_bounds {
+            tp_bounds.push(bb.clean(cx));
         }
 
-        // FIXME(#20299) -- should do something with projection bounds
+        let mut bindings = vec![];
+        for &ty::Binder(ref pb) in &self.projection_bounds {
+            bindings.push(TypeBinding {
+                name: pb.projection_ty.item_name.clean(cx),
+                ty: pb.ty.clean(cx)
+            });
+        }
 
-        vec
+        (tp_bounds, bindings)
     }
 }
 
-fn external_path_params(cx: &DocContext, trait_did: Option<ast::DefId>,
-                        substs: &subst::Substs) -> PathParameters {
-    use rustc::middle::ty::sty;
+fn external_path_params(cx: &DocContext, trait_did: Option<DefId>,
+                        bindings: Vec<TypeBinding>, substs: &subst::Substs) -> PathParameters {
     let lifetimes = substs.regions().get_slice(subst::TypeSpace)
                     .iter()
                     .filter_map(|v| v.clean(cx))
@@ -524,21 +592,23 @@ fn external_path_params(cx: &DocContext, trait_did: Option<ast::DefId>,
     match (trait_did, cx.tcx_opt()) {
         // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
         (Some(did), Some(ref tcx)) if tcx.lang_items.fn_trait_kind(did).is_some() => {
-            assert_eq!(types.len(), 2);
+            assert_eq!(types.len(), 1);
             let inputs = match types[0].sty {
-                sty::ty_tup(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
+                ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
                 _ => {
                     return PathParameters::AngleBracketed {
                         lifetimes: lifetimes,
                         types: types.clean(cx),
-                        bindings: vec![]
+                        bindings: bindings
                     }
                 }
             };
-            let output = match types[1].sty {
-                sty::ty_tup(ref v) if v.is_empty() => None, // -> ()
-                _ => Some(types[1].clean(cx))
-            };
+            let output = None;
+            // FIXME(#20299) return type comes from a projection now
+            // match types[1].sty {
+            //     ty::TyTuple(ref v) if v.is_empty() => None, // -> ()
+            //     _ => Some(types[1].clean(cx))
+            // };
             PathParameters::Parenthesized {
                 inputs: inputs,
                 output: output
@@ -548,7 +618,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option<ast::DefId>,
             PathParameters::AngleBracketed {
                 lifetimes: lifetimes,
                 types: types.clean(cx),
-                bindings: vec![] // FIXME(#20646)
+                bindings: bindings
             }
         }
     }
@@ -556,13 +626,13 @@ fn external_path_params(cx: &DocContext, trait_did: Option<ast::DefId>,
 
 // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
 // from Fn<(A, B,), C> to Fn(A, B) -> C
-fn external_path(cx: &DocContext, name: &str, trait_did: Option<ast::DefId>,
-                 substs: &subst::Substs) -> Path {
+fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>,
+                 bindings: Vec<TypeBinding>, substs: &subst::Substs) -> Path {
     Path {
         global: false,
         segments: vec![PathSegment {
             name: name.to_string(),
-            params: external_path_params(cx, trait_did, substs)
+            params: external_path_params(cx, trait_did, bindings, substs)
         }],
     }
 }
@@ -577,16 +647,16 @@ impl Clean<TyParamBound> for ty::BuiltinBound {
         let (did, path) = match *self {
             ty::BoundSend =>
                 (tcx.lang_items.send_trait().unwrap(),
-                 external_path(cx, "Send", None, &empty)),
+                 external_path(cx, "Send", None, vec![], &empty)),
             ty::BoundSized =>
                 (tcx.lang_items.sized_trait().unwrap(),
-                 external_path(cx, "Sized", None, &empty)),
+                 external_path(cx, "Sized", None, vec![], &empty)),
             ty::BoundCopy =>
                 (tcx.lang_items.copy_trait().unwrap(),
-                 external_path(cx, "Copy", None, &empty)),
+                 external_path(cx, "Copy", None, vec![], &empty)),
             ty::BoundSync =>
                 (tcx.lang_items.sync_trait().unwrap(),
-                 external_path(cx, "Sync", None, &empty)),
+                 external_path(cx, "Sync", None, vec![], &empty)),
         };
         let fqn = csearch::get_item_path(tcx, did);
         let fqn = fqn.into_iter().map(|i| i.to_string()).collect();
@@ -597,15 +667,10 @@ impl Clean<TyParamBound> for ty::BuiltinBound {
                 path: path,
                 typarams: None,
                 did: did,
+                is_generic: false,
             },
             lifetimes: vec![]
-        }, ast::TraitBoundModifier::None)
-    }
-}
-
-impl<'tcx> Clean<TyParamBound> for ty::PolyTraitRef<'tcx> {
-    fn clean(&self, cx: &DocContext) -> TyParamBound {
-        self.0.clean(cx)
+        }, hir::TraitBoundModifier::None)
     }
 }
 
@@ -618,8 +683,8 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
         let fqn = csearch::get_item_path(tcx, self.def_id);
         let fqn = fqn.into_iter().map(|i| i.to_string())
                      .collect::<Vec<String>>();
-        let path = external_path(cx, fqn.last().unwrap().as_slice(),
-                                 Some(self.def_id), self.substs);
+        let path = external_path(cx, fqn.last().unwrap(),
+                                 Some(self.def_id), vec![], self.substs);
         cx.external_paths.borrow_mut().as_mut().unwrap().insert(self.def_id,
                                                             (fqn, TypeTrait));
 
@@ -628,12 +693,11 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
 
         // collect any late bound regions
         let mut late_bounds = vec![];
-        for &ty_s in self.substs.types.get_slice(ParamSpace::TypeSpace).iter() {
-            use rustc::middle::ty::{Region, sty};
-            if let sty::ty_tup(ref ts) = ty_s.sty {
-                for &ty_s in ts.iter() {
-                    if let sty::ty_rptr(ref reg, _) = ty_s.sty {
-                        if let &Region::ReLateBound(_, _) = *reg {
+        for &ty_s in self.substs.types.get_slice(ParamSpace::TypeSpace) {
+            if let ty::TyTuple(ref ts) = ty_s.sty {
+                for &ty_s in ts {
+                    if let ty::TyRef(ref reg, _) = ty_s.sty {
+                        if let &ty::Region::ReLateBound(_, _) = *reg {
                             debug!("  hit an ReLateBound {:?}", reg);
                             if let Some(lt) = reg.clean(cx) {
                                 late_bounds.push(lt)
@@ -645,22 +709,14 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
         }
 
         TraitBound(PolyTrait {
-            trait_: ResolvedPath { path: path, typarams: None, did: self.def_id, },
+            trait_: ResolvedPath {
+                path: path,
+                typarams: None,
+                did: self.def_id,
+                is_generic: false,
+            },
             lifetimes: late_bounds
-        }, ast::TraitBoundModifier::None)
-    }
-}
-
-impl<'tcx> Clean<Vec<TyParamBound>> for ty::ParamBounds<'tcx> {
-    fn clean(&self, cx: &DocContext) -> Vec<TyParamBound> {
-        let mut v = Vec::new();
-        for t in self.trait_bounds.iter() {
-            v.push(t.clean(cx));
-        }
-        for r in self.region_bounds.iter().filter_map(|r| r.clean(cx)) {
-            v.push(RegionBound(r));
-        }
-        v
+        }, hir::TraitBoundModifier::None)
     }
 }
 
@@ -671,18 +727,18 @@ impl<'tcx> Clean<Option<Vec<TyParamBound>>> for subst::Substs<'tcx> {
         v.extend(self.types.iter().map(|t| TraitBound(PolyTrait {
             trait_: t.clean(cx),
             lifetimes: vec![]
-        }, ast::TraitBoundModifier::None)));
-        if v.len() > 0 {Some(v)} else {None}
+        }, hir::TraitBoundModifier::None)));
+        if !v.is_empty() {Some(v)} else {None}
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub struct Lifetime(String);
 
 impl Lifetime {
     pub fn get_ref<'a>(&'a self) -> &'a str {
         let Lifetime(ref s) = *self;
-        let s: &'a str = s.as_slice();
+        let s: &'a str = s;
         return s;
     }
 
@@ -691,21 +747,21 @@ impl Lifetime {
     }
 }
 
-impl Clean<Lifetime> for ast::Lifetime {
+impl Clean<Lifetime> for hir::Lifetime {
     fn clean(&self, _: &DocContext) -> Lifetime {
-        Lifetime(token::get_name(self.name).get().to_string())
+        Lifetime(self.name.to_string())
     }
 }
 
-impl Clean<Lifetime> for ast::LifetimeDef {
+impl Clean<Lifetime> for hir::LifetimeDef {
     fn clean(&self, _: &DocContext) -> Lifetime {
-        Lifetime(token::get_name(self.lifetime.name).get().to_string())
+        Lifetime(self.lifetime.name.to_string())
     }
 }
 
 impl Clean<Lifetime> for ty::RegionParameterDef {
     fn clean(&self, _: &DocContext) -> Lifetime {
-        Lifetime(token::get_name(self.name).get().to_string())
+        Lifetime(self.name.to_string())
     }
 }
 
@@ -714,59 +770,140 @@ impl Clean<Option<Lifetime>> for ty::Region {
         match *self {
             ty::ReStatic => Some(Lifetime::statik()),
             ty::ReLateBound(_, ty::BrNamed(_, name)) =>
-                Some(Lifetime(token::get_name(name).get().to_string())),
-            ty::ReEarlyBound(_, _, _, name) => Some(Lifetime(name.clean(cx))),
+                Some(Lifetime(name.to_string())),
+            ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))),
 
             ty::ReLateBound(..) |
             ty::ReFree(..) |
             ty::ReScope(..) |
-            ty::ReInfer(..) |
+            ty::ReVar(..) |
+            ty::ReSkolemized(..) |
             ty::ReEmpty(..) => None
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub enum WherePredicate {
     BoundPredicate { ty: Type, bounds: Vec<TyParamBound> },
     RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>},
-    // FIXME (#20041)
-    EqPredicate
+    EqPredicate { lhs: Type, rhs: Type }
 }
 
-impl Clean<WherePredicate> for ast::WherePredicate {
+impl Clean<WherePredicate> for hir::WherePredicate {
     fn clean(&self, cx: &DocContext) -> WherePredicate {
         match *self {
-            ast::WherePredicate::BoundPredicate(ref wbp) => {
+            hir::WherePredicate::BoundPredicate(ref wbp) => {
                 WherePredicate::BoundPredicate {
                     ty: wbp.bounded_ty.clean(cx),
                     bounds: wbp.bounds.clean(cx)
                 }
             }
 
-            ast::WherePredicate::RegionPredicate(ref wrp) => {
+            hir::WherePredicate::RegionPredicate(ref wrp) => {
                 WherePredicate::RegionPredicate {
                     lifetime: wrp.lifetime.clean(cx),
                     bounds: wrp.bounds.clean(cx)
                 }
             }
 
-            ast::WherePredicate::EqPredicate(_) => {
-                WherePredicate::EqPredicate
+            hir::WherePredicate::EqPredicate(_) => {
+                unimplemented!() // FIXME(#20041)
             }
         }
     }
 }
 
-// maybe use a Generic enum and use ~[Generic]?
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
+impl<'a> Clean<WherePredicate> for ty::Predicate<'a> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        use rustc::middle::ty::Predicate;
+
+        match *self {
+            Predicate::Trait(ref pred) => pred.clean(cx),
+            Predicate::Equate(ref pred) => pred.clean(cx),
+            Predicate::RegionOutlives(ref pred) => pred.clean(cx),
+            Predicate::TypeOutlives(ref pred) => pred.clean(cx),
+            Predicate::Projection(ref pred) => pred.clean(cx),
+            Predicate::WellFormed(_) => panic!("not user writable"),
+            Predicate::ObjectSafe(_) => panic!("not user writable"),
+        }
+    }
+}
+
+impl<'a> Clean<WherePredicate> for ty::TraitPredicate<'a> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        WherePredicate::BoundPredicate {
+            ty: self.trait_ref.substs.self_ty().clean(cx).unwrap(),
+            bounds: vec![self.trait_ref.clean(cx)]
+        }
+    }
+}
+
+impl<'tcx> Clean<WherePredicate> for ty::EquatePredicate<'tcx> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        let ty::EquatePredicate(ref lhs, ref rhs) = *self;
+        WherePredicate::EqPredicate {
+            lhs: lhs.clean(cx),
+            rhs: rhs.clean(cx)
+        }
+    }
+}
+
+impl Clean<WherePredicate> for ty::OutlivesPredicate<ty::Region, ty::Region> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        let ty::OutlivesPredicate(ref a, ref b) = *self;
+        WherePredicate::RegionPredicate {
+            lifetime: a.clean(cx).unwrap(),
+            bounds: vec![b.clean(cx).unwrap()]
+        }
+    }
+}
+
+impl<'tcx> Clean<WherePredicate> for ty::OutlivesPredicate<ty::Ty<'tcx>, ty::Region> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        let ty::OutlivesPredicate(ref ty, ref lt) = *self;
+
+        WherePredicate::BoundPredicate {
+            ty: ty.clean(cx),
+            bounds: vec![TyParamBound::RegionBound(lt.clean(cx).unwrap())]
+        }
+    }
+}
+
+impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        WherePredicate::EqPredicate {
+            lhs: self.projection_ty.clean(cx),
+            rhs: self.ty.clean(cx)
+        }
+    }
+}
+
+impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
+    fn clean(&self, cx: &DocContext) -> Type {
+        let trait_ = match self.trait_ref.clean(cx) {
+            TyParamBound::TraitBound(t, _) => t.trait_,
+            TyParamBound::RegionBound(_) => {
+                panic!("cleaning a trait got a region")
+            }
+        };
+        Type::QPath {
+            name: self.item_name.clean(cx),
+            self_type: box self.trait_ref.self_ty().clean(cx),
+            trait_: box trait_
+        }
+    }
+}
+
+// maybe use a Generic enum and use Vec<Generic>?
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub struct Generics {
     pub lifetimes: Vec<Lifetime>,
     pub type_params: Vec<TyParam>,
     pub where_predicates: Vec<WherePredicate>
 }
 
-impl Clean<Generics> for ast::Generics {
+impl Clean<Generics> for hir::Generics {
     fn clean(&self, cx: &DocContext) -> Generics {
         Generics {
             lifetimes: self.lifetimes.clean(cx),
@@ -776,95 +913,145 @@ impl Clean<Generics> for ast::Generics {
     }
 }
 
-impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>, subst::ParamSpace) {
+impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
+                                    &'a ty::GenericPredicates<'tcx>,
+                                    subst::ParamSpace) {
     fn clean(&self, cx: &DocContext) -> Generics {
-        let (me, space) = *self;
+        use std::collections::HashSet;
+        use self::WherePredicate as WP;
+
+        let (gens, preds, space) = *self;
+
+        // Bounds in the type_params and lifetimes fields are repeated in the
+        // predicates field (see rustc_typeck::collect::ty_generics), so remove
+        // them.
+        let stripped_typarams = gens.types.get_slice(space).iter().map(|tp| {
+            tp.clean(cx)
+        }).collect::<Vec<_>>();
+        let stripped_lifetimes = gens.regions.get_slice(space).iter().map(|rp| {
+            let mut srp = rp.clone();
+            srp.bounds = Vec::new();
+            srp.clean(cx)
+        }).collect::<Vec<_>>();
+
+        let mut where_predicates = preds.predicates.get_slice(space)
+                                                   .to_vec().clean(cx);
+
+        // Type parameters and have a Sized bound by default unless removed with
+        // ?Sized.  Scan through the predicates and mark any type parameter with
+        // a Sized bound, removing the bounds as we find them.
+        //
+        // Note that associated types also have a sized bound by default, but we
+        // don't actually know the set of associated types right here so that's
+        // handled in cleaning associated types
+        let mut sized_params = HashSet::new();
+        where_predicates.retain(|pred| {
+            match *pred {
+                WP::BoundPredicate { ty: Generic(ref g), ref bounds } => {
+                    if bounds.iter().any(|b| b.is_sized_bound(cx)) {
+                        sized_params.insert(g.clone());
+                        false
+                    } else {
+                        true
+                    }
+                }
+                _ => true,
+            }
+        });
+
+        // Run through the type parameters again and insert a ?Sized
+        // unbound for any we didn't find to be Sized.
+        for tp in &stripped_typarams {
+            if !sized_params.contains(&tp.name) {
+                where_predicates.push(WP::BoundPredicate {
+                    ty: Type::Generic(tp.name.clone()),
+                    bounds: vec![TyParamBound::maybe_sized(cx)],
+                })
+            }
+        }
+
+        // It would be nice to collect all of the bounds on a type and recombine
+        // them if possible, to avoid e.g. `where T: Foo, T: Bar, T: Sized, T: 'a`
+        // and instead see `where T: Foo + Bar + Sized + 'a`
+
         Generics {
-            type_params: me.types.get_slice(space).to_vec().clean(cx),
-            lifetimes: me.regions.get_slice(space).to_vec().clean(cx),
-            where_predicates: vec![]
+            type_params: simplify::ty_params(stripped_typarams),
+            lifetimes: stripped_lifetimes,
+            where_predicates: simplify::where_clauses(cx, where_predicates),
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Method {
     pub generics: Generics,
     pub self_: SelfTy,
-    pub unsafety: ast::Unsafety,
+    pub unsafety: hir::Unsafety,
+    pub constness: hir::Constness,
     pub decl: FnDecl,
+    pub abi: abi::Abi
 }
 
-impl Clean<Item> for ast::Method {
-    fn clean(&self, cx: &DocContext) -> Item {
-        let all_inputs = &self.pe_fn_decl().inputs;
-        let inputs = match self.pe_explicit_self().node {
-            ast::SelfStatic => all_inputs.as_slice(),
+impl Clean<Method> for hir::MethodSig {
+    fn clean(&self, cx: &DocContext) -> Method {
+        let all_inputs = &self.decl.inputs;
+        let inputs = match self.explicit_self.node {
+            hir::SelfStatic => &**all_inputs,
             _ => &all_inputs[1..]
         };
         let decl = FnDecl {
             inputs: Arguments {
-                values: inputs.iter().map(|x| x.clean(cx)).collect(),
+                values: inputs.clean(cx),
             },
-            output: self.pe_fn_decl().output.clean(cx),
+            output: self.decl.output.clean(cx),
+            variadic: false,
             attrs: Vec::new()
         };
-        Item {
-            name: Some(self.pe_ident().clean(cx)),
-            attrs: self.attrs.clean(cx),
-            source: self.span.clean(cx),
-            def_id: ast_util::local_def(self.id),
-            visibility: self.pe_vis().clean(cx),
-            stability: get_stability(cx, ast_util::local_def(self.id)),
-            inner: MethodItem(Method {
-                generics: self.pe_generics().clean(cx),
-                self_: self.pe_explicit_self().node.clean(cx),
-                unsafety: self.pe_unsafety().clone(),
-                decl: decl,
-            }),
+        Method {
+            generics: self.generics.clean(cx),
+            self_: self.explicit_self.node.clean(cx),
+            unsafety: self.unsafety,
+            constness: self.constness,
+            decl: decl,
+            abi: self.abi
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct TyMethod {
-    pub unsafety: ast::Unsafety,
+    pub unsafety: hir::Unsafety,
     pub decl: FnDecl,
     pub generics: Generics,
     pub self_: SelfTy,
+    pub abi: abi::Abi
 }
 
-impl Clean<Item> for ast::TypeMethod {
-    fn clean(&self, cx: &DocContext) -> Item {
+impl Clean<TyMethod> for hir::MethodSig {
+    fn clean(&self, cx: &DocContext) -> TyMethod {
         let inputs = match self.explicit_self.node {
-            ast::SelfStatic => self.decl.inputs.as_slice(),
+            hir::SelfStatic => &*self.decl.inputs,
             _ => &self.decl.inputs[1..]
         };
         let decl = FnDecl {
             inputs: Arguments {
-                values: inputs.iter().map(|x| x.clean(cx)).collect(),
+                values: inputs.clean(cx),
             },
             output: self.decl.output.clean(cx),
+            variadic: false,
             attrs: Vec::new()
         };
-        Item {
-            name: Some(self.ident.clean(cx)),
-            attrs: self.attrs.clean(cx),
-            source: self.span.clean(cx),
-            def_id: ast_util::local_def(self.id),
-            visibility: None,
-            stability: get_stability(cx, ast_util::local_def(self.id)),
-            inner: TyMethodItem(TyMethod {
-                unsafety: self.unsafety.clone(),
-                decl: decl,
-                self_: self.explicit_self.node.clean(cx),
-                generics: self.generics.clean(cx),
-            }),
+        TyMethod {
+            unsafety: self.unsafety.clone(),
+            decl: decl,
+            self_: self.explicit_self.node.clean(cx),
+            generics: self.generics.clean(cx),
+            abi: self.abi
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq)]
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub enum SelfTy {
     SelfStatic,
     SelfValue,
@@ -872,24 +1059,26 @@ pub enum SelfTy {
     SelfExplicit(Type),
 }
 
-impl Clean<SelfTy> for ast::ExplicitSelf_ {
+impl Clean<SelfTy> for hir::ExplicitSelf_ {
     fn clean(&self, cx: &DocContext) -> SelfTy {
         match *self {
-            ast::SelfStatic => SelfStatic,
-            ast::SelfValue(_) => SelfValue,
-            ast::SelfRegion(ref lt, ref mt, _) => {
+            hir::SelfStatic => SelfStatic,
+            hir::SelfValue(_) => SelfValue,
+            hir::SelfRegion(ref lt, ref mt, _) => {
                 SelfBorrowed(lt.clean(cx), mt.clean(cx))
             }
-            ast::SelfExplicit(ref typ, _) => SelfExplicit(typ.clean(cx)),
+            hir::SelfExplicit(ref typ, _) => SelfExplicit(typ.clean(cx)),
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Function {
     pub decl: FnDecl,
     pub generics: Generics,
-    pub unsafety: ast::Unsafety,
+    pub unsafety: hir::Unsafety,
+    pub constness: hir::Constness,
+    pub abi: abi::Abi,
 }
 
 impl Clean<Item> for doctree::Function {
@@ -900,56 +1089,39 @@ impl Clean<Item> for doctree::Function {
             source: self.whence.clean(cx),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
-            def_id: ast_util::local_def(self.id),
+            def_id: DefId::local(self.id),
             inner: FunctionItem(Function {
                 decl: self.decl.clean(cx),
                 generics: self.generics.clean(cx),
                 unsafety: self.unsafety,
+                constness: self.constness,
+                abi: self.abi,
             }),
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
-pub struct ClosureDecl {
-    pub lifetimes: Vec<Lifetime>,
-    pub decl: FnDecl,
-    pub onceness: ast::Onceness,
-    pub unsafety: ast::Unsafety,
-    pub bounds: Vec<TyParamBound>,
-}
-
-impl Clean<ClosureDecl> for ast::ClosureTy {
-    fn clean(&self, cx: &DocContext) -> ClosureDecl {
-        ClosureDecl {
-            lifetimes: self.lifetimes.clean(cx),
-            decl: self.decl.clean(cx),
-            onceness: self.onceness,
-            unsafety: self.unsafety,
-            bounds: self.bounds.clean(cx)
-        }
-    }
-}
-
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub struct FnDecl {
     pub inputs: Arguments,
     pub output: FunctionRetTy,
+    pub variadic: bool,
     pub attrs: Vec<Attribute>,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub struct Arguments {
     pub values: Vec<Argument>,
 }
 
-impl Clean<FnDecl> for ast::FnDecl {
+impl Clean<FnDecl> for hir::FnDecl {
     fn clean(&self, cx: &DocContext) -> FnDecl {
         FnDecl {
             inputs: Arguments {
                 values: self.inputs.clean(cx),
             },
             output: self.output.clean(cx),
+            variadic: self.variadic,
             attrs: Vec::new()
         }
     }
@@ -964,7 +1136,7 @@ impl<'tcx> Clean<Type> for ty::FnOutput<'tcx> {
     }
 }
 
-impl<'a, 'tcx> Clean<FnDecl> for (ast::DefId, &'a ty::PolyFnSig<'tcx>) {
+impl<'a, 'tcx> Clean<FnDecl> for (DefId, &'a ty::PolyFnSig<'tcx>) {
     fn clean(&self, cx: &DocContext) -> FnDecl {
         let (did, sig) = *self;
         let mut names = if did.node != 0 {
@@ -972,12 +1144,13 @@ impl<'a, 'tcx> Clean<FnDecl> for (ast::DefId, &'a ty::PolyFnSig<'tcx>) {
         } else {
             Vec::new().into_iter()
         }.peekable();
-        if names.peek().map(|s| s.as_slice()) == Some("self") {
+        if names.peek().map(|s| &**s) == Some("self") {
             let _ = names.next();
         }
         FnDecl {
             output: Return(sig.0.output.clean(cx)),
             attrs: Vec::new(),
+            variadic: sig.0.variadic,
             inputs: Arguments {
                 values: sig.0.inputs.iter().map(|t| {
                     Argument {
@@ -991,14 +1164,14 @@ impl<'a, 'tcx> Clean<FnDecl> for (ast::DefId, &'a ty::PolyFnSig<'tcx>) {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub struct Argument {
     pub type_: Type,
     pub name: String,
     pub id: ast::NodeId,
 }
 
-impl Clean<Argument> for ast::Arg {
+impl Clean<Argument> for hir::Arg {
     fn clean(&self, cx: &DocContext) -> Argument {
         Argument {
             name: name_from_pat(&*self.pat),
@@ -1008,25 +1181,27 @@ impl Clean<Argument> for ast::Arg {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub enum FunctionRetTy {
     Return(Type),
+    DefaultReturn,
     NoReturn
 }
 
-impl Clean<FunctionRetTy> for ast::FunctionRetTy {
+impl Clean<FunctionRetTy> for hir::FunctionRetTy {
     fn clean(&self, cx: &DocContext) -> FunctionRetTy {
         match *self {
-            ast::Return(ref typ) => Return(typ.clean(cx)),
-            ast::NoReturn(_) => NoReturn
+            hir::Return(ref typ) => Return(typ.clean(cx)),
+            hir::DefaultReturn(..) => DefaultReturn,
+            hir::NoReturn(..) => NoReturn
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Trait {
-    pub unsafety: ast::Unsafety,
-    pub items: Vec<TraitMethod>,
+    pub unsafety: hir::Unsafety,
+    pub items: Vec<Item>,
     pub generics: Generics,
     pub bounds: Vec<TyParamBound>,
 }
@@ -1037,7 +1212,7 @@ impl Clean<Item> for doctree::Trait {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            def_id: ast_util::local_def(self.id),
+            def_id: DefId::local(self.id),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
             inner: TraitItem(Trait {
@@ -1050,13 +1225,13 @@ impl Clean<Item> for doctree::Trait {
     }
 }
 
-impl Clean<Type> for ast::TraitRef {
+impl Clean<Type> for hir::TraitRef {
     fn clean(&self, cx: &DocContext) -> Type {
         resolve_type(cx, self.path.clean(cx), self.ref_id)
     }
 }
 
-impl Clean<PolyTrait> for ast::PolyTraitRef {
+impl Clean<PolyTrait> for hir::PolyTraitRef {
     fn clean(&self, cx: &DocContext) -> PolyTrait {
         PolyTrait {
             trait_: self.trait_ref.clean(cx),
@@ -1065,64 +1240,65 @@ impl Clean<PolyTrait> for ast::PolyTraitRef {
     }
 }
 
-/// An item belonging to a trait, whether a method or associated. Could be named
-/// TraitItem except that's already taken by an exported enum variant.
-#[derive(Clone, RustcEncodable, RustcDecodable)]
-pub enum TraitMethod {
-    RequiredMethod(Item),
-    ProvidedMethod(Item),
-    TypeTraitItem(Item),
-}
-
-impl TraitMethod {
-    pub fn is_req(&self) -> bool {
-        match self {
-            &RequiredMethod(..) => true,
-            _ => false,
-        }
-    }
-    pub fn is_def(&self) -> bool {
-        match self {
-            &ProvidedMethod(..) => true,
-            _ => false,
-        }
-    }
-    pub fn is_type(&self) -> bool {
-        match self {
-            &TypeTraitItem(..) => true,
-            _ => false,
-        }
-    }
-    pub fn item<'a>(&'a self) -> &'a Item {
-        match *self {
-            RequiredMethod(ref item) => item,
-            ProvidedMethod(ref item) => item,
-            TypeTraitItem(ref item) => item,
-        }
-    }
-}
-
-impl Clean<TraitMethod> for ast::TraitItem {
-    fn clean(&self, cx: &DocContext) -> TraitMethod {
-        match self {
-            &ast::RequiredMethod(ref t) => RequiredMethod(t.clean(cx)),
-            &ast::ProvidedMethod(ref t) => ProvidedMethod(t.clean(cx)),
-            &ast::TypeTraitItem(ref t) => TypeTraitItem(t.clean(cx)),
+impl Clean<Item> for hir::TraitItem {
+    fn clean(&self, cx: &DocContext) -> Item {
+        let inner = match self.node {
+            hir::ConstTraitItem(ref ty, ref default) => {
+                AssociatedConstItem(ty.clean(cx),
+                                    default.as_ref().map(|expr|
+                                                         expr.span.to_src(cx)))
+            }
+            hir::MethodTraitItem(ref sig, Some(_)) => {
+                MethodItem(sig.clean(cx))
+            }
+            hir::MethodTraitItem(ref sig, None) => {
+                TyMethodItem(sig.clean(cx))
+            }
+            hir::TypeTraitItem(ref bounds, ref default) => {
+                AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
+            }
+        };
+        Item {
+            name: Some(self.ident.clean(cx)),
+            attrs: self.attrs.clean(cx),
+            source: self.span.clean(cx),
+            def_id: DefId::local(self.id),
+            visibility: None,
+            stability: get_stability(cx, DefId::local(self.id)),
+            inner: inner
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
-pub enum ImplMethod {
-    MethodImplItem(Item),
-    TypeImplItem(Item),
-}
-
-impl Clean<ImplMethod> for ast::ImplItem {
-    fn clean(&self, cx: &DocContext) -> ImplMethod {
-        match self {
-            &ast::MethodImplItem(ref t) => MethodImplItem(t.clean(cx)),
-            &ast::TypeImplItem(ref t) => TypeImplItem(t.clean(cx)),
+impl Clean<Item> for hir::ImplItem {
+    fn clean(&self, cx: &DocContext) -> Item {
+        let inner = match self.node {
+            hir::ConstImplItem(ref ty, ref expr) => {
+                ConstantItem(Constant{
+                    type_: ty.clean(cx),
+                    expr: expr.span.to_src(cx),
+                })
+            }
+            hir::MethodImplItem(ref sig, _) => {
+                MethodItem(sig.clean(cx))
+            }
+            hir::TypeImplItem(ref ty) => TypedefItem(Typedef {
+                type_: ty.clean(cx),
+                generics: Generics {
+                    lifetimes: Vec::new(),
+                    type_params: Vec::new(),
+                    where_predicates: Vec::new()
+                },
+            }, true),
+        };
+        Item {
+            name: Some(self.ident.clean(cx)),
+            source: self.span.clean(cx),
+            attrs: self.attrs.clean(cx),
+            def_id: DefId::local(self.id),
+            visibility: self.vis.clean(cx),
+            stability: get_stability(cx, DefId::local(self.id)),
+            inner: inner
         }
     }
 }
@@ -1130,7 +1306,7 @@ impl Clean<ImplMethod> for ast::ImplItem {
 impl<'tcx> Clean<Item> for ty::Method<'tcx> {
     fn clean(&self, cx: &DocContext) -> Item {
         let (self_, sig) = match self.explicit_self {
-            ty::StaticExplicitSelfCategory => (ast::SelfStatic.clean(cx),
+            ty::StaticExplicitSelfCategory => (hir::SelfStatic.clean(cx),
                                                self.fty.sig.clone()),
             s => {
                 let sig = ty::Binder(ty::FnSig {
@@ -1141,7 +1317,7 @@ impl<'tcx> Clean<Item> for ty::Method<'tcx> {
                     ty::ByValueExplicitSelfCategory => SelfValue,
                     ty::ByReferenceExplicitSelfCategory(..) => {
                         match self.fty.sig.0.inputs[0].sty {
-                            ty::ty_rptr(r, mt) => {
+                            ty::TyRef(r, mt) => {
                                 SelfBorrowed(r.clean(cx), mt.mutbl.clean(cx))
                             }
                             _ => unreachable!(),
@@ -1156,19 +1332,46 @@ impl<'tcx> Clean<Item> for ty::Method<'tcx> {
             }
         };
 
+        let generics = (&self.generics, &self.predicates,
+                        subst::FnSpace).clean(cx);
+        let decl = (self.def_id, &sig).clean(cx);
+        let provided = match self.container {
+            ty::ImplContainer(..) => false,
+            ty::TraitContainer(did) => {
+                cx.tcx().provided_trait_methods(did).iter().any(|m| {
+                    m.def_id == self.def_id
+                })
+            }
+        };
+        let inner = if provided {
+            MethodItem(Method {
+                unsafety: self.fty.unsafety,
+                generics: generics,
+                self_: self_,
+                decl: decl,
+                abi: self.fty.abi,
+
+                // trait methods canot (currently, at least) be const
+                constness: hir::Constness::NotConst,
+            })
+        } else {
+            TyMethodItem(TyMethod {
+                unsafety: self.fty.unsafety,
+                generics: generics,
+                self_: self_,
+                decl: decl,
+                abi: self.fty.abi,
+            })
+        };
+
         Item {
             name: Some(self.name.clean(cx)),
-            visibility: Some(ast::Inherited),
+            visibility: Some(hir::Inherited),
             stability: get_stability(cx, self.def_id),
             def_id: self.def_id,
             attrs: inline::load_attrs(cx, cx.tcx(), self.def_id),
             source: Span::empty(),
-            inner: TyMethodItem(TyMethod {
-                unsafety: self.fty.unsafety,
-                generics: (&self.generics, subst::FnSpace).clean(cx),
-                self_: self_,
-                decl: (self.def_id, &sig).clean(cx),
-            })
+            inner: inner,
         }
     }
 }
@@ -1176,6 +1379,7 @@ impl<'tcx> Clean<Item> for ty::Method<'tcx> {
 impl<'tcx> Clean<Item> for ty::ImplOrTraitItem<'tcx> {
     fn clean(&self, cx: &DocContext) -> Item {
         match *self {
+            ty::ConstTraitItem(ref cti) => cti.clean(cx),
             ty::MethodTraitItem(ref mti) => mti.clean(cx),
             ty::TypeTraitItem(ref tti) => tti.clean(cx),
         }
@@ -1183,7 +1387,7 @@ impl<'tcx> Clean<Item> for ty::ImplOrTraitItem<'tcx> {
 }
 
 /// A trait reference, which may have higher ranked lifetimes.
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub struct PolyTrait {
     pub trait_: Type,
     pub lifetimes: Vec<Lifetime>
@@ -1192,23 +1396,22 @@ pub struct PolyTrait {
 /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
 /// type out of the AST/ty::ctxt given one of these, if more information is needed. Most importantly
 /// it does not preserve mutability or boxes.
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub enum Type {
-    /// structs/enums/traits (anything that'd be an ast::TyPath)
+    /// structs/enums/traits (most that'd be an hir::TyPath)
     ResolvedPath {
         path: Path,
         typarams: Option<Vec<TyParamBound>>,
-        did: ast::DefId,
+        did: DefId,
+        /// true if is a `T::Name` path for associated types
+        is_generic: bool,
     },
-    // I have no idea how to usefully use this.
-    TyParamBinder(ast::NodeId),
     /// For parameterized types, so the consumer of the JSON don't go
     /// looking for types which don't exist anywhere.
     Generic(String),
-    /// Primitives are just the fixed-size numeric types (plus int/uint/float), and char.
+    /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
+    /// arrays, slices, and tuples.
     Primitive(PrimitiveType),
-    Closure(Box<ClosureDecl>),
-    Proc(Box<ClosureDecl>),
     /// extern "ABI" fn
     BareFunction(Box<BareFunctionDecl>),
     Tuple(Vec<Type>),
@@ -1238,7 +1441,7 @@ pub enum Type {
     PolyTraitRef(Vec<TyParamBound>),
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
 pub enum PrimitiveType {
     Isize, I8, I16, I32, I64,
     Usize, U8, U16, U32, U64,
@@ -1247,10 +1450,12 @@ pub enum PrimitiveType {
     Bool,
     Str,
     Slice,
+    Array,
     PrimitiveTuple,
+    PrimitiveRawPointer,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Copy)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
 pub enum TypeKind {
     TypeEnum,
     TypeFunction,
@@ -1263,15 +1468,30 @@ pub enum TypeKind {
     TypeTypedef,
 }
 
+impl Type {
+    pub fn primitive_type(&self) -> Option<PrimitiveType> {
+        match *self {
+            Primitive(p) | BorrowedRef { type_: box Primitive(p), ..} => Some(p),
+            Vector(..) | BorrowedRef{ type_: box Vector(..), ..  } => Some(Slice),
+            FixedVector(..) | BorrowedRef { type_: box FixedVector(..), .. } => {
+                Some(Array)
+            }
+            Tuple(..) => Some(PrimitiveTuple),
+            RawPointer(..) => Some(PrimitiveRawPointer),
+            _ => None,
+        }
+    }
+}
+
 impl PrimitiveType {
     fn from_str(s: &str) -> Option<PrimitiveType> {
-        match s.as_slice() {
-            "isize" | "int" => Some(Isize),
+        match s {
+            "isize" => Some(Isize),
             "i8" => Some(I8),
             "i16" => Some(I16),
             "i32" => Some(I32),
             "i64" => Some(I64),
-            "usize" | "uint" => Some(Usize),
+            "usize" => Some(Usize),
             "u8" => Some(U8),
             "u16" => Some(U16),
             "u32" => Some(U32),
@@ -1281,22 +1501,24 @@ impl PrimitiveType {
             "str" => Some(Str),
             "f32" => Some(F32),
             "f64" => Some(F64),
+            "array" => Some(Array),
             "slice" => Some(Slice),
             "tuple" => Some(PrimitiveTuple),
+            "pointer" => Some(PrimitiveRawPointer),
             _ => None,
         }
     }
 
     fn find(attrs: &[Attribute]) -> Option<PrimitiveType> {
-        for attr in attrs.iter() {
+        for attr in attrs {
             let list = match *attr {
                 List(ref k, ref l) if *k == "doc" => l,
                 _ => continue,
             };
-            for sub_attr in list.iter() {
+            for sub_attr in list {
                 let value = match *sub_attr {
                     NameValue(ref k, ref v)
-                        if *k == "primitive" => v.as_slice(),
+                        if *k == "primitive" => v,
                     _ => continue,
                 };
                 match PrimitiveType::from_str(value) {
@@ -1325,8 +1547,10 @@ impl PrimitiveType {
             Str => "str",
             Bool => "bool",
             Char => "char",
+            Array => "array",
             Slice => "slice",
             PrimitiveTuple => "tuple",
+            PrimitiveRawPointer => "pointer",
         }
     }
 
@@ -1342,9 +1566,9 @@ impl PrimitiveType {
     }
 }
 
-impl Clean<Type> for ast::Ty {
+impl Clean<Type> for hir::Ty {
     fn clean(&self, cx: &DocContext) -> Type {
-        use syntax::ast::*;
+        use rustc_front::hir::*;
         match self.node {
             TyPtr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
             TyRptr(ref l, ref m) =>
@@ -1354,14 +1578,28 @@ impl Clean<Type> for ast::Ty {
             TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx),
                                                            e.span.to_src(cx)),
             TyTup(ref tys) => Tuple(tys.clean(cx)),
-            TyPath(ref p, id) => {
-                resolve_type(cx, p.clean(cx), id)
+            TyPath(None, ref p) => {
+                resolve_type(cx, p.clean(cx), self.id)
+            }
+            TyPath(Some(ref qself), ref p) => {
+                let mut trait_path = p.clone();
+                trait_path.segments.pop();
+                Type::QPath {
+                    name: p.segments.last().unwrap().identifier.clean(cx),
+                    self_type: box qself.ty.clean(cx),
+                    trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
+                }
             }
             TyObjectSum(ref lhs, ref bounds) => {
                 let lhs_ty = lhs.clean(cx);
                 match lhs_ty {
-                    ResolvedPath { path, typarams: None, did } => {
-                        ResolvedPath { path: path, typarams: Some(bounds.clean(cx)), did: did}
+                    ResolvedPath { path, typarams: None, did, is_generic } => {
+                        ResolvedPath {
+                            path: path,
+                            typarams: Some(bounds.clean(cx)),
+                            did: did,
+                            is_generic: is_generic,
+                        }
                     }
                     _ => {
                         lhs_ty // shouldn't happen
@@ -1370,7 +1608,6 @@ impl Clean<Type> for ast::Ty {
             }
             TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
             TyParen(ref ty) => ty.clean(cx),
-            TyQPath(ref qp) => qp.clean(cx),
             TyPolyTraitRef(ref bounds) => {
                 PolyTraitRef(bounds.clean(cx))
             },
@@ -1387,171 +1624,152 @@ impl Clean<Type> for ast::Ty {
 impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
     fn clean(&self, cx: &DocContext) -> Type {
         match self.sty {
-            ty::ty_bool => Primitive(Bool),
-            ty::ty_char => Primitive(Char),
-            ty::ty_int(ast::TyIs(_)) => Primitive(Isize),
-            ty::ty_int(ast::TyI8) => Primitive(I8),
-            ty::ty_int(ast::TyI16) => Primitive(I16),
-            ty::ty_int(ast::TyI32) => Primitive(I32),
-            ty::ty_int(ast::TyI64) => Primitive(I64),
-            ty::ty_uint(ast::TyUs(_)) => Primitive(Usize),
-            ty::ty_uint(ast::TyU8) => Primitive(U8),
-            ty::ty_uint(ast::TyU16) => Primitive(U16),
-            ty::ty_uint(ast::TyU32) => Primitive(U32),
-            ty::ty_uint(ast::TyU64) => Primitive(U64),
-            ty::ty_float(ast::TyF32) => Primitive(F32),
-            ty::ty_float(ast::TyF64) => Primitive(F64),
-            ty::ty_str => Primitive(Str),
-            ty::ty_uniq(t) => {
+            ty::TyBool => Primitive(Bool),
+            ty::TyChar => Primitive(Char),
+            ty::TyInt(hir::TyIs) => Primitive(Isize),
+            ty::TyInt(hir::TyI8) => Primitive(I8),
+            ty::TyInt(hir::TyI16) => Primitive(I16),
+            ty::TyInt(hir::TyI32) => Primitive(I32),
+            ty::TyInt(hir::TyI64) => Primitive(I64),
+            ty::TyUint(hir::TyUs) => Primitive(Usize),
+            ty::TyUint(hir::TyU8) => Primitive(U8),
+            ty::TyUint(hir::TyU16) => Primitive(U16),
+            ty::TyUint(hir::TyU32) => Primitive(U32),
+            ty::TyUint(hir::TyU64) => Primitive(U64),
+            ty::TyFloat(hir::TyF32) => Primitive(F32),
+            ty::TyFloat(hir::TyF64) => Primitive(F64),
+            ty::TyStr => Primitive(Str),
+            ty::TyBox(t) => {
                 let box_did = cx.tcx_opt().and_then(|tcx| {
                     tcx.lang_items.owned_box()
                 });
                 lang_struct(cx, box_did, t, "Box", Unique)
             }
-            ty::ty_vec(ty, None) => Vector(box ty.clean(cx)),
-            ty::ty_vec(ty, Some(i)) => FixedVector(box ty.clean(cx),
-                                                   format!("{}", i)),
-            ty::ty_ptr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
-            ty::ty_rptr(r, mt) => BorrowedRef {
+            ty::TySlice(ty) => Vector(box ty.clean(cx)),
+            ty::TyArray(ty, i) => FixedVector(box ty.clean(cx),
+                                              format!("{}", i)),
+            ty::TyRawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
+            ty::TyRef(r, mt) => BorrowedRef {
                 lifetime: r.clean(cx),
                 mutability: mt.mutbl.clean(cx),
                 type_: box mt.ty.clean(cx),
             },
-            ty::ty_bare_fn(_, ref fty) => BareFunction(box BareFunctionDecl {
+            ty::TyBareFn(_, ref fty) => BareFunction(box BareFunctionDecl {
                 unsafety: fty.unsafety,
                 generics: Generics {
                     lifetimes: Vec::new(),
                     type_params: Vec::new(),
                     where_predicates: Vec::new()
                 },
-                decl: (ast_util::local_def(0), &fty.sig).clean(cx),
+                decl: (DefId::local(0), &fty.sig).clean(cx),
                 abi: fty.abi.to_string(),
             }),
-            ty::ty_struct(did, substs) |
-            ty::ty_enum(did, substs) => {
+            ty::TyStruct(def, substs) |
+            ty::TyEnum(def, substs) => {
+                let did = def.did;
                 let fqn = csearch::get_item_path(cx.tcx(), did);
                 let fqn: Vec<_> = fqn.into_iter().map(|i| i.to_string()).collect();
                 let kind = match self.sty {
-                    ty::ty_struct(..) => TypeStruct,
+                    ty::TyStruct(..) => TypeStruct,
                     _ => TypeEnum,
                 };
-                let path = external_path(cx, fqn.last().unwrap().to_string().as_slice(),
-                                         None, substs);
+                let path = external_path(cx, &fqn.last().unwrap().to_string(),
+                                         None, vec![], substs);
                 cx.external_paths.borrow_mut().as_mut().unwrap().insert(did, (fqn, kind));
                 ResolvedPath {
                     path: path,
                     typarams: None,
                     did: did,
+                    is_generic: false,
                 }
             }
-            ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => {
+            ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => {
                 let did = principal.def_id();
                 let fqn = csearch::get_item_path(cx.tcx(), did);
                 let fqn: Vec<_> = fqn.into_iter().map(|i| i.to_string()).collect();
-                let path = external_path(cx, fqn.last().unwrap().to_string().as_slice(),
-                                         Some(did), principal.substs());
+                let (typarams, bindings) = bounds.clean(cx);
+                let path = external_path(cx, &fqn.last().unwrap().to_string(),
+                                         Some(did), bindings, principal.substs());
                 cx.external_paths.borrow_mut().as_mut().unwrap().insert(did, (fqn, TypeTrait));
                 ResolvedPath {
                     path: path,
-                    typarams: Some(bounds.clean(cx)),
+                    typarams: Some(typarams),
                     did: did,
+                    is_generic: false,
                 }
             }
-            ty::ty_tup(ref t) => Tuple(t.clean(cx)),
+            ty::TyTuple(ref t) => Tuple(t.clean(cx)),
 
-            ty::ty_projection(ref data) => {
-                let trait_ref = match data.trait_ref.clean(cx) {
-                    TyParamBound::TraitBound(t, _) => t.trait_,
-                    TyParamBound::RegionBound(_) => panic!("cleaning a trait got a region??"),
-                };
-                Type::QPath {
-                    name: data.item_name.clean(cx),
-                    self_type: box data.trait_ref.self_ty().clean(cx),
-                    trait_: box trait_ref,
-                }
-            }
-
-            ty::ty_param(ref p) => Generic(token::get_name(p.name).to_string()),
+            ty::TyProjection(ref data) => data.clean(cx),
 
-            ty::ty_unboxed_closure(..) => Tuple(vec![]), // FIXME(pcwalton)
+            ty::TyParam(ref p) => Generic(p.name.to_string()),
 
-            ty::ty_infer(..) => panic!("ty_infer"),
-            ty::ty_open(..) => panic!("ty_open"),
-            ty::ty_err => panic!("ty_err"),
-        }
-    }
-}
+            ty::TyClosure(..) => Tuple(vec![]), // FIXME(pcwalton)
 
-impl Clean<Type> for ast::QPath {
-    fn clean(&self, cx: &DocContext) -> Type {
-        Type::QPath {
-            name: self.item_name.clean(cx),
-            self_type: box self.self_type.clean(cx),
-            trait_: box self.trait_ref.clean(cx)
+            ty::TyInfer(..) => panic!("TyInfer"),
+            ty::TyError => panic!("TyError"),
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub enum StructField {
     HiddenStructField, // inserted later by strip passes
     TypedStructField(Type),
 }
 
-impl Clean<Item> for ast::StructField {
+impl Clean<Item> for hir::StructField {
     fn clean(&self, cx: &DocContext) -> Item {
         let (name, vis) = match self.node.kind {
-            ast::NamedField(id, vis) => (Some(id), vis),
-            ast::UnnamedField(vis) => (None, vis)
+            hir::NamedField(id, vis) => (Some(id), vis),
+            hir::UnnamedField(vis) => (None, vis)
         };
         Item {
             name: name.clean(cx),
             attrs: self.node.attrs.clean(cx),
             source: self.span.clean(cx),
             visibility: Some(vis),
-            stability: get_stability(cx, ast_util::local_def(self.node.id)),
-            def_id: ast_util::local_def(self.node.id),
+            stability: get_stability(cx, DefId::local(self.node.id)),
+            def_id: DefId::local(self.node.id),
             inner: StructFieldItem(TypedStructField(self.node.ty.clean(cx))),
         }
     }
 }
 
-impl Clean<Item> for ty::field_ty {
+impl<'tcx> Clean<Item> for ty::FieldDefData<'tcx, 'static> {
     fn clean(&self, cx: &DocContext) -> Item {
         use syntax::parse::token::special_idents::unnamed_field;
         use rustc::metadata::csearch;
 
-        let attr_map = csearch::get_struct_field_attrs(&cx.tcx().sess.cstore, self.id);
+        let attr_map = csearch::get_struct_field_attrs(&cx.tcx().sess.cstore, self.did);
 
         let (name, attrs) = if self.name == unnamed_field.name {
             (None, None)
         } else {
-            (Some(self.name), Some(attr_map.get(&self.id.node).unwrap()))
+            (Some(self.name), Some(attr_map.get(&self.did.node).unwrap()))
         };
 
-        let ty = ty::lookup_item_type(cx.tcx(), self.id);
-
         Item {
             name: name.clean(cx),
             attrs: attrs.unwrap_or(&Vec::new()).clean(cx),
             source: Span::empty(),
             visibility: Some(self.vis),
-            stability: get_stability(cx, self.id),
-            def_id: self.id,
-            inner: StructFieldItem(TypedStructField(ty.ty.clean(cx))),
+            stability: get_stability(cx, self.did),
+            def_id: self.did,
+            inner: StructFieldItem(TypedStructField(self.unsubst_ty().clean(cx))),
         }
     }
 }
 
-pub type Visibility = ast::Visibility;
+pub type Visibility = hir::Visibility;
 
-impl Clean<Option<Visibility>> for ast::Visibility {
+impl Clean<Option<Visibility>> for hir::Visibility {
     fn clean(&self, _: &DocContext) -> Option<Visibility> {
         Some(*self)
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Struct {
     pub struct_type: doctree::StructType,
     pub generics: Generics,
@@ -1565,7 +1783,7 @@ impl Clean<Item> for doctree::Struct {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            def_id: ast_util::local_def(self.id),
+            def_id: DefId::local(self.id),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
             inner: StructItem(Struct {
@@ -1581,14 +1799,14 @@ impl Clean<Item> for doctree::Struct {
 /// This is a more limited form of the standard Struct, different in that
 /// it lacks the things most items have (name, id, parameterization). Found
 /// only as a variant in an enum.
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct VariantStruct {
     pub struct_type: doctree::StructType,
     pub fields: Vec<Item>,
     pub fields_stripped: bool,
 }
 
-impl Clean<VariantStruct> for syntax::ast::StructDef {
+impl Clean<VariantStruct> for ::rustc_front::hir::StructDef {
     fn clean(&self, cx: &DocContext) -> VariantStruct {
         VariantStruct {
             struct_type: doctree::struct_type_from_def(self),
@@ -1598,7 +1816,7 @@ impl Clean<VariantStruct> for syntax::ast::StructDef {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Enum {
     pub variants: Vec<Item>,
     pub generics: Generics,
@@ -1611,7 +1829,7 @@ impl Clean<Item> for doctree::Enum {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            def_id: ast_util::local_def(self.id),
+            def_id: DefId::local(self.id),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
             inner: EnumItem(Enum {
@@ -1623,7 +1841,7 @@ impl Clean<Item> for doctree::Enum {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Variant {
     pub kind: VariantKind,
 }
@@ -1636,7 +1854,7 @@ impl Clean<Item> for doctree::Variant {
             source: self.whence.clean(cx),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
-            def_id: ast_util::local_def(self.id),
+            def_id: DefId::local(self.id),
             inner: VariantItem(Variant {
                 kind: self.kind.clean(cx),
             }),
@@ -1644,24 +1862,26 @@ impl Clean<Item> for doctree::Variant {
     }
 }
 
-impl<'tcx> Clean<Item> for ty::VariantInfo<'tcx> {
+impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
     fn clean(&self, cx: &DocContext) -> Item {
         // use syntax::parse::token::special_idents::unnamed_field;
-        let kind = match self.arg_names.as_ref().map(|s| s.as_slice()) {
-            None | Some([]) if self.args.len() == 0 => CLikeVariant,
-            None | Some([]) => {
-                TupleVariant(self.args.clean(cx))
+        let kind = match self.kind() {
+            ty::VariantKind::Unit => CLikeVariant,
+            ty::VariantKind::Tuple => {
+                TupleVariant(
+                    self.fields.iter().map(|f| f.unsubst_ty().clean(cx)).collect()
+                )
             }
-            Some(s) => {
+            ty::VariantKind::Dict => {
                 StructVariant(VariantStruct {
                     struct_type: doctree::Plain,
                     fields_stripped: false,
-                    fields: s.iter().zip(self.args.iter()).map(|(name, ty)| {
+                    fields: self.fields.iter().map(|field| {
                         Item {
                             source: Span::empty(),
-                            name: Some(name.clean(cx)),
+                            name: Some(field.name.clean(cx)),
                             attrs: Vec::new(),
-                            visibility: Some(ast::Public),
+                            visibility: Some(hir::Public),
                             // FIXME: this is not accurate, we need an id for
                             //        the specific field but we're using the id
                             //        for the whole variant. Thus we read the
@@ -1669,10 +1889,10 @@ impl<'tcx> Clean<Item> for ty::VariantInfo<'tcx> {
                             //        Struct variants are experimental and need
                             //        more infrastructure work before we can get
                             //        at the needed information here.
-                            def_id: self.id,
-                            stability: get_stability(cx, self.id),
+                            def_id: self.did,
+                            stability: get_stability(cx, self.did),
                             inner: StructFieldItem(
-                                TypedStructField(ty.clean(cx))
+                                TypedStructField(field.unsubst_ty().clean(cx))
                             )
                         }
                     }).collect()
@@ -1681,45 +1901,45 @@ impl<'tcx> Clean<Item> for ty::VariantInfo<'tcx> {
         };
         Item {
             name: Some(self.name.clean(cx)),
-            attrs: inline::load_attrs(cx, cx.tcx(), self.id),
+            attrs: inline::load_attrs(cx, cx.tcx(), self.did),
             source: Span::empty(),
-            visibility: Some(ast::Public),
-            def_id: self.id,
+            visibility: Some(hir::Public),
+            def_id: self.did,
             inner: VariantItem(Variant { kind: kind }),
-            stability: get_stability(cx, self.id),
+            stability: get_stability(cx, self.did),
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub enum VariantKind {
     CLikeVariant,
     TupleVariant(Vec<Type>),
     StructVariant(VariantStruct),
 }
 
-impl Clean<VariantKind> for ast::VariantKind {
+impl Clean<VariantKind> for hir::VariantKind {
     fn clean(&self, cx: &DocContext) -> VariantKind {
         match self {
-            &ast::TupleVariantKind(ref args) => {
-                if args.len() == 0 {
+            &hir::TupleVariantKind(ref args) => {
+                if args.is_empty() {
                     CLikeVariant
                 } else {
                     TupleVariant(args.iter().map(|x| x.ty.clean(cx)).collect())
                 }
             },
-            &ast::StructVariantKind(ref sd) => StructVariant(sd.clean(cx)),
+            &hir::StructVariantKind(ref sd) => StructVariant(sd.clean(cx)),
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Span {
     pub filename: String,
-    pub loline: uint,
-    pub locol: uint,
-    pub hiline: uint,
-    pub hicol: uint,
+    pub loline: usize,
+    pub locol: usize,
+    pub hiline: usize,
+    pub hicol: usize,
 }
 
 impl Span {
@@ -1734,6 +1954,10 @@ impl Span {
 
 impl Clean<Span> for syntax::codemap::Span {
     fn clean(&self, cx: &DocContext) -> Span {
+        if *self == DUMMY_SP {
+            return Span::empty();
+        }
+
         let cm = cx.sess().codemap();
         let filename = cm.span_to_filename(*self);
         let lo = cm.lookup_char_pos(self.lo);
@@ -1741,20 +1965,36 @@ impl Clean<Span> for syntax::codemap::Span {
         Span {
             filename: filename.to_string(),
             loline: lo.line,
-            locol: lo.col.to_uint(),
+            locol: lo.col.to_usize(),
             hiline: hi.line,
-            hicol: hi.col.to_uint(),
+            hicol: hi.col.to_usize(),
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub struct Path {
     pub global: bool,
     pub segments: Vec<PathSegment>,
 }
 
-impl Clean<Path> for ast::Path {
+impl Path {
+    pub fn singleton(name: String) -> Path {
+        Path {
+            global: false,
+            segments: vec![PathSegment {
+                name: name,
+                params: PathParameters::AngleBracketed {
+                    lifetimes: Vec::new(),
+                    types: Vec::new(),
+                    bindings: Vec::new()
+                }
+            }]
+        }
+    }
+}
+
+impl Clean<Path> for hir::Path {
     fn clean(&self, cx: &DocContext) -> Path {
         Path {
             global: self.global,
@@ -1763,7 +2003,7 @@ impl Clean<Path> for ast::Path {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub enum PathParameters {
     AngleBracketed {
         lifetimes: Vec<Lifetime>,
@@ -1776,10 +2016,10 @@ pub enum PathParameters {
     }
 }
 
-impl Clean<PathParameters> for ast::PathParameters {
+impl Clean<PathParameters> for hir::PathParameters {
     fn clean(&self, cx: &DocContext) -> PathParameters {
         match *self {
-            ast::AngleBracketedParameters(ref data) => {
+            hir::AngleBracketedParameters(ref data) => {
                 PathParameters::AngleBracketed {
                     lifetimes: data.lifetimes.clean(cx),
                     types: data.types.clean(cx),
@@ -1787,7 +2027,7 @@ impl Clean<PathParameters> for ast::PathParameters {
                 }
             }
 
-            ast::ParenthesizedParameters(ref data) => {
+            hir::ParenthesizedParameters(ref data) => {
                 PathParameters::Parenthesized {
                     inputs: data.inputs.clean(cx),
                     output: data.output.clean(cx)
@@ -1797,13 +2037,13 @@ impl Clean<PathParameters> for ast::PathParameters {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub struct PathSegment {
     pub name: String,
     pub params: PathParameters
 }
 
-impl Clean<PathSegment> for ast::PathSegment {
+impl Clean<PathSegment> for hir::PathSegment {
     fn clean(&self, cx: &DocContext) -> PathSegment {
         PathSegment {
             name: self.identifier.clean(cx),
@@ -1812,33 +2052,33 @@ impl Clean<PathSegment> for ast::PathSegment {
     }
 }
 
-fn path_to_string(p: &ast::Path) -> String {
+fn path_to_string(p: &hir::Path) -> String {
     let mut s = String::new();
     let mut first = true;
-    for i in p.segments.iter().map(|x| token::get_ident(x.identifier)) {
+    for i in p.segments.iter().map(|x| x.identifier.name.as_str()) {
         if !first || p.global {
             s.push_str("::");
         } else {
             first = false;
         }
-        s.push_str(i.get());
+        s.push_str(&i);
     }
     s
 }
 
 impl Clean<String> for ast::Ident {
     fn clean(&self, _: &DocContext) -> String {
-        token::get_ident(*self).get().to_string()
+        self.to_string()
     }
 }
 
 impl Clean<String> for ast::Name {
     fn clean(&self, _: &DocContext) -> String {
-        token::get_name(*self).get().to_string()
+        self.to_string()
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Typedef {
     pub type_: Type,
     pub generics: Generics,
@@ -1850,26 +2090,26 @@ impl Clean<Item> for doctree::Typedef {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            def_id: ast_util::local_def(self.id.clone()),
+            def_id: DefId::local(self.id.clone()),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
             inner: TypedefItem(Typedef {
                 type_: self.ty.clean(cx),
                 generics: self.gen.clean(cx),
-            }),
+            }, false),
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
 pub struct BareFunctionDecl {
-    pub unsafety: ast::Unsafety,
+    pub unsafety: hir::Unsafety,
     pub generics: Generics,
     pub decl: FnDecl,
     pub abi: String,
 }
 
-impl Clean<BareFunctionDecl> for ast::BareFnTy {
+impl Clean<BareFunctionDecl> for hir::BareFnTy {
     fn clean(&self, cx: &DocContext) -> BareFunctionDecl {
         BareFunctionDecl {
             unsafety: self.unsafety,
@@ -1884,7 +2124,7 @@ impl Clean<BareFunctionDecl> for ast::BareFnTy {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Static {
     pub type_: Type,
     pub mutability: Mutability,
@@ -1901,7 +2141,7 @@ impl Clean<Item> for doctree::Static {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            def_id: ast_util::local_def(self.id),
+            def_id: DefId::local(self.id),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
             inner: StaticItem(Static {
@@ -1913,7 +2153,7 @@ impl Clean<Item> for doctree::Static {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Show)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Constant {
     pub type_: Type,
     pub expr: String,
@@ -1925,7 +2165,7 @@ impl Clean<Item> for doctree::Constant {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            def_id: ast_util::local_def(self.id),
+            def_id: DefId::local(self.id),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
             inner: ConstantItem(Constant {
@@ -1936,150 +2176,244 @@ impl Clean<Item> for doctree::Constant {
     }
 }
 
-#[derive(Show, Clone, RustcEncodable, RustcDecodable, PartialEq, Copy)]
+#[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Copy)]
 pub enum Mutability {
     Mutable,
     Immutable,
 }
 
-impl Clean<Mutability> for ast::Mutability {
+impl Clean<Mutability> for hir::Mutability {
     fn clean(&self, _: &DocContext) -> Mutability {
         match self {
-            &ast::MutMutable => Mutable,
-            &ast::MutImmutable => Immutable,
+            &hir::MutMutable => Mutable,
+            &hir::MutImmutable => Immutable,
+        }
+    }
+}
+
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Copy, Debug)]
+pub enum ImplPolarity {
+    Positive,
+    Negative,
+}
+
+impl Clean<ImplPolarity> for hir::ImplPolarity {
+    fn clean(&self, _: &DocContext) -> ImplPolarity {
+        match self {
+            &hir::ImplPolarity::Positive => ImplPolarity::Positive,
+            &hir::ImplPolarity::Negative => ImplPolarity::Negative,
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Impl {
+    pub unsafety: hir::Unsafety,
     pub generics: Generics,
     pub trait_: Option<Type>,
     pub for_: Type,
     pub items: Vec<Item>,
     pub derived: bool,
+    pub polarity: Option<ImplPolarity>,
 }
 
 fn detect_derived<M: AttrMetaMethods>(attrs: &[M]) -> bool {
     attr::contains_name(attrs, "automatically_derived")
 }
 
-impl Clean<Item> for doctree::Impl {
-    fn clean(&self, cx: &DocContext) -> Item {
-        Item {
+impl Clean<Vec<Item>> for doctree::Impl {
+    fn clean(&self, cx: &DocContext) -> Vec<Item> {
+        let mut ret = Vec::new();
+        let trait_ = self.trait_.clean(cx);
+        let items = self.items.clean(cx);
+
+        // If this impl block is an implementation of the Deref trait, then we
+        // need to try inlining the target's inherent impl blocks as well.
+        if let Some(ResolvedPath { did, .. }) = trait_ {
+            if Some(did) == cx.deref_trait_did.get() {
+                build_deref_target_impls(cx, &items, &mut ret);
+            }
+        }
+
+        ret.push(Item {
             name: None,
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            def_id: ast_util::local_def(self.id),
+            def_id: DefId::local(self.id),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
             inner: ImplItem(Impl {
+                unsafety: self.unsafety,
                 generics: self.generics.clean(cx),
-                trait_: self.trait_.clean(cx),
+                trait_: trait_,
                 for_: self.for_.clean(cx),
-                items: self.items.clean(cx).into_iter().map(|ti| {
-                        match ti {
-                            MethodImplItem(i) => i,
-                            TypeImplItem(i) => i,
-                        }
-                    }).collect(),
-                derived: detect_derived(self.attrs.as_slice()),
+                items: items,
+                derived: detect_derived(&self.attrs),
+                polarity: Some(self.polarity.clean(cx)),
+            }),
+        });
+        return ret;
+    }
+}
+
+fn build_deref_target_impls(cx: &DocContext,
+                            items: &[Item],
+                            ret: &mut Vec<Item>) {
+    let tcx = match cx.tcx_opt() {
+        Some(t) => t,
+        None => return,
+    };
+
+    for item in items {
+        let target = match item.inner {
+            TypedefItem(ref t, true) => &t.type_,
+            _ => continue,
+        };
+        let primitive = match *target {
+            ResolvedPath { did, .. } if did.is_local() => continue,
+            ResolvedPath { did, .. } => {
+                ret.extend(inline::build_impls(cx, tcx, did));
+                continue
+            }
+            _ => match target.primitive_type() {
+                Some(prim) => prim,
+                None => continue,
+            }
+        };
+        let did = match primitive {
+            Isize => tcx.lang_items.isize_impl(),
+            I8 => tcx.lang_items.i8_impl(),
+            I16 => tcx.lang_items.i16_impl(),
+            I32 => tcx.lang_items.i32_impl(),
+            I64 => tcx.lang_items.i64_impl(),
+            Usize => tcx.lang_items.usize_impl(),
+            U8 => tcx.lang_items.u8_impl(),
+            U16 => tcx.lang_items.u16_impl(),
+            U32 => tcx.lang_items.u32_impl(),
+            U64 => tcx.lang_items.u64_impl(),
+            F32 => tcx.lang_items.f32_impl(),
+            F64 => tcx.lang_items.f64_impl(),
+            Char => tcx.lang_items.char_impl(),
+            Bool => None,
+            Str => tcx.lang_items.str_impl(),
+            Slice => tcx.lang_items.slice_impl(),
+            Array => tcx.lang_items.slice_impl(),
+            PrimitiveTuple => None,
+            PrimitiveRawPointer => tcx.lang_items.const_ptr_impl(),
+        };
+        if let Some(did) = did {
+            if !did.is_local() {
+                inline::build_impl(cx, tcx, did, ret);
+            }
+        }
+    }
+}
+
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+pub struct DefaultImpl {
+    pub unsafety: hir::Unsafety,
+    pub trait_: Type,
+}
+
+impl Clean<Item> for doctree::DefaultImpl {
+    fn clean(&self, cx: &DocContext) -> Item {
+        Item {
+            name: None,
+            attrs: self.attrs.clean(cx),
+            source: self.whence.clean(cx),
+            def_id: DefId::local(self.id),
+            visibility: Some(hir::Public),
+            stability: None,
+            inner: DefaultImplItem(DefaultImpl {
+                unsafety: self.unsafety,
+                trait_: self.trait_.clean(cx),
             }),
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
-pub struct ViewItem {
-    pub inner: ViewItemInner,
+impl Clean<Item> for doctree::ExternCrate {
+    fn clean(&self, cx: &DocContext) -> Item {
+        Item {
+            name: None,
+            attrs: self.attrs.clean(cx),
+            source: self.whence.clean(cx),
+            def_id: DefId::local(0),
+            visibility: self.vis.clean(cx),
+            stability: None,
+            inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
+        }
+    }
 }
 
-impl Clean<Vec<Item>> for ast::ViewItem {
+impl Clean<Vec<Item>> for doctree::Import {
     fn clean(&self, cx: &DocContext) -> Vec<Item> {
         // We consider inlining the documentation of `pub use` statements, but we
         // forcefully don't inline if this is not public or if the
         // #[doc(no_inline)] attribute is present.
-        let denied = self.vis != ast::Public || self.attrs.iter().any(|a| {
-            a.name().get() == "doc" && match a.meta_item_list() {
+        let denied = self.vis != hir::Public || self.attrs.iter().any(|a| {
+            &a.name()[..] == "doc" && match a.meta_item_list() {
                 Some(l) => attr::contains_name(l, "no_inline"),
                 None => false,
             }
         });
-        let convert = |&: node: &ast::ViewItem_| {
-            Item {
-                name: None,
-                attrs: self.attrs.clean(cx),
-                source: self.span.clean(cx),
-                def_id: ast_util::local_def(0),
-                visibility: self.vis.clean(cx),
-                stability: None,
-                inner: ViewItemItem(ViewItem { inner: node.clean(cx) }),
+        let (mut ret, inner) = match self.node {
+            hir::ViewPathGlob(ref p) => {
+                (vec![], GlobImport(resolve_use_source(cx, p.clean(cx), self.id)))
             }
-        };
-        let mut ret = Vec::new();
-        match self.node {
-            ast::ViewItemUse(ref path) if !denied => {
-                match path.node {
-                    ast::ViewPathGlob(..) => ret.push(convert(&self.node)),
-                    ast::ViewPathList(ref a, ref list, ref b) => {
-                        // Attempt to inline all reexported items, but be sure
-                        // to keep any non-inlineable reexports so they can be
-                        // listed in the documentation.
-                        let remaining = list.iter().filter(|path| {
-                            match inline::try_inline(cx, path.node.id(), None) {
-                                Some(items) => {
-                                    ret.extend(items.into_iter()); false
-                                }
-                                None => true,
+            hir::ViewPathList(ref p, ref list) => {
+                // Attempt to inline all reexported items, but be sure
+                // to keep any non-inlineable reexports so they can be
+                // listed in the documentation.
+                let mut ret = vec![];
+                let remaining = if !denied {
+                    let mut remaining = vec![];
+                    for path in list {
+                        match inline::try_inline(cx, path.node.id(), path.node.rename()) {
+                            Some(items) => {
+                                ret.extend(items);
+                            }
+                            None => {
+                                remaining.push(path.clean(cx));
                             }
-                        }).map(|a| a.clone()).collect::<Vec<ast::PathListItem>>();
-                        if remaining.len() > 0 {
-                            let path = ast::ViewPathList(a.clone(),
-                                                         remaining,
-                                                         b.clone());
-                            let path = syntax::codemap::dummy_spanned(path);
-                            ret.push(convert(&ast::ViewItemUse(P(path))));
-                        }
-                    }
-                    ast::ViewPathSimple(ident, _, id) => {
-                        match inline::try_inline(cx, id, Some(ident)) {
-                            Some(items) => ret.extend(items.into_iter()),
-                            None => ret.push(convert(&self.node)),
                         }
                     }
-                }
-            }
-            ref n => ret.push(convert(n)),
-        }
-        return ret;
-    }
-}
-
-#[derive(Clone, RustcEncodable, RustcDecodable)]
-pub enum ViewItemInner {
-    ExternCrate(String, Option<String>, ast::NodeId),
-    Import(ViewPath)
-}
-
-impl Clean<ViewItemInner> for ast::ViewItem_ {
-    fn clean(&self, cx: &DocContext) -> ViewItemInner {
-        match self {
-            &ast::ViewItemExternCrate(ref i, ref p, ref id) => {
-                let string = match *p {
-                    None => None,
-                    Some((ref x, _)) => Some(x.get().to_string()),
+                    remaining
+                } else {
+                    list.clean(cx)
                 };
-                ExternCrate(i.clean(cx), string, *id)
+                if remaining.is_empty() {
+                    return ret;
+                }
+                (ret, ImportList(resolve_use_source(cx, p.clean(cx), self.id),
+                                 remaining))
             }
-            &ast::ViewItemUse(ref vp) => {
-                Import(vp.clean(cx))
+            hir::ViewPathSimple(i, ref p) => {
+                if !denied {
+                    match inline::try_inline(cx, self.id, Some(i)) {
+                        Some(items) => return items,
+                        None => {}
+                    }
+                }
+                (vec![], SimpleImport(i.clean(cx),
+                                      resolve_use_source(cx, p.clean(cx), self.id)))
             }
-        }
+        };
+        ret.push(Item {
+            name: None,
+            attrs: self.attrs.clean(cx),
+            source: self.whence.clean(cx),
+            def_id: DefId::local(0),
+            visibility: self.vis.clean(cx),
+            stability: None,
+            inner: ImportItem(inner)
+        });
+        ret
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
-pub enum ViewPath {
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+pub enum Import {
     // use source as str;
     SimpleImport(String, ImportSource),
     // use source::*;
@@ -2088,65 +2422,62 @@ pub enum ViewPath {
     ImportList(ImportSource, Vec<ViewListIdent>),
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct ImportSource {
     pub path: Path,
-    pub did: Option<ast::DefId>,
+    pub did: Option<DefId>,
 }
 
-impl Clean<ViewPath> for ast::ViewPath {
-    fn clean(&self, cx: &DocContext) -> ViewPath {
-        match self.node {
-            ast::ViewPathSimple(ref i, ref p, id) =>
-                SimpleImport(i.clean(cx), resolve_use_source(cx, p.clean(cx), id)),
-            ast::ViewPathGlob(ref p, id) =>
-                GlobImport(resolve_use_source(cx, p.clean(cx), id)),
-            ast::ViewPathList(ref p, ref pl, id) => {
-                ImportList(resolve_use_source(cx, p.clean(cx), id),
-                           pl.clean(cx))
-            }
-        }
-    }
-}
-
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct ViewListIdent {
     pub name: String,
-    pub source: Option<ast::DefId>,
+    pub rename: Option<String>,
+    pub source: Option<DefId>,
 }
 
-impl Clean<ViewListIdent> for ast::PathListItem {
+impl Clean<ViewListIdent> for hir::PathListItem {
     fn clean(&self, cx: &DocContext) -> ViewListIdent {
         match self.node {
-            ast::PathListIdent { id, name } => ViewListIdent {
+            hir::PathListIdent { id, name, rename } => ViewListIdent {
                 name: name.clean(cx),
+                rename: rename.map(|r| r.clean(cx)),
                 source: resolve_def(cx, id)
             },
-            ast::PathListMod { id } => ViewListIdent {
-                name: "mod".to_string(),
+            hir::PathListMod { id, rename } => ViewListIdent {
+                name: "self".to_string(),
+                rename: rename.map(|r| r.clean(cx)),
                 source: resolve_def(cx, id)
             }
         }
     }
 }
 
-impl Clean<Vec<Item>> for ast::ForeignMod {
+impl Clean<Vec<Item>> for hir::ForeignMod {
     fn clean(&self, cx: &DocContext) -> Vec<Item> {
-        self.items.clean(cx)
+        let mut items = self.items.clean(cx);
+        for item in &mut items {
+            match item.inner {
+                ForeignFunctionItem(ref mut f) => f.abi = self.abi,
+                _ => {}
+            }
+        }
+        items
     }
 }
 
-impl Clean<Item> for ast::ForeignItem {
+impl Clean<Item> for hir::ForeignItem {
     fn clean(&self, cx: &DocContext) -> Item {
         let inner = match self.node {
-            ast::ForeignItemFn(ref decl, ref generics) => {
+            hir::ForeignItemFn(ref decl, ref generics) => {
                 ForeignFunctionItem(Function {
                     decl: decl.clean(cx),
                     generics: generics.clean(cx),
-                    unsafety: ast::Unsafety::Unsafe,
+                    unsafety: hir::Unsafety::Unsafe,
+                    abi: abi::Rust,
+                    constness: hir::Constness::NotConst,
                 })
             }
-            ast::ForeignItemStatic(ref ty, mutbl) => {
+            hir::ForeignItemStatic(ref ty, mutbl) => {
                 ForeignStaticItem(Static {
                     type_: ty.clean(cx),
                     mutability: if mutbl {Mutable} else {Immutable},
@@ -2158,9 +2489,9 @@ impl Clean<Item> for ast::ForeignItem {
             name: Some(self.ident.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.span.clean(cx),
-            def_id: ast_util::local_def(self.id),
+            def_id: DefId::local(self.id),
             visibility: self.vis.clean(cx),
-            stability: get_stability(cx, ast_util::local_def(self.id)),
+            stability: get_stability(cx, DefId::local(self.id)),
             inner: inner,
         }
     }
@@ -2176,53 +2507,55 @@ impl ToSource for syntax::codemap::Span {
     fn to_src(&self, cx: &DocContext) -> String {
         debug!("converting span {:?} to snippet", self.clean(cx));
         let sn = match cx.sess().codemap().span_to_snippet(*self) {
-            Some(x) => x.to_string(),
-            None    => "".to_string()
+            Ok(x) => x.to_string(),
+            Err(_) => "".to_string()
         };
         debug!("got snippet {}", sn);
         sn
     }
 }
 
-fn lit_to_string(lit: &ast::Lit) -> String {
+fn lit_to_string(lit: &hir::Lit) -> String {
     match lit.node {
-        ast::LitStr(ref st, _) => st.get().to_string(),
-        ast::LitBinary(ref data) => format!("{:?}", data),
-        ast::LitByte(b) => {
-            let mut res = String::from_str("b'");
+        hir::LitStr(ref st, _) => st.to_string(),
+        hir::LitByteStr(ref data) => format!("{:?}", data),
+        hir::LitByte(b) => {
+            let mut res = String::from("b'");
             for c in (b as char).escape_default() {
                 res.push(c);
             }
             res.push('\'');
             res
         },
-        ast::LitChar(c) => format!("'{}'", c),
-        ast::LitInt(i, _t) => i.to_string(),
-        ast::LitFloat(ref f, _t) => f.get().to_string(),
-        ast::LitFloatUnsuffixed(ref f) => f.get().to_string(),
-        ast::LitBool(b) => b.to_string(),
+        hir::LitChar(c) => format!("'{}'", c),
+        hir::LitInt(i, _t) => i.to_string(),
+        hir::LitFloat(ref f, _t) => f.to_string(),
+        hir::LitFloatUnsuffixed(ref f) => f.to_string(),
+        hir::LitBool(b) => b.to_string(),
     }
 }
 
-fn name_from_pat(p: &ast::Pat) -> String {
-    use syntax::ast::*;
+fn name_from_pat(p: &hir::Pat) -> String {
+    use rustc_front::hir::*;
     debug!("Trying to get a name from pattern: {:?}", p);
 
     match p.node {
         PatWild(PatWildSingle) => "_".to_string(),
         PatWild(PatWildMulti) => "..".to_string(),
-        PatIdent(_, ref p, _) => token::get_ident(p.node).get().to_string(),
+        PatIdent(_, ref p, _) => p.node.to_string(),
         PatEnum(ref p, _) => path_to_string(p),
+        PatQPath(..) => panic!("tried to get argument name from PatQPath, \
+                                which is not allowed in function arguments"),
         PatStruct(ref name, ref fields, etc) => {
             format!("{} {{ {}{} }}", path_to_string(name),
                 fields.iter().map(|&Spanned { node: ref fp, .. }|
-                                  format!("{}: {}", fp.ident.as_str(), name_from_pat(&*fp.pat)))
-                             .collect::<Vec<String>>().connect(", "),
+                                  format!("{}: {}", fp.ident, name_from_pat(&*fp.pat)))
+                             .collect::<Vec<String>>().join(", "),
                 if etc { ", ..." } else { "" }
             )
         },
         PatTup(ref elts) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
-                                            .collect::<Vec<String>>().connect(", ")),
+                                            .collect::<Vec<String>>().join(", ")),
         PatBox(ref p) => name_from_pat(&**p),
         PatRegion(ref p, _) => name_from_pat(&**p),
         PatLit(..) => {
@@ -2236,13 +2569,8 @@ fn name_from_pat(p: &ast::Pat) -> String {
             let begin = begin.iter().map(|p| name_from_pat(&**p));
             let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
             let end = end.iter().map(|p| name_from_pat(&**p));
-            format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().connect(", "))
+            format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
         },
-        PatMac(..) => {
-            warn!("can't document the name of a function argument \
-                   produced by a pattern macro");
-            "(argument produced by macro)".to_string()
-        }
     }
 }
 
@@ -2257,40 +2585,39 @@ fn resolve_type(cx: &DocContext,
     };
     debug!("searching for {} in defmap", id);
     let def = match tcx.def_map.borrow().get(&id) {
-        Some(&k) => k,
+        Some(k) => k.full_def(),
         None => panic!("unresolved id not in defmap")
     };
 
-    match def {
-        def::DefSelfTy(..) => {
-            return Generic(token::get_name(special_idents::type_self.name).to_string());
-        }
+    let is_generic = match def {
         def::DefPrimTy(p) => match p {
-            ast::TyStr => return Primitive(Str),
-            ast::TyBool => return Primitive(Bool),
-            ast::TyChar => return Primitive(Char),
-            ast::TyInt(ast::TyIs(_)) => return Primitive(Isize),
-            ast::TyInt(ast::TyI8) => return Primitive(I8),
-            ast::TyInt(ast::TyI16) => return Primitive(I16),
-            ast::TyInt(ast::TyI32) => return Primitive(I32),
-            ast::TyInt(ast::TyI64) => return Primitive(I64),
-            ast::TyUint(ast::TyUs(_)) => return Primitive(Usize),
-            ast::TyUint(ast::TyU8) => return Primitive(U8),
-            ast::TyUint(ast::TyU16) => return Primitive(U16),
-            ast::TyUint(ast::TyU32) => return Primitive(U32),
-            ast::TyUint(ast::TyU64) => return Primitive(U64),
-            ast::TyFloat(ast::TyF32) => return Primitive(F32),
-            ast::TyFloat(ast::TyF64) => return Primitive(F64),
+            hir::TyStr => return Primitive(Str),
+            hir::TyBool => return Primitive(Bool),
+            hir::TyChar => return Primitive(Char),
+            hir::TyInt(hir::TyIs) => return Primitive(Isize),
+            hir::TyInt(hir::TyI8) => return Primitive(I8),
+            hir::TyInt(hir::TyI16) => return Primitive(I16),
+            hir::TyInt(hir::TyI32) => return Primitive(I32),
+            hir::TyInt(hir::TyI64) => return Primitive(I64),
+            hir::TyUint(hir::TyUs) => return Primitive(Usize),
+            hir::TyUint(hir::TyU8) => return Primitive(U8),
+            hir::TyUint(hir::TyU16) => return Primitive(U16),
+            hir::TyUint(hir::TyU32) => return Primitive(U32),
+            hir::TyUint(hir::TyU64) => return Primitive(U64),
+            hir::TyFloat(hir::TyF32) => return Primitive(F32),
+            hir::TyFloat(hir::TyF64) => return Primitive(F64),
         },
-        def::DefTyParam(_, _, _, n) => return Generic(token::get_name(n).to_string()),
-        def::DefTyParamBinder(i) => return TyParamBinder(i),
-        _ => {}
+        def::DefSelfTy(..) if path.segments.len() == 1 => {
+            return Generic(special_idents::type_self.name.to_string());
+        }
+        def::DefSelfTy(..) | def::DefTyParam(..) => true,
+        _ => false,
     };
     let did = register_def(&*cx, def);
-    ResolvedPath { path: path, typarams: None, did: did }
+    ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
 }
 
-fn register_def(cx: &DocContext, def: def::Def) -> ast::DefId {
+fn register_def(cx: &DocContext, def: def::Def) -> DefId {
     let (did, kind) = match def {
         def::DefFn(i, _) => (i, TypeFunction),
         def::DefTy(i, false) => (i, TypeTypedef),
@@ -2302,7 +2629,7 @@ fn register_def(cx: &DocContext, def: def::Def) -> ast::DefId {
         def::DefVariant(i, _, _) => (i, TypeEnum),
         _ => return def.def_id()
     };
-    if ast_util::is_local(did) { return did }
+    if did.is_local() { return did }
     let tcx = match cx.tcx_opt() {
         Some(tcx) => tcx,
         None => return did
@@ -2322,15 +2649,16 @@ fn resolve_use_source(cx: &DocContext, path: Path, id: ast::NodeId) -> ImportSou
     }
 }
 
-fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<ast::DefId> {
+fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<DefId> {
     cx.tcx_opt().and_then(|tcx| {
-        tcx.def_map.borrow().get(&id).map(|&def| register_def(cx, def))
+        tcx.def_map.borrow().get(&id).map(|d| register_def(cx, d.full_def()))
     })
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Macro {
     pub source: String,
+    pub imported_from: Option<String>,
 }
 
 impl Clean<Item> for doctree::Macro {
@@ -2339,63 +2667,66 @@ impl Clean<Item> for doctree::Macro {
             name: Some(format!("{}!", self.name.clean(cx))),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            visibility: ast::Public.clean(cx),
+            visibility: hir::Public.clean(cx),
             stability: self.stab.clean(cx),
-            def_id: ast_util::local_def(self.id),
+            def_id: DefId::local(self.id),
             inner: MacroItem(Macro {
                 source: self.whence.to_src(cx),
+                imported_from: self.imported_from.clean(cx),
             }),
         }
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Stability {
     pub level: attr::StabilityLevel,
-    pub text: String
+    pub feature: String,
+    pub since: String,
+    pub deprecated_since: String,
+    pub reason: String,
+    pub issue: Option<u32>
 }
 
 impl Clean<Stability> for attr::Stability {
     fn clean(&self, _: &DocContext) -> Stability {
         Stability {
             level: self.level,
-            text: self.text.as_ref().map_or("".to_string(),
-                                            |interned| interned.get().to_string()),
+            feature: self.feature.to_string(),
+            since: self.since.as_ref().map_or("".to_string(),
+                                              |interned| interned.to_string()),
+            deprecated_since: self.deprecated_since.as_ref().map_or("".to_string(),
+                                                                    |istr| istr.to_string()),
+            reason: self.reason.as_ref().map_or("".to_string(),
+                                                |interned| interned.to_string()),
+            issue: self.issue,
         }
     }
 }
 
-impl Clean<Item> for ast::AssociatedType {
-    fn clean(&self, cx: &DocContext) -> Item {
-        Item {
-            source: self.ty_param.span.clean(cx),
-            name: Some(self.ty_param.ident.clean(cx)),
-            attrs: self.attrs.clean(cx),
-            inner: AssociatedTypeItem(self.ty_param.clean(cx)),
-            visibility: None,
-            def_id: ast_util::local_def(self.ty_param.id),
-            stability: None,
+impl<'a> Clean<Stability> for &'a attr::Stability {
+    fn clean(&self, _: &DocContext) -> Stability {
+        Stability {
+            level: self.level,
+            feature: self.feature.to_string(),
+            since: self.since.as_ref().map_or("".to_string(),
+                                              |interned| interned.to_string()),
+            deprecated_since: self.deprecated_since.as_ref().map_or("".to_string(),
+                                                                    |istr| istr.to_string()),
+            reason: self.reason.as_ref().map_or("".to_string(),
+                                                |interned| interned.to_string()),
+            issue: self.issue,
         }
     }
 }
 
-impl Clean<Item> for ty::AssociatedType {
+impl<'tcx> Clean<Item> for ty::AssociatedConst<'tcx> {
     fn clean(&self, cx: &DocContext) -> Item {
         Item {
             source: DUMMY_SP.clean(cx),
             name: Some(self.name.clean(cx)),
             attrs: Vec::new(),
-            // FIXME(#18048): this is wrong, but cross-crate associated types are broken
-            // anyway, for the time being.
-            inner: AssociatedTypeItem(TyParam {
-                name: self.name.clean(cx),
-                did: ast::DefId {
-                    krate: 0,
-                    node: ast::DUMMY_NODE_ID
-                },
-                bounds: vec![],
-                default: None,
-            }),
+            inner: AssociatedConstItem(self.ty.clean(cx), None),
             visibility: None,
             def_id: self.def_id,
             stability: None,
@@ -2403,28 +2734,75 @@ impl Clean<Item> for ty::AssociatedType {
     }
 }
 
-impl Clean<Item> for ast::Typedef {
+impl<'tcx> Clean<Item> for ty::AssociatedType<'tcx> {
     fn clean(&self, cx: &DocContext) -> Item {
+        let my_name = self.name.clean(cx);
+
+        let mut bounds = if let ty::TraitContainer(did) = self.container {
+            // When loading a cross-crate associated type, the bounds for this type
+            // are actually located on the trait/impl itself, so we need to load
+            // all of the generics from there and then look for bounds that are
+            // applied to this associated type in question.
+            let def = cx.tcx().lookup_trait_def(did);
+            let predicates = cx.tcx().lookup_predicates(did);
+            let generics = (&def.generics, &predicates, subst::TypeSpace).clean(cx);
+            generics.where_predicates.iter().filter_map(|pred| {
+                let (name, self_type, trait_, bounds) = match *pred {
+                    WherePredicate::BoundPredicate {
+                        ty: QPath { ref name, ref self_type, ref trait_ },
+                        ref bounds
+                    } => (name, self_type, trait_, bounds),
+                    _ => return None,
+                };
+                if *name != my_name { return None }
+                match **trait_ {
+                    ResolvedPath { did, .. } if did == self.container.id() => {}
+                    _ => return None,
+                }
+                match **self_type {
+                    Generic(ref s) if *s == "Self" => {}
+                    _ => return None,
+                }
+                Some(bounds)
+            }).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>()
+        } else {
+            vec![]
+        };
+
+        // Our Sized/?Sized bound didn't get handled when creating the generics
+        // because we didn't actually get our whole set of bounds until just now
+        // (some of them may have come from the trait). If we do have a sized
+        // bound, we remove it, and if we don't then we add the `?Sized` bound
+        // at the end.
+        match bounds.iter().position(|b| b.is_sized_bound(cx)) {
+            Some(i) => { bounds.remove(i); }
+            None => bounds.push(TyParamBound::maybe_sized(cx)),
+        }
+
         Item {
-            source: self.span.clean(cx),
-            name: Some(self.ident.clean(cx)),
-            attrs: self.attrs.clean(cx),
-            inner: TypedefItem(Typedef {
-                type_: self.typ.clean(cx),
-                generics: Generics {
-                    lifetimes: Vec::new(),
-                    type_params: Vec::new(),
-                    where_predicates: Vec::new()
-                },
-            }),
-            visibility: None,
-            def_id: ast_util::local_def(self.id),
-            stability: None,
+            source: DUMMY_SP.clean(cx),
+            name: Some(self.name.clean(cx)),
+            attrs: inline::load_attrs(cx, cx.tcx(), self.def_id),
+            inner: AssociatedTypeItem(bounds, self.ty.clean(cx)),
+            visibility: self.vis.clean(cx),
+            def_id: self.def_id,
+            stability: stability::lookup(cx.tcx(), self.def_id).clean(cx),
+        }
+    }
+}
+
+impl<'a> Clean<Typedef> for (ty::TypeScheme<'a>, ty::GenericPredicates<'a>,
+                             ParamSpace) {
+    fn clean(&self, cx: &DocContext) -> Typedef {
+        let (ref ty_scheme, ref predicates, ps) = *self;
+        Typedef {
+            type_: ty_scheme.ty.clean(cx),
+            generics: (&ty_scheme.generics, predicates, ps).clean(cx)
         }
     }
 }
 
-fn lang_struct(cx: &DocContext, did: Option<ast::DefId>,
+fn lang_struct(cx: &DocContext, did: Option<DefId>,
                t: ty::Ty, name: &str,
                fallback: fn(Box<Type>) -> Type) -> Type {
     let did = match did {
@@ -2450,17 +2828,18 @@ fn lang_struct(cx: &DocContext, did: Option<ast::DefId>,
                 }
             }],
         },
+        is_generic: false,
     }
 }
 
 /// An equality constraint on an associated type, e.g. `A=Bar` in `Foo<A=Bar>`
-#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Show)]
+#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Debug)]
 pub struct TypeBinding {
     pub name: String,
     pub ty: Type
 }
 
-impl Clean<TypeBinding> for ast::TypeBinding {
+impl Clean<TypeBinding> for hir::TypeBinding {
     fn clean(&self, cx: &DocContext) -> TypeBinding {
         TypeBinding {
             name: self.ident.clean(cx),