From 8a6118b74840727e17ec42b0aa6d7a215d57d2df Mon Sep 17 00:00:00 2001
From: Niko Matsakis <niko@alum.mit.edu>
Date: Thu, 13 Aug 2015 10:57:34 -0400
Subject: [PATCH 1/7] move InlinedItem into librustc, where it belongs

---
 src/librustc/ast_map/mod.rs        | 32 ++++++++-------
 src/librustc/metadata/csearch.rs   |  5 ++-
 src/librustc/metadata/decoder.rs   |  3 +-
 src/librustc/metadata/encoder.rs   | 30 +++++---------
 src/librustc/metadata/inline.rs    | 64 ++++++++++++++++++++++++++++++
 src/librustc/metadata/mod.rs       |  1 +
 src/librustc/middle/astencode.rs   | 61 ++++++++++++++--------------
 src/librustc/middle/const_eval.rs  | 13 +++---
 src/librustc/middle/region.rs      |  7 ++--
 src/librustc_trans/trans/inline.rs | 11 ++---
 src/libsyntax/ast.rs               | 12 ------
 src/libsyntax/ast_util.rs          | 33 +++++----------
 src/libsyntax/visit.rs             | 11 -----
 13 files changed, 157 insertions(+), 126 deletions(-)
 create mode 100644 src/librustc/metadata/inline.rs

diff --git a/src/librustc/ast_map/mod.rs b/src/librustc/ast_map/mod.rs
index a193ffcc731..b38c15d0f6a 100644
--- a/src/librustc/ast_map/mod.rs
+++ b/src/librustc/ast_map/mod.rs
@@ -12,6 +12,8 @@ pub use self::Node::*;
 pub use self::PathElem::*;
 use self::MapEntry::*;
 
+use metadata::inline::InlinedItem;
+use metadata::inline::InlinedItem as II;
 use syntax::abi;
 use syntax::ast::*;
 use syntax::ast_util;
@@ -374,8 +376,8 @@ impl<'ast> Map<'ast> {
     pub fn get_parent_did(&self, id: NodeId) -> DefId {
         let parent = self.get_parent(id);
         match self.find_entry(parent) {
-            Some(RootInlinedParent(&InlinedParent {ii: IITraitItem(did, _), ..})) => did,
-            Some(RootInlinedParent(&InlinedParent {ii: IIImplItem(did, _), ..})) => did,
+            Some(RootInlinedParent(&InlinedParent {ii: II::TraitItem(did, _), ..})) => did,
+            Some(RootInlinedParent(&InlinedParent {ii: II::ImplItem(did, _), ..})) => did,
             _ => ast_util::local_def(parent)
         }
     }
@@ -967,16 +969,16 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
                                           -> &'ast InlinedItem {
     let mut fld = IdAndSpanUpdater { fold_ops: fold_ops };
     let ii = match ii {
-        IIItem(i) => IIItem(fld.fold_item(i).expect_one("expected one item")),
-        IITraitItem(d, ti) => {
-            IITraitItem(fld.fold_ops.new_def_id(d),
-                        fld.fold_trait_item(ti).expect_one("expected one trait item"))
+        II::Item(i) => II::Item(fld.fold_item(i).expect_one("expected one item")),
+        II::TraitItem(d, ti) => {
+            II::TraitItem(fld.fold_ops.new_def_id(d),
+                          fld.fold_trait_item(ti).expect_one("expected one trait item"))
         }
-        IIImplItem(d, ii) => {
-            IIImplItem(fld.fold_ops.new_def_id(d),
-                       fld.fold_impl_item(ii).expect_one("expected one impl item"))
+        II::ImplItem(d, ii) => {
+            II::ImplItem(fld.fold_ops.new_def_id(d),
+                         fld.fold_impl_item(ii).expect_one("expected one impl item"))
         }
-        IIForeign(i) => IIForeign(fld.fold_foreign_item(i))
+        II::Foreign(i) => II::Foreign(fld.fold_foreign_item(i))
     };
 
     let ii_parent = map.forest.inlined_items.alloc(InlinedParent {
@@ -990,20 +992,20 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
         parent_node: ii_parent_id,
     };
     collector.insert_entry(ii_parent_id, RootInlinedParent(ii_parent));
-    visit::walk_inlined_item(&mut collector, &ii_parent.ii);
+    ii_parent.ii.visit(&mut collector);
 
     // Methods get added to the AST map when their impl is visited.  Since we
     // don't decode and instantiate the impl, but just the method, we have to
     // add it to the table now. Likewise with foreign items.
     match ii_parent.ii {
-        IIItem(_) => {}
-        IITraitItem(_, ref ti) => {
+        II::Item(_) => {}
+        II::TraitItem(_, ref ti) => {
             collector.insert(ti.id, NodeTraitItem(ti));
         }
-        IIImplItem(_, ref ii) => {
+        II::ImplItem(_, ref ii) => {
             collector.insert(ii.id, NodeImplItem(ii));
         }
-        IIForeign(ref i) => {
+        II::Foreign(ref i) => {
             collector.insert(i.id, NodeForeignItem(i));
         }
     }
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index 2ade251018f..d33b163c972 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -14,6 +14,7 @@ use ast_map;
 use metadata::common::*;
 use metadata::cstore;
 use metadata::decoder;
+use metadata::inline::InlinedItem;
 use middle::lang_items;
 use middle::ty;
 
@@ -96,8 +97,8 @@ pub fn get_item_path(tcx: &ty::ctxt, def: ast::DefId) -> Vec<ast_map::PathElem>
 }
 
 pub enum FoundAst<'ast> {
-    Found(&'ast ast::InlinedItem),
-    FoundParent(ast::DefId, &'ast ast::InlinedItem),
+    Found(&'ast InlinedItem),
+    FoundParent(ast::DefId, &'ast InlinedItem),
     NotFound,
 }
 
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index c6c18fa14a3..11a5cc8c9d7 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -23,6 +23,7 @@ use metadata::csearch::MethodInfo;
 use metadata::csearch;
 use metadata::cstore;
 use metadata::encoder::def_to_u64;
+use metadata::inline::InlinedItem;
 use metadata::tydecode::{parse_ty_data, parse_region_data,
                          parse_type_param_def_data, parse_bare_fn_ty_data,
                          parse_trait_ref_data, parse_predicate_data};
@@ -776,7 +777,7 @@ pub type DecodeInlinedItem<'a> =
                         &ty::ctxt<'tcx>,
                         Vec<ast_map::PathElem>,
                         rbml::Doc)
-                        -> Result<&'tcx ast::InlinedItem, Vec<ast_map::PathElem>> + 'a>;
+                        -> Result<&'tcx InlinedItem, Vec<ast_map::PathElem>> + 'a>;
 
 pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: ast::NodeId,
                                 mut decode_inlined_item: DecodeInlinedItem)
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index e0f35b6817b..03f5f477bd8 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -13,8 +13,6 @@
 #![allow(unused_must_use)] // everything is just a MemWriter, can't fail
 #![allow(non_camel_case_types)]
 
-pub use self::InlinedItemRef::*;
-
 use ast_map::{self, LinkedPath, PathElem, PathElems};
 use back::svh::Svh;
 use session::config;
@@ -22,6 +20,7 @@ use metadata::common::*;
 use metadata::cstore;
 use metadata::decoder;
 use metadata::tyencode;
+use metadata::inline::InlinedItemRef;
 use middle::def;
 use middle::ty::{self, Ty};
 use middle::stability;
@@ -46,14 +45,6 @@ use syntax::visit;
 use syntax;
 use rbml::writer::Encoder;
 
-/// A borrowed version of `ast::InlinedItem`.
-pub enum InlinedItemRef<'a> {
-    IIItemRef(&'a ast::Item),
-    IITraitItemRef(DefId, &'a ast::TraitItem),
-    IIImplItemRef(DefId, &'a ast::ImplItem),
-    IIForeignRef(&'a ast::ForeignItem)
-}
-
 pub type EncodeInlinedItem<'a> =
     Box<FnMut(&EncodeContext, &mut Encoder, InlinedItemRef) + 'a>;
 
@@ -830,7 +821,7 @@ fn encode_info_for_associated_const(ecx: &EncodeContext,
 
     if let Some(ii) = impl_item_opt {
         encode_attributes(rbml_w, &ii.attrs);
-        encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id), ii));
+        encode_inlined_item(ecx, rbml_w, InlinedItemRef::ImplItem(local_def(parent_id), ii));
     }
 
     rbml_w.end_tag();
@@ -868,7 +859,7 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
             let needs_inline = any_types || is_default_impl ||
                                attr::requests_inline(&impl_item.attrs);
             if needs_inline || sig.constness == ast::Constness::Const {
-                encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id),
+                encode_inlined_item(ecx, rbml_w, InlinedItemRef::ImplItem(local_def(parent_id),
                                                                impl_item));
             }
             encode_constness(rbml_w, sig.constness);
@@ -1050,7 +1041,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_name(rbml_w, item.ident.name);
         encode_path(rbml_w, path);
         encode_attributes(rbml_w, &item.attrs);
-        encode_inlined_item(ecx, rbml_w, IIItemRef(item));
+        encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
         encode_visibility(rbml_w, vis);
         encode_stability(rbml_w, stab);
         rbml_w.end_tag();
@@ -1067,7 +1058,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_attributes(rbml_w, &item.attrs);
         let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs);
         if needs_inline || constness == ast::Constness::Const {
-            encode_inlined_item(ecx, rbml_w, IIItemRef(item));
+            encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
         }
         if tps_len == 0 {
             encode_symbol(ecx, rbml_w, item.id);
@@ -1132,7 +1123,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         for v in &enum_definition.variants {
             encode_variant_id(rbml_w, local_def(v.node.id));
         }
-        encode_inlined_item(ecx, rbml_w, IIItemRef(item));
+        encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
         encode_path(rbml_w, path);
 
         // Encode inherent implementations for this enumeration.
@@ -1180,7 +1171,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         needs to know*/
         encode_struct_fields(rbml_w, variant, def_id);
 
-        encode_inlined_item(ecx, rbml_w, IIItemRef(item));
+        encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
 
         // Encode inherent implementations for this structure.
         encode_inherent_implementations(ecx, rbml_w, def_id);
@@ -1455,7 +1446,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
             match trait_item.node {
                 ast::ConstTraitItem(_, _) => {
                     encode_inlined_item(ecx, rbml_w,
-                                        IITraitItemRef(def_id, trait_item));
+                                        InlinedItemRef::TraitItem(def_id, trait_item));
                 }
                 ast::MethodTraitItem(ref sig, ref body) => {
                     // If this is a static method, we've already
@@ -1469,7 +1460,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
 
                     if body.is_some() {
                         encode_item_sort(rbml_w, 'p');
-                        encode_inlined_item(ecx, rbml_w, IITraitItemRef(def_id, trait_item));
+                        encode_inlined_item(ecx, rbml_w,
+                                            InlinedItemRef::TraitItem(def_id, trait_item));
                     } else {
                         encode_item_sort(rbml_w, 'r');
                     }
@@ -1508,7 +1500,7 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
         encode_bounds_and_type_for_item(rbml_w, ecx, nitem.id);
         encode_name(rbml_w, nitem.ident.name);
         if abi == abi::RustIntrinsic {
-            encode_inlined_item(ecx, rbml_w, IIForeignRef(nitem));
+            encode_inlined_item(ecx, rbml_w, InlinedItemRef::Foreign(nitem));
         }
         encode_attributes(rbml_w, &*nitem.attrs);
         let stab = stability::lookup(ecx.tcx, ast_util::local_def(nitem.id));
diff --git a/src/librustc/metadata/inline.rs b/src/librustc/metadata/inline.rs
new file mode 100644
index 00000000000..ba09e173fd8
--- /dev/null
+++ b/src/librustc/metadata/inline.rs
@@ -0,0 +1,64 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use syntax::ast;
+use syntax::ast_util::{IdRange, IdRangeComputingVisitor,
+                       IdVisitor, IdVisitingOperation};
+use syntax::ptr::P;
+use syntax::visit::Visitor;
+use self::InlinedItem::*;
+
+/// The data we save and restore about an inlined item or method.  This is not
+/// part of the AST that we parse from a file, but it becomes part of the tree
+/// that we trans.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum InlinedItem {
+    Item(P<ast::Item>),
+    TraitItem(ast::DefId /* impl id */, P<ast::TraitItem>),
+    ImplItem(ast::DefId /* impl id */, P<ast::ImplItem>),
+    Foreign(P<ast::ForeignItem>),
+}
+
+/// A borrowed version of `ast::InlinedItem`.
+pub enum InlinedItemRef<'a> {
+    Item(&'a ast::Item),
+    TraitItem(ast::DefId, &'a ast::TraitItem),
+    ImplItem(ast::DefId, &'a ast::ImplItem),
+    Foreign(&'a ast::ForeignItem)
+}
+
+impl InlinedItem {
+    pub fn visit<'ast,V>(&'ast self, visitor: &mut V)
+        where V: Visitor<'ast>
+    {
+        match *self {
+            Item(ref i) => visitor.visit_item(&**i),
+            Foreign(ref i) => visitor.visit_foreign_item(&**i),
+            TraitItem(_, ref ti) => visitor.visit_trait_item(ti),
+            ImplItem(_, ref ii) => visitor.visit_impl_item(ii),
+        }
+    }
+
+    pub fn visit_ids<O: IdVisitingOperation>(&self, operation: &mut O) {
+        let mut id_visitor = IdVisitor {
+            operation: operation,
+            pass_through_items: true,
+            visited_outermost: false,
+        };
+        self.visit(&mut id_visitor);
+    }
+
+    pub fn compute_id_range(&self) -> IdRange {
+        let mut visitor = IdRangeComputingVisitor::new();
+        self.visit_ids(&mut visitor);
+        visitor.result()
+    }
+}
+
diff --git a/src/librustc/metadata/mod.rs b/src/librustc/metadata/mod.rs
index 0bf1e6d198f..44901eb0547 100644
--- a/src/librustc/metadata/mod.rs
+++ b/src/librustc/metadata/mod.rs
@@ -19,3 +19,4 @@ pub mod csearch;
 pub mod loader;
 pub mod filesearch;
 pub mod macro_import;
+pub mod inline;
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index c064b31173f..a07b849b400 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -17,16 +17,17 @@ use metadata::common as c;
 use metadata::cstore as cstore;
 use session::Session;
 use metadata::decoder;
-use middle::def;
 use metadata::encoder as e;
-use middle::region;
+use metadata::inline::{InlinedItem, InlinedItemRef};
 use metadata::tydecode;
 use metadata::tydecode::{DefIdSource, NominalType, TypeWithId};
 use metadata::tydecode::{RegionParameter, ClosureSource};
 use metadata::tyencode;
 use middle::cast;
 use middle::check_const::ConstQualif;
+use middle::def;
 use middle::privacy::{AllPublic, LastMod};
+use middle::region;
 use middle::subst;
 use middle::subst::VecPerParamSpace;
 use middle::ty::{self, Ty};
@@ -75,12 +76,12 @@ trait tr_intern {
 
 pub fn encode_inlined_item(ecx: &e::EncodeContext,
                            rbml_w: &mut Encoder,
-                           ii: e::InlinedItemRef) {
+                           ii: InlinedItemRef) {
     let id = match ii {
-        e::IIItemRef(i) => i.id,
-        e::IIForeignRef(i) => i.id,
-        e::IITraitItemRef(_, ti) => ti.id,
-        e::IIImplItemRef(_, ii) => ii.id,
+        InlinedItemRef::Item(i) => i.id,
+        InlinedItemRef::Foreign(i) => i.id,
+        InlinedItemRef::TraitItem(_, ti) => ti.id,
+        InlinedItemRef::ImplItem(_, ii) => ii.id,
     };
     debug!("> Encoding inlined item: {} ({:?})",
            ecx.tcx.map.path_to_string(id),
@@ -88,7 +89,7 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext,
 
     // Folding could be avoided with a smarter encoder.
     let ii = simplify_ast(ii);
-    let id_range = ast_util::compute_id_range_for_inlined_item(&ii);
+    let id_range = ii.compute_id_range();
 
     rbml_w.start_tag(c::tag_ast as usize);
     id_range.encode(rbml_w);
@@ -124,7 +125,7 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
                                  tcx: &ty::ctxt<'tcx>,
                                  path: Vec<ast_map::PathElem>,
                                  par_doc: rbml::Doc)
-                                 -> Result<&'tcx ast::InlinedItem, Vec<ast_map::PathElem>> {
+                                 -> Result<&'tcx InlinedItem, Vec<ast_map::PathElem>> {
     match par_doc.opt_child(c::tag_ast) {
       None => Err(path),
       Some(ast_doc) => {
@@ -150,10 +151,10 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
         let ii = ast_map::map_decoded_item(&dcx.tcx.map, path, raw_ii, dcx);
 
         let ident = match *ii {
-            ast::IIItem(ref i) => i.ident,
-            ast::IIForeign(ref i) => i.ident,
-            ast::IITraitItem(_, ref ti) => ti.ident,
-            ast::IIImplItem(_, ref ii) => ii.ident
+            InlinedItem::Item(ref i) => i.ident,
+            InlinedItem::Foreign(ref i) => i.ident,
+            InlinedItem::TraitItem(_, ref ti) => ti.ident,
+            InlinedItem::ImplItem(_, ref ii) => ii.ident
         };
         debug!("Fn named: {}", ident);
         debug!("< Decoded inlined fn: {}::{}",
@@ -162,7 +163,7 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
         region::resolve_inlined_item(&tcx.sess, &tcx.region_maps, ii);
         decode_side_tables(dcx, ast_doc);
         match *ii {
-          ast::IIItem(ref i) => {
+          InlinedItem::Item(ref i) => {
             debug!(">>> DECODED ITEM >>>\n{}\n<<< DECODED ITEM <<<",
                    syntax::print::pprust::item_to_string(&**i));
           }
@@ -349,7 +350,7 @@ impl<D:serialize::Decoder> def_id_decoder_helpers for D
 // We also have to adjust the spans: for now we just insert a dummy span,
 // but eventually we should add entries to the local codemap as required.
 
-fn encode_ast(rbml_w: &mut Encoder, item: &ast::InlinedItem) {
+fn encode_ast(rbml_w: &mut Encoder, item: &InlinedItem) {
     rbml_w.start_tag(c::tag_tree as usize);
     item.encode(rbml_w);
     rbml_w.end_tag();
@@ -399,34 +400,34 @@ impl Folder for NestedItemsDropper {
 // As it happens, trans relies on the fact that we do not export
 // nested items, as otherwise it would get confused when translating
 // inlined items.
-fn simplify_ast(ii: e::InlinedItemRef) -> ast::InlinedItem {
+fn simplify_ast(ii: InlinedItemRef) -> InlinedItem {
     let mut fld = NestedItemsDropper;
 
     match ii {
         // HACK we're not dropping items.
-        e::IIItemRef(i) => {
-            ast::IIItem(fold::noop_fold_item(P(i.clone()), &mut fld)
+        InlinedItemRef::Item(i) => {
+            InlinedItem::Item(fold::noop_fold_item(P(i.clone()), &mut fld)
                             .expect_one("expected one item"))
         }
-        e::IITraitItemRef(d, ti) => {
-            ast::IITraitItem(d,
+        InlinedItemRef::TraitItem(d, ti) => {
+            InlinedItem::TraitItem(d,
                 fold::noop_fold_trait_item(P(ti.clone()), &mut fld)
                     .expect_one("noop_fold_trait_item must produce \
                                  exactly one trait item"))
         }
-        e::IIImplItemRef(d, ii) => {
-            ast::IIImplItem(d,
+        InlinedItemRef::ImplItem(d, ii) => {
+            InlinedItem::ImplItem(d,
                 fold::noop_fold_impl_item(P(ii.clone()), &mut fld)
                     .expect_one("noop_fold_impl_item must produce \
                                  exactly one impl item"))
         }
-        e::IIForeignRef(i) => {
-            ast::IIForeign(fold::noop_fold_foreign_item(P(i.clone()), &mut fld))
+        InlinedItemRef::Foreign(i) => {
+            InlinedItem::Foreign(fold::noop_fold_foreign_item(P(i.clone()), &mut fld))
         }
     }
 }
 
-fn decode_ast(par_doc: rbml::Doc) -> ast::InlinedItem {
+fn decode_ast(par_doc: rbml::Doc) -> InlinedItem {
     let chi_doc = par_doc.get(c::tag_tree as usize);
     let mut d = reader::Decoder::new(chi_doc);
     Decodable::decode(&mut d).unwrap()
@@ -920,9 +921,9 @@ impl<'a, 'b, 'c, 'tcx> ast_util::IdVisitingOperation for
 
 fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
                              rbml_w: &mut Encoder,
-                             ii: &ast::InlinedItem) {
+                             ii: &InlinedItem) {
     rbml_w.start_tag(c::tag_table as usize);
-    ast_util::visit_ids_for_inlined_item(ii, &mut SideTableEncodingIdVisitor {
+    ii.visit_ids(&mut SideTableEncodingIdVisitor {
         ecx: ecx,
         rbml_w: rbml_w
     });
@@ -1644,15 +1645,15 @@ fn test_simplification() {
             return alist {eq_fn: eq_int, data: Vec::new()};
         }
     ).unwrap();
-    let item_in = e::IIItemRef(&*item);
+    let item_in = InlinedItemRef::Item(&*item);
     let item_out = simplify_ast(item_in);
-    let item_exp = ast::IIItem(quote_item!(&cx,
+    let item_exp = InlinedItem::Item(quote_item!(&cx,
         fn new_int_alist<B>() -> alist<isize, B> {
             return alist {eq_fn: eq_int, data: Vec::new()};
         }
     ).unwrap());
     match (item_out, item_exp) {
-      (ast::IIItem(item_out), ast::IIItem(item_exp)) => {
+      (InlinedItem::Item(item_out), InlinedItem::Item(item_exp)) => {
         assert!(pprust::item_to_string(&*item_out) ==
                 pprust::item_to_string(&*item_exp));
       }
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index fd1c8d4892a..a1327df224a 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -17,6 +17,7 @@ use self::EvalHint::*;
 use ast_map;
 use ast_map::blocks::FnLikeNode;
 use metadata::csearch;
+use metadata::inline::InlinedItem;
 use middle::{astencode, def, infer, subst, traits};
 use middle::pat_util::def_to_path;
 use middle::ty::{self, Ty};
@@ -86,7 +87,7 @@ fn lookup_variant_by_id<'a>(tcx: &'a ty::ctxt,
         }
         let expr_id = match csearch::maybe_get_item_ast(tcx, enum_def,
             Box::new(|a, b, c, d| astencode::decode_inlined_item(a, b, c, d))) {
-            csearch::FoundAst::Found(&ast::IIItem(ref item)) => match item.node {
+            csearch::FoundAst::Found(&InlinedItem::Item(ref item)) => match item.node {
                 ast::ItemEnum(ast::EnumDef { ref variants }, _) => {
                     // NOTE this doesn't do the right thing, it compares inlined
                     // NodeId's to the original variant_def's NodeId, but they
@@ -161,11 +162,11 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
         let mut used_ref_id = false;
         let expr_id = match csearch::maybe_get_item_ast(tcx, def_id,
             Box::new(|a, b, c, d| astencode::decode_inlined_item(a, b, c, d))) {
-            csearch::FoundAst::Found(&ast::IIItem(ref item)) => match item.node {
+            csearch::FoundAst::Found(&InlinedItem::Item(ref item)) => match item.node {
                 ast::ItemConst(_, ref const_expr) => Some(const_expr.id),
                 _ => None
             },
-            csearch::FoundAst::Found(&ast::IITraitItem(trait_id, ref ti)) => match ti.node {
+            csearch::FoundAst::Found(&InlinedItem::TraitItem(trait_id, ref ti)) => match ti.node {
                 ast::ConstTraitItem(_, _) => {
                     used_ref_id = true;
                     match maybe_ref_id {
@@ -184,7 +185,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
                 }
                 _ => None
             },
-            csearch::FoundAst::Found(&ast::IIImplItem(_, ref ii)) => match ii.node {
+            csearch::FoundAst::Found(&InlinedItem::ImplItem(_, ref ii)) => match ii.node {
                 ast::ConstImplItem(_, ref expr) => Some(expr.id),
                 _ => None
             },
@@ -217,8 +218,8 @@ fn inline_const_fn_from_external_crate(tcx: &ty::ctxt, def_id: ast::DefId)
 
     let fn_id = match csearch::maybe_get_item_ast(tcx, def_id,
         box |a, b, c, d| astencode::decode_inlined_item(a, b, c, d)) {
-        csearch::FoundAst::Found(&ast::IIItem(ref item)) => Some(item.id),
-        csearch::FoundAst::Found(&ast::IIImplItem(_, ref item)) => Some(item.id),
+        csearch::FoundAst::Found(&InlinedItem::Item(ref item)) => Some(item.id),
+        csearch::FoundAst::Found(&InlinedItem::ImplItem(_, ref item)) => Some(item.id),
         _ => None
     };
     tcx.extern_const_fns.borrow_mut().insert(def_id,
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 2a033d36a47..dafc1e900f3 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -17,8 +17,9 @@
 //! `middle/typeck/infer/region_inference.rs`
 
 use ast_map;
-use session::Session;
+use metadata::inline::InlinedItem;
 use middle::ty::{self, Ty};
+use session::Session;
 use util::nodemap::{FnvHashMap, FnvHashSet, NodeMap};
 
 use std::cell::RefCell;
@@ -1231,7 +1232,7 @@ pub fn resolve_crate(sess: &Session, krate: &ast::Crate) -> RegionMaps {
 
 pub fn resolve_inlined_item(sess: &Session,
                             region_maps: &RegionMaps,
-                            item: &ast::InlinedItem) {
+                            item: &InlinedItem) {
     let mut visitor = RegionResolutionVisitor {
         sess: sess,
         region_maps: region_maps,
@@ -1241,5 +1242,5 @@ pub fn resolve_inlined_item(sess: &Session,
             var_parent: InnermostDeclaringBlock::None
         }
     };
-    visit::walk_inlined_item(&mut visitor, item);
+    item.visit(&mut visitor);
 }
diff --git a/src/librustc_trans/trans/inline.rs b/src/librustc_trans/trans/inline.rs
index 01bfc51a5c0..c6450d06eb6 100644
--- a/src/librustc_trans/trans/inline.rs
+++ b/src/librustc_trans/trans/inline.rs
@@ -10,6 +10,7 @@
 
 use llvm::{AvailableExternallyLinkage, InternalLinkage, SetLinkage};
 use metadata::csearch;
+use metadata::inline::InlinedItem;
 use middle::astencode;
 use middle::subst::Substs;
 use trans::base::{push_ctxt, trans_item, get_item_val, trans_fn};
@@ -48,7 +49,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
             ccx.external().borrow_mut().insert(fn_id, None);
             return None;
         }
-        csearch::FoundAst::Found(&ast::IIItem(ref item)) => {
+        csearch::FoundAst::Found(&InlinedItem::Item(ref item)) => {
             ccx.external().borrow_mut().insert(fn_id, Some(item.id));
             ccx.external_srcs().borrow_mut().insert(item.id, fn_id);
 
@@ -91,12 +92,12 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
 
             item.id
         }
-        csearch::FoundAst::Found(&ast::IIForeign(ref item)) => {
+        csearch::FoundAst::Found(&InlinedItem::Foreign(ref item)) => {
             ccx.external().borrow_mut().insert(fn_id, Some(item.id));
             ccx.external_srcs().borrow_mut().insert(item.id, fn_id);
             item.id
         }
-        csearch::FoundAst::FoundParent(parent_id, &ast::IIItem(ref item)) => {
+        csearch::FoundAst::FoundParent(parent_id, &InlinedItem::Item(ref item)) => {
             ccx.external().borrow_mut().insert(parent_id, Some(item.id));
             ccx.external_srcs().borrow_mut().insert(item.id, parent_id);
 
@@ -131,7 +132,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
             ccx.sess().bug("maybe_get_item_ast returned a FoundParent \
                             with a non-item parent");
         }
-        csearch::FoundAst::Found(&ast::IITraitItem(_, ref trait_item)) => {
+        csearch::FoundAst::Found(&InlinedItem::TraitItem(_, ref trait_item)) => {
             ccx.external().borrow_mut().insert(fn_id, Some(trait_item.id));
             ccx.external_srcs().borrow_mut().insert(trait_item.id, fn_id);
 
@@ -150,7 +151,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
             // don't.
             trait_item.id
         }
-        csearch::FoundAst::Found(&ast::IIImplItem(impl_did, ref impl_item)) => {
+        csearch::FoundAst::Found(&InlinedItem::ImplItem(impl_did, ref impl_item)) => {
             ccx.external().borrow_mut().insert(fn_id, Some(impl_item.id));
             ccx.external_srcs().borrow_mut().insert(impl_item.id, fn_id);
 
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 08c6dcc7f87..0bcd97cfe87 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -23,7 +23,6 @@ pub use self::FloatTy::*;
 pub use self::FunctionRetTy::*;
 pub use self::ForeignItem_::*;
 pub use self::ImplItem_::*;
-pub use self::InlinedItem::*;
 pub use self::IntTy::*;
 pub use self::Item_::*;
 pub use self::KleeneOp::*;
@@ -1925,17 +1924,6 @@ impl ForeignItem_ {
     }
 }
 
-/// The data we save and restore about an inlined item or method.  This is not
-/// part of the AST that we parse from a file, but it becomes part of the tree
-/// that we trans.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum InlinedItem {
-    IIItem(P<Item>),
-    IITraitItem(DefId /* impl id */, P<TraitItem>),
-    IIImplItem(DefId /* impl id */, P<ImplItem>),
-    IIForeign(P<ForeignItem>),
-}
-
 /// A macro definition, in this crate or imported from another.
 ///
 /// Not parsed directly, but created on macro import or `macro_rules!` expansion.
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 83d3c9c4ec5..7aff92ecb70 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -503,19 +503,18 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
     }
 }
 
-pub fn visit_ids_for_inlined_item<O: IdVisitingOperation>(item: &InlinedItem,
-                                                          operation: &mut O) {
-    let mut id_visitor = IdVisitor {
-        operation: operation,
-        pass_through_items: true,
-        visited_outermost: false,
-    };
-
-    visit::walk_inlined_item(&mut id_visitor, item);
+pub struct IdRangeComputingVisitor {
+    result: IdRange,
 }
 
-struct IdRangeComputingVisitor {
-    result: IdRange,
+impl IdRangeComputingVisitor {
+    pub fn new() -> IdRangeComputingVisitor {
+        IdRangeComputingVisitor { result: IdRange::max() }
+    }
+
+    pub fn result(&self) -> IdRange {
+        self.result
+    }
 }
 
 impl IdVisitingOperation for IdRangeComputingVisitor {
@@ -524,14 +523,6 @@ impl IdVisitingOperation for IdRangeComputingVisitor {
     }
 }
 
-pub fn compute_id_range_for_inlined_item(item: &InlinedItem) -> IdRange {
-    let mut visitor = IdRangeComputingVisitor {
-        result: IdRange::max()
-    };
-    visit_ids_for_inlined_item(item, &mut visitor);
-    visitor.result
-}
-
 /// Computes the id range for a single fn body, ignoring nested items.
 pub fn compute_id_range_for_fn_body(fk: visit::FnKind,
                                     decl: &FnDecl,
@@ -540,9 +531,7 @@ pub fn compute_id_range_for_fn_body(fk: visit::FnKind,
                                     id: NodeId)
                                     -> IdRange
 {
-    let mut visitor = IdRangeComputingVisitor {
-        result: IdRange::max()
-    };
+    let mut visitor = IdRangeComputingVisitor::new();
     let mut id_visitor = IdVisitor {
         operation: &mut visitor,
         pass_through_items: false,
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index ad144d6033b..259564337a2 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -142,17 +142,6 @@ pub trait Visitor<'v> : Sized {
     fn visit_attribute(&mut self, _attr: &'v Attribute) {}
 }
 
-pub fn walk_inlined_item<'v,V>(visitor: &mut V, item: &'v InlinedItem)
-                         where V: Visitor<'v> {
-    match *item {
-        IIItem(ref i) => visitor.visit_item(&**i),
-        IIForeign(ref i) => visitor.visit_foreign_item(&**i),
-        IITraitItem(_, ref ti) => visitor.visit_trait_item(ti),
-        IIImplItem(_, ref ii) => visitor.visit_impl_item(ii),
-    }
-}
-
-
 pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
     visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
     for attr in &krate.attrs {

From c9bb5a68f866a11a7507ccd4994978ad6d080eb0 Mon Sep 17 00:00:00 2001
From: Niko Matsakis <niko@alum.mit.edu>
Date: Fri, 14 Aug 2015 04:56:07 -0400
Subject: [PATCH 2/7] convert tydecode to use a closure for def-id conversion
 and to store the closure in the PSState struct

---
 src/librustc/metadata/tydecode.rs | 401 +++++++++++-------------------
 1 file changed, 142 insertions(+), 259 deletions(-)

diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index a8b22846b78..bdeae1c4bc9 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -57,13 +57,14 @@ pub enum DefIdSource {
     ClosureSource
 }
 
-// type conv_did = impl FnMut(DefIdSource, ast::DefId) -> ast::DefId;
+pub type DefIdConvert<'a> = &'a mut FnMut(DefIdSource, ast::DefId) -> ast::DefId;
 
 pub struct PState<'a, 'tcx: 'a> {
     data: &'a [u8],
     krate: ast::CrateNum,
     pos: usize,
-    tcx: &'a ty::ctxt<'tcx>
+    tcx: &'a ty::ctxt<'tcx>,
+    conv_def_id: DefIdConvert<'a>,
 }
 
 fn peek(st: &PState) -> char {
@@ -82,9 +83,8 @@ fn next_byte(st: &mut PState) -> u8 {
     return b;
 }
 
-fn scan<R, F, G>(st: &mut PState, mut is_last: F, op: G) -> R where
+fn scan<'a, 'tcx, F>(st: &mut PState<'a,'tcx>, mut is_last: F) -> &'a [u8] where
     F: FnMut(char) -> bool,
-    G: FnOnce(&[u8]) -> R,
 {
     let start_pos = st.pos;
     debug!("scan: '{}' (start)", st.data[st.pos] as char);
@@ -94,30 +94,27 @@ fn scan<R, F, G>(st: &mut PState, mut is_last: F, op: G) -> R where
     }
     let end_pos = st.pos;
     st.pos += 1;
-    return op(&st.data[start_pos..end_pos]);
+    return &st.data[start_pos..end_pos];
 }
 
 pub fn parse_name(st: &mut PState, last: char) -> ast::Name {
     fn is_last(b: char, c: char) -> bool { return c == b; }
-    parse_name_(st, |a| is_last(last, a) )
+    let bytes = scan(st, |a| is_last(last, a));
+    token::intern(str::from_utf8(bytes).unwrap())
 }
 
-fn parse_name_<F>(st: &mut PState, is_last: F) -> ast::Name where
-    F: FnMut(char) -> bool,
-{
-    scan(st, is_last, |bytes| {
-        token::intern(str::from_utf8(bytes).unwrap())
-    })
-}
-
-pub fn parse_state_from_data<'a, 'tcx>(data: &'a [u8], crate_num: ast::CrateNum,
-                                       pos: usize, tcx: &'a ty::ctxt<'tcx>)
+pub fn parse_state_from_data<'a, 'tcx>(data: &'a [u8],
+                                       crate_num: ast::CrateNum,
+                                       pos: usize,
+                                       tcx: &'a ty::ctxt<'tcx>,
+                                       conv: DefIdConvert<'a>)
                                        -> PState<'a, 'tcx> {
     PState {
         data: data,
         krate: crate_num,
         pos: pos,
-        tcx: tcx
+        tcx: tcx,
+        conv_def_id: conv,
     }
 }
 
@@ -140,77 +137,77 @@ pub fn parse_ty_closure_data<'tcx, F>(data: &[u8],
                                       crate_num: ast::CrateNum,
                                       pos: usize,
                                       tcx: &ty::ctxt<'tcx>,
-                                      conv: F)
+                                      mut conv: F)
                                       -> ty::ClosureTy<'tcx> where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
-    let mut st = parse_state_from_data(data, crate_num, pos, tcx);
-    parse_closure_ty(&mut st, conv)
+    let mut st = parse_state_from_data(data, crate_num, pos, tcx, &mut conv);
+    parse_closure_ty(&mut st)
 }
 
 pub fn parse_ty_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize,
-                              tcx: &ty::ctxt<'tcx>, conv: F) -> Ty<'tcx> where
+                              tcx: &ty::ctxt<'tcx>, mut conv: F) -> Ty<'tcx> where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
     debug!("parse_ty_data {}", data_log_string(data, pos));
-    let mut st = parse_state_from_data(data, crate_num, pos, tcx);
-    parse_ty(&mut st, conv)
+    let mut st = parse_state_from_data(data, crate_num, pos, tcx, &mut conv);
+    parse_ty(&mut st)
 }
 
 pub fn parse_region_data<F>(data: &[u8], crate_num: ast::CrateNum, pos: usize, tcx: &ty::ctxt,
-                            conv: F) -> ty::Region where
+                            mut conv: F) -> ty::Region where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
     debug!("parse_region_data {}", data_log_string(data, pos));
-    let mut st = parse_state_from_data(data, crate_num, pos, tcx);
-    parse_region(&mut st, conv)
+    let mut st = parse_state_from_data(data, crate_num, pos, tcx, &mut conv);
+    parse_region(&mut st)
 }
 
 pub fn parse_bare_fn_ty_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize,
-                                      tcx: &ty::ctxt<'tcx>, conv: F)
+                                      tcx: &ty::ctxt<'tcx>, mut conv: F)
                                       -> ty::BareFnTy<'tcx> where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
     debug!("parse_bare_fn_ty_data {}", data_log_string(data, pos));
-    let mut st = parse_state_from_data(data, crate_num, pos, tcx);
-    parse_bare_fn_ty(&mut st, conv)
+    let mut st = parse_state_from_data(data, crate_num, pos, tcx, &mut conv);
+    parse_bare_fn_ty(&mut st)
 }
 
 pub fn parse_trait_ref_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize,
-                                     tcx: &ty::ctxt<'tcx>, conv: F)
+                                     tcx: &ty::ctxt<'tcx>, mut conv: F)
                                      -> ty::TraitRef<'tcx> where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
     debug!("parse_trait_ref_data {}", data_log_string(data, pos));
-    let mut st = parse_state_from_data(data, crate_num, pos, tcx);
-    parse_trait_ref(&mut st, conv)
+    let mut st = parse_state_from_data(data, crate_num, pos, tcx, &mut conv);
+    parse_trait_ref(&mut st)
 }
 
 pub fn parse_substs_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize,
-                                  tcx: &ty::ctxt<'tcx>, conv: F) -> subst::Substs<'tcx> where
+                                  tcx: &ty::ctxt<'tcx>, mut conv: F) -> subst::Substs<'tcx> where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
     debug!("parse_substs_data{}", data_log_string(data, pos));
-    let mut st = parse_state_from_data(data, crate_num, pos, tcx);
-    parse_substs(&mut st, conv)
+    let mut st = parse_state_from_data(data, crate_num, pos, tcx, &mut conv);
+    parse_substs(&mut st)
 }
 
 pub fn parse_existential_bounds_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum,
-                                              pos: usize, tcx: &ty::ctxt<'tcx>, conv: F)
+                                              pos: usize, tcx: &ty::ctxt<'tcx>, mut conv: F)
                                               -> ty::ExistentialBounds<'tcx> where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
-    let mut st = parse_state_from_data(data, crate_num, pos, tcx);
-    parse_existential_bounds(&mut st, conv)
+    let mut st = parse_state_from_data(data, crate_num, pos, tcx, &mut conv);
+    parse_existential_bounds(&mut st)
 }
 
 pub fn parse_builtin_bounds_data<F>(data: &[u8], crate_num: ast::CrateNum,
-                                    pos: usize, tcx: &ty::ctxt, conv: F)
+                                    pos: usize, tcx: &ty::ctxt, mut conv: F)
                                     -> ty::BuiltinBounds where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
-    let mut st = parse_state_from_data(data, crate_num, pos, tcx);
-    parse_builtin_bounds(&mut st, conv)
+    let mut st = parse_state_from_data(data, crate_num, pos, tcx, &mut conv);
+    parse_builtin_bounds(&mut st)
 }
 
 fn parse_size(st: &mut PState) -> Option<usize> {
@@ -242,44 +239,25 @@ fn parse_vec_per_param_space<'a, 'tcx, T, F>(st: &mut PState<'a, 'tcx>,
     r
 }
 
-fn parse_substs<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>,
-                             mut conv: F) -> subst::Substs<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    parse_substs_(st, &mut conv)
+fn parse_substs<'a, 'tcx>(st: &mut PState<'a, 'tcx>) -> subst::Substs<'tcx> {
+    let regions = parse_region_substs(st);
+    let types = parse_vec_per_param_space(st, |st| parse_ty(st));
+    subst::Substs { types: types, regions: regions }
 }
 
-fn parse_substs_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>,
-                              conv: &mut F) -> subst::Substs<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    let regions =
-        parse_region_substs_(st, conv);
-
-    let types =
-        parse_vec_per_param_space(st, |st| parse_ty_(st, conv));
-
-    subst::Substs { types: types,
-                    regions: regions }
-}
-
-fn parse_region_substs_<F>(st: &mut PState, conv: &mut F) -> subst::RegionSubsts where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
+fn parse_region_substs(st: &mut PState) -> subst::RegionSubsts {
     match next(st) {
         'e' => subst::ErasedRegions,
         'n' => {
             subst::NonerasedRegions(
                 parse_vec_per_param_space(
-                    st, |st| parse_region_(st, conv)))
+                    st, |st| parse_region(st)))
         }
         _ => panic!("parse_bound_region: bad input")
     }
 }
 
-fn parse_bound_region_<F>(st: &mut PState, conv: &mut F) -> ty::BoundRegion where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
+fn parse_bound_region(st: &mut PState) -> ty::BoundRegion {
     match next(st) {
         'a' => {
             let id = parse_u32(st);
@@ -287,7 +265,7 @@ fn parse_bound_region_<F>(st: &mut PState, conv: &mut F) -> ty::BoundRegion wher
             ty::BrAnon(id)
         }
         '[' => {
-            let def = parse_def_(st, RegionParameter, conv);
+            let def = parse_def(st, RegionParameter);
             let ident = token::str_to_ident(&parse_str(st, ']'));
             ty::BrNamed(def, ident.name)
         }
@@ -301,21 +279,13 @@ fn parse_bound_region_<F>(st: &mut PState, conv: &mut F) -> ty::BoundRegion wher
     }
 }
 
-fn parse_region<F>(st: &mut PState, mut conv: F) -> ty::Region where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    parse_region_(st, &mut conv)
-}
-
-fn parse_region_<F>(st: &mut PState, conv: &mut F) -> ty::Region where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
+fn parse_region(st: &mut PState) -> ty::Region {
     match next(st) {
       'b' => {
         assert_eq!(next(st), '[');
         let id = ty::DebruijnIndex::new(parse_u32(st));
         assert_eq!(next(st), '|');
-        let br = parse_bound_region_(st, conv);
+        let br = parse_bound_region(st);
         assert_eq!(next(st), ']');
         ty::ReLateBound(id, br)
       }
@@ -339,7 +309,7 @@ fn parse_region_<F>(st: &mut PState, conv: &mut F) -> ty::Region where
         assert_eq!(next(st), '[');
         let scope = parse_destruction_scope_data(st);
         assert_eq!(next(st), '|');
-        let br = parse_bound_region_(st, conv);
+        let br = parse_bound_region(st);
         assert_eq!(next(st), ']');
         ty::ReFree(ty::FreeRegion { scope: scope,
                                     bound_region: br})
@@ -420,31 +390,13 @@ fn parse_str(st: &mut PState, term: char) -> String {
     result
 }
 
-fn parse_trait_ref<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, mut conv: F)
-                                -> ty::TraitRef<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    parse_trait_ref_(st, &mut conv)
-}
-
-fn parse_trait_ref_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
-                              -> ty::TraitRef<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    let def = parse_def_(st, NominalType, conv);
-    let substs = st.tcx.mk_substs(parse_substs_(st, conv));
+fn parse_trait_ref<'a, 'tcx>(st: &mut PState<'a, 'tcx>) -> ty::TraitRef<'tcx> {
+    let def = parse_def(st, NominalType);
+    let substs = st.tcx.mk_substs(parse_substs(st));
     ty::TraitRef {def_id: def, substs: substs}
 }
 
-fn parse_ty<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, mut conv: F) -> Ty<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    parse_ty_(st, &mut conv)
-}
-
-fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
+fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>) -> Ty<'tcx> {
     let tcx = st.tcx;
     match next(st) {
       'b' => return tcx.types.bool,
@@ -468,16 +420,16 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w
       'c' => return tcx.types.char,
       't' => {
         assert_eq!(next(st), '[');
-        let did = parse_def_(st, NominalType, conv);
-        let substs = parse_substs_(st, conv);
+        let did = parse_def(st, NominalType);
+        let substs = parse_substs(st);
         assert_eq!(next(st), ']');
         let def = st.tcx.lookup_adt_def(did);
         return tcx.mk_enum(def, st.tcx.mk_substs(substs));
       }
       'x' => {
         assert_eq!(next(st), '[');
-        let trait_ref = ty::Binder(parse_trait_ref_(st, conv));
-        let bounds = parse_existential_bounds_(st, conv);
+        let trait_ref = ty::Binder(parse_trait_ref(st));
+        let bounds = parse_existential_bounds(st);
         assert_eq!(next(st), ']');
         return tcx.mk_trait(trait_ref, bounds);
       }
@@ -490,15 +442,15 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w
         let name = token::intern(&parse_str(st, ']'));
         return tcx.mk_param(space, index, name);
       }
-      '~' => return tcx.mk_box(parse_ty_(st, conv)),
-      '*' => return tcx.mk_ptr(parse_mt_(st, conv)),
+      '~' => return tcx.mk_box(parse_ty(st)),
+      '*' => return tcx.mk_ptr(parse_mt(st)),
       '&' => {
-        let r = parse_region_(st, conv);
-        let mt = parse_mt_(st, conv);
+        let r = parse_region(st);
+        let mt = parse_mt(st);
         return tcx.mk_ref(tcx.mk_region(r), mt);
       }
       'V' => {
-        let t = parse_ty_(st, conv);
+        let t = parse_ty(st);
         return match parse_size(st) {
             Some(n) => tcx.mk_array(t, n),
             None => tcx.mk_slice(t)
@@ -510,26 +462,31 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w
       'T' => {
         assert_eq!(next(st), '[');
         let mut params = Vec::new();
-        while peek(st) != ']' { params.push(parse_ty_(st, conv)); }
+        while peek(st) != ']' { params.push(parse_ty(st)); }
         st.pos = st.pos + 1;
         return tcx.mk_tup(params);
       }
       'F' => {
-          let def_id = parse_def_(st, NominalType, conv);
-          return tcx.mk_fn(Some(def_id), tcx.mk_bare_fn(parse_bare_fn_ty_(st, conv)));
+          let def_id = parse_def(st, NominalType);
+          return tcx.mk_fn(Some(def_id), tcx.mk_bare_fn(parse_bare_fn_ty(st)));
       }
       'G' => {
-          return tcx.mk_fn(None, tcx.mk_bare_fn(parse_bare_fn_ty_(st, conv)));
+          return tcx.mk_fn(None, tcx.mk_bare_fn(parse_bare_fn_ty(st)));
       }
       '#' => {
+        // This is a hacky little caching scheme. The idea is that if we encode
+        // the same type twice, the second (and third, and fourth...) time we will
+        // just write `#123`, where `123` is the offset in the metadata of the
+        // first appearance. Now when we are *decoding*, if we see a `#123`, we
+        // can first check a cache (`tcx.rcache`) for that offset. If we find something,
+        // we return it (modulo closure types, see below). But if not, then we
+        // jump to offset 123 and read the type from there.
+
         let pos = parse_hex(st);
         assert_eq!(next(st), ':');
         let len = parse_hex(st);
         assert_eq!(next(st), '#');
-        let key = ty::CReaderCacheKey {cnum: st.krate,
-                                         pos: pos,
-                                         len: len };
-
+        let key = ty::CReaderCacheKey {cnum: st.krate, pos: pos, len: len };
         match tcx.rcache.borrow().get(&key).cloned() {
           Some(tt) => {
             // If there is a closure buried in the type some where, then we
@@ -541,34 +498,39 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w
           }
           None => {}
         }
+
         let mut ps = PState {
             pos: pos,
-            .. *st
+            conv_def_id: st.conv_def_id, // -+ Have to call out these fields specifically,
+            tcx: st.tcx,                 //  | rather than writing `..*st`, so that we
+            data: st.data,               //  | trigger reborrow coercions. Suboptimal,
+            krate: st.krate,             // -+ I suppose.
         };
-        let tt = parse_ty_(&mut ps, conv);
+
+        let tt = parse_ty(&mut ps);
         tcx.rcache.borrow_mut().insert(key, tt);
         return tt;
       }
       '\"' => {
-        let _ = parse_def_(st, TypeWithId, conv);
-        let inner = parse_ty_(st, conv);
+        let _ = parse_def(st, TypeWithId);
+        let inner = parse_ty(st);
         inner
       }
       'a' => {
           assert_eq!(next(st), '[');
-          let did = parse_def_(st, NominalType, conv);
-          let substs = parse_substs_(st, conv);
+          let did = parse_def(st, NominalType);
+          let substs = parse_substs(st);
           assert_eq!(next(st), ']');
           let def = st.tcx.lookup_adt_def(did);
           return st.tcx.mk_struct(def, st.tcx.mk_substs(substs));
       }
       'k' => {
           assert_eq!(next(st), '[');
-          let did = parse_def_(st, ClosureSource, conv);
-          let substs = parse_substs_(st, conv);
+          let did = parse_def(st, ClosureSource);
+          let substs = parse_substs(st);
           let mut tys = vec![];
           while peek(st) != '.' {
-              tys.push(parse_ty_(st, conv));
+              tys.push(parse_ty(st));
           }
           assert_eq!(next(st), '.');
           assert_eq!(next(st), ']');
@@ -576,7 +538,7 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w
       }
       'P' => {
           assert_eq!(next(st), '[');
-          let trait_ref = parse_trait_ref_(st, conv);
+          let trait_ref = parse_trait_ref(st);
           let name = token::intern(&parse_str(st, ']'));
           return tcx.mk_projection(trait_ref, name);
       }
@@ -594,17 +556,14 @@ fn parse_mutability(st: &mut PState) -> ast::Mutability {
     }
 }
 
-fn parse_mt_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> ty::TypeAndMut<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
+fn parse_mt<'a, 'tcx>(st: &mut PState<'a, 'tcx>) -> ty::TypeAndMut<'tcx> {
     let m = parse_mutability(st);
-    ty::TypeAndMut { ty: parse_ty_(st, conv), mutbl: m }
+    ty::TypeAndMut { ty: parse_ty(st), mutbl: m }
 }
 
-fn parse_def_<F>(st: &mut PState, source: DefIdSource, conv: &mut F) -> ast::DefId where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    return (*conv)(source, scan(st, |c| { c == '|' }, parse_def_id));
+fn parse_def(st: &mut PState, source: DefIdSource) -> ast::DefId {
+    let def_id = parse_defid(scan(st, |c| c == '|'));
+    return (st.conv_def_id)(source, def_id);
 }
 
 fn parse_uint(st: &mut PState) -> usize {
@@ -652,25 +611,14 @@ fn parse_unsafety(c: char) -> ast::Unsafety {
 
 fn parse_abi_set(st: &mut PState) -> abi::Abi {
     assert_eq!(next(st), '[');
-    scan(st, |c| c == ']', |bytes| {
-        let abi_str = str::from_utf8(bytes).unwrap();
-        abi::lookup(&abi_str[..]).expect(abi_str)
-    })
+    let bytes = scan(st, |c| c == ']');
+    let abi_str = str::from_utf8(bytes).unwrap();
+    abi::lookup(&abi_str[..]).expect(abi_str)
 }
 
-fn parse_closure_ty<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>,
-                                 mut conv: F) -> ty::ClosureTy<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    parse_closure_ty_(st, &mut conv)
-}
-
-fn parse_closure_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>,
-                                 conv: &mut F) -> ty::ClosureTy<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
+fn parse_closure_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>) -> ty::ClosureTy<'tcx> {
     let unsafety = parse_unsafety(next(st));
-    let sig = parse_sig_(st, conv);
+    let sig = parse_sig(st);
     let abi = parse_abi_set(st);
     ty::ClosureTy {
         unsafety: unsafety,
@@ -679,20 +627,10 @@ fn parse_closure_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>,
     }
 }
 
-fn parse_bare_fn_ty<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>,
-                                 mut conv: F) -> ty::BareFnTy<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    parse_bare_fn_ty_(st, &mut conv)
-}
-
-fn parse_bare_fn_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>,
-                                 conv: &mut F) -> ty::BareFnTy<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
+fn parse_bare_fn_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>) -> ty::BareFnTy<'tcx> {
     let unsafety = parse_unsafety(next(st));
     let abi = parse_abi_set(st);
-    let sig = parse_sig_(st, conv);
+    let sig = parse_sig(st);
     ty::BareFnTy {
         unsafety: unsafety,
         abi: abi,
@@ -700,13 +638,11 @@ fn parse_bare_fn_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>,
     }
 }
 
-fn parse_sig_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> ty::PolyFnSig<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
+fn parse_sig<'a, 'tcx>(st: &mut PState<'a, 'tcx>) -> ty::PolyFnSig<'tcx> {
     assert_eq!(next(st), '[');
     let mut inputs = Vec::new();
     while peek(st) != ']' {
-        inputs.push(parse_ty_(st, conv));
+        inputs.push(parse_ty(st));
     }
     st.pos += 1; // eat the ']'
     let variadic = match next(st) {
@@ -719,15 +655,15 @@ fn parse_sig_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> ty::PolyF
           st.pos += 1;
           ty::FnDiverging
         }
-        _ => ty::FnConverging(parse_ty_(st, conv))
+        _ => ty::FnConverging(parse_ty(st))
     };
     ty::Binder(ty::FnSig {inputs: inputs,
-                        output: output,
-                        variadic: variadic})
+                          output: output,
+                          variadic: variadic})
 }
 
 // Rust metadata parsing
-pub fn parse_def_id(buf: &[u8]) -> ast::DefId {
+pub fn parse_defid(buf: &[u8]) -> ast::DefId {
     let mut colon_idx = 0;
     let len = buf.len();
     while colon_idx < len && buf[colon_idx] != ':' as u8 { colon_idx += 1; }
@@ -743,14 +679,14 @@ pub fn parse_def_id(buf: &[u8]) -> ast::DefId {
         s.parse::<usize>().ok()
     }) {
        Some(cn) => cn as ast::CrateNum,
-       None => panic!("internal error: parse_def_id: crate number expected, found {:?}",
+       None => panic!("internal error: parse_defid: crate number expected, found {:?}",
                      crate_part)
     };
     let def_num = match str::from_utf8(def_part).ok().and_then(|s| {
         s.parse::<usize>().ok()
     }) {
        Some(dn) => dn as ast::NodeId,
-       None => panic!("internal error: parse_def_id: id expected, found {:?}",
+       None => panic!("internal error: parse_defid: id expected, found {:?}",
                      def_part)
     };
     ast::DefId { krate: crate_num, node: def_num }
@@ -760,39 +696,27 @@ pub fn parse_predicate_data<'tcx, F>(data: &[u8],
                                      start: usize,
                                      crate_num: ast::CrateNum,
                                      tcx: &ty::ctxt<'tcx>,
-                                     conv: F)
+                                     mut conv: F)
                                      -> ty::Predicate<'tcx> where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
-    let mut st = parse_state_from_data(data, crate_num, start, tcx);
-    parse_predicate(&mut st, conv)
+    let mut st = parse_state_from_data(data, crate_num, start, tcx, &mut conv);
+    parse_predicate(&mut st)
 }
 
-pub fn parse_predicate<'a,'tcx, F>(st: &mut PState<'a, 'tcx>,
-                                   mut conv: F)
-                                   -> ty::Predicate<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    parse_predicate_(st, &mut conv)
-}
-
-fn parse_predicate_<'a,'tcx, F>(st: &mut PState<'a, 'tcx>,
-                                conv: &mut F)
-                                -> ty::Predicate<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
+pub fn parse_predicate<'a,'tcx>(st: &mut PState<'a, 'tcx>) -> ty::Predicate<'tcx> {
     match next(st) {
-        't' => ty::Binder(parse_trait_ref_(st, conv)).to_predicate(),
-        'e' => ty::Binder(ty::EquatePredicate(parse_ty_(st, conv),
-                                              parse_ty_(st, conv))).to_predicate(),
-        'r' => ty::Binder(ty::OutlivesPredicate(parse_region_(st, conv),
-                                                parse_region_(st, conv))).to_predicate(),
-        'o' => ty::Binder(ty::OutlivesPredicate(parse_ty_(st, conv),
-                                                parse_region_(st, conv))).to_predicate(),
-        'p' => ty::Binder(parse_projection_predicate_(st, conv)).to_predicate(),
-        'w' => ty::Predicate::WellFormed(parse_ty_(st, conv)),
+        't' => ty::Binder(parse_trait_ref(st)).to_predicate(),
+        'e' => ty::Binder(ty::EquatePredicate(parse_ty(st),
+                                              parse_ty(st))).to_predicate(),
+        'r' => ty::Binder(ty::OutlivesPredicate(parse_region(st),
+                                                parse_region(st))).to_predicate(),
+        'o' => ty::Binder(ty::OutlivesPredicate(parse_ty(st),
+                                                parse_region(st))).to_predicate(),
+        'p' => ty::Binder(parse_projection_predicate(st)).to_predicate(),
+        'w' => ty::Predicate::WellFormed(parse_ty(st)),
         'O' => {
-            let def_id = parse_def_(st, NominalType, conv);
+            let def_id = parse_def(st, NominalType);
             assert_eq!(next(st), '|');
             ty::Predicate::ObjectSafe(def_id)
         }
@@ -800,50 +724,35 @@ fn parse_predicate_<'a,'tcx, F>(st: &mut PState<'a, 'tcx>,
     }
 }
 
-fn parse_projection_predicate_<'a,'tcx, F>(
-    st: &mut PState<'a, 'tcx>,
-    conv: &mut F,
-) -> ty::ProjectionPredicate<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
+fn parse_projection_predicate<'a,'tcx>(st: &mut PState<'a, 'tcx>) -> ty::ProjectionPredicate<'tcx> {
     ty::ProjectionPredicate {
         projection_ty: ty::ProjectionTy {
-            trait_ref: parse_trait_ref_(st, conv),
+            trait_ref: parse_trait_ref(st),
             item_name: token::str_to_ident(&parse_str(st, '|')).name,
         },
-        ty: parse_ty_(st, conv),
+        ty: parse_ty(st),
     }
 }
 
 pub fn parse_type_param_def_data<'tcx, F>(data: &[u8], start: usize,
                                           crate_num: ast::CrateNum, tcx: &ty::ctxt<'tcx>,
-                                          conv: F) -> ty::TypeParameterDef<'tcx> where
+                                          mut conv: F) -> ty::TypeParameterDef<'tcx> where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
-    let mut st = parse_state_from_data(data, crate_num, start, tcx);
-    parse_type_param_def(&mut st, conv)
+    let mut st = parse_state_from_data(data, crate_num, start, tcx, &mut conv);
+    parse_type_param_def(&mut st)
 }
 
-fn parse_type_param_def<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, mut conv: F)
-                                     -> ty::TypeParameterDef<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    parse_type_param_def_(st, &mut conv)
-}
-
-fn parse_type_param_def_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
-                                      -> ty::TypeParameterDef<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
+fn parse_type_param_def<'a, 'tcx>(st: &mut PState<'a, 'tcx>) -> ty::TypeParameterDef<'tcx> {
     let name = parse_name(st, ':');
-    let def_id = parse_def_(st, NominalType, conv);
+    let def_id = parse_def(st, NominalType);
     let space = parse_param_space(st);
     assert_eq!(next(st), '|');
     let index = parse_u32(st);
     assert_eq!(next(st), '|');
-    let default_def_id = parse_def_(st, NominalType, conv);
-    let default = parse_opt(st, |st| parse_ty_(st, conv));
-    let object_lifetime_default = parse_object_lifetime_default(st, conv);
+    let default_def_id = parse_def(st, NominalType);
+    let default = parse_opt(st, |st| parse_ty(st));
+    let object_lifetime_default = parse_object_lifetime_default(st);
 
     ty::TypeParameterDef {
         name: name,
@@ -856,44 +765,27 @@ fn parse_type_param_def_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
     }
 }
 
-fn parse_object_lifetime_default<'a,'tcx, F>(st: &mut PState<'a,'tcx>,
-                                             conv: &mut F)
-                                             -> ty::ObjectLifetimeDefault
-    where F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
+fn parse_object_lifetime_default<'a,'tcx>(st: &mut PState<'a,'tcx>) -> ty::ObjectLifetimeDefault {
     match next(st) {
         'a' => ty::ObjectLifetimeDefault::Ambiguous,
         'b' => ty::ObjectLifetimeDefault::BaseDefault,
         's' => {
-            let region = parse_region_(st, conv);
+            let region = parse_region(st);
             ty::ObjectLifetimeDefault::Specific(region)
         }
         _ => panic!("parse_object_lifetime_default: bad input")
     }
 }
 
-fn parse_existential_bounds<'a,'tcx, F>(st: &mut PState<'a,'tcx>,
-                                        mut conv: F)
-                                        -> ty::ExistentialBounds<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    parse_existential_bounds_(st, &mut conv)
-}
-
-fn parse_existential_bounds_<'a,'tcx, F>(st: &mut PState<'a,'tcx>,
-                                        conv: &mut F)
-                                        -> ty::ExistentialBounds<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    let builtin_bounds = parse_builtin_bounds_(st, conv);
-    let region_bound = parse_region_(st, conv);
+fn parse_existential_bounds<'a,'tcx>(st: &mut PState<'a,'tcx>) -> ty::ExistentialBounds<'tcx> {
+    let builtin_bounds = parse_builtin_bounds(st);
+    let region_bound = parse_region(st);
     let mut projection_bounds = Vec::new();
 
     loop {
         match next(st) {
             'P' => {
-                projection_bounds.push(
-                    ty::Binder(parse_projection_predicate_(st, conv)));
+                projection_bounds.push(ty::Binder(parse_projection_predicate(st)));
                 }
             '.' => { break; }
             c => {
@@ -907,17 +799,8 @@ fn parse_existential_bounds_<'a,'tcx, F>(st: &mut PState<'a,'tcx>,
                                    projection_bounds: projection_bounds };
 }
 
-fn parse_builtin_bounds<F>(st: &mut PState, mut _conv: F) -> ty::BuiltinBounds where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    parse_builtin_bounds_(st, &mut _conv)
-}
-
-fn parse_builtin_bounds_<F>(st: &mut PState, _conv: &mut F) -> ty::BuiltinBounds where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
+fn parse_builtin_bounds(st: &mut PState) -> ty::BuiltinBounds {
     let mut builtin_bounds = ty::BuiltinBounds::empty();
-
     loop {
         match next(st) {
             'S' => {

From 2a53744aaacb7bdaba2a20b49f7bf484222f5813 Mon Sep 17 00:00:00 2001
From: Niko Matsakis <niko@alum.mit.edu>
Date: Fri, 14 Aug 2015 05:11:54 -0400
Subject: [PATCH 3/7] convert tydecode to use an impl, eliminating a lot of
 boilerplate

---
 src/librustc/metadata/tydecode.rs | 1415 ++++++++++++++---------------
 1 file changed, 706 insertions(+), 709 deletions(-)

diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index bdeae1c4bc9..2ddb0697c17 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -57,6 +57,104 @@ pub enum DefIdSource {
     ClosureSource
 }
 
+pub fn parse_ty_closure_data<'tcx, F>(data: &[u8],
+                                      crate_num: ast::CrateNum,
+                                      pos: usize,
+                                      tcx: &ty::ctxt<'tcx>,
+                                      mut conv: F)
+                                      -> ty::ClosureTy<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    let mut st = PState::new(data, crate_num, pos, tcx, &mut conv);
+    st.parse_closure_ty()
+}
+
+pub fn parse_ty_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize,
+                              tcx: &ty::ctxt<'tcx>, mut conv: F) -> Ty<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    debug!("parse_ty_data {}", data_log_string(data, pos));
+    let mut st = PState::new(data, crate_num, pos, tcx, &mut conv);
+    st.parse_ty()
+}
+
+pub fn parse_region_data<F>(data: &[u8], crate_num: ast::CrateNum, pos: usize, tcx: &ty::ctxt,
+                            mut conv: F) -> ty::Region where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    debug!("parse_region_data {}", data_log_string(data, pos));
+    let mut st = PState::new(data, crate_num, pos, tcx, &mut conv);
+    st.parse_region()
+}
+
+pub fn parse_bare_fn_ty_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize,
+                                      tcx: &ty::ctxt<'tcx>, mut conv: F)
+                                      -> ty::BareFnTy<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    debug!("parse_bare_fn_ty_data {}", data_log_string(data, pos));
+    let mut st = PState::new(data, crate_num, pos, tcx, &mut conv);
+    st.parse_bare_fn_ty()
+}
+
+pub fn parse_trait_ref_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize,
+                                     tcx: &ty::ctxt<'tcx>, mut conv: F)
+                                     -> ty::TraitRef<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    debug!("parse_trait_ref_data {}", data_log_string(data, pos));
+    let mut st = PState::new(data, crate_num, pos, tcx, &mut conv);
+    st.parse_trait_ref()
+}
+
+pub fn parse_substs_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize,
+                                  tcx: &ty::ctxt<'tcx>, mut conv: F) -> subst::Substs<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    debug!("parse_substs_data{}", data_log_string(data, pos));
+    let mut st = PState::new(data, crate_num, pos, tcx, &mut conv);
+    st.parse_substs()
+}
+
+pub fn parse_existential_bounds_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum,
+                                              pos: usize, tcx: &ty::ctxt<'tcx>, mut conv: F)
+                                              -> ty::ExistentialBounds<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    let mut st = PState::new(data, crate_num, pos, tcx, &mut conv);
+    st.parse_existential_bounds()
+}
+
+pub fn parse_builtin_bounds_data<F>(data: &[u8], crate_num: ast::CrateNum,
+                                    pos: usize, tcx: &ty::ctxt, mut conv: F)
+                                    -> ty::BuiltinBounds where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    let mut st = PState::new(data, crate_num, pos, tcx, &mut conv);
+    st.parse_builtin_bounds()
+}
+
+pub fn parse_type_param_def_data<'tcx, F>(data: &[u8], start: usize,
+                                          crate_num: ast::CrateNum, tcx: &ty::ctxt<'tcx>,
+                                          mut conv: F) -> ty::TypeParameterDef<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    let mut st = PState::new(data, crate_num, start, tcx, &mut conv);
+    st.parse_type_param_def()
+}
+
+pub fn parse_predicate_data<'tcx, F>(data: &[u8],
+                                     start: usize,
+                                     crate_num: ast::CrateNum,
+                                     tcx: &ty::ctxt<'tcx>,
+                                     mut conv: F)
+                                     -> ty::Predicate<'tcx> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    let mut st = PState::new(data, crate_num, start, tcx, &mut conv);
+    st.parse_predicate()
+}
+
 pub type DefIdConvert<'a> = &'a mut FnMut(DefIdSource, ast::DefId) -> ast::DefId;
 
 pub struct PState<'a, 'tcx: 'a> {
@@ -67,54 +165,606 @@ pub struct PState<'a, 'tcx: 'a> {
     conv_def_id: DefIdConvert<'a>,
 }
 
-fn peek(st: &PState) -> char {
-    st.data[st.pos] as char
-}
-
-fn next(st: &mut PState) -> char {
-    let ch = st.data[st.pos] as char;
-    st.pos = st.pos + 1;
-    return ch;
-}
-
-fn next_byte(st: &mut PState) -> u8 {
-    let b = st.data[st.pos];
-    st.pos = st.pos + 1;
-    return b;
-}
-
-fn scan<'a, 'tcx, F>(st: &mut PState<'a,'tcx>, mut is_last: F) -> &'a [u8] where
-    F: FnMut(char) -> bool,
-{
-    let start_pos = st.pos;
-    debug!("scan: '{}' (start)", st.data[st.pos] as char);
-    while !is_last(st.data[st.pos] as char) {
-        st.pos += 1;
-        debug!("scan: '{}'", st.data[st.pos] as char);
+impl<'a,'tcx> PState<'a,'tcx> {
+    pub fn new(data: &'a [u8],
+               crate_num: ast::CrateNum,
+               pos: usize,
+               tcx: &'a ty::ctxt<'tcx>,
+               conv: DefIdConvert<'a>)
+               -> PState<'a, 'tcx> {
+        PState {
+            data: data,
+            krate: crate_num,
+            pos: pos,
+            tcx: tcx,
+            conv_def_id: conv,
+        }
     }
-    let end_pos = st.pos;
-    st.pos += 1;
-    return &st.data[start_pos..end_pos];
-}
 
-pub fn parse_name(st: &mut PState, last: char) -> ast::Name {
-    fn is_last(b: char, c: char) -> bool { return c == b; }
-    let bytes = scan(st, |a| is_last(last, a));
-    token::intern(str::from_utf8(bytes).unwrap())
-}
+    fn peek(&self) -> char {
+        self.data[self.pos] as char
+    }
 
-pub fn parse_state_from_data<'a, 'tcx>(data: &'a [u8],
-                                       crate_num: ast::CrateNum,
-                                       pos: usize,
-                                       tcx: &'a ty::ctxt<'tcx>,
-                                       conv: DefIdConvert<'a>)
-                                       -> PState<'a, 'tcx> {
-    PState {
-        data: data,
-        krate: crate_num,
-        pos: pos,
-        tcx: tcx,
-        conv_def_id: conv,
+    fn next(&mut self) -> char {
+        let ch = self.data[self.pos] as char;
+        self.pos = self.pos + 1;
+        return ch;
+    }
+
+    fn next_byte(&mut self) -> u8 {
+        let b = self.data[self.pos];
+        self.pos = self.pos + 1;
+        return b;
+    }
+
+    fn scan<F>(&mut self, mut is_last: F) -> &'a [u8]
+        where F: FnMut(char) -> bool,
+    {
+        let start_pos = self.pos;
+        debug!("scan: '{}' (start)", self.data[self.pos] as char);
+        while !is_last(self.data[self.pos] as char) {
+            self.pos += 1;
+            debug!("scan: '{}'", self.data[self.pos] as char);
+        }
+        let end_pos = self.pos;
+        self.pos += 1;
+        return &self.data[start_pos..end_pos];
+    }
+
+    pub fn parse_name(&mut self, last: char) -> ast::Name {
+        fn is_last(b: char, c: char) -> bool { return c == b; }
+        let bytes = self.scan(|a| is_last(last, a));
+        token::intern(str::from_utf8(bytes).unwrap())
+    }
+
+    fn parse_size(&mut self) -> Option<usize> {
+        assert_eq!(self.next(), '/');
+
+        if self.peek() == '|' {
+            assert_eq!(self.next(), '|');
+            None
+        } else {
+            let n = self.parse_uint();
+            assert_eq!(self.next(), '|');
+            Some(n)
+        }
+    }
+
+    fn parse_vec_per_param_space<T, F>(&mut self, mut f: F) -> VecPerParamSpace<T> where
+        F: FnMut(&mut PState<'a, 'tcx>) -> T,
+    {
+        let mut r = VecPerParamSpace::empty();
+        for &space in &subst::ParamSpace::all() {
+            assert_eq!(self.next(), '[');
+            while self.peek() != ']' {
+                r.push(space, f(self));
+            }
+            assert_eq!(self.next(), ']');
+        }
+        r
+    }
+
+    fn parse_substs(&mut self) -> subst::Substs<'tcx> {
+        let regions = self.parse_region_substs();
+        let types = self.parse_vec_per_param_space(|this| this.parse_ty());
+        subst::Substs { types: types, regions: regions }
+    }
+
+    fn parse_region_substs(&mut self) -> subst::RegionSubsts {
+        match self.next() {
+            'e' => subst::ErasedRegions,
+            'n' => {
+                subst::NonerasedRegions(
+                    self.parse_vec_per_param_space(|this| this.parse_region()))
+            }
+            _ => panic!("parse_bound_region: bad input")
+        }
+    }
+
+    fn parse_bound_region(&mut self) -> ty::BoundRegion {
+        match self.next() {
+            'a' => {
+                let id = self.parse_u32();
+                assert_eq!(self.next(), '|');
+                ty::BrAnon(id)
+            }
+            '[' => {
+                let def = self.parse_def(RegionParameter);
+                let ident = token::str_to_ident(&self.parse_str(']'));
+                ty::BrNamed(def, ident.name)
+            }
+            'f' => {
+                let id = self.parse_u32();
+                assert_eq!(self.next(), '|');
+                ty::BrFresh(id)
+            }
+            'e' => ty::BrEnv,
+            _ => panic!("parse_bound_region: bad input")
+        }
+    }
+
+    fn parse_region(&mut self) -> ty::Region {
+        match self.next() {
+            'b' => {
+                assert_eq!(self.next(), '[');
+                let id = ty::DebruijnIndex::new(self.parse_u32());
+                assert_eq!(self.next(), '|');
+                let br = self.parse_bound_region();
+                assert_eq!(self.next(), ']');
+                ty::ReLateBound(id, br)
+            }
+            'B' => {
+                assert_eq!(self.next(), '[');
+                let node_id = self.parse_uint() as ast::NodeId;
+                assert_eq!(self.next(), '|');
+                let space = self.parse_param_space();
+                assert_eq!(self.next(), '|');
+                let index = self.parse_u32();
+                assert_eq!(self.next(), '|');
+                let nm = token::str_to_ident(&self.parse_str(']'));
+                ty::ReEarlyBound(ty::EarlyBoundRegion {
+                    param_id: node_id,
+                    space: space,
+                    index: index,
+                    name: nm.name
+                })
+            }
+            'f' => {
+                assert_eq!(self.next(), '[');
+                let scope = self.parse_destruction_scope_data();
+                assert_eq!(self.next(), '|');
+                let br = self.parse_bound_region();
+                assert_eq!(self.next(), ']');
+                ty::ReFree(ty::FreeRegion { scope: scope,
+                                            bound_region: br})
+            }
+            's' => {
+                let scope = self.parse_scope();
+                assert_eq!(self.next(), '|');
+                ty::ReScope(scope)
+            }
+            't' => {
+                ty::ReStatic
+            }
+            'e' => {
+                ty::ReStatic
+            }
+            _ => panic!("parse_region: bad input")
+        }
+    }
+
+    fn parse_scope(&mut self) -> region::CodeExtent {
+        match self.next() {
+            'P' => {
+                assert_eq!(self.next(), '[');
+                let fn_id = self.parse_uint() as ast::NodeId;
+                assert_eq!(self.next(), '|');
+                let body_id = self.parse_uint() as ast::NodeId;
+                assert_eq!(self.next(), ']');
+                region::CodeExtent::ParameterScope {
+                    fn_id: fn_id, body_id: body_id
+                }
+            }
+            'M' => {
+                let node_id = self.parse_uint() as ast::NodeId;
+                region::CodeExtent::Misc(node_id)
+            }
+            'D' => {
+                let node_id = self.parse_uint() as ast::NodeId;
+                region::CodeExtent::DestructionScope(node_id)
+            }
+            'B' => {
+                assert_eq!(self.next(), '[');
+                let node_id = self.parse_uint() as ast::NodeId;
+                assert_eq!(self.next(), '|');
+                let first_stmt_index = self.parse_uint();
+                assert_eq!(self.next(), ']');
+                let block_remainder = region::BlockRemainder {
+                    block: node_id, first_statement_index: first_stmt_index,
+                };
+                region::CodeExtent::Remainder(block_remainder)
+            }
+            _ => panic!("parse_scope: bad input")
+        }
+    }
+
+    fn parse_destruction_scope_data(&mut self) -> region::DestructionScopeData {
+        let node_id = self.parse_uint() as ast::NodeId;
+        region::DestructionScopeData::new(node_id)
+    }
+
+    fn parse_opt<T, F>(&mut self, f: F) -> Option<T>
+        where F: FnOnce(&mut PState<'a, 'tcx>) -> T,
+    {
+        match self.next() {
+            'n' => None,
+            's' => Some(f(self)),
+            _ => panic!("parse_opt: bad input")
+        }
+    }
+
+    fn parse_str(&mut self, term: char) -> String {
+        let mut result = String::new();
+        while self.peek() != term {
+            unsafe {
+                result.as_mut_vec().push_all(&[self.next_byte()])
+            }
+        }
+        self.next();
+        result
+    }
+
+    fn parse_trait_ref(&mut self) -> ty::TraitRef<'tcx> {
+        let def = self.parse_def(NominalType);
+        let substs = self.tcx.mk_substs(self.parse_substs());
+        ty::TraitRef {def_id: def, substs: substs}
+    }
+
+    fn parse_ty(&mut self) -> Ty<'tcx> {
+        let tcx = self.tcx;
+        match self.next() {
+            'b' => return tcx.types.bool,
+            'i' => { /* eat the s of is */ self.next(); return tcx.types.isize },
+            'u' => { /* eat the s of us */ self.next(); return tcx.types.usize },
+            'M' => {
+                match self.next() {
+                    'b' => return tcx.types.u8,
+                    'w' => return tcx.types.u16,
+                    'l' => return tcx.types.u32,
+                    'd' => return tcx.types.u64,
+                    'B' => return tcx.types.i8,
+                    'W' => return tcx.types.i16,
+                    'L' => return tcx.types.i32,
+                    'D' => return tcx.types.i64,
+                    'f' => return tcx.types.f32,
+                    'F' => return tcx.types.f64,
+                    _ => panic!("parse_ty: bad numeric type")
+                }
+            }
+            'c' => return tcx.types.char,
+            't' => {
+                assert_eq!(self.next(), '[');
+                let did = self.parse_def(NominalType);
+                let substs = self.parse_substs();
+                assert_eq!(self.next(), ']');
+                let def = self.tcx.lookup_adt_def(did);
+                return tcx.mk_enum(def, self.tcx.mk_substs(substs));
+            }
+            'x' => {
+                assert_eq!(self.next(), '[');
+                let trait_ref = ty::Binder(self.parse_trait_ref());
+                let bounds = self.parse_existential_bounds();
+                assert_eq!(self.next(), ']');
+                return tcx.mk_trait(trait_ref, bounds);
+            }
+            'p' => {
+                assert_eq!(self.next(), '[');
+                let index = self.parse_u32();
+                assert_eq!(self.next(), '|');
+                let space = self.parse_param_space();
+                assert_eq!(self.next(), '|');
+                let name = token::intern(&self.parse_str(']'));
+                return tcx.mk_param(space, index, name);
+            }
+            '~' => return tcx.mk_box(self.parse_ty()),
+            '*' => return tcx.mk_ptr(self.parse_mt()),
+            '&' => {
+                let r = self.parse_region();
+                let mt = self.parse_mt();
+                return tcx.mk_ref(tcx.mk_region(r), mt);
+            }
+            'V' => {
+                let t = self.parse_ty();
+                return match self.parse_size() {
+                    Some(n) => tcx.mk_array(t, n),
+                    None => tcx.mk_slice(t)
+                };
+            }
+            'v' => {
+                return tcx.mk_str();
+            }
+            'T' => {
+                assert_eq!(self.next(), '[');
+                let mut params = Vec::new();
+                while self.peek() != ']' { params.push(self.parse_ty()); }
+                self.pos = self.pos + 1;
+                return tcx.mk_tup(params);
+            }
+            'F' => {
+                let def_id = self.parse_def(NominalType);
+                return tcx.mk_fn(Some(def_id), tcx.mk_bare_fn(self.parse_bare_fn_ty()));
+            }
+            'G' => {
+                return tcx.mk_fn(None, tcx.mk_bare_fn(self.parse_bare_fn_ty()));
+            }
+            '#' => {
+                // This is a hacky little caching scheme. The idea is that if we encode
+                // the same type twice, the second (and third, and fourth...) time we will
+                // just write `#123`, where `123` is the offset in the metadata of the
+                // first appearance. Now when we are *decoding*, if we see a `#123`, we
+                // can first check a cache (`tcx.rcache`) for that offset. If we find something,
+                // we return it (modulo closure types, see below). But if not, then we
+                // jump to offset 123 and read the type from there.
+
+                let pos = self.parse_hex();
+                assert_eq!(self.next(), ':');
+                let len = self.parse_hex();
+                assert_eq!(self.next(), '#');
+                let key = ty::CReaderCacheKey {cnum: self.krate, pos: pos, len: len };
+                match tcx.rcache.borrow().get(&key).cloned() {
+                    Some(tt) => {
+                        // If there is a closure buried in the type some where, then we
+                        // need to re-convert any def ids (see case 'k', below). That means
+                        // we can't reuse the cached version.
+                        if !tt.has_closure_types() {
+                            return tt;
+                        }
+                    }
+                    None => {}
+                }
+
+                let mut substate = PState::new(self.data,
+                                               self.krate,
+                                               pos,
+                                               self.tcx,
+                                               self.conv_def_id);
+                let tt = substate.parse_ty();
+                tcx.rcache.borrow_mut().insert(key, tt);
+                return tt;
+            }
+            '\"' => {
+                let _ = self.parse_def(TypeWithId);
+                let inner = self.parse_ty();
+                inner
+            }
+            'a' => {
+                assert_eq!(self.next(), '[');
+                let did = self.parse_def(NominalType);
+                let substs = self.parse_substs();
+                assert_eq!(self.next(), ']');
+                let def = self.tcx.lookup_adt_def(did);
+                return self.tcx.mk_struct(def, self.tcx.mk_substs(substs));
+            }
+            'k' => {
+                assert_eq!(self.next(), '[');
+                let did = self.parse_def(ClosureSource);
+                let substs = self.parse_substs();
+                let mut tys = vec![];
+                while self.peek() != '.' {
+                    tys.push(self.parse_ty());
+                }
+                assert_eq!(self.next(), '.');
+                assert_eq!(self.next(), ']');
+                return self.tcx.mk_closure(did, self.tcx.mk_substs(substs), tys);
+            }
+            'P' => {
+                assert_eq!(self.next(), '[');
+                let trait_ref = self.parse_trait_ref();
+                let name = token::intern(&self.parse_str(']'));
+                return tcx.mk_projection(trait_ref, name);
+            }
+            'e' => {
+                return tcx.types.err;
+            }
+            c => { panic!("unexpected char in type string: {}", c);}
+        }
+    }
+
+    fn parse_mutability(&mut self) -> ast::Mutability {
+        match self.peek() {
+            'm' => { self.next(); ast::MutMutable }
+            _ => { ast::MutImmutable }
+        }
+    }
+
+    fn parse_mt(&mut self) -> ty::TypeAndMut<'tcx> {
+        let m = self.parse_mutability();
+        ty::TypeAndMut { ty: self.parse_ty(), mutbl: m }
+    }
+
+    fn parse_def(&mut self, source: DefIdSource) -> ast::DefId {
+        let def_id = parse_defid(self.scan(|c| c == '|'));
+        return (self.conv_def_id)(source, def_id);
+    }
+
+    fn parse_uint(&mut self) -> usize {
+        let mut n = 0;
+        loop {
+            let cur = self.peek();
+            if cur < '0' || cur > '9' { return n; }
+            self.pos = self.pos + 1;
+            n *= 10;
+            n += (cur as usize) - ('0' as usize);
+        };
+    }
+
+    fn parse_u32(&mut self) -> u32 {
+        let n = self.parse_uint();
+        let m = n as u32;
+        assert_eq!(m as usize, n);
+        m
+    }
+
+    fn parse_param_space(&mut self) -> subst::ParamSpace {
+        subst::ParamSpace::from_uint(self.parse_uint())
+    }
+
+    fn parse_hex(&mut self) -> usize {
+        let mut n = 0;
+        loop {
+            let cur = self.peek();
+            if (cur < '0' || cur > '9') && (cur < 'a' || cur > 'f') { return n; }
+            self.pos = self.pos + 1;
+            n *= 16;
+            if '0' <= cur && cur <= '9' {
+                n += (cur as usize) - ('0' as usize);
+            } else { n += 10 + (cur as usize) - ('a' as usize); }
+        };
+    }
+
+    fn parse_abi_set(&mut self) -> abi::Abi {
+        assert_eq!(self.next(), '[');
+        let bytes = self.scan(|c| c == ']');
+        let abi_str = str::from_utf8(bytes).unwrap();
+        abi::lookup(&abi_str[..]).expect(abi_str)
+    }
+
+    fn parse_closure_ty(&mut self) -> ty::ClosureTy<'tcx> {
+        let unsafety = parse_unsafety(self.next());
+        let sig = self.parse_sig();
+        let abi = self.parse_abi_set();
+        ty::ClosureTy {
+            unsafety: unsafety,
+            sig: sig,
+            abi: abi,
+        }
+    }
+
+    fn parse_bare_fn_ty(&mut self) -> ty::BareFnTy<'tcx> {
+        let unsafety = parse_unsafety(self.next());
+        let abi = self.parse_abi_set();
+        let sig = self.parse_sig();
+        ty::BareFnTy {
+            unsafety: unsafety,
+            abi: abi,
+            sig: sig
+        }
+    }
+
+    fn parse_sig(&mut self) -> ty::PolyFnSig<'tcx> {
+        assert_eq!(self.next(), '[');
+        let mut inputs = Vec::new();
+        while self.peek() != ']' {
+            inputs.push(self.parse_ty());
+        }
+        self.pos += 1; // eat the ']'
+        let variadic = match self.next() {
+            'V' => true,
+            'N' => false,
+            r => panic!(format!("bad variadic: {}", r)),
+        };
+        let output = match self.peek() {
+            'z' => {
+                self.pos += 1;
+                ty::FnDiverging
+            }
+            _ => ty::FnConverging(self.parse_ty())
+        };
+        ty::Binder(ty::FnSig {inputs: inputs,
+                              output: output,
+                              variadic: variadic})
+    }
+
+    pub fn parse_predicate(&mut self) -> ty::Predicate<'tcx> {
+        match self.next() {
+            't' => ty::Binder(self.parse_trait_ref()).to_predicate(),
+            'e' => ty::Binder(ty::EquatePredicate(self.parse_ty(),
+                                                  self.parse_ty())).to_predicate(),
+            'r' => ty::Binder(ty::OutlivesPredicate(self.parse_region(),
+                                                    self.parse_region())).to_predicate(),
+            'o' => ty::Binder(ty::OutlivesPredicate(self.parse_ty(),
+                                                    self.parse_region())).to_predicate(),
+            'p' => ty::Binder(self.parse_projection_predicate()).to_predicate(),
+            'w' => ty::Predicate::WellFormed(self.parse_ty()),
+            'O' => {
+                let def_id = self.parse_def(NominalType);
+                assert_eq!(self.next(), '|');
+                ty::Predicate::ObjectSafe(def_id)
+            }
+            c => panic!("Encountered invalid character in metadata: {}", c)
+        }
+    }
+
+    fn parse_projection_predicate(&mut self) -> ty::ProjectionPredicate<'tcx> {
+        ty::ProjectionPredicate {
+            projection_ty: ty::ProjectionTy {
+                trait_ref: self.parse_trait_ref(),
+                item_name: token::str_to_ident(&self.parse_str('|')).name,
+            },
+            ty: self.parse_ty(),
+        }
+    }
+
+    fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> {
+        let name = self.parse_name(':');
+        let def_id = self.parse_def(NominalType);
+        let space = self.parse_param_space();
+        assert_eq!(self.next(), '|');
+        let index = self.parse_u32();
+        assert_eq!(self.next(), '|');
+        let default_def_id = self.parse_def(NominalType);
+        let default = self.parse_opt(|this| this.parse_ty());
+        let object_lifetime_default = self.parse_object_lifetime_default();
+
+        ty::TypeParameterDef {
+            name: name,
+            def_id: def_id,
+            space: space,
+            index: index,
+            default_def_id: default_def_id,
+            default: default,
+            object_lifetime_default: object_lifetime_default,
+        }
+    }
+
+    fn parse_object_lifetime_default(&mut self) -> ty::ObjectLifetimeDefault {
+        match self.next() {
+            'a' => ty::ObjectLifetimeDefault::Ambiguous,
+            'b' => ty::ObjectLifetimeDefault::BaseDefault,
+            's' => {
+                let region = self.parse_region();
+                ty::ObjectLifetimeDefault::Specific(region)
+            }
+            _ => panic!("parse_object_lifetime_default: bad input")
+        }
+    }
+
+    fn parse_existential_bounds(&mut self) -> ty::ExistentialBounds<'tcx> {
+        let builtin_bounds = self.parse_builtin_bounds();
+        let region_bound = self.parse_region();
+        let mut projection_bounds = Vec::new();
+
+        loop {
+            match self.next() {
+                'P' => {
+                    projection_bounds.push(ty::Binder(self.parse_projection_predicate()));
+                }
+                '.' => { break; }
+                c => {
+                    panic!("parse_bounds: bad bounds ('{}')", c)
+                }
+            }
+        }
+
+        return ty::ExistentialBounds { region_bound: region_bound,
+                                       builtin_bounds: builtin_bounds,
+                                       projection_bounds: projection_bounds };
+    }
+
+    fn parse_builtin_bounds(&mut self) -> ty::BuiltinBounds {
+        let mut builtin_bounds = ty::BuiltinBounds::empty();
+        loop {
+            match self.next() {
+                'S' => {
+                    builtin_bounds.insert(ty::BoundSend);
+                }
+                'Z' => {
+                    builtin_bounds.insert(ty::BoundSized);
+                }
+                'P' => {
+                    builtin_bounds.insert(ty::BoundCopy);
+                }
+                'T' => {
+                    builtin_bounds.insert(ty::BoundSync);
+                }
+                '.' => {
+                    return builtin_bounds;
+                }
+                c => {
+                    panic!("parse_bounds: bad builtin bounds ('{}')", c)
+                }
+            }
+        }
     }
 }
 
@@ -133,535 +783,6 @@ fn data_log_string(data: &[u8], pos: usize) -> String {
     buf
 }
 
-pub fn parse_ty_closure_data<'tcx, F>(data: &[u8],
-                                      crate_num: ast::CrateNum,
-                                      pos: usize,
-                                      tcx: &ty::ctxt<'tcx>,
-                                      mut conv: F)
-                                      -> ty::ClosureTy<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    let mut st = parse_state_from_data(data, crate_num, pos, tcx, &mut conv);
-    parse_closure_ty(&mut st)
-}
-
-pub fn parse_ty_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize,
-                              tcx: &ty::ctxt<'tcx>, mut conv: F) -> Ty<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    debug!("parse_ty_data {}", data_log_string(data, pos));
-    let mut st = parse_state_from_data(data, crate_num, pos, tcx, &mut conv);
-    parse_ty(&mut st)
-}
-
-pub fn parse_region_data<F>(data: &[u8], crate_num: ast::CrateNum, pos: usize, tcx: &ty::ctxt,
-                            mut conv: F) -> ty::Region where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    debug!("parse_region_data {}", data_log_string(data, pos));
-    let mut st = parse_state_from_data(data, crate_num, pos, tcx, &mut conv);
-    parse_region(&mut st)
-}
-
-pub fn parse_bare_fn_ty_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize,
-                                      tcx: &ty::ctxt<'tcx>, mut conv: F)
-                                      -> ty::BareFnTy<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    debug!("parse_bare_fn_ty_data {}", data_log_string(data, pos));
-    let mut st = parse_state_from_data(data, crate_num, pos, tcx, &mut conv);
-    parse_bare_fn_ty(&mut st)
-}
-
-pub fn parse_trait_ref_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize,
-                                     tcx: &ty::ctxt<'tcx>, mut conv: F)
-                                     -> ty::TraitRef<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    debug!("parse_trait_ref_data {}", data_log_string(data, pos));
-    let mut st = parse_state_from_data(data, crate_num, pos, tcx, &mut conv);
-    parse_trait_ref(&mut st)
-}
-
-pub fn parse_substs_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize,
-                                  tcx: &ty::ctxt<'tcx>, mut conv: F) -> subst::Substs<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    debug!("parse_substs_data{}", data_log_string(data, pos));
-    let mut st = parse_state_from_data(data, crate_num, pos, tcx, &mut conv);
-    parse_substs(&mut st)
-}
-
-pub fn parse_existential_bounds_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum,
-                                              pos: usize, tcx: &ty::ctxt<'tcx>, mut conv: F)
-                                              -> ty::ExistentialBounds<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    let mut st = parse_state_from_data(data, crate_num, pos, tcx, &mut conv);
-    parse_existential_bounds(&mut st)
-}
-
-pub fn parse_builtin_bounds_data<F>(data: &[u8], crate_num: ast::CrateNum,
-                                    pos: usize, tcx: &ty::ctxt, mut conv: F)
-                                    -> ty::BuiltinBounds where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    let mut st = parse_state_from_data(data, crate_num, pos, tcx, &mut conv);
-    parse_builtin_bounds(&mut st)
-}
-
-fn parse_size(st: &mut PState) -> Option<usize> {
-    assert_eq!(next(st), '/');
-
-    if peek(st) == '|' {
-        assert_eq!(next(st), '|');
-        None
-    } else {
-        let n = parse_uint(st);
-        assert_eq!(next(st), '|');
-        Some(n)
-    }
-}
-
-fn parse_vec_per_param_space<'a, 'tcx, T, F>(st: &mut PState<'a, 'tcx>,
-                                             mut f: F)
-                                             -> VecPerParamSpace<T> where
-    F: FnMut(&mut PState<'a, 'tcx>) -> T,
-{
-    let mut r = VecPerParamSpace::empty();
-    for &space in &subst::ParamSpace::all() {
-        assert_eq!(next(st), '[');
-        while peek(st) != ']' {
-            r.push(space, f(st));
-        }
-        assert_eq!(next(st), ']');
-    }
-    r
-}
-
-fn parse_substs<'a, 'tcx>(st: &mut PState<'a, 'tcx>) -> subst::Substs<'tcx> {
-    let regions = parse_region_substs(st);
-    let types = parse_vec_per_param_space(st, |st| parse_ty(st));
-    subst::Substs { types: types, regions: regions }
-}
-
-fn parse_region_substs(st: &mut PState) -> subst::RegionSubsts {
-    match next(st) {
-        'e' => subst::ErasedRegions,
-        'n' => {
-            subst::NonerasedRegions(
-                parse_vec_per_param_space(
-                    st, |st| parse_region(st)))
-        }
-        _ => panic!("parse_bound_region: bad input")
-    }
-}
-
-fn parse_bound_region(st: &mut PState) -> ty::BoundRegion {
-    match next(st) {
-        'a' => {
-            let id = parse_u32(st);
-            assert_eq!(next(st), '|');
-            ty::BrAnon(id)
-        }
-        '[' => {
-            let def = parse_def(st, RegionParameter);
-            let ident = token::str_to_ident(&parse_str(st, ']'));
-            ty::BrNamed(def, ident.name)
-        }
-        'f' => {
-            let id = parse_u32(st);
-            assert_eq!(next(st), '|');
-            ty::BrFresh(id)
-        }
-        'e' => ty::BrEnv,
-        _ => panic!("parse_bound_region: bad input")
-    }
-}
-
-fn parse_region(st: &mut PState) -> ty::Region {
-    match next(st) {
-      'b' => {
-        assert_eq!(next(st), '[');
-        let id = ty::DebruijnIndex::new(parse_u32(st));
-        assert_eq!(next(st), '|');
-        let br = parse_bound_region(st);
-        assert_eq!(next(st), ']');
-        ty::ReLateBound(id, br)
-      }
-      'B' => {
-        assert_eq!(next(st), '[');
-        let node_id = parse_uint(st) as ast::NodeId;
-        assert_eq!(next(st), '|');
-        let space = parse_param_space(st);
-        assert_eq!(next(st), '|');
-        let index = parse_u32(st);
-        assert_eq!(next(st), '|');
-        let nm = token::str_to_ident(&parse_str(st, ']'));
-        ty::ReEarlyBound(ty::EarlyBoundRegion {
-            param_id: node_id,
-            space: space,
-            index: index,
-            name: nm.name
-        })
-      }
-      'f' => {
-        assert_eq!(next(st), '[');
-        let scope = parse_destruction_scope_data(st);
-        assert_eq!(next(st), '|');
-        let br = parse_bound_region(st);
-        assert_eq!(next(st), ']');
-        ty::ReFree(ty::FreeRegion { scope: scope,
-                                    bound_region: br})
-      }
-      's' => {
-        let scope = parse_scope(st);
-        assert_eq!(next(st), '|');
-        ty::ReScope(scope)
-      }
-      't' => {
-        ty::ReStatic
-      }
-      'e' => {
-        ty::ReStatic
-      }
-      _ => panic!("parse_region: bad input")
-    }
-}
-
-fn parse_scope(st: &mut PState) -> region::CodeExtent {
-    match next(st) {
-        'P' => {
-            assert_eq!(next(st), '[');
-            let fn_id = parse_uint(st) as ast::NodeId;
-            assert_eq!(next(st), '|');
-            let body_id = parse_uint(st) as ast::NodeId;
-            assert_eq!(next(st), ']');
-            region::CodeExtent::ParameterScope {
-                fn_id: fn_id, body_id: body_id
-            }
-        }
-        'M' => {
-            let node_id = parse_uint(st) as ast::NodeId;
-            region::CodeExtent::Misc(node_id)
-        }
-        'D' => {
-            let node_id = parse_uint(st) as ast::NodeId;
-            region::CodeExtent::DestructionScope(node_id)
-        }
-        'B' => {
-            assert_eq!(next(st), '[');
-            let node_id = parse_uint(st) as ast::NodeId;
-            assert_eq!(next(st), '|');
-            let first_stmt_index = parse_uint(st);
-            assert_eq!(next(st), ']');
-            let block_remainder = region::BlockRemainder {
-                block: node_id, first_statement_index: first_stmt_index,
-            };
-            region::CodeExtent::Remainder(block_remainder)
-        }
-        _ => panic!("parse_scope: bad input")
-    }
-}
-
-fn parse_destruction_scope_data(st: &mut PState) -> region::DestructionScopeData {
-    let node_id = parse_uint(st) as ast::NodeId;
-    region::DestructionScopeData::new(node_id)
-}
-
-fn parse_opt<'a, 'tcx, T, F>(st: &mut PState<'a, 'tcx>, f: F) -> Option<T> where
-    F: FnOnce(&mut PState<'a, 'tcx>) -> T,
-{
-    match next(st) {
-      'n' => None,
-      's' => Some(f(st)),
-      _ => panic!("parse_opt: bad input")
-    }
-}
-
-fn parse_str(st: &mut PState, term: char) -> String {
-    let mut result = String::new();
-    while peek(st) != term {
-        unsafe {
-            result.as_mut_vec().push_all(&[next_byte(st)])
-        }
-    }
-    next(st);
-    result
-}
-
-fn parse_trait_ref<'a, 'tcx>(st: &mut PState<'a, 'tcx>) -> ty::TraitRef<'tcx> {
-    let def = parse_def(st, NominalType);
-    let substs = st.tcx.mk_substs(parse_substs(st));
-    ty::TraitRef {def_id: def, substs: substs}
-}
-
-fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>) -> Ty<'tcx> {
-    let tcx = st.tcx;
-    match next(st) {
-      'b' => return tcx.types.bool,
-      'i' => { /* eat the s of is */ next(st); return tcx.types.isize },
-      'u' => { /* eat the s of us */ next(st); return tcx.types.usize },
-      'M' => {
-        match next(st) {
-          'b' => return tcx.types.u8,
-          'w' => return tcx.types.u16,
-          'l' => return tcx.types.u32,
-          'd' => return tcx.types.u64,
-          'B' => return tcx.types.i8,
-          'W' => return tcx.types.i16,
-          'L' => return tcx.types.i32,
-          'D' => return tcx.types.i64,
-          'f' => return tcx.types.f32,
-          'F' => return tcx.types.f64,
-          _ => panic!("parse_ty: bad numeric type")
-        }
-      }
-      'c' => return tcx.types.char,
-      't' => {
-        assert_eq!(next(st), '[');
-        let did = parse_def(st, NominalType);
-        let substs = parse_substs(st);
-        assert_eq!(next(st), ']');
-        let def = st.tcx.lookup_adt_def(did);
-        return tcx.mk_enum(def, st.tcx.mk_substs(substs));
-      }
-      'x' => {
-        assert_eq!(next(st), '[');
-        let trait_ref = ty::Binder(parse_trait_ref(st));
-        let bounds = parse_existential_bounds(st);
-        assert_eq!(next(st), ']');
-        return tcx.mk_trait(trait_ref, bounds);
-      }
-      'p' => {
-        assert_eq!(next(st), '[');
-        let index = parse_u32(st);
-        assert_eq!(next(st), '|');
-        let space = parse_param_space(st);
-        assert_eq!(next(st), '|');
-        let name = token::intern(&parse_str(st, ']'));
-        return tcx.mk_param(space, index, name);
-      }
-      '~' => return tcx.mk_box(parse_ty(st)),
-      '*' => return tcx.mk_ptr(parse_mt(st)),
-      '&' => {
-        let r = parse_region(st);
-        let mt = parse_mt(st);
-        return tcx.mk_ref(tcx.mk_region(r), mt);
-      }
-      'V' => {
-        let t = parse_ty(st);
-        return match parse_size(st) {
-            Some(n) => tcx.mk_array(t, n),
-            None => tcx.mk_slice(t)
-        };
-      }
-      'v' => {
-        return tcx.mk_str();
-      }
-      'T' => {
-        assert_eq!(next(st), '[');
-        let mut params = Vec::new();
-        while peek(st) != ']' { params.push(parse_ty(st)); }
-        st.pos = st.pos + 1;
-        return tcx.mk_tup(params);
-      }
-      'F' => {
-          let def_id = parse_def(st, NominalType);
-          return tcx.mk_fn(Some(def_id), tcx.mk_bare_fn(parse_bare_fn_ty(st)));
-      }
-      'G' => {
-          return tcx.mk_fn(None, tcx.mk_bare_fn(parse_bare_fn_ty(st)));
-      }
-      '#' => {
-        // This is a hacky little caching scheme. The idea is that if we encode
-        // the same type twice, the second (and third, and fourth...) time we will
-        // just write `#123`, where `123` is the offset in the metadata of the
-        // first appearance. Now when we are *decoding*, if we see a `#123`, we
-        // can first check a cache (`tcx.rcache`) for that offset. If we find something,
-        // we return it (modulo closure types, see below). But if not, then we
-        // jump to offset 123 and read the type from there.
-
-        let pos = parse_hex(st);
-        assert_eq!(next(st), ':');
-        let len = parse_hex(st);
-        assert_eq!(next(st), '#');
-        let key = ty::CReaderCacheKey {cnum: st.krate, pos: pos, len: len };
-        match tcx.rcache.borrow().get(&key).cloned() {
-          Some(tt) => {
-            // If there is a closure buried in the type some where, then we
-            // need to re-convert any def ids (see case 'k', below). That means
-            // we can't reuse the cached version.
-            if !tt.has_closure_types() {
-                return tt;
-            }
-          }
-          None => {}
-        }
-
-        let mut ps = PState {
-            pos: pos,
-            conv_def_id: st.conv_def_id, // -+ Have to call out these fields specifically,
-            tcx: st.tcx,                 //  | rather than writing `..*st`, so that we
-            data: st.data,               //  | trigger reborrow coercions. Suboptimal,
-            krate: st.krate,             // -+ I suppose.
-        };
-
-        let tt = parse_ty(&mut ps);
-        tcx.rcache.borrow_mut().insert(key, tt);
-        return tt;
-      }
-      '\"' => {
-        let _ = parse_def(st, TypeWithId);
-        let inner = parse_ty(st);
-        inner
-      }
-      'a' => {
-          assert_eq!(next(st), '[');
-          let did = parse_def(st, NominalType);
-          let substs = parse_substs(st);
-          assert_eq!(next(st), ']');
-          let def = st.tcx.lookup_adt_def(did);
-          return st.tcx.mk_struct(def, st.tcx.mk_substs(substs));
-      }
-      'k' => {
-          assert_eq!(next(st), '[');
-          let did = parse_def(st, ClosureSource);
-          let substs = parse_substs(st);
-          let mut tys = vec![];
-          while peek(st) != '.' {
-              tys.push(parse_ty(st));
-          }
-          assert_eq!(next(st), '.');
-          assert_eq!(next(st), ']');
-          return st.tcx.mk_closure(did, st.tcx.mk_substs(substs), tys);
-      }
-      'P' => {
-          assert_eq!(next(st), '[');
-          let trait_ref = parse_trait_ref(st);
-          let name = token::intern(&parse_str(st, ']'));
-          return tcx.mk_projection(trait_ref, name);
-      }
-      'e' => {
-          return tcx.types.err;
-      }
-      c => { panic!("unexpected char in type string: {}", c);}
-    }
-}
-
-fn parse_mutability(st: &mut PState) -> ast::Mutability {
-    match peek(st) {
-      'm' => { next(st); ast::MutMutable }
-      _ => { ast::MutImmutable }
-    }
-}
-
-fn parse_mt<'a, 'tcx>(st: &mut PState<'a, 'tcx>) -> ty::TypeAndMut<'tcx> {
-    let m = parse_mutability(st);
-    ty::TypeAndMut { ty: parse_ty(st), mutbl: m }
-}
-
-fn parse_def(st: &mut PState, source: DefIdSource) -> ast::DefId {
-    let def_id = parse_defid(scan(st, |c| c == '|'));
-    return (st.conv_def_id)(source, def_id);
-}
-
-fn parse_uint(st: &mut PState) -> usize {
-    let mut n = 0;
-    loop {
-        let cur = peek(st);
-        if cur < '0' || cur > '9' { return n; }
-        st.pos = st.pos + 1;
-        n *= 10;
-        n += (cur as usize) - ('0' as usize);
-    };
-}
-
-fn parse_u32(st: &mut PState) -> u32 {
-    let n = parse_uint(st);
-    let m = n as u32;
-    assert_eq!(m as usize, n);
-    m
-}
-
-fn parse_param_space(st: &mut PState) -> subst::ParamSpace {
-    subst::ParamSpace::from_uint(parse_uint(st))
-}
-
-fn parse_hex(st: &mut PState) -> usize {
-    let mut n = 0;
-    loop {
-        let cur = peek(st);
-        if (cur < '0' || cur > '9') && (cur < 'a' || cur > 'f') { return n; }
-        st.pos = st.pos + 1;
-        n *= 16;
-        if '0' <= cur && cur <= '9' {
-            n += (cur as usize) - ('0' as usize);
-        } else { n += 10 + (cur as usize) - ('a' as usize); }
-    };
-}
-
-fn parse_unsafety(c: char) -> ast::Unsafety {
-    match c {
-        'u' => ast::Unsafety::Unsafe,
-        'n' => ast::Unsafety::Normal,
-        _ => panic!("parse_unsafety: bad unsafety {}", c)
-    }
-}
-
-fn parse_abi_set(st: &mut PState) -> abi::Abi {
-    assert_eq!(next(st), '[');
-    let bytes = scan(st, |c| c == ']');
-    let abi_str = str::from_utf8(bytes).unwrap();
-    abi::lookup(&abi_str[..]).expect(abi_str)
-}
-
-fn parse_closure_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>) -> ty::ClosureTy<'tcx> {
-    let unsafety = parse_unsafety(next(st));
-    let sig = parse_sig(st);
-    let abi = parse_abi_set(st);
-    ty::ClosureTy {
-        unsafety: unsafety,
-        sig: sig,
-        abi: abi,
-    }
-}
-
-fn parse_bare_fn_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>) -> ty::BareFnTy<'tcx> {
-    let unsafety = parse_unsafety(next(st));
-    let abi = parse_abi_set(st);
-    let sig = parse_sig(st);
-    ty::BareFnTy {
-        unsafety: unsafety,
-        abi: abi,
-        sig: sig
-    }
-}
-
-fn parse_sig<'a, 'tcx>(st: &mut PState<'a, 'tcx>) -> ty::PolyFnSig<'tcx> {
-    assert_eq!(next(st), '[');
-    let mut inputs = Vec::new();
-    while peek(st) != ']' {
-        inputs.push(parse_ty(st));
-    }
-    st.pos += 1; // eat the ']'
-    let variadic = match next(st) {
-        'V' => true,
-        'N' => false,
-        r => panic!(format!("bad variadic: {}", r)),
-    };
-    let output = match peek(st) {
-        'z' => {
-          st.pos += 1;
-          ty::FnDiverging
-        }
-        _ => ty::FnConverging(parse_ty(st))
-    };
-    ty::Binder(ty::FnSig {inputs: inputs,
-                          output: output,
-                          variadic: variadic})
-}
-
 // Rust metadata parsing
 pub fn parse_defid(buf: &[u8]) -> ast::DefId {
     let mut colon_idx = 0;
@@ -678,149 +799,25 @@ pub fn parse_defid(buf: &[u8]) -> ast::DefId {
     let crate_num = match str::from_utf8(crate_part).ok().and_then(|s| {
         s.parse::<usize>().ok()
     }) {
-       Some(cn) => cn as ast::CrateNum,
-       None => panic!("internal error: parse_defid: crate number expected, found {:?}",
-                     crate_part)
+        Some(cn) => cn as ast::CrateNum,
+        None => panic!("internal error: parse_defid: crate number expected, found {:?}",
+                       crate_part)
     };
     let def_num = match str::from_utf8(def_part).ok().and_then(|s| {
         s.parse::<usize>().ok()
     }) {
-       Some(dn) => dn as ast::NodeId,
-       None => panic!("internal error: parse_defid: id expected, found {:?}",
-                     def_part)
+        Some(dn) => dn as ast::NodeId,
+        None => panic!("internal error: parse_defid: id expected, found {:?}",
+                       def_part)
     };
     ast::DefId { krate: crate_num, node: def_num }
 }
 
-pub fn parse_predicate_data<'tcx, F>(data: &[u8],
-                                     start: usize,
-                                     crate_num: ast::CrateNum,
-                                     tcx: &ty::ctxt<'tcx>,
-                                     mut conv: F)
-                                     -> ty::Predicate<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    let mut st = parse_state_from_data(data, crate_num, start, tcx, &mut conv);
-    parse_predicate(&mut st)
-}
-
-pub fn parse_predicate<'a,'tcx>(st: &mut PState<'a, 'tcx>) -> ty::Predicate<'tcx> {
-    match next(st) {
-        't' => ty::Binder(parse_trait_ref(st)).to_predicate(),
-        'e' => ty::Binder(ty::EquatePredicate(parse_ty(st),
-                                              parse_ty(st))).to_predicate(),
-        'r' => ty::Binder(ty::OutlivesPredicate(parse_region(st),
-                                                parse_region(st))).to_predicate(),
-        'o' => ty::Binder(ty::OutlivesPredicate(parse_ty(st),
-                                                parse_region(st))).to_predicate(),
-        'p' => ty::Binder(parse_projection_predicate(st)).to_predicate(),
-        'w' => ty::Predicate::WellFormed(parse_ty(st)),
-        'O' => {
-            let def_id = parse_def(st, NominalType);
-            assert_eq!(next(st), '|');
-            ty::Predicate::ObjectSafe(def_id)
-        }
-        c => panic!("Encountered invalid character in metadata: {}", c)
+fn parse_unsafety(c: char) -> ast::Unsafety {
+    match c {
+        'u' => ast::Unsafety::Unsafe,
+        'n' => ast::Unsafety::Normal,
+        _ => panic!("parse_unsafety: bad unsafety {}", c)
     }
 }
 
-fn parse_projection_predicate<'a,'tcx>(st: &mut PState<'a, 'tcx>) -> ty::ProjectionPredicate<'tcx> {
-    ty::ProjectionPredicate {
-        projection_ty: ty::ProjectionTy {
-            trait_ref: parse_trait_ref(st),
-            item_name: token::str_to_ident(&parse_str(st, '|')).name,
-        },
-        ty: parse_ty(st),
-    }
-}
-
-pub fn parse_type_param_def_data<'tcx, F>(data: &[u8], start: usize,
-                                          crate_num: ast::CrateNum, tcx: &ty::ctxt<'tcx>,
-                                          mut conv: F) -> ty::TypeParameterDef<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    let mut st = parse_state_from_data(data, crate_num, start, tcx, &mut conv);
-    parse_type_param_def(&mut st)
-}
-
-fn parse_type_param_def<'a, 'tcx>(st: &mut PState<'a, 'tcx>) -> ty::TypeParameterDef<'tcx> {
-    let name = parse_name(st, ':');
-    let def_id = parse_def(st, NominalType);
-    let space = parse_param_space(st);
-    assert_eq!(next(st), '|');
-    let index = parse_u32(st);
-    assert_eq!(next(st), '|');
-    let default_def_id = parse_def(st, NominalType);
-    let default = parse_opt(st, |st| parse_ty(st));
-    let object_lifetime_default = parse_object_lifetime_default(st);
-
-    ty::TypeParameterDef {
-        name: name,
-        def_id: def_id,
-        space: space,
-        index: index,
-        default_def_id: default_def_id,
-        default: default,
-        object_lifetime_default: object_lifetime_default,
-    }
-}
-
-fn parse_object_lifetime_default<'a,'tcx>(st: &mut PState<'a,'tcx>) -> ty::ObjectLifetimeDefault {
-    match next(st) {
-        'a' => ty::ObjectLifetimeDefault::Ambiguous,
-        'b' => ty::ObjectLifetimeDefault::BaseDefault,
-        's' => {
-            let region = parse_region(st);
-            ty::ObjectLifetimeDefault::Specific(region)
-        }
-        _ => panic!("parse_object_lifetime_default: bad input")
-    }
-}
-
-fn parse_existential_bounds<'a,'tcx>(st: &mut PState<'a,'tcx>) -> ty::ExistentialBounds<'tcx> {
-    let builtin_bounds = parse_builtin_bounds(st);
-    let region_bound = parse_region(st);
-    let mut projection_bounds = Vec::new();
-
-    loop {
-        match next(st) {
-            'P' => {
-                projection_bounds.push(ty::Binder(parse_projection_predicate(st)));
-                }
-            '.' => { break; }
-            c => {
-                panic!("parse_bounds: bad bounds ('{}')", c)
-            }
-        }
-    }
-
-    return ty::ExistentialBounds { region_bound: region_bound,
-                                   builtin_bounds: builtin_bounds,
-                                   projection_bounds: projection_bounds };
-}
-
-fn parse_builtin_bounds(st: &mut PState) -> ty::BuiltinBounds {
-    let mut builtin_bounds = ty::BuiltinBounds::empty();
-    loop {
-        match next(st) {
-            'S' => {
-                builtin_bounds.insert(ty::BoundSend);
-            }
-            'Z' => {
-                builtin_bounds.insert(ty::BoundSized);
-            }
-            'P' => {
-                builtin_bounds.insert(ty::BoundCopy);
-            }
-            'T' => {
-                builtin_bounds.insert(ty::BoundSync);
-            }
-            '.' => {
-                return builtin_bounds;
-            }
-            c => {
-                panic!("parse_bounds: bad builtin bounds ('{}')", c)
-            }
-        }
-    }
-}

From 70e2df5b1bedbab6fc1087fc9b3e66dd5e80b044 Mon Sep 17 00:00:00 2001
From: Niko Matsakis <niko@alum.mit.edu>
Date: Fri, 14 Aug 2015 05:14:54 -0400
Subject: [PATCH 4/7] tydecode: tighten privacy

---
 src/librustc/metadata/tydecode.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 2ddb0697c17..270fc284997 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -211,7 +211,7 @@ impl<'a,'tcx> PState<'a,'tcx> {
         return &self.data[start_pos..end_pos];
     }
 
-    pub fn parse_name(&mut self, last: char) -> ast::Name {
+    fn parse_name(&mut self, last: char) -> ast::Name {
         fn is_last(b: char, c: char) -> bool { return c == b; }
         let bytes = self.scan(|a| is_last(last, a));
         token::intern(str::from_utf8(bytes).unwrap())
@@ -655,7 +655,7 @@ impl<'a,'tcx> PState<'a,'tcx> {
                               variadic: variadic})
     }
 
-    pub fn parse_predicate(&mut self) -> ty::Predicate<'tcx> {
+    fn parse_predicate(&mut self) -> ty::Predicate<'tcx> {
         match self.next() {
             't' => ty::Binder(self.parse_trait_ref()).to_predicate(),
             'e' => ty::Binder(ty::EquatePredicate(self.parse_ty(),
@@ -784,7 +784,7 @@ fn data_log_string(data: &[u8], pos: usize) -> String {
 }
 
 // Rust metadata parsing
-pub fn parse_defid(buf: &[u8]) -> ast::DefId {
+fn parse_defid(buf: &[u8]) -> ast::DefId {
     let mut colon_idx = 0;
     let len = buf.len();
     while colon_idx < len && buf[colon_idx] != ':' as u8 { colon_idx += 1; }

From 38e6b5780e59977608f3b989410bc3b038f1ddc9 Mon Sep 17 00:00:00 2001
From: Niko Matsakis <niko@alum.mit.edu>
Date: Fri, 14 Aug 2015 05:37:49 -0400
Subject: [PATCH 5/7] s/PState/TyDecoder/

---
 src/librustc/metadata/tydecode.rs | 42 +++++++++++++++----------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 270fc284997..a24bf76ca76 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -65,7 +65,7 @@ pub fn parse_ty_closure_data<'tcx, F>(data: &[u8],
                                       -> ty::ClosureTy<'tcx> where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
-    let mut st = PState::new(data, crate_num, pos, tcx, &mut conv);
+    let mut st = TyDecoder::new(data, crate_num, pos, tcx, &mut conv);
     st.parse_closure_ty()
 }
 
@@ -74,7 +74,7 @@ pub fn parse_ty_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize,
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
     debug!("parse_ty_data {}", data_log_string(data, pos));
-    let mut st = PState::new(data, crate_num, pos, tcx, &mut conv);
+    let mut st = TyDecoder::new(data, crate_num, pos, tcx, &mut conv);
     st.parse_ty()
 }
 
@@ -83,7 +83,7 @@ pub fn parse_region_data<F>(data: &[u8], crate_num: ast::CrateNum, pos: usize, t
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
     debug!("parse_region_data {}", data_log_string(data, pos));
-    let mut st = PState::new(data, crate_num, pos, tcx, &mut conv);
+    let mut st = TyDecoder::new(data, crate_num, pos, tcx, &mut conv);
     st.parse_region()
 }
 
@@ -93,7 +93,7 @@ pub fn parse_bare_fn_ty_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
     debug!("parse_bare_fn_ty_data {}", data_log_string(data, pos));
-    let mut st = PState::new(data, crate_num, pos, tcx, &mut conv);
+    let mut st = TyDecoder::new(data, crate_num, pos, tcx, &mut conv);
     st.parse_bare_fn_ty()
 }
 
@@ -103,7 +103,7 @@ pub fn parse_trait_ref_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos:
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
     debug!("parse_trait_ref_data {}", data_log_string(data, pos));
-    let mut st = PState::new(data, crate_num, pos, tcx, &mut conv);
+    let mut st = TyDecoder::new(data, crate_num, pos, tcx, &mut conv);
     st.parse_trait_ref()
 }
 
@@ -112,7 +112,7 @@ pub fn parse_substs_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: us
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
     debug!("parse_substs_data{}", data_log_string(data, pos));
-    let mut st = PState::new(data, crate_num, pos, tcx, &mut conv);
+    let mut st = TyDecoder::new(data, crate_num, pos, tcx, &mut conv);
     st.parse_substs()
 }
 
@@ -121,7 +121,7 @@ pub fn parse_existential_bounds_data<'tcx, F>(data: &[u8], crate_num: ast::Crate
                                               -> ty::ExistentialBounds<'tcx> where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
-    let mut st = PState::new(data, crate_num, pos, tcx, &mut conv);
+    let mut st = TyDecoder::new(data, crate_num, pos, tcx, &mut conv);
     st.parse_existential_bounds()
 }
 
@@ -130,7 +130,7 @@ pub fn parse_builtin_bounds_data<F>(data: &[u8], crate_num: ast::CrateNum,
                                     -> ty::BuiltinBounds where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
-    let mut st = PState::new(data, crate_num, pos, tcx, &mut conv);
+    let mut st = TyDecoder::new(data, crate_num, pos, tcx, &mut conv);
     st.parse_builtin_bounds()
 }
 
@@ -139,7 +139,7 @@ pub fn parse_type_param_def_data<'tcx, F>(data: &[u8], start: usize,
                                           mut conv: F) -> ty::TypeParameterDef<'tcx> where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
-    let mut st = PState::new(data, crate_num, start, tcx, &mut conv);
+    let mut st = TyDecoder::new(data, crate_num, start, tcx, &mut conv);
     st.parse_type_param_def()
 }
 
@@ -151,13 +151,13 @@ pub fn parse_predicate_data<'tcx, F>(data: &[u8],
                                      -> ty::Predicate<'tcx> where
     F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
 {
-    let mut st = PState::new(data, crate_num, start, tcx, &mut conv);
+    let mut st = TyDecoder::new(data, crate_num, start, tcx, &mut conv);
     st.parse_predicate()
 }
 
 pub type DefIdConvert<'a> = &'a mut FnMut(DefIdSource, ast::DefId) -> ast::DefId;
 
-pub struct PState<'a, 'tcx: 'a> {
+pub struct TyDecoder<'a, 'tcx: 'a> {
     data: &'a [u8],
     krate: ast::CrateNum,
     pos: usize,
@@ -165,14 +165,14 @@ pub struct PState<'a, 'tcx: 'a> {
     conv_def_id: DefIdConvert<'a>,
 }
 
-impl<'a,'tcx> PState<'a,'tcx> {
+impl<'a,'tcx> TyDecoder<'a,'tcx> {
     pub fn new(data: &'a [u8],
                crate_num: ast::CrateNum,
                pos: usize,
                tcx: &'a ty::ctxt<'tcx>,
                conv: DefIdConvert<'a>)
-               -> PState<'a, 'tcx> {
-        PState {
+               -> TyDecoder<'a, 'tcx> {
+        TyDecoder {
             data: data,
             krate: crate_num,
             pos: pos,
@@ -231,7 +231,7 @@ impl<'a,'tcx> PState<'a,'tcx> {
     }
 
     fn parse_vec_per_param_space<T, F>(&mut self, mut f: F) -> VecPerParamSpace<T> where
-        F: FnMut(&mut PState<'a, 'tcx>) -> T,
+        F: FnMut(&mut TyDecoder<'a, 'tcx>) -> T,
     {
         let mut r = VecPerParamSpace::empty();
         for &space in &subst::ParamSpace::all() {
@@ -374,7 +374,7 @@ impl<'a,'tcx> PState<'a,'tcx> {
     }
 
     fn parse_opt<T, F>(&mut self, f: F) -> Option<T>
-        where F: FnOnce(&mut PState<'a, 'tcx>) -> T,
+        where F: FnOnce(&mut TyDecoder<'a, 'tcx>) -> T,
     {
         match self.next() {
             'n' => None,
@@ -503,11 +503,11 @@ impl<'a,'tcx> PState<'a,'tcx> {
                     None => {}
                 }
 
-                let mut substate = PState::new(self.data,
-                                               self.krate,
-                                               pos,
-                                               self.tcx,
-                                               self.conv_def_id);
+                let mut substate = TyDecoder::new(self.data,
+                                                  self.krate,
+                                                  pos,
+                                                  self.tcx,
+                                                  self.conv_def_id);
                 let tt = substate.parse_ty();
                 tcx.rcache.borrow_mut().insert(key, tt);
                 return tt;

From b09cf1293a2123d316b2434a101a7c10599d7d43 Mon Sep 17 00:00:00 2001
From: Niko Matsakis <niko@alum.mit.edu>
Date: Fri, 14 Aug 2015 05:58:10 -0400
Subject: [PATCH 6/7] astencode: convert code to use TyDecoder directly

---
 src/librustc/metadata/tydecode.rs |  23 ++++--
 src/librustc/middle/astencode.rs  | 112 ++++++++++--------------------
 2 files changed, 54 insertions(+), 81 deletions(-)

diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index a24bf76ca76..52370f652a2 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -23,6 +23,7 @@ use middle::subst;
 use middle::subst::VecPerParamSpace;
 use middle::ty::{self, ToPredicate, Ty, HasTypeFlags};
 
+use rbml;
 use std::str;
 use syntax::abi;
 use syntax::ast;
@@ -166,6 +167,14 @@ pub struct TyDecoder<'a, 'tcx: 'a> {
 }
 
 impl<'a,'tcx> TyDecoder<'a,'tcx> {
+    pub fn with_doc(tcx: &'a ty::ctxt<'tcx>,
+                    crate_num: ast::CrateNum,
+                    doc: rbml::Doc<'a>,
+                    conv: DefIdConvert<'a>)
+                    -> TyDecoder<'a,'tcx> {
+        TyDecoder::new(doc.data, crate_num, doc.start, tcx, conv)
+    }
+
     pub fn new(data: &'a [u8],
                crate_num: ast::CrateNum,
                pos: usize,
@@ -244,7 +253,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
         r
     }
 
-    fn parse_substs(&mut self) -> subst::Substs<'tcx> {
+    pub fn parse_substs(&mut self) -> subst::Substs<'tcx> {
         let regions = self.parse_region_substs();
         let types = self.parse_vec_per_param_space(|this| this.parse_ty());
         subst::Substs { types: types, regions: regions }
@@ -394,13 +403,13 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
         result
     }
 
-    fn parse_trait_ref(&mut self) -> ty::TraitRef<'tcx> {
+    pub fn parse_trait_ref(&mut self) -> ty::TraitRef<'tcx> {
         let def = self.parse_def(NominalType);
         let substs = self.tcx.mk_substs(self.parse_substs());
         ty::TraitRef {def_id: def, substs: substs}
     }
 
-    fn parse_ty(&mut self) -> Ty<'tcx> {
+    pub fn parse_ty(&mut self) -> Ty<'tcx> {
         let tcx = self.tcx;
         match self.next() {
             'b' => return tcx.types.bool,
@@ -609,7 +618,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
         abi::lookup(&abi_str[..]).expect(abi_str)
     }
 
-    fn parse_closure_ty(&mut self) -> ty::ClosureTy<'tcx> {
+    pub fn parse_closure_ty(&mut self) -> ty::ClosureTy<'tcx> {
         let unsafety = parse_unsafety(self.next());
         let sig = self.parse_sig();
         let abi = self.parse_abi_set();
@@ -655,7 +664,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
                               variadic: variadic})
     }
 
-    fn parse_predicate(&mut self) -> ty::Predicate<'tcx> {
+    pub fn parse_predicate(&mut self) -> ty::Predicate<'tcx> {
         match self.next() {
             't' => ty::Binder(self.parse_trait_ref()).to_predicate(),
             'e' => ty::Binder(ty::EquatePredicate(self.parse_ty(),
@@ -685,7 +694,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
         }
     }
 
-    fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> {
+    pub fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> {
         let name = self.parse_name(':');
         let def_id = self.parse_def(NominalType);
         let space = self.parse_param_space();
@@ -719,7 +728,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
         }
     }
 
-    fn parse_existential_bounds(&mut self) -> ty::ExistentialBounds<'tcx> {
+    pub fn parse_existential_bounds(&mut self) -> ty::ExistentialBounds<'tcx> {
         let builtin_bounds = self.parse_builtin_bounds();
         let region_bound = self.parse_region();
         let mut projection_bounds = Vec::new();
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index a07b849b400..e544d8d4749 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -1075,6 +1075,10 @@ impl<'a> doc_decoder_helpers for rbml::Doc<'a> {
 }
 
 trait rbml_decoder_decoder_helpers<'tcx> {
+    fn read_ty_encoded<'a, 'b, F, R>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>,
+                                     f: F) -> R
+        where F: for<'x> FnOnce(&mut tydecode::TyDecoder<'x, 'tcx>) -> R;
+
     fn read_ty<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> Ty<'tcx>;
     fn read_tys<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> Vec<Ty<'tcx>>;
     fn read_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
@@ -1123,14 +1127,14 @@ trait rbml_decoder_decoder_helpers<'tcx> {
 
 impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
     fn read_ty_nodcx(&mut self,
-                     tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata) -> Ty<'tcx> {
+                     tcx: &ty::ctxt<'tcx>,
+                     cdata: &cstore::crate_metadata)
+                     -> Ty<'tcx> {
         self.read_opaque(|_, doc| {
-            Ok(tydecode::parse_ty_data(
-                doc.data,
-                cdata.cnum,
-                doc.start,
-                tcx,
-                |_, id| decoder::translate_def_id(cdata, id)))
+            Ok(
+                tydecode::TyDecoder::with_doc(tcx, cdata.cnum, doc,
+                                              &mut |_, id| decoder::translate_def_id(cdata, id))
+                    .parse_ty())
         }).unwrap()
     }
 
@@ -1149,32 +1153,22 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
                          -> subst::Substs<'tcx>
     {
         self.read_opaque(|_, doc| {
-            Ok(tydecode::parse_substs_data(
-                doc.data,
-                cdata.cnum,
-                doc.start,
-                tcx,
-                |_, id| decoder::translate_def_id(cdata, id)))
+            Ok(
+                tydecode::TyDecoder::with_doc(tcx, cdata.cnum, doc,
+                                              &mut |_, id| decoder::translate_def_id(cdata, id))
+                    .parse_substs())
         }).unwrap()
     }
 
-    fn read_ty<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) -> Ty<'tcx> {
-        // Note: regions types embed local node ids.  In principle, we
-        // should translate these node ids into the new decode
-        // context.  However, we do not bother, because region types
-        // are not used during trans.
-
+    fn read_ty_encoded<'b, 'c, F, R>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>, op: F) -> R
+        where F: for<'x> FnOnce(&mut tydecode::TyDecoder<'x,'tcx>) -> R
+    {
         return self.read_opaque(|this, doc| {
-            debug!("read_ty({})", type_string(doc));
-
-            let ty = tydecode::parse_ty_data(
-                doc.data,
-                dcx.cdata.cnum,
-                doc.start,
-                dcx.tcx,
-                |s, a| this.convert_def_id(dcx, s, a));
-
-            Ok(ty)
+            debug!("read_ty_encoded({})", type_string(doc));
+            Ok(op(
+                &mut tydecode::TyDecoder::with_doc(
+                    dcx.tcx, dcx.cdata.cnum, doc,
+                    &mut |s, a| this.convert_def_id(dcx, s, a))))
         }).unwrap();
 
         fn type_string(doc: rbml::Doc) -> String {
@@ -1186,6 +1180,15 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
         }
     }
 
+    fn read_ty<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) -> Ty<'tcx> {
+        // Note: regions types embed local node ids.  In principle, we
+        // should translate these node ids into the new decode
+        // context.  However, we do not bother, because region types
+        // are not used during trans.
+
+        return self.read_ty_encoded(dcx, |decoder| decoder.parse_ty());
+    }
+
     fn read_tys<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
                         -> Vec<Ty<'tcx>> {
         self.read_to_vec(|this| Ok(this.read_ty(dcx))).unwrap().into_iter().collect()
@@ -1193,49 +1196,23 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
 
     fn read_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
                               -> ty::TraitRef<'tcx> {
-        self.read_opaque(|this, doc| {
-            let ty = tydecode::parse_trait_ref_data(
-                doc.data,
-                dcx.cdata.cnum,
-                doc.start,
-                dcx.tcx,
-                |s, a| this.convert_def_id(dcx, s, a));
-            Ok(ty)
-        }).unwrap()
+        self.read_ty_encoded(dcx, |decoder| decoder.parse_trait_ref())
     }
 
     fn read_poly_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
                                    -> ty::PolyTraitRef<'tcx> {
-        ty::Binder(self.read_opaque(|this, doc| {
-            let ty = tydecode::parse_trait_ref_data(
-                doc.data,
-                dcx.cdata.cnum,
-                doc.start,
-                dcx.tcx,
-                |s, a| this.convert_def_id(dcx, s, a));
-            Ok(ty)
-        }).unwrap())
+        ty::Binder(self.read_ty_encoded(dcx, |decoder| decoder.parse_trait_ref()))
     }
 
     fn read_type_param_def<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
                                    -> ty::TypeParameterDef<'tcx> {
-        self.read_opaque(|this, doc| {
-            Ok(tydecode::parse_type_param_def_data(
-                doc.data,
-                doc.start,
-                dcx.cdata.cnum,
-                dcx.tcx,
-                |s, a| this.convert_def_id(dcx, s, a)))
-        }).unwrap()
+        self.read_ty_encoded(dcx, |decoder| decoder.parse_type_param_def())
     }
 
     fn read_predicate<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
                               -> ty::Predicate<'tcx>
     {
-        self.read_opaque(|this, doc| {
-            Ok(tydecode::parse_predicate_data(doc.data, doc.start, dcx.cdata.cnum, dcx.tcx,
-                                              |s, a| this.convert_def_id(dcx, s, a)))
-        }).unwrap()
+        self.read_ty_encoded(dcx, |decoder| decoder.parse_predicate())
     }
 
     fn read_type_scheme<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
@@ -1269,13 +1246,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
     fn read_existential_bounds<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
                                        -> ty::ExistentialBounds<'tcx>
     {
-        self.read_opaque(|this, doc| {
-            Ok(tydecode::parse_existential_bounds_data(doc.data,
-                                                       dcx.cdata.cnum,
-                                                       doc.start,
-                                                       dcx.tcx,
-                                                       |s, a| this.convert_def_id(dcx, s, a)))
-        }).unwrap()
+        self.read_ty_encoded(dcx, |decoder| decoder.parse_existential_bounds())
     }
 
     fn read_substs<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
@@ -1380,14 +1351,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
     fn read_closure_ty<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
                                -> ty::ClosureTy<'tcx>
     {
-        self.read_opaque(|this, doc| {
-            Ok(tydecode::parse_ty_closure_data(
-                doc.data,
-                dcx.cdata.cnum,
-                doc.start,
-                dcx.tcx,
-                |s, a| this.convert_def_id(dcx, s, a)))
-        }).unwrap()
+        self.read_ty_encoded(dcx, |decoder| decoder.parse_closure_ty())
     }
 
     /// Converts a def-id that appears in a type.  The correct

From 7a3a1be5e462775ff5556db79c35ea5979aac8f8 Mon Sep 17 00:00:00 2001
From: Niko Matsakis <niko@alum.mit.edu>
Date: Sat, 15 Aug 2015 21:35:49 -0400
Subject: [PATCH 7/7] remove the last remnants of old interface

---
 src/librustc/metadata/decoder.rs  |  42 ++++++-----
 src/librustc/metadata/tydecode.rs | 117 +-----------------------------
 src/librustc/middle/astencode.rs  |   8 +-
 3 files changed, 29 insertions(+), 138 deletions(-)

diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 11a5cc8c9d7..e8393d754f2 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -24,9 +24,7 @@ use metadata::csearch;
 use metadata::cstore;
 use metadata::encoder::def_to_u64;
 use metadata::inline::InlinedItem;
-use metadata::tydecode::{parse_ty_data, parse_region_data,
-                         parse_type_param_def_data, parse_bare_fn_ty_data,
-                         parse_trait_ref_data, parse_predicate_data};
+use metadata::tydecode::TyDecoder;
 use middle::def;
 use middle::lang_items;
 use middle::subst;
@@ -235,22 +233,25 @@ fn variant_disr_val(d: rbml::Doc) -> Option<ty::Disr> {
 
 fn doc_type<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd) -> Ty<'tcx> {
     let tp = reader::get_doc(doc, tag_items_data_item_type);
-    parse_ty_data(tp.data, cdata.cnum, tp.start, tcx,
-                  |_, did| translate_def_id(cdata, did))
+    TyDecoder::with_doc(tcx, cdata.cnum, tp,
+                        &mut |_, did| translate_def_id(cdata, did))
+        .parse_ty()
 }
 
 fn maybe_doc_type<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd) -> Option<Ty<'tcx>> {
     reader::maybe_get_doc(doc, tag_items_data_item_type).map(|tp| {
-        parse_ty_data(tp.data, cdata.cnum, tp.start, tcx,
-                      |_, did| translate_def_id(cdata, did))
+        TyDecoder::with_doc(tcx, cdata.cnum, tp,
+                            &mut |_, did| translate_def_id(cdata, did))
+            .parse_ty()
     })
 }
 
 fn doc_method_fty<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>,
                         cdata: Cmd) -> ty::BareFnTy<'tcx> {
     let tp = reader::get_doc(doc, tag_item_method_fty);
-    parse_bare_fn_ty_data(tp.data, cdata.cnum, tp.start, tcx,
-                          |_, did| translate_def_id(cdata, did))
+    TyDecoder::with_doc(tcx, cdata.cnum, tp,
+                        &mut |_, did| translate_def_id(cdata, did))
+        .parse_bare_fn_ty()
 }
 
 pub fn item_type<'tcx>(_item_id: ast::DefId, item: rbml::Doc,
@@ -260,8 +261,9 @@ pub fn item_type<'tcx>(_item_id: ast::DefId, item: rbml::Doc,
 
 fn doc_trait_ref<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd)
                        -> ty::TraitRef<'tcx> {
-    parse_trait_ref_data(doc.data, cdata.cnum, doc.start, tcx,
-                         |_, did| translate_def_id(cdata, did))
+    TyDecoder::with_doc(tcx, cdata.cnum, doc,
+                        &mut |_, did| translate_def_id(cdata, did))
+        .parse_trait_ref()
 }
 
 fn item_trait_ref<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd)
@@ -1465,9 +1467,10 @@ fn doc_generics<'tcx>(base_doc: rbml::Doc,
 
     let mut types = subst::VecPerParamSpace::empty();
     for p in reader::tagged_docs(doc, tag_type_param_def) {
-        let bd = parse_type_param_def_data(
-            p.data, p.start, cdata.cnum, tcx,
-            |_, did| translate_def_id(cdata, did));
+        let bd =
+            TyDecoder::with_doc(tcx, cdata.cnum, p,
+                                &mut |_, did| translate_def_id(cdata, did))
+            .parse_type_param_def();
         types.push(bd.space, bd);
     }
 
@@ -1487,8 +1490,9 @@ fn doc_generics<'tcx>(base_doc: rbml::Doc,
         let index = reader::doc_as_u64(doc) as u32;
 
         let bounds = reader::tagged_docs(rp_doc, tag_items_data_region).map(|p| {
-            parse_region_data(p.data, cdata.cnum, p.start, tcx,
-                              |_, did| translate_def_id(cdata, did))
+            TyDecoder::with_doc(tcx, cdata.cnum, p,
+                                &mut |_, did| translate_def_id(cdata, did))
+            .parse_region()
         }).collect();
 
         regions.push(space, ty::RegionParameterDef { name: name,
@@ -1515,8 +1519,10 @@ fn doc_predicates<'tcx>(base_doc: rbml::Doc,
         let space = subst::ParamSpace::from_uint(reader::doc_as_u8(space_doc) as usize);
 
         let data_doc = reader::get_doc(predicate_doc, tag_predicate_data);
-        let data = parse_predicate_data(data_doc.data, data_doc.start, cdata.cnum, tcx,
-                                        |_, did| translate_def_id(cdata, did));
+        let data =
+            TyDecoder::with_doc(tcx, cdata.cnum, data_doc,
+                                &mut |_, did| translate_def_id(cdata, did))
+            .parse_predicate();
 
         predicates.push(space, data);
     }
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 52370f652a2..9219442cf62 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -58,104 +58,6 @@ pub enum DefIdSource {
     ClosureSource
 }
 
-pub fn parse_ty_closure_data<'tcx, F>(data: &[u8],
-                                      crate_num: ast::CrateNum,
-                                      pos: usize,
-                                      tcx: &ty::ctxt<'tcx>,
-                                      mut conv: F)
-                                      -> ty::ClosureTy<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    let mut st = TyDecoder::new(data, crate_num, pos, tcx, &mut conv);
-    st.parse_closure_ty()
-}
-
-pub fn parse_ty_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize,
-                              tcx: &ty::ctxt<'tcx>, mut conv: F) -> Ty<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    debug!("parse_ty_data {}", data_log_string(data, pos));
-    let mut st = TyDecoder::new(data, crate_num, pos, tcx, &mut conv);
-    st.parse_ty()
-}
-
-pub fn parse_region_data<F>(data: &[u8], crate_num: ast::CrateNum, pos: usize, tcx: &ty::ctxt,
-                            mut conv: F) -> ty::Region where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    debug!("parse_region_data {}", data_log_string(data, pos));
-    let mut st = TyDecoder::new(data, crate_num, pos, tcx, &mut conv);
-    st.parse_region()
-}
-
-pub fn parse_bare_fn_ty_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize,
-                                      tcx: &ty::ctxt<'tcx>, mut conv: F)
-                                      -> ty::BareFnTy<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    debug!("parse_bare_fn_ty_data {}", data_log_string(data, pos));
-    let mut st = TyDecoder::new(data, crate_num, pos, tcx, &mut conv);
-    st.parse_bare_fn_ty()
-}
-
-pub fn parse_trait_ref_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize,
-                                     tcx: &ty::ctxt<'tcx>, mut conv: F)
-                                     -> ty::TraitRef<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    debug!("parse_trait_ref_data {}", data_log_string(data, pos));
-    let mut st = TyDecoder::new(data, crate_num, pos, tcx, &mut conv);
-    st.parse_trait_ref()
-}
-
-pub fn parse_substs_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize,
-                                  tcx: &ty::ctxt<'tcx>, mut conv: F) -> subst::Substs<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    debug!("parse_substs_data{}", data_log_string(data, pos));
-    let mut st = TyDecoder::new(data, crate_num, pos, tcx, &mut conv);
-    st.parse_substs()
-}
-
-pub fn parse_existential_bounds_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum,
-                                              pos: usize, tcx: &ty::ctxt<'tcx>, mut conv: F)
-                                              -> ty::ExistentialBounds<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    let mut st = TyDecoder::new(data, crate_num, pos, tcx, &mut conv);
-    st.parse_existential_bounds()
-}
-
-pub fn parse_builtin_bounds_data<F>(data: &[u8], crate_num: ast::CrateNum,
-                                    pos: usize, tcx: &ty::ctxt, mut conv: F)
-                                    -> ty::BuiltinBounds where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    let mut st = TyDecoder::new(data, crate_num, pos, tcx, &mut conv);
-    st.parse_builtin_bounds()
-}
-
-pub fn parse_type_param_def_data<'tcx, F>(data: &[u8], start: usize,
-                                          crate_num: ast::CrateNum, tcx: &ty::ctxt<'tcx>,
-                                          mut conv: F) -> ty::TypeParameterDef<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    let mut st = TyDecoder::new(data, crate_num, start, tcx, &mut conv);
-    st.parse_type_param_def()
-}
-
-pub fn parse_predicate_data<'tcx, F>(data: &[u8],
-                                     start: usize,
-                                     crate_num: ast::CrateNum,
-                                     tcx: &ty::ctxt<'tcx>,
-                                     mut conv: F)
-                                     -> ty::Predicate<'tcx> where
-    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
-{
-    let mut st = TyDecoder::new(data, crate_num, start, tcx, &mut conv);
-    st.parse_predicate()
-}
-
 pub type DefIdConvert<'a> = &'a mut FnMut(DefIdSource, ast::DefId) -> ast::DefId;
 
 pub struct TyDecoder<'a, 'tcx: 'a> {
@@ -292,7 +194,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
         }
     }
 
-    fn parse_region(&mut self) -> ty::Region {
+    pub fn parse_region(&mut self) -> ty::Region {
         match self.next() {
             'b' => {
                 assert_eq!(self.next(), '[');
@@ -629,7 +531,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
         }
     }
 
-    fn parse_bare_fn_ty(&mut self) -> ty::BareFnTy<'tcx> {
+    pub fn parse_bare_fn_ty(&mut self) -> ty::BareFnTy<'tcx> {
         let unsafety = parse_unsafety(self.next());
         let abi = self.parse_abi_set();
         let sig = self.parse_sig();
@@ -777,21 +679,6 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
     }
 }
 
-fn data_log_string(data: &[u8], pos: usize) -> String {
-    let mut buf = String::new();
-    buf.push_str("<<");
-    for i in pos..data.len() {
-        let c = data[i];
-        if c > 0x20 && c <= 0x7F {
-            buf.push(c as char);
-        } else {
-            buf.push('.');
-        }
-    }
-    buf.push_str(">>");
-    buf
-}
-
 // Rust metadata parsing
 fn parse_defid(buf: &[u8]) -> ast::DefId {
     let mut colon_idx = 0;
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index e544d8d4749..591fc043f91 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -1252,11 +1252,9 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
     fn read_substs<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
                            -> subst::Substs<'tcx> {
         self.read_opaque(|this, doc| {
-            Ok(tydecode::parse_substs_data(doc.data,
-                                           dcx.cdata.cnum,
-                                           doc.start,
-                                           dcx.tcx,
-                                           |s, a| this.convert_def_id(dcx, s, a)))
+            Ok(tydecode::TyDecoder::with_doc(dcx.tcx, dcx.cdata.cnum, doc,
+                                             &mut |s, a| this.convert_def_id(dcx, s, a))
+               .parse_substs())
         }).unwrap()
     }