]> git.lizzy.rs Git - rust.git/commitdiff
split ty.rs into smaller parts
authorAriel Ben-Yehuda <arielb1@mail.tau.ac.il>
Sun, 6 Sep 2015 18:51:58 +0000 (21:51 +0300)
committerAriel Ben-Yehuda <ariel.byd@gmail.com>
Mon, 14 Sep 2015 09:32:52 +0000 (12:32 +0300)
25 files changed:
src/librustc/middle/infer/combine.rs
src/librustc/middle/infer/error_reporting.rs
src/librustc/middle/infer/higher_ranked/mod.rs
src/librustc/middle/infer/mod.rs
src/librustc/middle/infer/region_inference/mod.rs
src/librustc/middle/traits/mod.rs
src/librustc/middle/traits/project.rs
src/librustc/middle/ty/_match.rs
src/librustc/middle/ty/contents.rs [new file with mode: 0644]
src/librustc/middle/ty/context.rs [new file with mode: 0644]
src/librustc/middle/ty/error.rs [new file with mode: 0644]
src/librustc/middle/ty/flags.rs [new file with mode: 0644]
src/librustc/middle/ty/fold.rs
src/librustc/middle/ty/ivar.rs [new file with mode: 0644]
src/librustc/middle/ty/mod.rs
src/librustc/middle/ty/relate.rs
src/librustc/middle/ty/structural_impls.rs [new file with mode: 0644]
src/librustc/middle/ty/sty.rs [new file with mode: 0644]
src/librustc/util/ppaux.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/collect.rs

index 3a29fdfae2307dfb74ef1c3849dc3ab46be8eee4..2447a8cee7bbb9d56bf9c0e1d2f8969a350e04f1 100644 (file)
@@ -43,7 +43,8 @@
 
 use middle::ty::{TyVar};
 use middle::ty::{IntType, UintType};
-use middle::ty::{self, Ty, TypeError};
+use middle::ty::{self, Ty};
+use middle::ty::error::TypeError;
 use middle::ty::fold::{TypeFolder, TypeFoldable};
 use middle::ty::relate::{Relate, RelateResult, TypeRelation};
 
@@ -362,12 +363,12 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
 
 pub trait RelateResultCompare<'tcx, T> {
     fn compare<F>(&self, t: T, f: F) -> RelateResult<'tcx, T> where
-        F: FnOnce() -> ty::TypeError<'tcx>;
+        F: FnOnce() -> TypeError<'tcx>;
 }
 
 impl<'tcx, T:Clone + PartialEq> RelateResultCompare<'tcx, T> for RelateResult<'tcx, T> {
     fn compare<F>(&self, t: T, f: F) -> RelateResult<'tcx, T> where
-        F: FnOnce() -> ty::TypeError<'tcx>,
+        F: FnOnce() -> TypeError<'tcx>,
     {
         self.clone().and_then(|s| {
             if s == t {
@@ -380,7 +381,7 @@ fn compare<F>(&self, t: T, f: F) -> RelateResult<'tcx, T> where
 }
 
 fn int_unification_error<'tcx>(a_is_expected: bool, v: (ty::IntVarValue, ty::IntVarValue))
-                               -> ty::TypeError<'tcx>
+                               -> TypeError<'tcx>
 {
     let (a, b) = v;
     TypeError::IntMismatch(ty::relate::expected_found_bool(a_is_expected, &a, &b))
@@ -388,7 +389,7 @@ fn int_unification_error<'tcx>(a_is_expected: bool, v: (ty::IntVarValue, ty::Int
 
 fn float_unification_error<'tcx>(a_is_expected: bool,
                                  v: (hir::FloatTy, hir::FloatTy))
-                                 -> ty::TypeError<'tcx>
+                                 -> TypeError<'tcx>
 {
     let (a, b) = v;
     TypeError::FloatMismatch(ty::relate::expected_found_bool(a_is_expected, &a, &b))
index 7ec39ac851574dda434a6cbc1163d0d73777e95f..f0fa7d7cdf851b0f5a12bfbeb6a5423e5fc3de9e 100644 (file)
@@ -82,8 +82,9 @@
 use middle::infer;
 use middle::region;
 use middle::subst;
-use middle::ty::{self, Ty, TypeError, HasTypeFlags};
+use middle::ty::{self, Ty, HasTypeFlags};
 use middle::ty::{Region, ReFree};
+use middle::ty::error::TypeError;
 
 use std::cell::{Cell, RefCell};
 use std::char::from_u32;
@@ -225,19 +226,19 @@ fn report_region_errors(&self,
     fn process_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>)
                       -> Vec<RegionResolutionError<'tcx>>;
 
-    fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &ty::TypeError<'tcx>);
+    fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &TypeError<'tcx>);
 
-    fn check_and_note_conflicting_crates(&self, terr: &ty::TypeError<'tcx>, sp: Span);
+    fn check_and_note_conflicting_crates(&self, terr: &TypeError<'tcx>, sp: Span);
 
     fn report_and_explain_type_error(&self,
                                      trace: TypeTrace<'tcx>,
-                                     terr: &ty::TypeError<'tcx>);
+                                     terr: &TypeError<'tcx>);
 
     fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<String>;
 
     fn expected_found_str<T: fmt::Display + Resolvable<'tcx> + HasTypeFlags>(
         &self,
-        exp_found: &ty::ExpectedFound<T>)
+        exp_found: &ty::error::ExpectedFound<T>)
         -> Option<String>;
 
     fn report_concrete_failure(&self,
@@ -266,7 +267,7 @@ fn report_sup_sup_conflict(&self,
 
     fn report_processed_errors(&self,
                                var_origin: &[RegionVariableOrigin],
-                               trace_origin: &[(TypeTrace<'tcx>, ty::TypeError<'tcx>)],
+                               trace_origin: &[(TypeTrace<'tcx>, TypeError<'tcx>)],
                                same_regions: &[SameRegions]);
 
     fn give_suggestion(&self, same_regions: &[SameRegions]);
@@ -473,7 +474,7 @@ fn append_to_same_regions(same_regions: &mut Vec<SameRegions>,
         }
     }
 
-    fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &ty::TypeError<'tcx>) {
+    fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &TypeError<'tcx>) {
         let expected_found_str = match self.values_str(&trace.values) {
             Some(v) => v,
             None => {
@@ -497,7 +498,7 @@ fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &ty::TypeError<'tcx>)
     }
 
     /// Adds a note if the types come from similarly named crates
-    fn check_and_note_conflicting_crates(&self, terr: &ty::TypeError<'tcx>, sp: Span) {
+    fn check_and_note_conflicting_crates(&self, terr: &TypeError<'tcx>, sp: Span) {
         let report_path_match = |did1: DefId, did2: DefId| {
             // Only external crates, if either is from a local
             // module we could have false positives
@@ -520,7 +521,7 @@ fn check_and_note_conflicting_crates(&self, terr: &ty::TypeError<'tcx>, sp: Span
             }
         };
         match *terr {
-            ty::TypeError::Sorts(ref exp_found) => {
+            TypeError::Sorts(ref exp_found) => {
                 // if they are both "path types", there's a chance of ambiguity
                 // due to different versions of the same crate
                 match (&exp_found.expected.sty, &exp_found.found.sty) {
@@ -533,7 +534,7 @@ fn check_and_note_conflicting_crates(&self, terr: &ty::TypeError<'tcx>, sp: Span
                     _ => ()
                 }
             },
-            ty::TypeError::Traits(ref exp_found) => {
+            TypeError::Traits(ref exp_found) => {
                 self.tcx.sess.note("errrr0");
                 report_path_match(exp_found.expected, exp_found.found);
             },
@@ -543,7 +544,7 @@ fn check_and_note_conflicting_crates(&self, terr: &ty::TypeError<'tcx>, sp: Span
 
     fn report_and_explain_type_error(&self,
                                      trace: TypeTrace<'tcx>,
-                                     terr: &ty::TypeError<'tcx>) {
+                                     terr: &TypeError<'tcx>) {
         let span = trace.origin.span();
         self.report_type_error(trace, terr);
         self.tcx.note_and_explain_type_err(terr, span);
@@ -561,7 +562,7 @@ fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<String> {
 
     fn expected_found_str<T: fmt::Display + Resolvable<'tcx> + HasTypeFlags>(
         &self,
-        exp_found: &ty::ExpectedFound<T>)
+        exp_found: &ty::error::ExpectedFound<T>)
         -> Option<String>
     {
         let expected = exp_found.expected.resolve(self);
@@ -975,7 +976,7 @@ fn report_sup_sup_conflict(&self,
 
     fn report_processed_errors(&self,
                                var_origins: &[RegionVariableOrigin],
-                               trace_origins: &[(TypeTrace<'tcx>, ty::TypeError<'tcx>)],
+                               trace_origins: &[(TypeTrace<'tcx>, TypeError<'tcx>)],
                                same_regions: &[SameRegions]) {
         for vo in var_origins {
             self.report_inference_failure(vo.clone());
index 10a31f0e657e57481e4571b448aed43537c5bfa8..b0fce71d3f06143523856dacc51e85acd62164e0 100644 (file)
@@ -14,7 +14,8 @@
 use super::{CombinedSnapshot, InferCtxt, HigherRankedType, SkolemizationMap};
 use super::combine::CombineFields;
 
-use middle::ty::{self, TypeError, Binder};
+use middle::ty::{self, Binder};
+use middle::ty::error::TypeError;
 use middle::ty::fold::TypeFoldable;
 use middle::ty::relate::{Relate, RelateResult, TypeRelation};
 use syntax::codemap::Span;
@@ -358,7 +359,7 @@ fn fold_regions_in<'tcx, T, F>(tcx: &ty::ctxt<'tcx>,
     where T: TypeFoldable<'tcx>,
           F: FnMut(ty::Region, ty::DebruijnIndex) -> ty::Region,
 {
-    ty::fold::fold_regions(tcx, unbound_value, &mut false, |region, current_depth| {
+    tcx.fold_regions(unbound_value, &mut false, |region, current_depth| {
         // we should only be encountering "escaping" late-bound regions here,
         // because the ones at the current level should have been replaced
         // with fresh variables
@@ -438,7 +439,7 @@ fn region_vars_confined_to_snapshot(&self,
 
         let mut escaping_region_vars = FnvHashSet();
         for ty in &escaping_types {
-            ty::fold::collect_regions(self.tcx, ty, &mut escaping_region_vars);
+            self.tcx.collect_regions(ty, &mut escaping_region_vars);
         }
 
         region_vars.retain(|&region_vid| {
@@ -468,7 +469,7 @@ pub fn skolemize_late_bound_regions<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
      * details.
      */
 
-    let (result, map) = ty::fold::replace_late_bound_regions(infcx.tcx, binder, |br| {
+    let (result, map) = infcx.tcx.replace_late_bound_regions(binder, |br| {
         infcx.region_vars.new_skolemized(br, &snapshot.region_vars_snapshot)
     });
 
@@ -590,7 +591,7 @@ pub fn plug_leaks<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
     // binder is that we encountered in `value`. The caller is
     // responsible for ensuring that (a) `value` contains at least one
     // binder and (b) that binder is the one we want to use.
-    let result = ty::fold::fold_regions(infcx.tcx, &value, &mut false, |r, current_depth| {
+    let result = infcx.tcx.fold_regions(&value, &mut false, |r, current_depth| {
         match inv_skol_map.get(&r) {
             None => r,
             Some(br) => {
index 5b94f5311fd0f6bf54ef99cae2a93898e99abbba..b9e9ee5e2449732dc7c469459ecbcef6d52c93b2 100644 (file)
@@ -30,8 +30,9 @@
 use middle::subst::Subst;
 use middle::traits::{self, FulfillmentContext, Normalized,
                      SelectionContext, ObligationCause};
-use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, UnconstrainedNumeric};
-use middle::ty::{self, Ty, TypeError, HasTypeFlags};
+use middle::ty::{TyVid, IntVid, FloatVid, RegionVid};
+use middle::ty::{self, Ty, HasTypeFlags};
+use middle::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
 use middle::ty::fold::{TypeFolder, TypeFoldable};
 use middle::ty::relate::{Relate, RelateResult, TypeRelation};
 use rustc_data_structures::unify::{self, UnificationTable};
@@ -171,9 +172,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error> {
 /// See `error_reporting.rs` for more details
 #[derive(Clone, Debug)]
 pub enum ValuePairs<'tcx> {
-    Types(ty::ExpectedFound<Ty<'tcx>>),
-    TraitRefs(ty::ExpectedFound<ty::TraitRef<'tcx>>),
-    PolyTraitRefs(ty::ExpectedFound<ty::PolyTraitRef<'tcx>>),
+    Types(ExpectedFound<Ty<'tcx>>),
+    TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>),
+    PolyTraitRefs(ExpectedFound<ty::PolyTraitRef<'tcx>>),
 }
 
 /// The trace designates the path through inference that we took to
@@ -479,12 +480,12 @@ pub fn mk_sub_poly_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
 fn expected_found<T>(a_is_expected: bool,
                      a: T,
                      b: T)
-                     -> ty::ExpectedFound<T>
+                     -> ExpectedFound<T>
 {
     if a_is_expected {
-        ty::ExpectedFound {expected: a, found: b}
+        ExpectedFound {expected: a, found: b}
     } else {
-        ty::ExpectedFound {expected: b, found: a}
+        ExpectedFound {expected: b, found: a}
     }
 }
 
@@ -656,7 +657,8 @@ pub fn freshener<'b>(&'b self) -> TypeFreshener<'b, 'tcx> {
     }
 
     pub fn type_is_unconstrained_numeric(&'a self, ty: Ty) -> UnconstrainedNumeric {
-        use middle::ty::UnconstrainedNumeric::{Neither, UnconstrainedInt, UnconstrainedFloat};
+        use middle::ty::error::UnconstrainedNumeric::Neither;
+        use middle::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
         match ty.sty {
             ty::TyInfer(ty::IntVar(vid)) => {
                 if self.int_unification_table.borrow_mut().has_value(vid) {
@@ -1312,7 +1314,7 @@ pub fn type_error_message_str<M>(&self,
                                      sp: Span,
                                      mk_msg: M,
                                      actual_ty: String,
-                                     err: Option<&ty::TypeError<'tcx>>) where
+                                     err: Option<&TypeError<'tcx>>) where
         M: FnOnce(Option<String>, String) -> String,
     {
         self.type_error_message_str_with_expected(sp, mk_msg, None, actual_ty, err)
@@ -1323,7 +1325,7 @@ pub fn type_error_message_str_with_expected<M>(&self,
                                                    mk_msg: M,
                                                    expected_ty: Option<Ty<'tcx>>,
                                                    actual_ty: String,
-                                                   err: Option<&ty::TypeError<'tcx>>) where
+                                                   err: Option<&TypeError<'tcx>>) where
         M: FnOnce(Option<String>, String) -> String,
     {
         debug!("hi! expected_ty = {:?}, actual_ty = {}", expected_ty, actual_ty);
@@ -1349,7 +1351,7 @@ pub fn type_error_message<M>(&self,
                                  sp: Span,
                                  mk_msg: M,
                                  actual_ty: Ty<'tcx>,
-                                 err: Option<&ty::TypeError<'tcx>>) where
+                                 err: Option<&TypeError<'tcx>>) where
         M: FnOnce(String) -> String,
     {
         let actual_ty = self.resolve_type_vars_if_possible(&actual_ty);
@@ -1368,10 +1370,10 @@ pub fn report_mismatched_types(&self,
                                    span: Span,
                                    expected: Ty<'tcx>,
                                    actual: Ty<'tcx>,
-                                   err: &ty::TypeError<'tcx>) {
+                                   err: &TypeError<'tcx>) {
         let trace = TypeTrace {
             origin: Misc(span),
-            values: Types(ty::ExpectedFound {
+            values: Types(ExpectedFound {
                 expected: expected,
                 found: actual
             })
@@ -1385,14 +1387,14 @@ pub fn report_conflicting_default_types(&self,
                                             actual: type_variable::Default<'tcx>) {
         let trace = TypeTrace {
             origin: Misc(span),
-            values: Types(ty::ExpectedFound {
+            values: Types(ExpectedFound {
                 expected: expected.ty,
                 found: actual.ty
             })
         };
 
         self.report_and_explain_type_error(trace,
-            &TypeError::TyParamDefaultMismatch(ty::ExpectedFound {
+            &TypeError::TyParamDefaultMismatch(ExpectedFound {
                 expected: expected,
                 found: actual
         }));
@@ -1406,8 +1408,7 @@ pub fn replace_late_bound_regions_with_fresh_var<T>(
         -> (T, FnvHashMap<ty::BoundRegion,ty::Region>)
         where T : TypeFoldable<'tcx>
     {
-        ty::fold::replace_late_bound_regions(
-            self.tcx,
+        self.tcx.replace_late_bound_regions(
             value,
             |br| self.next_region_var(LateBoundRegion(span, br, lbrct)))
     }
@@ -1555,7 +1556,7 @@ pub fn types(origin: TypeOrigin,
     pub fn dummy(tcx: &ty::ctxt<'tcx>) -> TypeTrace<'tcx> {
         TypeTrace {
             origin: Misc(codemap::DUMMY_SP),
-            values: Types(ty::ExpectedFound {
+            values: Types(ExpectedFound {
                 expected: tcx.types.err,
                 found: tcx.types.err,
             })
index a62fd8890baf6eb1e2cb02d66657b8634ce5f674..1fc5294877065efc2bffd945ff534fb2941ee3e7 100644 (file)
 use rustc_data_structures::graph::{self, Direction, NodeIndex};
 use middle::free_region::FreeRegionMap;
 use middle::region;
-use middle::ty::{self, Ty, TypeError};
+use middle::ty::{self, Ty};
 use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid};
 use middle::ty::{ReEmpty, ReStatic, ReFree, ReEarlyBound};
 use middle::ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
+use middle::ty::error::TypeError;
 use middle::ty::relate::RelateResult;
 use util::common::indenter;
 use util::nodemap::{FnvHashMap, FnvHashSet};
@@ -157,7 +158,7 @@ pub enum RegionResolutionError<'tcx> {
     /// should put a lifetime. In those cases we process and put those errors
     /// into `ProcessedErrors` before we do any reporting.
     ProcessedErrors(Vec<RegionVariableOrigin>,
-                    Vec<(TypeTrace<'tcx>, ty::TypeError<'tcx>)>,
+                    Vec<(TypeTrace<'tcx>, TypeError<'tcx>)>,
                     Vec<SameRegions>),
 }
 
index 6c581a701a27e0a82507b9ab910e8971c51cd6a8..a79837e7fb14f88bf61de5b5394bb27bb9ed3819 100644 (file)
@@ -168,7 +168,7 @@ pub enum SelectionError<'tcx> {
     Unimplemented,
     OutputTypeParameterMismatch(ty::PolyTraitRef<'tcx>,
                                 ty::PolyTraitRef<'tcx>,
-                                ty::TypeError<'tcx>),
+                                ty::error::TypeError<'tcx>),
     TraitNotObjectSafe(DefId),
 }
 
index 0d320989cbc7f42a1e67b512709ea152515d2659..f13b81ccdb22fd6ad3463520f10f614800478798 100644 (file)
@@ -51,7 +51,7 @@ pub enum ProjectionTyError<'tcx> {
 
 #[derive(Clone)]
 pub struct MismatchedProjectionTypes<'tcx> {
-    pub err: ty::TypeError<'tcx>
+    pub err: ty::error::TypeError<'tcx>
 }
 
 #[derive(PartialEq, Eq, Debug)]
index 2ebb23369bd0161973deca470e991e7ac391a683..5a3ad9095ad2c1b945b5f9af25ca7a85e93fee60 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use middle::ty::{self, Ty};
+use middle::ty::error::TypeError;
 use middle::ty::relate::{self, Relate, TypeRelation, RelateResult};
 
 /// A type "A" *matches* "B" if the fresh types in B could be
@@ -73,7 +74,7 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
 
             (&ty::TyInfer(_), _) |
             (_, &ty::TyInfer(_)) => {
-                Err(ty::TypeError::Sorts(relate::expected_found(self, &a, &b)))
+                Err(TypeError::Sorts(relate::expected_found(self, &a, &b)))
             }
 
             (&ty::TyError, _) | (_, &ty::TyError) => {
diff --git a/src/librustc/middle/ty/contents.rs b/src/librustc/middle/ty/contents.rs
new file mode 100644 (file)
index 0000000..bcce9e8
--- /dev/null
@@ -0,0 +1,269 @@
+// 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 middle::def_id::{DefId};
+use middle::ty::{self, Ty};
+use util::common::{memoized};
+use util::nodemap::FnvHashMap;
+
+use std::fmt;
+use std::ops;
+
+use rustc_front::hir;
+
+/// Type contents is how the type checker reasons about kinds.
+/// They track what kinds of things are found within a type.  You can
+/// think of them as kind of an "anti-kind".  They track the kinds of values
+/// and thinks that are contained in types.  Having a larger contents for
+/// a type tends to rule that type *out* from various kinds.  For example,
+/// a type that contains a reference is not sendable.
+///
+/// The reason we compute type contents and not kinds is that it is
+/// easier for me (nmatsakis) to think about what is contained within
+/// a type than to think about what is *not* contained within a type.
+#[derive(Clone, Copy)]
+pub struct TypeContents {
+    pub bits: u64
+}
+
+macro_rules! def_type_content_sets {
+    (mod $mname:ident { $($name:ident = $bits:expr),+ }) => {
+        #[allow(non_snake_case)]
+        mod $mname {
+            use super::TypeContents;
+            $(
+                #[allow(non_upper_case_globals)]
+                pub const $name: TypeContents = TypeContents { bits: $bits };
+             )+
+        }
+    }
+}
+
+def_type_content_sets! {
+    mod TC {
+        None                                = 0b0000_0000__0000_0000__0000,
+
+        // Things that are interior to the value (first nibble):
+        InteriorUnsafe                      = 0b0000_0000__0000_0000__0010,
+        InteriorParam                       = 0b0000_0000__0000_0000__0100,
+        // InteriorAll                         = 0b00000000__00000000__1111,
+
+        // Things that are owned by the value (second and third nibbles):
+        OwnsOwned                           = 0b0000_0000__0000_0001__0000,
+        OwnsDtor                            = 0b0000_0000__0000_0010__0000,
+        OwnsAll                             = 0b0000_0000__1111_1111__0000,
+
+        // Things that mean drop glue is necessary
+        NeedsDrop                           = 0b0000_0000__0000_0111__0000,
+
+        // All bits
+        All                                 = 0b1111_1111__1111_1111__1111
+    }
+}
+
+impl TypeContents {
+    pub fn when(&self, cond: bool) -> TypeContents {
+        if cond {*self} else {TC::None}
+    }
+
+    pub fn intersects(&self, tc: TypeContents) -> bool {
+        (self.bits & tc.bits) != 0
+    }
+
+    pub fn owns_owned(&self) -> bool {
+        self.intersects(TC::OwnsOwned)
+    }
+
+    pub fn interior_param(&self) -> bool {
+        self.intersects(TC::InteriorParam)
+    }
+
+    pub fn interior_unsafe(&self) -> bool {
+        self.intersects(TC::InteriorUnsafe)
+    }
+
+    pub fn needs_drop(&self, _: &ty::ctxt) -> bool {
+        self.intersects(TC::NeedsDrop)
+    }
+
+    /// Includes only those bits that still apply when indirected through a `Box` pointer
+    pub fn owned_pointer(&self) -> TypeContents {
+        TC::OwnsOwned | (*self & TC::OwnsAll)
+    }
+
+    pub fn union<T, F>(v: &[T], mut f: F) -> TypeContents where
+        F: FnMut(&T) -> TypeContents,
+    {
+        v.iter().fold(TC::None, |tc, ty| tc | f(ty))
+    }
+
+    pub fn has_dtor(&self) -> bool {
+        self.intersects(TC::OwnsDtor)
+    }
+}
+
+impl ops::BitOr for TypeContents {
+    type Output = TypeContents;
+
+    fn bitor(self, other: TypeContents) -> TypeContents {
+        TypeContents {bits: self.bits | other.bits}
+    }
+}
+
+impl ops::BitAnd for TypeContents {
+    type Output = TypeContents;
+
+    fn bitand(self, other: TypeContents) -> TypeContents {
+        TypeContents {bits: self.bits & other.bits}
+    }
+}
+
+impl ops::Sub for TypeContents {
+    type Output = TypeContents;
+
+    fn sub(self, other: TypeContents) -> TypeContents {
+        TypeContents {bits: self.bits & !other.bits}
+    }
+}
+
+impl fmt::Debug for TypeContents {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "TypeContents({:b})", self.bits)
+    }
+}
+
+impl<'tcx> ty::TyS<'tcx> {
+    pub fn type_contents(&'tcx self, cx: &ty::ctxt<'tcx>) -> TypeContents {
+        return memoized(&cx.tc_cache, self, |ty| {
+            tc_ty(cx, ty, &mut FnvHashMap())
+        });
+
+        fn tc_ty<'tcx>(cx: &ty::ctxt<'tcx>,
+                       ty: Ty<'tcx>,
+                       cache: &mut FnvHashMap<Ty<'tcx>, TypeContents>) -> TypeContents
+        {
+            // Subtle: Note that we are *not* using cx.tc_cache here but rather a
+            // private cache for this walk.  This is needed in the case of cyclic
+            // types like:
+            //
+            //     struct List { next: Box<Option<List>>, ... }
+            //
+            // When computing the type contents of such a type, we wind up deeply
+            // recursing as we go.  So when we encounter the recursive reference
+            // to List, we temporarily use TC::None as its contents.  Later we'll
+            // patch up the cache with the correct value, once we've computed it
+            // (this is basically a co-inductive process, if that helps).  So in
+            // the end we'll compute TC::OwnsOwned, in this case.
+            //
+            // The problem is, as we are doing the computation, we will also
+            // compute an *intermediate* contents for, e.g., Option<List> of
+            // TC::None.  This is ok during the computation of List itself, but if
+            // we stored this intermediate value into cx.tc_cache, then later
+            // requests for the contents of Option<List> would also yield TC::None
+            // which is incorrect.  This value was computed based on the crutch
+            // value for the type contents of list.  The correct value is
+            // TC::OwnsOwned.  This manifested as issue #4821.
+            match cache.get(&ty) {
+                Some(tc) => { return *tc; }
+                None => {}
+            }
+            match cx.tc_cache.borrow().get(&ty) {    // Must check both caches!
+                Some(tc) => { return *tc; }
+                None => {}
+            }
+            cache.insert(ty, TC::None);
+
+            let result = match ty.sty {
+                // usize and isize are ffi-unsafe
+                ty::TyUint(hir::TyUs) | ty::TyInt(hir::TyIs) => {
+                    TC::None
+                }
+
+                // Scalar and unique types are sendable, and durable
+                ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
+                ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) |
+                ty::TyBareFn(..) | ty::TyChar => {
+                    TC::None
+                }
+
+                ty::TyBox(typ) => {
+                    tc_ty(cx, typ, cache).owned_pointer()
+                }
+
+                ty::TyTrait(_) => {
+                    TC::All - TC::InteriorParam
+                }
+
+                ty::TyRawPtr(_) => {
+                    TC::None
+                }
+
+                ty::TyRef(_, _) => {
+                    TC::None
+                }
+
+                ty::TyArray(ty, _) => {
+                    tc_ty(cx, ty, cache)
+                }
+
+                ty::TySlice(ty) => {
+                    tc_ty(cx, ty, cache)
+                }
+                ty::TyStr => TC::None,
+
+                ty::TyClosure(_, ref substs) => {
+                    TypeContents::union(&substs.upvar_tys, |ty| tc_ty(cx, &ty, cache))
+                }
+
+                ty::TyTuple(ref tys) => {
+                    TypeContents::union(&tys[..],
+                                        |ty| tc_ty(cx, *ty, cache))
+                }
+
+                ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
+                    let mut res =
+                        TypeContents::union(&def.variants, |v| {
+                            TypeContents::union(&v.fields, |f| {
+                                tc_ty(cx, f.ty(cx, substs), cache)
+                            })
+                        });
+
+                    if def.has_dtor() {
+                        res = res | TC::OwnsDtor;
+                    }
+
+                    apply_lang_items(cx, def.did, res)
+                }
+
+                ty::TyProjection(..) |
+                ty::TyParam(_) => {
+                    TC::All
+                }
+
+                ty::TyInfer(_) |
+                ty::TyError => {
+                    cx.sess.bug("asked to compute contents of error type");
+                }
+            };
+
+            cache.insert(ty, result);
+            result
+        }
+
+        fn apply_lang_items(cx: &ty::ctxt, did: DefId, tc: TypeContents)
+                            -> TypeContents {
+            if Some(did) == cx.lang_items.unsafe_cell_type() {
+                tc | TC::InteriorUnsafe
+            } else {
+                tc
+            }
+        }
+    }
+}
diff --git a/src/librustc/middle/ty/context.rs b/src/librustc/middle/ty/context.rs
new file mode 100644 (file)
index 0000000..4d57e09
--- /dev/null
@@ -0,0 +1,964 @@
+// 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.
+
+//! type context book-keeping
+
+// FIXME: (@jroesch) @eddyb should remove this when he renames ctxt
+#![allow(non_camel_case_types)]
+
+use front::map as ast_map;
+use session::Session;
+use lint;
+use middle;
+use middle::def::DefMap;
+use middle::def_id::DefId;
+use middle::free_region::FreeRegionMap;
+use middle::region::RegionMaps;
+use middle::resolve_lifetime;
+use middle::stability;
+use middle::subst::{self, Subst, Substs};
+use middle::traits;
+use middle::ty::{self, TraitRef, Ty, TypeAndMut};
+use middle::ty::{TyS, TypeVariants};
+use middle::ty::{AdtDef, ClosureSubsts, ExistentialBounds, Region};
+use middle::ty::{FreevarMap, GenericPredicates};
+use middle::ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitTy};
+use middle::ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
+use middle::ty::TypeVariants::*;
+use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
+use util::nodemap::FnvHashMap;
+
+use arena::TypedArena;
+use std::borrow::Borrow;
+use std::cell::{Cell, RefCell, Ref};
+use std::hash::{Hash, Hasher};
+use std::rc::Rc;
+use syntax::abi;
+use syntax::ast::{Name, NodeId};
+use syntax::parse::token::special_idents;
+
+use rustc_front::hir;
+use rustc_front::attr;
+
+/// Internal storage
+pub struct CtxtArenas<'tcx> {
+    // internings
+    type_: TypedArena<TyS<'tcx>>,
+    substs: TypedArena<Substs<'tcx>>,
+    bare_fn: TypedArena<BareFnTy<'tcx>>,
+    region: TypedArena<Region>,
+    stability: TypedArena<attr::Stability>,
+
+    // references
+    trait_defs: TypedArena<ty::TraitDef<'tcx>>,
+    adt_defs: TypedArena<ty::AdtDefData<'tcx, 'tcx>>,
+}
+
+impl<'tcx> CtxtArenas<'tcx> {
+    pub fn new() -> CtxtArenas<'tcx> {
+        CtxtArenas {
+            type_: TypedArena::new(),
+            substs: TypedArena::new(),
+            bare_fn: TypedArena::new(),
+            region: TypedArena::new(),
+            stability: TypedArena::new(),
+
+            trait_defs: TypedArena::new(),
+            adt_defs: TypedArena::new()
+        }
+    }
+}
+
+pub struct CommonTypes<'tcx> {
+    pub bool: Ty<'tcx>,
+    pub char: Ty<'tcx>,
+    pub isize: Ty<'tcx>,
+    pub i8: Ty<'tcx>,
+    pub i16: Ty<'tcx>,
+    pub i32: Ty<'tcx>,
+    pub i64: Ty<'tcx>,
+    pub usize: Ty<'tcx>,
+    pub u8: Ty<'tcx>,
+    pub u16: Ty<'tcx>,
+    pub u32: Ty<'tcx>,
+    pub u64: Ty<'tcx>,
+    pub f32: Ty<'tcx>,
+    pub f64: Ty<'tcx>,
+    pub err: Ty<'tcx>,
+}
+
+pub struct Tables<'tcx> {
+    /// Stores the types for various nodes in the AST.  Note that this table
+    /// is not guaranteed to be populated until after typeck.  See
+    /// typeck::check::fn_ctxt for details.
+    pub node_types: NodeMap<Ty<'tcx>>,
+
+    /// Stores the type parameters which were substituted to obtain the type
+    /// of this node.  This only applies to nodes that refer to entities
+    /// parameterized by type parameters, such as generic fns, types, or
+    /// other items.
+    pub item_substs: NodeMap<ty::ItemSubsts<'tcx>>,
+
+    pub adjustments: NodeMap<ty::AutoAdjustment<'tcx>>,
+
+    pub method_map: ty::MethodMap<'tcx>,
+
+    /// Borrows
+    pub upvar_capture_map: ty::UpvarCaptureMap,
+
+    /// Records the type of each closure. The def ID is the ID of the
+    /// expression defining the closure.
+    pub closure_tys: DefIdMap<ty::ClosureTy<'tcx>>,
+
+    /// Records the type of each closure. The def ID is the ID of the
+    /// expression defining the closure.
+    pub closure_kinds: DefIdMap<ty::ClosureKind>,
+}
+
+impl<'tcx> Tables<'tcx> {
+    pub fn empty() -> Tables<'tcx> {
+        Tables {
+            node_types: FnvHashMap(),
+            item_substs: NodeMap(),
+            adjustments: NodeMap(),
+            method_map: FnvHashMap(),
+            upvar_capture_map: FnvHashMap(),
+            closure_tys: DefIdMap(),
+            closure_kinds: DefIdMap(),
+        }
+    }
+}
+
+impl<'tcx> CommonTypes<'tcx> {
+    fn new(arena: &'tcx TypedArena<TyS<'tcx>>,
+           interner: &RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>)
+           -> CommonTypes<'tcx>
+    {
+        let mk = |sty| ctxt::intern_ty(arena, interner, sty);
+        CommonTypes {
+            bool: mk(TyBool),
+            char: mk(TyChar),
+            err: mk(TyError),
+            isize: mk(TyInt(hir::TyIs)),
+            i8: mk(TyInt(hir::TyI8)),
+            i16: mk(TyInt(hir::TyI16)),
+            i32: mk(TyInt(hir::TyI32)),
+            i64: mk(TyInt(hir::TyI64)),
+            usize: mk(TyUint(hir::TyUs)),
+            u8: mk(TyUint(hir::TyU8)),
+            u16: mk(TyUint(hir::TyU16)),
+            u32: mk(TyUint(hir::TyU32)),
+            u64: mk(TyUint(hir::TyU64)),
+            f32: mk(TyFloat(hir::TyF32)),
+            f64: mk(TyFloat(hir::TyF64)),
+        }
+    }
+}
+
+/// The data structure to keep track of all the information that typechecker
+/// generates so that so that it can be reused and doesn't have to be redone
+/// later on.
+pub struct ctxt<'tcx> {
+    /// The arenas that types etc are allocated from.
+    arenas: &'tcx CtxtArenas<'tcx>,
+
+    /// Specifically use a speedy hash algorithm for this hash map, it's used
+    /// quite often.
+    // FIXME(eddyb) use a FnvHashSet<InternedTy<'tcx>> when equivalent keys can
+    // queried from a HashSet.
+    interner: RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>,
+
+    // FIXME as above, use a hashset if equivalent elements can be queried.
+    substs_interner: RefCell<FnvHashMap<&'tcx Substs<'tcx>, &'tcx Substs<'tcx>>>,
+    bare_fn_interner: RefCell<FnvHashMap<&'tcx BareFnTy<'tcx>, &'tcx BareFnTy<'tcx>>>,
+    region_interner: RefCell<FnvHashMap<&'tcx Region, &'tcx Region>>,
+    stability_interner: RefCell<FnvHashMap<&'tcx attr::Stability, &'tcx attr::Stability>>,
+
+    /// Common types, pre-interned for your convenience.
+    pub types: CommonTypes<'tcx>,
+
+    pub sess: Session,
+    pub def_map: DefMap,
+
+    pub named_region_map: resolve_lifetime::NamedRegionMap,
+
+    pub region_maps: RegionMaps,
+
+    // For each fn declared in the local crate, type check stores the
+    // free-region relationships that were deduced from its where
+    // clauses and parameter types. These are then read-again by
+    // borrowck. (They are not used during trans, and hence are not
+    // serialized or needed for cross-crate fns.)
+    free_region_maps: RefCell<NodeMap<FreeRegionMap>>,
+    // FIXME: jroesch make this a refcell
+
+    pub tables: RefCell<Tables<'tcx>>,
+
+    /// Maps from a trait item to the trait item "descriptor"
+    pub impl_or_trait_items: RefCell<DefIdMap<ty::ImplOrTraitItem<'tcx>>>,
+
+    /// Maps from a trait def-id to a list of the def-ids of its trait items
+    pub trait_item_def_ids: RefCell<DefIdMap<Rc<Vec<ty::ImplOrTraitItemId>>>>,
+
+    /// A cache for the trait_items() routine
+    pub trait_items_cache: RefCell<DefIdMap<Rc<Vec<ty::ImplOrTraitItem<'tcx>>>>>,
+
+    pub impl_trait_refs: RefCell<DefIdMap<Option<TraitRef<'tcx>>>>,
+    pub trait_defs: RefCell<DefIdMap<&'tcx ty::TraitDef<'tcx>>>,
+    pub adt_defs: RefCell<DefIdMap<ty::AdtDefMaster<'tcx>>>,
+
+    /// Maps from the def-id of an item (trait/struct/enum/fn) to its
+    /// associated predicates.
+    pub predicates: RefCell<DefIdMap<GenericPredicates<'tcx>>>,
+
+    /// Maps from the def-id of a trait to the list of
+    /// super-predicates. This is a subset of the full list of
+    /// predicates. We store these in a separate map because we must
+    /// evaluate them even during type conversion, often before the
+    /// full predicates are available (note that supertraits have
+    /// additional acyclicity requirements).
+    pub super_predicates: RefCell<DefIdMap<GenericPredicates<'tcx>>>,
+
+    pub map: ast_map::Map<'tcx>,
+    pub freevars: RefCell<FreevarMap>,
+    pub tcache: RefCell<DefIdMap<ty::TypeScheme<'tcx>>>,
+    pub rcache: RefCell<FnvHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
+    pub tc_cache: RefCell<FnvHashMap<Ty<'tcx>, ty::contents::TypeContents>>,
+    pub ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>,
+    pub ty_param_defs: RefCell<NodeMap<ty::TypeParameterDef<'tcx>>>,
+    pub normalized_cache: RefCell<FnvHashMap<Ty<'tcx>, Ty<'tcx>>>,
+    pub lang_items: middle::lang_items::LanguageItems,
+    /// A mapping of fake provided method def_ids to the default implementation
+    pub provided_method_sources: RefCell<DefIdMap<DefId>>,
+
+    /// Maps from def-id of a type or region parameter to its
+    /// (inferred) variance.
+    pub item_variance_map: RefCell<DefIdMap<Rc<ty::ItemVariances>>>,
+
+    /// True if the variance has been computed yet; false otherwise.
+    pub variance_computed: Cell<bool>,
+
+    /// A method will be in this list if and only if it is a destructor.
+    pub destructors: RefCell<DefIdSet>,
+
+    /// Maps a DefId of a type to a list of its inherent impls.
+    /// Contains implementations of methods that are inherent to a type.
+    /// Methods in these implementations don't need to be exported.
+    pub inherent_impls: RefCell<DefIdMap<Rc<Vec<DefId>>>>,
+
+    /// Maps a DefId of an impl to a list of its items.
+    /// Note that this contains all of the impls that we know about,
+    /// including ones in other crates. It's not clear that this is the best
+    /// way to do it.
+    pub impl_items: RefCell<DefIdMap<Vec<ty::ImplOrTraitItemId>>>,
+
+    /// Set of used unsafe nodes (functions or blocks). Unsafe nodes not
+    /// present in this set can be warned about.
+    pub used_unsafe: RefCell<NodeSet>,
+
+    /// Set of nodes which mark locals as mutable which end up getting used at
+    /// some point. Local variable definitions not in this set can be warned
+    /// about.
+    pub used_mut_nodes: RefCell<NodeSet>,
+
+    /// The set of external nominal types whose implementations have been read.
+    /// This is used for lazy resolution of methods.
+    pub populated_external_types: RefCell<DefIdSet>,
+    /// The set of external primitive types whose implementations have been read.
+    /// FIXME(arielb1): why is this separate from populated_external_types?
+    pub populated_external_primitive_impls: RefCell<DefIdSet>,
+
+    /// These caches are used by const_eval when decoding external constants.
+    pub extern_const_statics: RefCell<DefIdMap<NodeId>>,
+    pub extern_const_variants: RefCell<DefIdMap<NodeId>>,
+    pub extern_const_fns: RefCell<DefIdMap<NodeId>>,
+
+    pub node_lint_levels: RefCell<FnvHashMap<(NodeId, lint::LintId),
+                                              lint::LevelSource>>,
+
+    /// The types that must be asserted to be the same size for `transmute`
+    /// to be valid. We gather up these restrictions in the intrinsicck pass
+    /// and check them in trans.
+    pub transmute_restrictions: RefCell<Vec<ty::TransmuteRestriction<'tcx>>>,
+
+    /// Maps any item's def-id to its stability index.
+    pub stability: RefCell<stability::Index<'tcx>>,
+
+    /// Caches the results of trait selection. This cache is used
+    /// for things that do not have to do with the parameters in scope.
+    pub selection_cache: traits::SelectionCache<'tcx>,
+
+    /// A set of predicates that have been fulfilled *somewhere*.
+    /// This is used to avoid duplicate work. Predicates are only
+    /// added to this set when they mention only "global" names
+    /// (i.e., no type or lifetime parameters).
+    pub fulfilled_predicates: RefCell<traits::FulfilledPredicates<'tcx>>,
+
+    /// Caches the representation hints for struct definitions.
+    pub repr_hint_cache: RefCell<DefIdMap<Rc<Vec<attr::ReprAttr>>>>,
+
+    /// Maps Expr NodeId's to their constant qualification.
+    pub const_qualif_map: RefCell<NodeMap<middle::check_const::ConstQualif>>,
+
+    /// Caches CoerceUnsized kinds for impls on custom types.
+    pub custom_coerce_unsized_kinds: RefCell<DefIdMap<ty::CustomCoerceUnsized>>,
+
+    /// Maps a cast expression to its kind. This is keyed on the
+    /// *from* expression of the cast, not the cast itself.
+    pub cast_kinds: RefCell<NodeMap<ty::cast::CastKind>>,
+
+    /// Maps Fn items to a collection of fragment infos.
+    ///
+    /// The main goal is to identify data (each of which may be moved
+    /// or assigned) whose subparts are not moved nor assigned
+    /// (i.e. their state is *unfragmented*) and corresponding ast
+    /// nodes where the path to that data is moved or assigned.
+    ///
+    /// In the long term, unfragmented values will have their
+    /// destructor entirely driven by a single stack-local drop-flag,
+    /// and their parents, the collections of the unfragmented values
+    /// (or more simply, "fragmented values"), are mapped to the
+    /// corresponding collections of stack-local drop-flags.
+    ///
+    /// (However, in the short term that is not the case; e.g. some
+    /// unfragmented paths still need to be zeroed, namely when they
+    /// reference parent data from an outer scope that was not
+    /// entirely moved, and therefore that needs to be zeroed so that
+    /// we do not get double-drop when we hit the end of the parent
+    /// scope.)
+    ///
+    /// Also: currently the table solely holds keys for node-ids of
+    /// unfragmented values (see `FragmentInfo` enum definition), but
+    /// longer-term we will need to also store mappings from
+    /// fragmented data to the set of unfragmented pieces that
+    /// constitute it.
+    pub fragment_infos: RefCell<DefIdMap<Vec<ty::FragmentInfo>>>,
+}
+impl<'tcx> ctxt<'tcx> {
+    pub fn closure_kind(&self, def_id: DefId) -> ty::ClosureKind {
+        *self.tables.borrow().closure_kinds.get(&def_id).unwrap()
+    }
+
+    pub fn closure_type(&self,
+                        def_id: DefId,
+                        substs: &ClosureSubsts<'tcx>)
+                        -> ty::ClosureTy<'tcx>
+    {
+        self.tables.borrow().closure_tys.get(&def_id).unwrap().subst(self, &substs.func_substs)
+    }
+
+    pub fn type_parameter_def(&self,
+                              node_id: NodeId)
+                              -> ty::TypeParameterDef<'tcx>
+    {
+        self.ty_param_defs.borrow().get(&node_id).unwrap().clone()
+    }
+
+    pub fn node_types(&self) -> Ref<NodeMap<Ty<'tcx>>> {
+        fn projection<'a, 'tcx>(tables: &'a Tables<'tcx>) -> &'a NodeMap<Ty<'tcx>> {
+            &tables.node_types
+        }
+
+        Ref::map(self.tables.borrow(), projection)
+    }
+
+    pub fn node_type_insert(&self, id: NodeId, ty: Ty<'tcx>) {
+        self.tables.borrow_mut().node_types.insert(id, ty);
+    }
+
+    pub fn intern_trait_def(&self, def: ty::TraitDef<'tcx>)
+                            -> &'tcx ty::TraitDef<'tcx> {
+        let did = def.trait_ref.def_id;
+        let interned = self.arenas.trait_defs.alloc(def);
+        self.trait_defs.borrow_mut().insert(did, interned);
+        interned
+    }
+
+    pub fn alloc_trait_def(&self, def: ty::TraitDef<'tcx>)
+                           -> &'tcx ty::TraitDef<'tcx> {
+        self.arenas.trait_defs.alloc(def)
+    }
+
+    pub fn intern_adt_def(&self,
+                          did: DefId,
+                          kind: ty::AdtKind,
+                          variants: Vec<ty::VariantDefData<'tcx, 'tcx>>)
+                          -> ty::AdtDefMaster<'tcx> {
+        let def = ty::AdtDefData::new(self, did, kind, variants);
+        let interned = self.arenas.adt_defs.alloc(def);
+        // this will need a transmute when reverse-variance is removed
+        self.adt_defs.borrow_mut().insert(did, interned);
+        interned
+    }
+
+    pub fn intern_stability(&self, stab: attr::Stability) -> &'tcx attr::Stability {
+        if let Some(st) = self.stability_interner.borrow().get(&stab) {
+            return st;
+        }
+
+        let interned = self.arenas.stability.alloc(stab);
+        self.stability_interner.borrow_mut().insert(interned, interned);
+        interned
+    }
+
+    pub fn store_free_region_map(&self, id: NodeId, map: FreeRegionMap) {
+        self.free_region_maps.borrow_mut()
+                             .insert(id, map);
+    }
+
+    pub fn free_region_map(&self, id: NodeId) -> FreeRegionMap {
+        self.free_region_maps.borrow()[&id].clone()
+    }
+
+    pub fn lift<T: ?Sized + Lift<'tcx>>(&self, value: &T) -> Option<T::Lifted> {
+        value.lift_to_tcx(self)
+    }
+
+    /// Create a type context and call the closure with a `&ty::ctxt` reference
+    /// to the context. The closure enforces that the type context and any interned
+    /// value (types, substs, etc.) can only be used while `ty::tls` has a valid
+    /// reference to the context, to allow formatting values that need it.
+    pub fn create_and_enter<F, R>(s: Session,
+                                 arenas: &'tcx CtxtArenas<'tcx>,
+                                 def_map: DefMap,
+                                 named_region_map: resolve_lifetime::NamedRegionMap,
+                                 map: ast_map::Map<'tcx>,
+                                 freevars: RefCell<FreevarMap>,
+                                 region_maps: RegionMaps,
+                                 lang_items: middle::lang_items::LanguageItems,
+                                 stability: stability::Index<'tcx>,
+                                 f: F) -> (Session, R)
+                                 where F: FnOnce(&ctxt<'tcx>) -> R
+    {
+        let interner = RefCell::new(FnvHashMap());
+        let common_types = CommonTypes::new(&arenas.type_, &interner);
+
+        tls::enter(ctxt {
+            arenas: arenas,
+            interner: interner,
+            substs_interner: RefCell::new(FnvHashMap()),
+            bare_fn_interner: RefCell::new(FnvHashMap()),
+            region_interner: RefCell::new(FnvHashMap()),
+            stability_interner: RefCell::new(FnvHashMap()),
+            types: common_types,
+            named_region_map: named_region_map,
+            region_maps: region_maps,
+            free_region_maps: RefCell::new(FnvHashMap()),
+            item_variance_map: RefCell::new(DefIdMap()),
+            variance_computed: Cell::new(false),
+            sess: s,
+            def_map: def_map,
+            tables: RefCell::new(Tables::empty()),
+            impl_trait_refs: RefCell::new(DefIdMap()),
+            trait_defs: RefCell::new(DefIdMap()),
+            adt_defs: RefCell::new(DefIdMap()),
+            predicates: RefCell::new(DefIdMap()),
+            super_predicates: RefCell::new(DefIdMap()),
+            fulfilled_predicates: RefCell::new(traits::FulfilledPredicates::new()),
+            map: map,
+            freevars: freevars,
+            tcache: RefCell::new(DefIdMap()),
+            rcache: RefCell::new(FnvHashMap()),
+            tc_cache: RefCell::new(FnvHashMap()),
+            ast_ty_to_ty_cache: RefCell::new(NodeMap()),
+            impl_or_trait_items: RefCell::new(DefIdMap()),
+            trait_item_def_ids: RefCell::new(DefIdMap()),
+            trait_items_cache: RefCell::new(DefIdMap()),
+            ty_param_defs: RefCell::new(NodeMap()),
+            normalized_cache: RefCell::new(FnvHashMap()),
+            lang_items: lang_items,
+            provided_method_sources: RefCell::new(DefIdMap()),
+            destructors: RefCell::new(DefIdSet()),
+            inherent_impls: RefCell::new(DefIdMap()),
+            impl_items: RefCell::new(DefIdMap()),
+            used_unsafe: RefCell::new(NodeSet()),
+            used_mut_nodes: RefCell::new(NodeSet()),
+            populated_external_types: RefCell::new(DefIdSet()),
+            populated_external_primitive_impls: RefCell::new(DefIdSet()),
+            extern_const_statics: RefCell::new(DefIdMap()),
+            extern_const_variants: RefCell::new(DefIdMap()),
+            extern_const_fns: RefCell::new(DefIdMap()),
+            node_lint_levels: RefCell::new(FnvHashMap()),
+            transmute_restrictions: RefCell::new(Vec::new()),
+            stability: RefCell::new(stability),
+            selection_cache: traits::SelectionCache::new(),
+            repr_hint_cache: RefCell::new(DefIdMap()),
+            const_qualif_map: RefCell::new(NodeMap()),
+            custom_coerce_unsized_kinds: RefCell::new(DefIdMap()),
+            cast_kinds: RefCell::new(NodeMap()),
+            fragment_infos: RefCell::new(DefIdMap()),
+       }, f)
+    }
+}
+
+/// A trait implemented for all X<'a> types which can be safely and
+/// efficiently converted to X<'tcx> as long as they are part of the
+/// provided ty::ctxt<'tcx>.
+/// This can be done, for example, for Ty<'tcx> or &'tcx Substs<'tcx>
+/// by looking them up in their respective interners.
+/// None is returned if the value or one of the components is not part
+/// of the provided context.
+/// For Ty, None can be returned if either the type interner doesn't
+/// contain the TypeVariants key or if the address of the interned
+/// pointer differs. The latter case is possible if a primitive type,
+/// e.g. `()` or `u8`, was interned in a different context.
+pub trait Lift<'tcx> {
+    type Lifted;
+    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted>;
+}
+
+impl<'a, 'tcx> Lift<'tcx> for Ty<'a> {
+    type Lifted = Ty<'tcx>;
+    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Ty<'tcx>> {
+        if let Some(&ty) = tcx.interner.borrow().get(&self.sty) {
+            if *self as *const _ == ty as *const _ {
+                return Some(ty);
+            }
+        }
+        None
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
+    type Lifted = &'tcx Substs<'tcx>;
+    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<&'tcx Substs<'tcx>> {
+        if let Some(&substs) = tcx.substs_interner.borrow().get(*self) {
+            if *self as *const _ == substs as *const _ {
+                return Some(substs);
+            }
+        }
+        None
+    }
+}
+
+
+pub mod tls {
+    use middle::ty;
+    use session::Session;
+
+    use std::fmt;
+    use syntax::codemap;
+
+    /// Marker type used for the scoped TLS slot.
+    /// The type context cannot be used directly because the scoped TLS
+    /// in libstd doesn't allow types generic over lifetimes.
+    struct ThreadLocalTyCx;
+
+    scoped_thread_local!(static TLS_TCX: ThreadLocalTyCx);
+
+    fn span_debug(span: codemap::Span, f: &mut fmt::Formatter) -> fmt::Result {
+        with(|tcx| {
+            write!(f, "{}", tcx.sess.codemap().span_to_string(span))
+        })
+    }
+
+    pub fn enter<'tcx, F: FnOnce(&ty::ctxt<'tcx>) -> R, R>(tcx: ty::ctxt<'tcx>, f: F)
+                                                           -> (Session, R) {
+        let result = codemap::SPAN_DEBUG.with(|span_dbg| {
+            let original_span_debug = span_dbg.get();
+            span_dbg.set(span_debug);
+            let tls_ptr = &tcx as *const _ as *const ThreadLocalTyCx;
+            let result = TLS_TCX.set(unsafe { &*tls_ptr }, || f(&tcx));
+            span_dbg.set(original_span_debug);
+            result
+        });
+        (tcx.sess, result)
+    }
+
+    pub fn with<F: FnOnce(&ty::ctxt) -> R, R>(f: F) -> R {
+        TLS_TCX.with(|tcx| f(unsafe { &*(tcx as *const _ as *const ty::ctxt) }))
+    }
+
+    pub fn with_opt<F: FnOnce(Option<&ty::ctxt>) -> R, R>(f: F) -> R {
+        if TLS_TCX.is_set() {
+            with(|v| f(Some(v)))
+        } else {
+            f(None)
+        }
+    }
+}
+
+macro_rules! sty_debug_print {
+    ($ctxt: expr, $($variant: ident),*) => {{
+        // curious inner module to allow variant names to be used as
+        // variable names.
+        #[allow(non_snake_case)]
+        mod inner {
+            use middle::ty;
+            #[derive(Copy, Clone)]
+            struct DebugStat {
+                total: usize,
+                region_infer: usize,
+                ty_infer: usize,
+                both_infer: usize,
+            }
+
+            pub fn go(tcx: &ty::ctxt) {
+                let mut total = DebugStat {
+                    total: 0,
+                    region_infer: 0, ty_infer: 0, both_infer: 0,
+                };
+                $(let mut $variant = total;)*
+
+
+                for (_, t) in tcx.interner.borrow().iter() {
+                    let variant = match t.sty {
+                        ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) |
+                            ty::TyFloat(..) | ty::TyStr => continue,
+                        ty::TyError => /* unimportant */ continue,
+                        $(ty::$variant(..) => &mut $variant,)*
+                    };
+                    let region = t.flags.get().intersects(ty::TypeFlags::HAS_RE_INFER);
+                    let ty = t.flags.get().intersects(ty::TypeFlags::HAS_TY_INFER);
+
+                    variant.total += 1;
+                    total.total += 1;
+                    if region { total.region_infer += 1; variant.region_infer += 1 }
+                    if ty { total.ty_infer += 1; variant.ty_infer += 1 }
+                    if region && ty { total.both_infer += 1; variant.both_infer += 1 }
+                }
+                println!("Ty interner             total           ty region  both");
+                $(println!("    {:18}: {uses:6} {usespc:4.1}%, \
+{ty:4.1}% {region:5.1}% {both:4.1}%",
+                           stringify!($variant),
+                           uses = $variant.total,
+                           usespc = $variant.total as f64 * 100.0 / total.total as f64,
+                           ty = $variant.ty_infer as f64 * 100.0  / total.total as f64,
+                           region = $variant.region_infer as f64 * 100.0  / total.total as f64,
+                           both = $variant.both_infer as f64 * 100.0  / total.total as f64);
+                  )*
+                println!("                  total {uses:6}        \
+{ty:4.1}% {region:5.1}% {both:4.1}%",
+                         uses = total.total,
+                         ty = total.ty_infer as f64 * 100.0  / total.total as f64,
+                         region = total.region_infer as f64 * 100.0  / total.total as f64,
+                         both = total.both_infer as f64 * 100.0  / total.total as f64)
+            }
+        }
+
+        inner::go($ctxt)
+    }}
+}
+
+impl<'tcx> ctxt<'tcx> {
+    pub fn print_debug_stats(&self) {
+        sty_debug_print!(
+            self,
+            TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyBareFn, TyTrait,
+            TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection);
+
+        println!("Substs interner: #{}", self.substs_interner.borrow().len());
+        println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len());
+        println!("Region interner: #{}", self.region_interner.borrow().len());
+        println!("Stability interner: #{}", self.stability_interner.borrow().len());
+    }
+}
+
+
+/// An entry in the type interner.
+pub struct InternedTy<'tcx> {
+    ty: Ty<'tcx>
+}
+
+// NB: An InternedTy compares and hashes as a sty.
+impl<'tcx> PartialEq for InternedTy<'tcx> {
+    fn eq(&self, other: &InternedTy<'tcx>) -> bool {
+        self.ty.sty == other.ty.sty
+    }
+}
+
+impl<'tcx> Eq for InternedTy<'tcx> {}
+
+impl<'tcx> Hash for InternedTy<'tcx> {
+    fn hash<H: Hasher>(&self, s: &mut H) {
+        self.ty.sty.hash(s)
+    }
+}
+
+impl<'tcx> Borrow<TypeVariants<'tcx>> for InternedTy<'tcx> {
+    fn borrow<'a>(&'a self) -> &'a TypeVariants<'tcx> {
+        &self.ty.sty
+    }
+}
+
+fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool {
+    bounds.is_empty() ||
+        bounds[1..].iter().enumerate().all(
+            |(index, bound)| bounds[index].sort_key() <= bound.sort_key())
+}
+
+impl<'tcx> ctxt<'tcx> {
+    // Type constructors
+    pub fn mk_substs(&self, substs: Substs<'tcx>) -> &'tcx Substs<'tcx> {
+        if let Some(substs) = self.substs_interner.borrow().get(&substs) {
+            return *substs;
+        }
+
+        let substs = self.arenas.substs.alloc(substs);
+        self.substs_interner.borrow_mut().insert(substs, substs);
+        substs
+    }
+
+    /// Create an unsafe fn ty based on a safe fn ty.
+    pub fn safe_to_unsafe_fn_ty(&self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> {
+        assert_eq!(bare_fn.unsafety, hir::Unsafety::Normal);
+        let unsafe_fn_ty_a = self.mk_bare_fn(ty::BareFnTy {
+            unsafety: hir::Unsafety::Unsafe,
+            abi: bare_fn.abi,
+            sig: bare_fn.sig.clone()
+        });
+        self.mk_fn(None, unsafe_fn_ty_a)
+    }
+
+    pub fn mk_bare_fn(&self, bare_fn: BareFnTy<'tcx>) -> &'tcx BareFnTy<'tcx> {
+        if let Some(bare_fn) = self.bare_fn_interner.borrow().get(&bare_fn) {
+            return *bare_fn;
+        }
+
+        let bare_fn = self.arenas.bare_fn.alloc(bare_fn);
+        self.bare_fn_interner.borrow_mut().insert(bare_fn, bare_fn);
+        bare_fn
+    }
+
+    pub fn mk_region(&self, region: Region) -> &'tcx Region {
+        if let Some(region) = self.region_interner.borrow().get(&region) {
+            return *region;
+        }
+
+        let region = self.arenas.region.alloc(region);
+        self.region_interner.borrow_mut().insert(region, region);
+        region
+    }
+
+    fn intern_ty(type_arena: &'tcx TypedArena<TyS<'tcx>>,
+                 interner: &RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>,
+                 st: TypeVariants<'tcx>)
+                 -> Ty<'tcx> {
+        let ty: Ty /* don't be &mut TyS */ = {
+            let mut interner = interner.borrow_mut();
+            match interner.get(&st) {
+                Some(ty) => return *ty,
+                _ => ()
+            }
+
+            let flags = super::flags::FlagComputation::for_sty(&st);
+
+            let ty = match () {
+                () => type_arena.alloc(TyS { sty: st,
+                                             flags: Cell::new(flags.flags),
+                                             region_depth: flags.depth, }),
+            };
+
+            interner.insert(InternedTy { ty: ty }, ty);
+            ty
+        };
+
+        debug!("Interned type: {:?} Pointer: {:?}",
+            ty, ty as *const TyS);
+        ty
+    }
+
+    // Interns a type/name combination, stores the resulting box in cx.interner,
+    // and returns the box as cast to an unsafe ptr (see comments for Ty above).
+    pub fn mk_ty(&self, st: TypeVariants<'tcx>) -> Ty<'tcx> {
+        ctxt::intern_ty(&self.arenas.type_, &self.interner, st)
+    }
+
+    pub fn mk_mach_int(&self, tm: hir::IntTy) -> Ty<'tcx> {
+        match tm {
+            hir::TyIs   => self.types.isize,
+            hir::TyI8   => self.types.i8,
+            hir::TyI16  => self.types.i16,
+            hir::TyI32  => self.types.i32,
+            hir::TyI64  => self.types.i64,
+        }
+    }
+
+    pub fn mk_mach_uint(&self, tm: hir::UintTy) -> Ty<'tcx> {
+        match tm {
+            hir::TyUs   => self.types.usize,
+            hir::TyU8   => self.types.u8,
+            hir::TyU16  => self.types.u16,
+            hir::TyU32  => self.types.u32,
+            hir::TyU64  => self.types.u64,
+        }
+    }
+
+    pub fn mk_mach_float(&self, tm: hir::FloatTy) -> Ty<'tcx> {
+        match tm {
+            hir::TyF32  => self.types.f32,
+            hir::TyF64  => self.types.f64,
+        }
+    }
+
+    pub fn mk_str(&self) -> Ty<'tcx> {
+        self.mk_ty(TyStr)
+    }
+
+    pub fn mk_static_str(&self) -> Ty<'tcx> {
+        self.mk_imm_ref(self.mk_region(ty::ReStatic), self.mk_str())
+    }
+
+    pub fn mk_enum(&self, def: AdtDef<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
+        // take a copy of substs so that we own the vectors inside
+        self.mk_ty(TyEnum(def, substs))
+    }
+
+    pub fn mk_box(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        self.mk_ty(TyBox(ty))
+    }
+
+    pub fn mk_ptr(&self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
+        self.mk_ty(TyRawPtr(tm))
+    }
+
+    pub fn mk_ref(&self, r: &'tcx Region, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
+        self.mk_ty(TyRef(r, tm))
+    }
+
+    pub fn mk_mut_ref(&self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> {
+        self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutMutable})
+    }
+
+    pub fn mk_imm_ref(&self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> {
+        self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutImmutable})
+    }
+
+    pub fn mk_mut_ptr(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutMutable})
+    }
+
+    pub fn mk_imm_ptr(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutImmutable})
+    }
+
+    pub fn mk_nil_ptr(&self) -> Ty<'tcx> {
+        self.mk_imm_ptr(self.mk_nil())
+    }
+
+    pub fn mk_array(&self, ty: Ty<'tcx>, n: usize) -> Ty<'tcx> {
+        self.mk_ty(TyArray(ty, n))
+    }
+
+    pub fn mk_slice(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        self.mk_ty(TySlice(ty))
+    }
+
+    pub fn mk_tup(&self, ts: Vec<Ty<'tcx>>) -> Ty<'tcx> {
+        self.mk_ty(TyTuple(ts))
+    }
+
+    pub fn mk_nil(&self) -> Ty<'tcx> {
+        self.mk_tup(Vec::new())
+    }
+
+    pub fn mk_bool(&self) -> Ty<'tcx> {
+        self.mk_ty(TyBool)
+    }
+
+    pub fn mk_fn(&self,
+                 opt_def_id: Option<DefId>,
+                 fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> {
+        self.mk_ty(TyBareFn(opt_def_id, fty))
+    }
+
+    pub fn mk_ctor_fn(&self,
+                      def_id: DefId,
+                      input_tys: &[Ty<'tcx>],
+                      output: Ty<'tcx>) -> Ty<'tcx> {
+        let input_args = input_tys.iter().cloned().collect();
+        self.mk_fn(Some(def_id), self.mk_bare_fn(BareFnTy {
+            unsafety: hir::Unsafety::Normal,
+            abi: abi::Rust,
+            sig: ty::Binder(ty::FnSig {
+                inputs: input_args,
+                output: ty::FnConverging(output),
+                variadic: false
+            })
+        }))
+    }
+
+    pub fn mk_trait(&self,
+                    principal: ty::PolyTraitRef<'tcx>,
+                    bounds: ExistentialBounds<'tcx>)
+                    -> Ty<'tcx>
+    {
+        assert!(bound_list_is_sorted(&bounds.projection_bounds));
+
+        let inner = box TraitTy {
+            principal: principal,
+            bounds: bounds
+        };
+        self.mk_ty(TyTrait(inner))
+    }
+
+    pub fn mk_projection(&self,
+                         trait_ref: TraitRef<'tcx>,
+                         item_name: Name)
+                         -> Ty<'tcx> {
+        // take a copy of substs so that we own the vectors inside
+        let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name };
+        self.mk_ty(TyProjection(inner))
+    }
+
+    pub fn mk_struct(&self, def: AdtDef<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
+        // take a copy of substs so that we own the vectors inside
+        self.mk_ty(TyStruct(def, substs))
+    }
+
+    pub fn mk_closure(&self,
+                      closure_id: DefId,
+                      substs: &'tcx Substs<'tcx>,
+                      tys: Vec<Ty<'tcx>>)
+                      -> Ty<'tcx> {
+        self.mk_closure_from_closure_substs(closure_id, Box::new(ClosureSubsts {
+            func_substs: substs,
+            upvar_tys: tys
+        }))
+    }
+
+    pub fn mk_closure_from_closure_substs(&self,
+                                          closure_id: DefId,
+                                          closure_substs: Box<ClosureSubsts<'tcx>>)
+                                          -> Ty<'tcx> {
+        self.mk_ty(TyClosure(closure_id, closure_substs))
+    }
+
+    pub fn mk_var(&self, v: TyVid) -> Ty<'tcx> {
+        self.mk_infer(TyVar(v))
+    }
+
+    pub fn mk_int_var(&self, v: IntVid) -> Ty<'tcx> {
+        self.mk_infer(IntVar(v))
+    }
+
+    pub fn mk_float_var(&self, v: FloatVid) -> Ty<'tcx> {
+        self.mk_infer(FloatVar(v))
+    }
+
+    pub fn mk_infer(&self, it: InferTy) -> Ty<'tcx> {
+        self.mk_ty(TyInfer(it))
+    }
+
+    pub fn mk_param(&self,
+                    space: subst::ParamSpace,
+                    index: u32,
+                    name: Name) -> Ty<'tcx> {
+        self.mk_ty(TyParam(ParamTy { space: space, idx: index, name: name }))
+    }
+
+    pub fn mk_self_type(&self) -> Ty<'tcx> {
+        self.mk_param(subst::SelfSpace, 0, special_idents::type_self.name)
+    }
+
+    pub fn mk_param_from_def(&self, def: &ty::TypeParameterDef) -> Ty<'tcx> {
+        self.mk_param(def.space, def.index, def.name)
+    }
+}
diff --git a/src/librustc/middle/ty/error.rs b/src/librustc/middle/ty/error.rs
new file mode 100644 (file)
index 0000000..72c4366
--- /dev/null
@@ -0,0 +1,342 @@
+// 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 middle::def_id::DefId;
+use middle::subst;
+use middle::infer::type_variable;
+use middle::ty::{self, BoundRegion, Region, Ty};
+
+use std::fmt;
+use syntax::abi;
+use syntax::ast::Name;
+use syntax::codemap::Span;
+
+use rustc_front::hir;
+
+#[derive(Clone, Copy, Debug)]
+pub struct ExpectedFound<T> {
+    pub expected: T,
+    pub found: T
+}
+
+// Data structures used in type unification
+#[derive(Clone, Debug)]
+pub enum TypeError<'tcx> {
+    Mismatch,
+    UnsafetyMismatch(ExpectedFound<hir::Unsafety>),
+    AbiMismatch(ExpectedFound<abi::Abi>),
+    Mutability,
+    BoxMutability,
+    PtrMutability,
+    RefMutability,
+    VecMutability,
+    TupleSize(ExpectedFound<usize>),
+    FixedArraySize(ExpectedFound<usize>),
+    TyParamSize(ExpectedFound<usize>),
+    ArgCount,
+    RegionsDoesNotOutlive(Region, Region),
+    RegionsNotSame(Region, Region),
+    RegionsNoOverlap(Region, Region),
+    RegionsInsufficientlyPolymorphic(BoundRegion, Region),
+    RegionsOverlyPolymorphic(BoundRegion, Region),
+    Sorts(ExpectedFound<Ty<'tcx>>),
+    IntegerAsChar,
+    IntMismatch(ExpectedFound<ty::IntVarValue>),
+    FloatMismatch(ExpectedFound<hir::FloatTy>),
+    Traits(ExpectedFound<DefId>),
+    BuiltinBoundsMismatch(ExpectedFound<ty::BuiltinBounds>),
+    VariadicMismatch(ExpectedFound<bool>),
+    CyclicTy,
+    ConvergenceMismatch(ExpectedFound<bool>),
+    ProjectionNameMismatched(ExpectedFound<Name>),
+    ProjectionBoundsLength(ExpectedFound<usize>),
+    TyParamDefaultMismatch(ExpectedFound<type_variable::Default<'tcx>>)
+}
+
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
+pub enum UnconstrainedNumeric {
+    UnconstrainedFloat,
+    UnconstrainedInt,
+    Neither,
+}
+
+/// Explains the source of a type err in a short, human readable way. This is meant to be placed
+/// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
+/// afterwards to present additional details, particularly when it comes to lifetime-related
+/// errors.
+impl<'tcx> fmt::Display for TypeError<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        use self::TypeError::*;
+        fn report_maybe_different(f: &mut fmt::Formatter,
+                                  expected: String, found: String) -> fmt::Result {
+            // A naive approach to making sure that we're not reporting silly errors such as:
+            // (expected closure, found closure).
+            if expected == found {
+                write!(f, "expected {}, found a different {}", expected, found)
+            } else {
+                write!(f, "expected {}, found {}", expected, found)
+            }
+        }
+
+        match *self {
+            CyclicTy => write!(f, "cyclic type of infinite size"),
+            Mismatch => write!(f, "types differ"),
+            UnsafetyMismatch(values) => {
+                write!(f, "expected {} fn, found {} fn",
+                       values.expected,
+                       values.found)
+            }
+            AbiMismatch(values) => {
+                write!(f, "expected {} fn, found {} fn",
+                       values.expected,
+                       values.found)
+            }
+            Mutability => write!(f, "values differ in mutability"),
+            BoxMutability => {
+                write!(f, "boxed values differ in mutability")
+            }
+            VecMutability => write!(f, "vectors differ in mutability"),
+            PtrMutability => write!(f, "pointers differ in mutability"),
+            RefMutability => write!(f, "references differ in mutability"),
+            TyParamSize(values) => {
+                write!(f, "expected a type with {} type params, \
+                           found one with {} type params",
+                       values.expected,
+                       values.found)
+            }
+            FixedArraySize(values) => {
+                write!(f, "expected an array with a fixed size of {} elements, \
+                           found one with {} elements",
+                       values.expected,
+                       values.found)
+            }
+            TupleSize(values) => {
+                write!(f, "expected a tuple with {} elements, \
+                           found one with {} elements",
+                       values.expected,
+                       values.found)
+            }
+            ArgCount => {
+                write!(f, "incorrect number of function parameters")
+            }
+            RegionsDoesNotOutlive(..) => {
+                write!(f, "lifetime mismatch")
+            }
+            RegionsNotSame(..) => {
+                write!(f, "lifetimes are not the same")
+            }
+            RegionsNoOverlap(..) => {
+                write!(f, "lifetimes do not intersect")
+            }
+            RegionsInsufficientlyPolymorphic(br, _) => {
+                write!(f, "expected bound lifetime parameter {}, \
+                           found concrete lifetime", br)
+            }
+            RegionsOverlyPolymorphic(br, _) => {
+                write!(f, "expected concrete lifetime, \
+                           found bound lifetime parameter {}", br)
+            }
+            Sorts(values) => ty::tls::with(|tcx| {
+                report_maybe_different(f, values.expected.sort_string(tcx),
+                                       values.found.sort_string(tcx))
+            }),
+            Traits(values) => ty::tls::with(|tcx| {
+                report_maybe_different(f,
+                                       format!("trait `{}`",
+                                               tcx.item_path_str(values.expected)),
+                                       format!("trait `{}`",
+                                               tcx.item_path_str(values.found)))
+            }),
+            BuiltinBoundsMismatch(values) => {
+                if values.expected.is_empty() {
+                    write!(f, "expected no bounds, found `{}`",
+                           values.found)
+                } else if values.found.is_empty() {
+                    write!(f, "expected bounds `{}`, found no bounds",
+                           values.expected)
+                } else {
+                    write!(f, "expected bounds `{}`, found bounds `{}`",
+                           values.expected,
+                           values.found)
+                }
+            }
+            IntegerAsChar => {
+                write!(f, "expected an integral type, found `char`")
+            }
+            IntMismatch(ref values) => {
+                write!(f, "expected `{:?}`, found `{:?}`",
+                       values.expected,
+                       values.found)
+            }
+            FloatMismatch(ref values) => {
+                write!(f, "expected `{:?}`, found `{:?}`",
+                       values.expected,
+                       values.found)
+            }
+            VariadicMismatch(ref values) => {
+                write!(f, "expected {} fn, found {} function",
+                       if values.expected { "variadic" } else { "non-variadic" },
+                       if values.found { "variadic" } else { "non-variadic" })
+            }
+            ConvergenceMismatch(ref values) => {
+                write!(f, "expected {} fn, found {} function",
+                       if values.expected { "converging" } else { "diverging" },
+                       if values.found { "converging" } else { "diverging" })
+            }
+            ProjectionNameMismatched(ref values) => {
+                write!(f, "expected {}, found {}",
+                       values.expected,
+                       values.found)
+            }
+            ProjectionBoundsLength(ref values) => {
+                write!(f, "expected {} associated type bindings, found {}",
+                       values.expected,
+                       values.found)
+            },
+            TyParamDefaultMismatch(ref values) => {
+                write!(f, "conflicting type parameter defaults `{}` and `{}`",
+                       values.expected.ty,
+                       values.found.ty)
+            }
+        }
+    }
+}
+
+impl<'tcx> ty::TyS<'tcx> {
+    fn sort_string(&self, cx: &ty::ctxt) -> String {
+        match self.sty {
+            ty::TyBool | ty::TyChar | ty::TyInt(_) |
+            ty::TyUint(_) | ty::TyFloat(_) | ty::TyStr => self.to_string(),
+            ty::TyTuple(ref tys) if tys.is_empty() => self.to_string(),
+
+            ty::TyEnum(def, _) => format!("enum `{}`", cx.item_path_str(def.did)),
+            ty::TyBox(_) => "box".to_string(),
+            ty::TyArray(_, n) => format!("array of {} elements", n),
+            ty::TySlice(_) => "slice".to_string(),
+            ty::TyRawPtr(_) => "*-ptr".to_string(),
+            ty::TyRef(_, _) => "&-ptr".to_string(),
+            ty::TyBareFn(Some(_), _) => format!("fn item"),
+            ty::TyBareFn(None, _) => "fn pointer".to_string(),
+            ty::TyTrait(ref inner) => {
+                format!("trait {}", cx.item_path_str(inner.principal_def_id()))
+            }
+            ty::TyStruct(def, _) => {
+                format!("struct `{}`", cx.item_path_str(def.did))
+            }
+            ty::TyClosure(..) => "closure".to_string(),
+            ty::TyTuple(_) => "tuple".to_string(),
+            ty::TyInfer(ty::TyVar(_)) => "inferred type".to_string(),
+            ty::TyInfer(ty::IntVar(_)) => "integral variable".to_string(),
+            ty::TyInfer(ty::FloatVar(_)) => "floating-point variable".to_string(),
+            ty::TyInfer(ty::FreshTy(_)) => "skolemized type".to_string(),
+            ty::TyInfer(ty::FreshIntTy(_)) => "skolemized integral type".to_string(),
+            ty::TyInfer(ty::FreshFloatTy(_)) => "skolemized floating-point type".to_string(),
+            ty::TyProjection(_) => "associated type".to_string(),
+            ty::TyParam(ref p) => {
+                if p.space == subst::SelfSpace {
+                    "Self".to_string()
+                } else {
+                    "type parameter".to_string()
+                }
+            }
+            ty::TyError => "type error".to_string(),
+        }
+    }
+}
+
+impl<'tcx> ty::ctxt<'tcx> {
+    pub fn note_and_explain_type_err(&self, err: &TypeError<'tcx>, sp: Span) {
+        use self::TypeError::*;
+
+        match err.clone() {
+            RegionsDoesNotOutlive(subregion, superregion) => {
+                self.note_and_explain_region("", subregion, "...");
+                self.note_and_explain_region("...does not necessarily outlive ",
+                                           superregion, "");
+            }
+            RegionsNotSame(region1, region2) => {
+                self.note_and_explain_region("", region1, "...");
+                self.note_and_explain_region("...is not the same lifetime as ",
+                                           region2, "");
+            }
+            RegionsNoOverlap(region1, region2) => {
+                self.note_and_explain_region("", region1, "...");
+                self.note_and_explain_region("...does not overlap ",
+                                           region2, "");
+            }
+            RegionsInsufficientlyPolymorphic(_, conc_region) => {
+                self.note_and_explain_region("concrete lifetime that was found is ",
+                                           conc_region, "");
+            }
+            RegionsOverlyPolymorphic(_, ty::ReVar(_)) => {
+                // don't bother to print out the message below for
+                // inference variables, it's not very illuminating.
+            }
+            RegionsOverlyPolymorphic(_, conc_region) => {
+                self.note_and_explain_region("expected concrete lifetime is ",
+                                           conc_region, "");
+            }
+            Sorts(values) => {
+                let expected_str = values.expected.sort_string(self);
+                let found_str = values.found.sort_string(self);
+                if expected_str == found_str && expected_str == "closure" {
+                    self.sess.span_note(sp,
+                        &format!("no two closures, even if identical, have the same type"));
+                    self.sess.span_help(sp,
+                        &format!("consider boxing your closure and/or \
+                                  using it as a trait object"));
+                }
+            },
+            TyParamDefaultMismatch(values) => {
+                let expected = values.expected;
+                let found = values.found;
+                self.sess.span_note(sp,
+                                    &format!("conflicting type parameter defaults `{}` and `{}`",
+                                             expected.ty,
+                                             found.ty));
+
+                match (expected.def_id.is_local(),
+                       self.map.opt_span(expected.def_id.node)) {
+                    (true, Some(span)) => {
+                        self.sess.span_note(span,
+                                            &format!("a default was defined here..."));
+                    }
+                    (_, _) => {
+                        self.sess.note(
+                            &format!("a default is defined on `{}`",
+                                     self.item_path_str(expected.def_id)));
+                    }
+                }
+
+                self.sess.span_note(
+                    expected.origin_span,
+                    &format!("...that was applied to an unconstrained type variable here"));
+
+                match (found.def_id.is_local(),
+                       self.map.opt_span(found.def_id.node)) {
+                    (true, Some(span)) => {
+                        self.sess.span_note(span,
+                                            &format!("a second default was defined here..."));
+                    }
+                    (_, _) => {
+                        self.sess.note(
+                            &format!("a second default is defined on `{}`",
+                                     self.item_path_str(found.def_id)));
+                    }
+                }
+
+                self.sess.span_note(
+                    found.origin_span,
+                    &format!("...that also applies to the same type variable here"));
+            }
+            _ => {}
+        }
+    }
+}
diff --git a/src/librustc/middle/ty/flags.rs b/src/librustc/middle/ty/flags.rs
new file mode 100644 (file)
index 0000000..94a50e3
--- /dev/null
@@ -0,0 +1,205 @@
+// 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 middle::subst;
+use middle::ty::{self, HasTypeFlags, Ty, TypeFlags};
+
+pub struct FlagComputation {
+    pub flags: TypeFlags,
+
+    // maximum depth of any bound region that we have seen thus far
+    pub depth: u32,
+}
+
+impl FlagComputation {
+    fn new() -> FlagComputation {
+        FlagComputation { flags: TypeFlags::empty(), depth: 0 }
+    }
+
+    pub fn for_sty(st: &ty::TypeVariants) -> FlagComputation {
+        let mut result = FlagComputation::new();
+        result.add_sty(st);
+        result
+    }
+
+    fn add_flags(&mut self, flags: TypeFlags) {
+        self.flags = self.flags | (flags & TypeFlags::NOMINAL_FLAGS);
+    }
+
+    fn add_depth(&mut self, depth: u32) {
+        if depth > self.depth {
+            self.depth = depth;
+        }
+    }
+
+    /// Adds the flags/depth from a set of types that appear within the current type, but within a
+    /// region binder.
+    fn add_bound_computation(&mut self, computation: &FlagComputation) {
+        self.add_flags(computation.flags);
+
+        // The types that contributed to `computation` occurred within
+        // a region binder, so subtract one from the region depth
+        // within when adding the depth to `self`.
+        let depth = computation.depth;
+        if depth > 0 {
+            self.add_depth(depth - 1);
+        }
+    }
+
+    fn add_sty(&mut self, st: &ty::TypeVariants) {
+        match st {
+            &ty::TyBool |
+            &ty::TyChar |
+            &ty::TyInt(_) |
+            &ty::TyFloat(_) |
+            &ty::TyUint(_) |
+            &ty::TyStr => {
+            }
+
+            // You might think that we could just return TyError for
+            // any type containing TyError as a component, and get
+            // rid of the TypeFlags::HAS_TY_ERR flag -- likewise for ty_bot (with
+            // the exception of function types that return bot).
+            // But doing so caused sporadic memory corruption, and
+            // neither I (tjc) nor nmatsakis could figure out why,
+            // so we're doing it this way.
+            &ty::TyError => {
+                self.add_flags(TypeFlags::HAS_TY_ERR)
+            }
+
+            &ty::TyParam(ref p) => {
+                self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
+                if p.space == subst::SelfSpace {
+                    self.add_flags(TypeFlags::HAS_SELF);
+                } else {
+                    self.add_flags(TypeFlags::HAS_PARAMS);
+                }
+            }
+
+            &ty::TyClosure(_, ref substs) => {
+                self.add_flags(TypeFlags::HAS_TY_CLOSURE);
+                self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
+                self.add_substs(&substs.func_substs);
+                self.add_tys(&substs.upvar_tys);
+            }
+
+            &ty::TyInfer(_) => {
+                self.add_flags(TypeFlags::HAS_LOCAL_NAMES); // it might, right?
+                self.add_flags(TypeFlags::HAS_TY_INFER)
+            }
+
+            &ty::TyEnum(_, substs) | &ty::TyStruct(_, substs) => {
+                self.add_substs(substs);
+            }
+
+            &ty::TyProjection(ref data) => {
+                self.add_flags(TypeFlags::HAS_PROJECTION);
+                self.add_projection_ty(data);
+            }
+
+            &ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => {
+                let mut computation = FlagComputation::new();
+                computation.add_substs(principal.0.substs);
+                for projection_bound in &bounds.projection_bounds {
+                    let mut proj_computation = FlagComputation::new();
+                    proj_computation.add_projection_predicate(&projection_bound.0);
+                    self.add_bound_computation(&proj_computation);
+                }
+                self.add_bound_computation(&computation);
+
+                self.add_bounds(bounds);
+            }
+
+            &ty::TyBox(tt) | &ty::TyArray(tt, _) | &ty::TySlice(tt) => {
+                self.add_ty(tt)
+            }
+
+            &ty::TyRawPtr(ref m) => {
+                self.add_ty(m.ty);
+            }
+
+            &ty::TyRef(r, ref m) => {
+                self.add_region(*r);
+                self.add_ty(m.ty);
+            }
+
+            &ty::TyTuple(ref ts) => {
+                self.add_tys(&ts[..]);
+            }
+
+            &ty::TyBareFn(_, ref f) => {
+                self.add_fn_sig(&f.sig);
+            }
+        }
+    }
+
+    fn add_ty(&mut self, ty: Ty) {
+        self.add_flags(ty.flags.get());
+        self.add_depth(ty.region_depth);
+    }
+
+    fn add_tys(&mut self, tys: &[Ty]) {
+        for &ty in tys {
+            self.add_ty(ty);
+        }
+    }
+
+    fn add_fn_sig(&mut self, fn_sig: &ty::PolyFnSig) {
+        let mut computation = FlagComputation::new();
+
+        computation.add_tys(&fn_sig.0.inputs);
+
+        if let ty::FnConverging(output) = fn_sig.0.output {
+            computation.add_ty(output);
+        }
+
+        self.add_bound_computation(&computation);
+    }
+
+    fn add_region(&mut self, r: ty::Region) {
+        match r {
+            ty::ReVar(..) |
+            ty::ReSkolemized(..) => { self.add_flags(TypeFlags::HAS_RE_INFER); }
+            ty::ReLateBound(debruijn, _) => { self.add_depth(debruijn.depth); }
+            ty::ReEarlyBound(..) => { self.add_flags(TypeFlags::HAS_RE_EARLY_BOUND); }
+            ty::ReStatic => {}
+            _ => { self.add_flags(TypeFlags::HAS_FREE_REGIONS); }
+        }
+
+        if !r.is_global() {
+            self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
+        }
+    }
+
+    fn add_projection_predicate(&mut self, projection_predicate: &ty::ProjectionPredicate) {
+        self.add_projection_ty(&projection_predicate.projection_ty);
+        self.add_ty(projection_predicate.ty);
+    }
+
+    fn add_projection_ty(&mut self, projection_ty: &ty::ProjectionTy) {
+        self.add_substs(projection_ty.trait_ref.substs);
+    }
+
+    fn add_substs(&mut self, substs: &subst::Substs) {
+        self.add_tys(substs.types.as_slice());
+        match substs.regions {
+            subst::ErasedRegions => {}
+            subst::NonerasedRegions(ref regions) => {
+                for &r in regions {
+                    self.add_region(r);
+                }
+            }
+        }
+    }
+
+    fn add_bounds(&mut self, bounds: &ty::ExistentialBounds) {
+        self.add_region(bounds.region_bound);
+    }
+}
index c6d213583af20173cd367bee82715a715bad4a82..9de58369a63f8c68cff6276b6cb7f91261b1bd0b 100644 (file)
 //! If you ever *do* need an override that doesn't exist, it's not hard
 //! to convert the degenerate pattern into the proper thing.
 
+use middle::region;
 use middle::subst;
-use middle::subst::VecPerParamSpace;
-use middle::ty::{self, Ty, HasTypeFlags, RegionEscape};
-use middle::traits;
+use middle::ty::{self, Binder, Ty, HasTypeFlags, RegionEscape};
 
 use std::fmt;
-use std::rc::Rc;
-use syntax::abi;
-use rustc_front::hir;
-use syntax::owned_slice::OwnedSlice;
 use util::nodemap::{FnvHashMap, FnvHashSet};
 
 ///////////////////////////////////////////////////////////////////////////
@@ -74,7 +69,7 @@ fn enter_region_binder(&mut self) { }
     /// track the Debruijn index nesting level.
     fn exit_region_binder(&mut self) { }
 
-    fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
+    fn fold_binder<T>(&mut self, t: &Binder<T>) -> Binder<T>
         where T : TypeFoldable<'tcx>
     {
         // FIXME(#20526) this should replace `enter_region_binder`/`exit_region_binder`.
@@ -142,428 +137,18 @@ fn fold_item_substs(&mut self, i: ty::ItemSubsts<'tcx>) -> ty::ItemSubsts<'tcx>
     }
 }
 
-///////////////////////////////////////////////////////////////////////////
-// TypeFoldable implementations.
-//
-// Ideally, each type should invoke `folder.fold_foo(self)` and
-// nothing else. In some cases, though, we haven't gotten around to
-// adding methods on the `folder` yet, and thus the folding is
-// hard-coded here. This is less-flexible, because folders cannot
-// override the behavior, but there are a lot of random types and one
-// can easily refactor the folding into the TypeFolder trait as
-// needed.
-
-macro_rules! CopyImpls {
-    ($($ty:ty),+) => {
-        $(
-            impl<'tcx> TypeFoldable<'tcx> for $ty {
-                fn fold_with<F:TypeFolder<'tcx>>(&self, _: &mut F) -> $ty {
-                    *self
-                }
-            }
-        )+
-    }
-}
-
-CopyImpls! { (), hir::Unsafety, abi::Abi }
-
-impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) {
-    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> (T, U) {
-        (self.0.fold_with(folder), self.1.fold_with(folder))
-    }
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Option<T> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Option<T> {
-        self.as_ref().map(|t| t.fold_with(folder))
-    }
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Rc<T> {
-        Rc::new((**self).fold_with(folder))
-    }
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Box<T> {
-        let content: T = (**self).fold_with(folder);
-        box content
-    }
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Vec<T> {
-        self.iter().map(|t| t.fold_with(folder)).collect()
-    }
-}
-
-impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Binder<T> {
-        folder.fold_binder(self)
-    }
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for OwnedSlice<T> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> OwnedSlice<T> {
-        self.iter().map(|t| t.fold_with(folder)).collect()
-    }
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for VecPerParamSpace<T> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> VecPerParamSpace<T> {
-
-        // Things in the Fn space take place under an additional level
-        // of region binding relative to the other spaces. This is
-        // because those entries are attached to a method, and methods
-        // always introduce a level of region binding.
-
-        let result = self.map_enumerated(|(space, index, elem)| {
-            if space == subst::FnSpace && index == 0 {
-                // enter new level when/if we reach the first thing in fn space
-                folder.enter_region_binder();
-            }
-            elem.fold_with(folder)
-        });
-        if result.len(subst::FnSpace) > 0 {
-            // if there was anything in fn space, exit the region binding level
-            folder.exit_region_binder();
-        }
-        result
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Ty<'tcx> {
-        folder.fold_ty(*self)
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::BareFnTy<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::BareFnTy<'tcx> {
-        folder.fold_bare_fn_ty(self)
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::ClosureTy<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ClosureTy<'tcx> {
-        folder.fold_closure_ty(self)
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::TypeAndMut<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TypeAndMut<'tcx> {
-        folder.fold_mt(self)
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::FnOutput<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::FnOutput<'tcx> {
-        folder.fold_output(self)
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::FnSig<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::FnSig<'tcx> {
-        folder.fold_fn_sig(self)
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::TraitRef<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TraitRef<'tcx> {
-        folder.fold_trait_ref(self)
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::Region {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Region {
-        folder.fold_region(*self)
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for subst::Substs<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> subst::Substs<'tcx> {
-        folder.fold_substs(self)
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::ClosureSubsts<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ClosureSubsts<'tcx> {
-        let func_substs = self.func_substs.fold_with(folder);
-        ty::ClosureSubsts {
-            func_substs: folder.tcx().mk_substs(func_substs),
-            upvar_tys: self.upvar_tys.fold_with(folder),
-        }
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::ItemSubsts<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ItemSubsts<'tcx> {
-        ty::ItemSubsts {
-            substs: self.substs.fold_with(folder),
-        }
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::AutoRef<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::AutoRef<'tcx> {
-        folder.fold_autoref(self)
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::BuiltinBounds {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, _folder: &mut F) -> ty::BuiltinBounds {
-        *self
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ExistentialBounds<'tcx> {
-        folder.fold_existential_bounds(self)
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TypeParameterDef<'tcx> {
-        ty::TypeParameterDef {
-            name: self.name,
-            def_id: self.def_id,
-            space: self.space,
-            index: self.index,
-            default: self.default.fold_with(folder),
-            default_def_id: self.default_def_id,
-            object_lifetime_default: self.object_lifetime_default.fold_with(folder),
-        }
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::ObjectLifetimeDefault {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ObjectLifetimeDefault {
-        match *self {
-            ty::ObjectLifetimeDefault::Ambiguous =>
-                ty::ObjectLifetimeDefault::Ambiguous,
-
-            ty::ObjectLifetimeDefault::BaseDefault =>
-                ty::ObjectLifetimeDefault::BaseDefault,
-
-            ty::ObjectLifetimeDefault::Specific(r) =>
-                ty::ObjectLifetimeDefault::Specific(r.fold_with(folder)),
-        }
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::RegionParameterDef {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::RegionParameterDef {
-        ty::RegionParameterDef {
-            name: self.name,
-            def_id: self.def_id,
-            space: self.space,
-            index: self.index,
-            bounds: self.bounds.fold_with(folder)
-        }
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::Generics<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Generics<'tcx> {
-        ty::Generics {
-            types: self.types.fold_with(folder),
-            regions: self.regions.fold_with(folder),
-        }
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::GenericPredicates<'tcx> {
-        ty::GenericPredicates {
-            predicates: self.predicates.fold_with(folder),
-        }
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Predicate<'tcx> {
-        match *self {
-            ty::Predicate::Trait(ref a) =>
-                ty::Predicate::Trait(a.fold_with(folder)),
-            ty::Predicate::Equate(ref binder) =>
-                ty::Predicate::Equate(binder.fold_with(folder)),
-            ty::Predicate::RegionOutlives(ref binder) =>
-                ty::Predicate::RegionOutlives(binder.fold_with(folder)),
-            ty::Predicate::TypeOutlives(ref binder) =>
-                ty::Predicate::TypeOutlives(binder.fold_with(folder)),
-            ty::Predicate::Projection(ref binder) =>
-                ty::Predicate::Projection(binder.fold_with(folder)),
-            ty::Predicate::WellFormed(data) =>
-                ty::Predicate::WellFormed(data.fold_with(folder)),
-            ty::Predicate::ObjectSafe(trait_def_id) =>
-                ty::Predicate::ObjectSafe(trait_def_id),
-        }
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionPredicate<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ProjectionPredicate<'tcx> {
-        ty::ProjectionPredicate {
-            projection_ty: self.projection_ty.fold_with(folder),
-            ty: self.ty.fold_with(folder),
-        }
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ProjectionTy<'tcx> {
-        ty::ProjectionTy {
-            trait_ref: self.trait_ref.fold_with(folder),
-            item_name: self.item_name,
-        }
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::InstantiatedPredicates<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::InstantiatedPredicates<'tcx> {
-        ty::InstantiatedPredicates {
-            predicates: self.predicates.fold_with(folder),
-        }
-    }
-}
-
-impl<'tcx,O> TypeFoldable<'tcx> for traits::Obligation<'tcx,O>
-    where O : TypeFoldable<'tcx>
-{
-    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Obligation<'tcx, O> {
-        traits::Obligation {
-            cause: self.cause.clone(),
-            recursion_depth: self.recursion_depth,
-            predicate: self.predicate.fold_with(folder),
-        }
-    }
-}
-
-impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableImplData<'tcx, N> {
-    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableImplData<'tcx, N> {
-        traits::VtableImplData {
-            impl_def_id: self.impl_def_id,
-            substs: self.substs.fold_with(folder),
-            nested: self.nested.fold_with(folder),
-        }
-    }
-}
-
-impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableClosureData<'tcx, N> {
-    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableClosureData<'tcx, N> {
-        traits::VtableClosureData {
-            closure_def_id: self.closure_def_id,
-            substs: self.substs.fold_with(folder),
-            nested: self.nested.fold_with(folder),
-        }
-    }
-}
-
-impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableDefaultImplData<N> {
-    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableDefaultImplData<N> {
-        traits::VtableDefaultImplData {
-            trait_def_id: self.trait_def_id,
-            nested: self.nested.fold_with(folder),
-        }
-    }
-}
-
-impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableBuiltinData<N> {
-    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableBuiltinData<N> {
-        traits::VtableBuiltinData {
-            nested: self.nested.fold_with(folder),
-        }
-    }
-}
-
-impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> {
-    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Vtable<'tcx, N> {
-        match *self {
-            traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)),
-            traits::VtableDefaultImpl(ref t) => traits::VtableDefaultImpl(t.fold_with(folder)),
-            traits::VtableClosure(ref d) => {
-                traits::VtableClosure(d.fold_with(folder))
-            }
-            traits::VtableFnPointer(ref d) => {
-                traits::VtableFnPointer(d.fold_with(folder))
-            }
-            traits::VtableParam(ref n) => traits::VtableParam(n.fold_with(folder)),
-            traits::VtableBuiltin(ref d) => traits::VtableBuiltin(d.fold_with(folder)),
-            traits::VtableObject(ref d) => traits::VtableObject(d.fold_with(folder)),
-        }
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx> {
-    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableObjectData<'tcx> {
-        traits::VtableObjectData {
-            upcast_trait_ref: self.upcast_trait_ref.fold_with(folder),
-            vtable_base: self.vtable_base
-        }
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::EquatePredicate<'tcx> {
-    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::EquatePredicate<'tcx> {
-        ty::EquatePredicate(self.0.fold_with(folder),
-                            self.1.fold_with(folder))
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::TraitPredicate<'tcx> {
-    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TraitPredicate<'tcx> {
-        ty::TraitPredicate {
-            trait_ref: self.trait_ref.fold_with(folder)
-        }
-    }
-}
-
-impl<'tcx,T,U> TypeFoldable<'tcx> for ty::OutlivesPredicate<T,U>
-    where T : TypeFoldable<'tcx>,
-          U : TypeFoldable<'tcx>,
-{
-    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::OutlivesPredicate<T,U> {
-        ty::OutlivesPredicate(self.0.fold_with(folder),
-                              self.1.fold_with(folder))
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::ClosureUpvar<'tcx> {
-    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ClosureUpvar<'tcx> {
-        ty::ClosureUpvar {
-            def: self.def,
-            span: self.span,
-            ty: self.ty.fold_with(folder),
-        }
-    }
-}
-
-impl<'a, 'tcx> TypeFoldable<'tcx> for ty::ParameterEnvironment<'a, 'tcx> where 'tcx: 'a {
-    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ParameterEnvironment<'a, 'tcx> {
-        ty::ParameterEnvironment {
-            tcx: self.tcx,
-            free_substs: self.free_substs.fold_with(folder),
-            implicit_region_bound: self.implicit_region_bound.fold_with(folder),
-            caller_bounds: self.caller_bounds.fold_with(folder),
-            selection_cache: traits::SelectionCache::new(),
-            free_id: self.free_id,
-        }
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // "super" routines: these are the default implementations for TypeFolder.
 //
 // They should invoke `foo.fold_with()` to do recursive folding.
 
 pub fn super_fold_binder<'tcx, T, U>(this: &mut T,
-                                     binder: &ty::Binder<U>)
-                                     -> ty::Binder<U>
+                                     binder: &Binder<U>)
+                                     -> Binder<U>
     where T : TypeFolder<'tcx>, U : TypeFoldable<'tcx>
 {
     this.enter_region_binder();
-    let result = ty::Binder(binder.0.fold_with(this));
+    let result = Binder(binder.0.fold_with(this));
     this.exit_region_binder();
     result
 }
@@ -754,6 +339,36 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
 ///////////////////////////////////////////////////////////////////////////
 // Region folder
 
+impl<'tcx> ty::ctxt<'tcx> {
+    /// Collects the free and escaping regions in `value` into `region_set`. Returns
+    /// whether any late-bound regions were skipped
+    pub fn collect_regions<T>(&self,
+        value: &T,
+        region_set: &mut FnvHashSet<ty::Region>)
+        -> bool
+        where T : TypeFoldable<'tcx>
+    {
+        let mut have_bound_regions = false;
+        self.fold_regions(value, &mut have_bound_regions,
+                          |r, d| { region_set.insert(r.from_depth(d)); r });
+        have_bound_regions
+    }
+
+    /// Folds the escaping and free regions in `value` using `f`, and
+    /// sets `skipped_regions` to true if any late-bound region was found
+    /// and skipped.
+    pub fn fold_regions<T,F>(&self,
+        value: &T,
+        skipped_regions: &mut bool,
+        mut f: F)
+        -> T
+        where F : FnMut(ty::Region, u32) -> ty::Region,
+              T : TypeFoldable<'tcx>,
+    {
+        value.fold_with(&mut RegionFolder::new(self, skipped_regions, &mut f))
+    }
+}
+
 /// Folds over the substructure of a type, visiting its component
 /// types and all regions that occur *free* within it.
 ///
@@ -785,33 +400,6 @@ pub fn new<F>(tcx: &'a ty::ctxt<'tcx>,
     }
 }
 
-/// Collects the free and escaping regions in `value` into `region_set`. Returns
-/// whether any late-bound regions were skipped
-pub fn collect_regions<'tcx,T>(tcx: &ty::ctxt<'tcx>,
-                               value: &T,
-                               region_set: &mut FnvHashSet<ty::Region>) -> bool
-    where T : TypeFoldable<'tcx>
-{
-    let mut have_bound_regions = false;
-    fold_regions(tcx, value, &mut have_bound_regions,
-                 |r, d| { region_set.insert(r.from_depth(d)); r });
-    have_bound_regions
-}
-
-/// Folds the escaping and free regions in `value` using `f`, and
-/// sets `skipped_regions` to true if any late-bound region was found
-/// and skipped.
-pub fn fold_regions<'tcx,T,F>(tcx: &ty::ctxt<'tcx>,
-                              value: &T,
-                              skipped_regions: &mut bool,
-                              mut f: F)
-                              -> T
-    where F : FnMut(ty::Region, u32) -> ty::Region,
-          T : TypeFoldable<'tcx>,
-{
-    value.fold_with(&mut RegionFolder::new(tcx, skipped_regions, &mut f))
-}
-
 impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx>
 {
     fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
@@ -853,6 +441,94 @@ struct RegionReplacer<'a, 'tcx: 'a> {
     map: FnvHashMap<ty::BoundRegion, ty::Region>
 }
 
+impl<'tcx> ty::ctxt<'tcx> {
+    pub fn replace_late_bound_regions<T,F>(&self,
+        value: &Binder<T>,
+        mut f: F)
+        -> (T, FnvHashMap<ty::BoundRegion, ty::Region>)
+        where F : FnMut(ty::BoundRegion) -> ty::Region,
+              T : TypeFoldable<'tcx>,
+    {
+        debug!("replace_late_bound_regions({:?})", value);
+        let mut replacer = RegionReplacer::new(self, &mut f);
+        let result = value.skip_binder().fold_with(&mut replacer);
+        (result, replacer.map)
+    }
+
+
+    /// Replace any late-bound regions bound in `value` with free variants attached to scope-id
+    /// `scope_id`.
+    pub fn liberate_late_bound_regions<T>(&self,
+        all_outlive_scope: region::CodeExtent,
+        value: &Binder<T>)
+        -> T
+        where T : TypeFoldable<'tcx>
+    {
+        self.replace_late_bound_regions(value, |br| {
+            ty::ReFree(ty::FreeRegion{scope: all_outlive_scope, bound_region: br})
+        }).0
+    }
+
+    /// Flattens two binding levels into one. So `for<'a> for<'b> Foo`
+    /// becomes `for<'a,'b> Foo`.
+    pub fn flatten_late_bound_regions<T>(&self, bound2_value: &Binder<Binder<T>>)
+                                         -> Binder<T>
+        where T: TypeFoldable<'tcx>
+    {
+        let bound0_value = bound2_value.skip_binder().skip_binder();
+        let value = self.fold_regions(bound0_value, &mut false,
+                                      |region, current_depth| {
+            match region {
+                ty::ReLateBound(debruijn, br) if debruijn.depth >= current_depth => {
+                    // should be true if no escaping regions from bound2_value
+                    assert!(debruijn.depth - current_depth <= 1);
+                    ty::ReLateBound(ty::DebruijnIndex::new(current_depth), br)
+                }
+                _ => {
+                    region
+                }
+            }
+        });
+        Binder(value)
+    }
+
+    pub fn no_late_bound_regions<T>(&self, value: &Binder<T>) -> Option<T>
+        where T : TypeFoldable<'tcx> + RegionEscape
+    {
+        if value.0.has_escaping_regions() {
+            None
+        } else {
+            Some(value.0.clone())
+        }
+    }
+
+    /// Replace any late-bound regions bound in `value` with `'static`. Useful in trans but also
+    /// method lookup and a few other places where precise region relationships are not required.
+    pub fn erase_late_bound_regions<T>(&self, value: &Binder<T>) -> T
+        where T : TypeFoldable<'tcx>
+    {
+        self.replace_late_bound_regions(value, |_| ty::ReStatic).0
+    }
+
+    /// Rewrite any late-bound regions so that they are anonymous.  Region numbers are
+    /// assigned starting at 1 and increasing monotonically in the order traversed
+    /// by the fold operation.
+    ///
+    /// The chief purpose of this function is to canonicalize regions so that two
+    /// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become
+    /// structurally identical.  For example, `for<'a, 'b> fn(&'a isize, &'b isize)` and
+    /// `for<'a, 'b> fn(&'b isize, &'a isize)` will become identical after anonymization.
+    pub fn anonymize_late_bound_regions<T>(&self, sig: &Binder<T>) -> Binder<T>
+        where T : TypeFoldable<'tcx>,
+    {
+        let mut counter = 0;
+        Binder(self.replace_late_bound_regions(sig, |_| {
+            counter += 1;
+            ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(counter))
+        }).0)
+    }
+}
+
 impl<'a, 'tcx> RegionReplacer<'a, 'tcx> {
     fn new<F>(tcx: &'a ty::ctxt<'tcx>, fld_r: &'a mut F) -> RegionReplacer<'a, 'tcx>
         where F : FnMut(ty::BoundRegion) -> ty::Region
@@ -866,19 +542,6 @@ fn new<F>(tcx: &'a ty::ctxt<'tcx>, fld_r: &'a mut F) -> RegionReplacer<'a, 'tcx>
     }
 }
 
-pub fn replace_late_bound_regions<'tcx,T,F>(tcx: &ty::ctxt<'tcx>,
-                                            value: &ty::Binder<T>,
-                                            mut f: F)
-                                            -> (T, FnvHashMap<ty::BoundRegion, ty::Region>)
-    where F : FnMut(ty::BoundRegion) -> ty::Region,
-          T : TypeFoldable<'tcx>,
-{
-    debug!("replace_late_bound_regions({:?})", value);
-    let mut replacer = RegionReplacer::new(tcx, &mut f);
-    let result = value.skip_binder().fold_with(&mut replacer);
-    (result, replacer.map)
-}
-
 impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx>
 {
     fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
diff --git a/src/librustc/middle/ty/ivar.rs b/src/librustc/middle/ty/ivar.rs
new file mode 100644 (file)
index 0000000..73d567d
--- /dev/null
@@ -0,0 +1,72 @@
+// Copyright 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 middle::ty::{Ty, TyS};
+
+use rustc_data_structures::ivar;
+
+use std::fmt;
+use std::marker::PhantomData;
+use core::nonzero::NonZero;
+
+/// An IVar that contains a Ty. 'lt is a (reverse-variant) upper bound
+/// on the lifetime of the IVar. This is required because of variance
+/// problems: the IVar needs to be variant with respect to 'tcx (so
+/// it can be referred to from Ty) but can only be modified if its
+/// lifetime is exactly 'tcx.
+///
+/// Safety invariants:
+///     (A) self.0, if fulfilled, is a valid Ty<'tcx>
+///     (B) no aliases to this value with a 'tcx longer than this
+///         value's 'lt exist
+///
+/// NonZero is used rather than Unique because Unique isn't Copy.
+pub struct TyIVar<'tcx, 'lt: 'tcx>(ivar::Ivar<NonZero<*const TyS<'static>>>,
+                                   PhantomData<fn(TyS<'lt>)->TyS<'tcx>>);
+
+impl<'tcx, 'lt> TyIVar<'tcx, 'lt> {
+    #[inline]
+    pub fn new() -> Self {
+        // Invariant (A) satisfied because the IVar is unfulfilled
+        // Invariant (B) because 'lt : 'tcx
+        TyIVar(ivar::Ivar::new(), PhantomData)
+    }
+
+    #[inline]
+    pub fn get(&self) -> Option<Ty<'tcx>> {
+        match self.0.get() {
+            None => None,
+            // valid because of invariant (A)
+            Some(v) => Some(unsafe { &*(*v as *const TyS<'tcx>) })
+        }
+    }
+    #[inline]
+    pub fn unwrap(&self) -> Ty<'tcx> {
+        self.get().unwrap()
+    }
+
+    pub fn fulfill(&self, value: Ty<'lt>) {
+        // Invariant (A) is fulfilled, because by (B), every alias
+        // of this has a 'tcx longer than 'lt.
+        let value: *const TyS<'lt> = value;
+        // FIXME(27214): unneeded [as *const ()]
+        let value = value as *const () as *const TyS<'static>;
+        self.0.fulfill(unsafe { NonZero::new(value) })
+    }
+}
+
+impl<'tcx, 'lt> fmt::Debug for TyIVar<'tcx, 'lt> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self.get() {
+            Some(val) => write!(f, "TyIVar({:?})", val),
+            None => f.write_str("TyIVar(<unfulfilled>)")
+        }
+    }
+}
index 21f068ca887a0a35b3de02080eadfd1ae839aaf3..ab1160d7deb02292d1a7c4bc57713c29e21feea7 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,10 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// FIXME: (@jroesch) @eddyb should remove this when he renames ctxt
-#![allow(non_camel_case_types)]
-
-pub use self::InferTy::*;
 pub use self::ImplOrTraitItemId::*;
 pub use self::ClosureKind::*;
 pub use self::Variance::*;
 pub use self::AutoRef::*;
 pub use self::DtorKind::*;
 pub use self::ExplicitSelfCategory::*;
-pub use self::FnOutput::*;
-pub use self::Region::*;
 pub use self::ImplOrTraitItemContainer::*;
 pub use self::BorrowKind::*;
 pub use self::ImplOrTraitItem::*;
-pub use self::BoundRegion::*;
-pub use self::TypeVariants::*;
 pub use self::IntVarValue::*;
 pub use self::CopyImplementationError::*;
 pub use self::LvaluePreference::*;
 
-pub use self::BuiltinBound::Send as BoundSend;
-pub use self::BuiltinBound::Sized as BoundSized;
-pub use self::BuiltinBound::Copy as BoundCopy;
-pub use self::BuiltinBound::Sync as BoundSync;
-
 use back::svh::Svh;
-use session::Session;
-use lint;
 use front::map as ast_map;
 use front::map::LinkedPath;
 use metadata::csearch;
 use middle;
-use middle::check_const;
 use middle::const_eval::{self, ConstVal, ErrKind};
 use middle::const_eval::EvalHint::UncheckedExprHint;
-use middle::def::{self, DefMap, ExportMap};
+use middle::def::{self, ExportMap};
 use middle::def_id::{DefId, LOCAL_CRATE};
-use middle::free_region::FreeRegionMap;
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
-use middle::region;
-use middle::resolve_lifetime;
 use middle::infer;
-use middle::infer::type_variable;
 use middle::pat_util;
-use middle::region::RegionMaps;
-use middle::stability;
 use middle::subst::{self, ParamSpace, Subst, Substs, VecPerParamSpace};
 use middle::traits;
 use middle::ty;
-use middle::ty::fold::{TypeFoldable, TypeFolder};
-use middle::ty::walk::{TypeWalker};
-use util::common::{memoized, ErrorReported};
-use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
+use middle::ty::fold::TypeFolder;
+use middle::ty::walk::TypeWalker;
+use util::common::memoized;
+use util::nodemap::{NodeMap, NodeSet, DefIdMap};
 use util::nodemap::FnvHashMap;
 use util::num::ToPrimitive;
 
-use arena::TypedArena;
 use std::borrow::{Borrow, Cow};
-use std::cell::{Cell, RefCell, Ref};
+use std::cell::{Cell, RefCell};
 use std::cmp;
-use std::fmt;
 use std::hash::{Hash, SipHasher, Hasher};
 use std::iter;
-use std::marker::PhantomData;
-use std::mem;
-use std::ops;
 use std::rc::Rc;
 use std::slice;
 use std::vec::IntoIter;
-use collections::enum_set::{self, EnumSet, CLike};
-use core::nonzero::NonZero;
 use std::collections::{HashMap, HashSet};
-use rustc_data_structures::ivar;
-use syntax::abi;
 use syntax::ast::{self, CrateNum, Name, NodeId};
 use syntax::codemap::Span;
 use syntax::parse::token::{InternedString, special_idents};
 use rustc_front::hir::{MutImmutable, MutMutable, Visibility};
 use rustc_front::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt};
 
+pub use self::sty::{Binder, DebruijnIndex};
+pub use self::sty::{BuiltinBound, BuiltinBounds, ExistentialBounds};
+pub use self::sty::{BareFnTy, FnSig, PolyFnSig, FnOutput, PolyFnOutput};
+pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, TraitTy};
+pub use self::sty::{ClosureSubsts, TypeAndMut};
+pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef};
+pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
+pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid, SkolemizedRegionVid};
+pub use self::sty::BoundRegion::*;
+pub use self::sty::FnOutput::*;
+pub use self::sty::InferTy::*;
+pub use self::sty::Region::*;
+pub use self::sty::TypeVariants::*;
+
+pub use self::sty::BuiltinBound::Send as BoundSend;
+pub use self::sty::BuiltinBound::Sized as BoundSized;
+pub use self::sty::BuiltinBound::Copy as BoundCopy;
+pub use self::sty::BuiltinBound::Sync as BoundSync;
+
+pub use self::contents::TypeContents;
+pub use self::context::{ctxt, tls};
+pub use self::context::{CtxtArenas, Lift, Tables};
+
 pub mod cast;
+pub mod error;
 pub mod fast_reject;
 pub mod fold;
 pub mod _match;
 pub mod walk;
 pub mod wf;
 
+mod contents;
+mod context;
+mod flags;
+mod ivar;
+mod structural_impls;
+mod sty;
+
 pub type Disr = u64;
 
 pub const INITIAL_DISCRIMINANT_VALUE: Disr = 0;
@@ -421,13 +421,6 @@ pub struct AssociatedType<'tcx> {
     pub container: ImplOrTraitItemContainer,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
-pub struct TypeAndMut<'tcx> {
-    pub ty: Ty<'tcx>,
-    pub mutbl: hir::Mutability,
-}
-
-
 #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable)]
 pub struct ItemVariances {
     pub types: VecPerParamSpace<Variance>,
@@ -442,17 +435,6 @@ pub enum Variance {
     Bivariant,      // T<A> <: T<B>            -- e.g., unused type parameter
 }
 
-impl fmt::Debug for Variance {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.write_str(match *self {
-            Covariant => "+",
-            Contravariant => "-",
-            Invariant => "o",
-            Bivariant => "*",
-        })
-    }
-}
-
 #[derive(Copy, Clone)]
 pub enum AutoAdjustment<'tcx> {
     AdjustReifyFnPointer,   // go from a fn-item type to a fn-pointer type
@@ -638,275 +620,6 @@ pub struct TransmuteRestriction<'tcx> {
     pub id: NodeId,
 }
 
-/// Internal storage
-pub struct CtxtArenas<'tcx> {
-    // internings
-    type_: TypedArena<TyS<'tcx>>,
-    substs: TypedArena<Substs<'tcx>>,
-    bare_fn: TypedArena<BareFnTy<'tcx>>,
-    region: TypedArena<Region>,
-    stability: TypedArena<attr::Stability>,
-
-    // references
-    trait_defs: TypedArena<TraitDef<'tcx>>,
-    adt_defs: TypedArena<AdtDefData<'tcx, 'tcx>>,
-}
-
-impl<'tcx> CtxtArenas<'tcx> {
-    pub fn new() -> CtxtArenas<'tcx> {
-        CtxtArenas {
-            type_: TypedArena::new(),
-            substs: TypedArena::new(),
-            bare_fn: TypedArena::new(),
-            region: TypedArena::new(),
-            stability: TypedArena::new(),
-
-            trait_defs: TypedArena::new(),
-            adt_defs: TypedArena::new()
-        }
-    }
-}
-
-pub struct CommonTypes<'tcx> {
-    pub bool: Ty<'tcx>,
-    pub char: Ty<'tcx>,
-    pub isize: Ty<'tcx>,
-    pub i8: Ty<'tcx>,
-    pub i16: Ty<'tcx>,
-    pub i32: Ty<'tcx>,
-    pub i64: Ty<'tcx>,
-    pub usize: Ty<'tcx>,
-    pub u8: Ty<'tcx>,
-    pub u16: Ty<'tcx>,
-    pub u32: Ty<'tcx>,
-    pub u64: Ty<'tcx>,
-    pub f32: Ty<'tcx>,
-    pub f64: Ty<'tcx>,
-    pub err: Ty<'tcx>,
-}
-
-pub struct Tables<'tcx> {
-    /// Stores the types for various nodes in the AST.  Note that this table
-    /// is not guaranteed to be populated until after typeck.  See
-    /// typeck::check::fn_ctxt for details.
-    pub node_types: NodeMap<Ty<'tcx>>,
-
-    /// Stores the type parameters which were substituted to obtain the type
-    /// of this node.  This only applies to nodes that refer to entities
-    /// parameterized by type parameters, such as generic fns, types, or
-    /// other items.
-    pub item_substs: NodeMap<ItemSubsts<'tcx>>,
-
-    pub adjustments: NodeMap<ty::AutoAdjustment<'tcx>>,
-
-    pub method_map: MethodMap<'tcx>,
-
-    /// Borrows
-    pub upvar_capture_map: UpvarCaptureMap,
-
-    /// Records the type of each closure. The def ID is the ID of the
-    /// expression defining the closure.
-    pub closure_tys: DefIdMap<ClosureTy<'tcx>>,
-
-    /// Records the type of each closure. The def ID is the ID of the
-    /// expression defining the closure.
-    pub closure_kinds: DefIdMap<ClosureKind>,
-}
-
-impl<'tcx> Tables<'tcx> {
-    pub fn empty() -> Tables<'tcx> {
-        Tables {
-            node_types: FnvHashMap(),
-            item_substs: NodeMap(),
-            adjustments: NodeMap(),
-            method_map: FnvHashMap(),
-            upvar_capture_map: FnvHashMap(),
-            closure_tys: DefIdMap(),
-            closure_kinds: DefIdMap(),
-        }
-    }
-}
-
-/// The data structure to keep track of all the information that typechecker
-/// generates so that so that it can be reused and doesn't have to be redone
-/// later on.
-pub struct ctxt<'tcx> {
-    /// The arenas that types etc are allocated from.
-    arenas: &'tcx CtxtArenas<'tcx>,
-
-    /// Specifically use a speedy hash algorithm for this hash map, it's used
-    /// quite often.
-    // FIXME(eddyb) use a FnvHashSet<InternedTy<'tcx>> when equivalent keys can
-    // queried from a HashSet.
-    interner: RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>,
-
-    // FIXME as above, use a hashset if equivalent elements can be queried.
-    substs_interner: RefCell<FnvHashMap<&'tcx Substs<'tcx>, &'tcx Substs<'tcx>>>,
-    bare_fn_interner: RefCell<FnvHashMap<&'tcx BareFnTy<'tcx>, &'tcx BareFnTy<'tcx>>>,
-    region_interner: RefCell<FnvHashMap<&'tcx Region, &'tcx Region>>,
-    stability_interner: RefCell<FnvHashMap<&'tcx attr::Stability, &'tcx attr::Stability>>,
-
-    /// Common types, pre-interned for your convenience.
-    pub types: CommonTypes<'tcx>,
-
-    pub sess: Session,
-    pub def_map: DefMap,
-
-    pub named_region_map: resolve_lifetime::NamedRegionMap,
-
-    pub region_maps: RegionMaps,
-
-    // For each fn declared in the local crate, type check stores the
-    // free-region relationships that were deduced from its where
-    // clauses and parameter types. These are then read-again by
-    // borrowck. (They are not used during trans, and hence are not
-    // serialized or needed for cross-crate fns.)
-    free_region_maps: RefCell<NodeMap<FreeRegionMap>>,
-    // FIXME: jroesch make this a refcell
-
-    pub tables: RefCell<Tables<'tcx>>,
-
-    /// Maps from a trait item to the trait item "descriptor"
-    pub impl_or_trait_items: RefCell<DefIdMap<ImplOrTraitItem<'tcx>>>,
-
-    /// Maps from a trait def-id to a list of the def-ids of its trait items
-    pub trait_item_def_ids: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItemId>>>>,
-
-    /// A cache for the trait_items() routine
-    pub trait_items_cache: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItem<'tcx>>>>>,
-
-    pub impl_trait_refs: RefCell<DefIdMap<Option<TraitRef<'tcx>>>>,
-    pub trait_defs: RefCell<DefIdMap<&'tcx TraitDef<'tcx>>>,
-    pub adt_defs: RefCell<DefIdMap<AdtDefMaster<'tcx>>>,
-
-    /// Maps from the def-id of an item (trait/struct/enum/fn) to its
-    /// associated predicates.
-    pub predicates: RefCell<DefIdMap<GenericPredicates<'tcx>>>,
-
-    /// Maps from the def-id of a trait to the list of
-    /// super-predicates. This is a subset of the full list of
-    /// predicates. We store these in a separate map because we must
-    /// evaluate them even during type conversion, often before the
-    /// full predicates are available (note that supertraits have
-    /// additional acyclicity requirements).
-    pub super_predicates: RefCell<DefIdMap<GenericPredicates<'tcx>>>,
-
-    pub map: ast_map::Map<'tcx>,
-    pub freevars: RefCell<FreevarMap>,
-    pub tcache: RefCell<DefIdMap<TypeScheme<'tcx>>>,
-    pub rcache: RefCell<FnvHashMap<CReaderCacheKey, Ty<'tcx>>>,
-    pub tc_cache: RefCell<FnvHashMap<Ty<'tcx>, TypeContents>>,
-    pub ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>,
-    pub ty_param_defs: RefCell<NodeMap<TypeParameterDef<'tcx>>>,
-    pub normalized_cache: RefCell<FnvHashMap<Ty<'tcx>, Ty<'tcx>>>,
-    pub lang_items: middle::lang_items::LanguageItems,
-    /// A mapping of fake provided method def_ids to the default implementation
-    pub provided_method_sources: RefCell<DefIdMap<DefId>>,
-
-    /// Maps from def-id of a type or region parameter to its
-    /// (inferred) variance.
-    pub item_variance_map: RefCell<DefIdMap<Rc<ItemVariances>>>,
-
-    /// True if the variance has been computed yet; false otherwise.
-    pub variance_computed: Cell<bool>,
-
-    /// A method will be in this list if and only if it is a destructor.
-    pub destructors: RefCell<DefIdSet>,
-
-    /// Maps a DefId of a type to a list of its inherent impls.
-    /// Contains implementations of methods that are inherent to a type.
-    /// Methods in these implementations don't need to be exported.
-    pub inherent_impls: RefCell<DefIdMap<Rc<Vec<DefId>>>>,
-
-    /// Maps a DefId of an impl to a list of its items.
-    /// Note that this contains all of the impls that we know about,
-    /// including ones in other crates. It's not clear that this is the best
-    /// way to do it.
-    pub impl_items: RefCell<DefIdMap<Vec<ImplOrTraitItemId>>>,
-
-    /// Set of used unsafe nodes (functions or blocks). Unsafe nodes not
-    /// present in this set can be warned about.
-    pub used_unsafe: RefCell<NodeSet>,
-
-    /// Set of nodes which mark locals as mutable which end up getting used at
-    /// some point. Local variable definitions not in this set can be warned
-    /// about.
-    pub used_mut_nodes: RefCell<NodeSet>,
-
-    /// The set of external nominal types whose implementations have been read.
-    /// This is used for lazy resolution of methods.
-    pub populated_external_types: RefCell<DefIdSet>,
-    /// The set of external primitive types whose implementations have been read.
-    /// FIXME(arielb1): why is this separate from populated_external_types?
-    pub populated_external_primitive_impls: RefCell<DefIdSet>,
-
-    /// These caches are used by const_eval when decoding external constants.
-    pub extern_const_statics: RefCell<DefIdMap<NodeId>>,
-    pub extern_const_variants: RefCell<DefIdMap<NodeId>>,
-    pub extern_const_fns: RefCell<DefIdMap<NodeId>>,
-
-    pub node_lint_levels: RefCell<FnvHashMap<(NodeId, lint::LintId),
-                                              lint::LevelSource>>,
-
-    /// The types that must be asserted to be the same size for `transmute`
-    /// to be valid. We gather up these restrictions in the intrinsicck pass
-    /// and check them in trans.
-    pub transmute_restrictions: RefCell<Vec<TransmuteRestriction<'tcx>>>,
-
-    /// Maps any item's def-id to its stability index.
-    pub stability: RefCell<stability::Index<'tcx>>,
-
-    /// Caches the results of trait selection. This cache is used
-    /// for things that do not have to do with the parameters in scope.
-    pub selection_cache: traits::SelectionCache<'tcx>,
-
-    /// A set of predicates that have been fulfilled *somewhere*.
-    /// This is used to avoid duplicate work. Predicates are only
-    /// added to this set when they mention only "global" names
-    /// (i.e., no type or lifetime parameters).
-    pub fulfilled_predicates: RefCell<traits::FulfilledPredicates<'tcx>>,
-
-    /// Caches the representation hints for struct definitions.
-    pub repr_hint_cache: RefCell<DefIdMap<Rc<Vec<attr::ReprAttr>>>>,
-
-    /// Maps Expr NodeId's to their constant qualification.
-    pub const_qualif_map: RefCell<NodeMap<check_const::ConstQualif>>,
-
-    /// Caches CoerceUnsized kinds for impls on custom types.
-    pub custom_coerce_unsized_kinds: RefCell<DefIdMap<CustomCoerceUnsized>>,
-
-    /// Maps a cast expression to its kind. This is keyed on the
-    /// *from* expression of the cast, not the cast itself.
-    pub cast_kinds: RefCell<NodeMap<cast::CastKind>>,
-
-    /// Maps Fn items to a collection of fragment infos.
-    ///
-    /// The main goal is to identify data (each of which may be moved
-    /// or assigned) whose subparts are not moved nor assigned
-    /// (i.e. their state is *unfragmented*) and corresponding ast
-    /// nodes where the path to that data is moved or assigned.
-    ///
-    /// In the long term, unfragmented values will have their
-    /// destructor entirely driven by a single stack-local drop-flag,
-    /// and their parents, the collections of the unfragmented values
-    /// (or more simply, "fragmented values"), are mapped to the
-    /// corresponding collections of stack-local drop-flags.
-    ///
-    /// (However, in the short term that is not the case; e.g. some
-    /// unfragmented paths still need to be zeroed, namely when they
-    /// reference parent data from an outer scope that was not
-    /// entirely moved, and therefore that needs to be zeroed so that
-    /// we do not get double-drop when we hit the end of the parent
-    /// scope.)
-    ///
-    /// Also: currently the table solely holds keys for node-ids of
-    /// unfragmented values (see `FragmentInfo` enum definition), but
-    /// longer-term we will need to also store mappings from
-    /// fragmented data to the set of unfragmented pieces that
-    /// constitute it.
-    pub fragment_infos: RefCell<DefIdMap<Vec<FragmentInfo>>>,
-}
-
 /// Describes the fragment-state associated with a NodeId.
 ///
 /// Currently only unfragmented paths have entries in the table,
@@ -918,232 +631,6 @@ pub enum FragmentInfo {
     Assigned { var: NodeId, assign_expr: NodeId, assignee_id: NodeId },
 }
 
-impl<'tcx> ctxt<'tcx> {
-    pub fn node_types(&self) -> Ref<NodeMap<Ty<'tcx>>> {
-        fn projection<'a, 'tcx>(tables: &'a Tables<'tcx>) ->  &'a NodeMap<Ty<'tcx>> {
-            &tables.node_types
-        }
-
-        Ref::map(self.tables.borrow(), projection)
-    }
-
-    pub fn node_type_insert(&self, id: NodeId, ty: Ty<'tcx>) {
-        self.tables.borrow_mut().node_types.insert(id, ty);
-    }
-
-    pub fn intern_trait_def(&self, def: TraitDef<'tcx>) -> &'tcx TraitDef<'tcx> {
-        let did = def.trait_ref.def_id;
-        let interned = self.arenas.trait_defs.alloc(def);
-        self.trait_defs.borrow_mut().insert(did, interned);
-        interned
-    }
-
-    pub fn intern_adt_def(&self,
-                          did: DefId,
-                          kind: AdtKind,
-                          variants: Vec<VariantDefData<'tcx, 'tcx>>)
-                          -> AdtDefMaster<'tcx> {
-        let def = AdtDefData::new(self, did, kind, variants);
-        let interned = self.arenas.adt_defs.alloc(def);
-        // this will need a transmute when reverse-variance is removed
-        self.adt_defs.borrow_mut().insert(did, interned);
-        interned
-    }
-
-    pub fn intern_stability(&self, stab: attr::Stability) -> &'tcx attr::Stability {
-        if let Some(st) = self.stability_interner.borrow().get(&stab) {
-            return st;
-        }
-
-        let interned = self.arenas.stability.alloc(stab);
-        self.stability_interner.borrow_mut().insert(interned, interned);
-        interned
-    }
-
-    pub fn store_free_region_map(&self, id: NodeId, map: FreeRegionMap) {
-        self.free_region_maps.borrow_mut()
-                             .insert(id, map);
-    }
-
-    pub fn free_region_map(&self, id: NodeId) -> FreeRegionMap {
-        self.free_region_maps.borrow()[&id].clone()
-    }
-
-    pub fn lift<T: ?Sized + Lift<'tcx>>(&self, value: &T) -> Option<T::Lifted> {
-        value.lift_to_tcx(self)
-    }
-}
-
-/// A trait implemented for all X<'a> types which can be safely and
-/// efficiently converted to X<'tcx> as long as they are part of the
-/// provided ty::ctxt<'tcx>.
-/// This can be done, for example, for Ty<'tcx> or &'tcx Substs<'tcx>
-/// by looking them up in their respective interners.
-/// None is returned if the value or one of the components is not part
-/// of the provided context.
-/// For Ty, None can be returned if either the type interner doesn't
-/// contain the TypeVariants key or if the address of the interned
-/// pointer differs. The latter case is possible if a primitive type,
-/// e.g. `()` or `u8`, was interned in a different context.
-pub trait Lift<'tcx> {
-    type Lifted;
-    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted>;
-}
-
-impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>> Lift<'tcx> for (A, B) {
-    type Lifted = (A::Lifted, B::Lifted);
-    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(&self.0).and_then(|a| tcx.lift(&self.1).map(|b| (a, b)))
-    }
-}
-
-impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for [T] {
-    type Lifted = Vec<T::Lifted>;
-    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted> {
-        let mut result = Vec::with_capacity(self.len());
-        for x in self {
-            if let Some(value) = tcx.lift(x) {
-                result.push(value);
-            } else {
-                return None;
-            }
-        }
-        Some(result)
-    }
-}
-
-impl<'tcx> Lift<'tcx> for Region {
-    type Lifted = Self;
-    fn lift_to_tcx(&self, _: &ctxt<'tcx>) -> Option<Region> {
-        Some(*self)
-    }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for Ty<'a> {
-    type Lifted = Ty<'tcx>;
-    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Ty<'tcx>> {
-        if let Some(&ty) = tcx.interner.borrow().get(&self.sty) {
-            if *self as *const _ == ty as *const _ {
-                return Some(ty);
-            }
-        }
-        None
-    }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
-    type Lifted = &'tcx Substs<'tcx>;
-    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<&'tcx Substs<'tcx>> {
-        if let Some(&substs) = tcx.substs_interner.borrow().get(*self) {
-            if *self as *const _ == substs as *const _ {
-                return Some(substs);
-            }
-        }
-        None
-    }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for TraitRef<'a> {
-    type Lifted = TraitRef<'tcx>;
-    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<TraitRef<'tcx>> {
-        tcx.lift(&self.substs).map(|substs| TraitRef {
-            def_id: self.def_id,
-            substs: substs
-        })
-    }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for TraitPredicate<'a> {
-    type Lifted = TraitPredicate<'tcx>;
-    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<TraitPredicate<'tcx>> {
-        tcx.lift(&self.trait_ref).map(|trait_ref| TraitPredicate {
-            trait_ref: trait_ref
-        })
-    }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for EquatePredicate<'a> {
-    type Lifted = EquatePredicate<'tcx>;
-    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<EquatePredicate<'tcx>> {
-        tcx.lift(&(self.0, self.1)).map(|(a, b)| EquatePredicate(a, b))
-    }
-}
-
-impl<'tcx, A: Copy+Lift<'tcx>, B: Copy+Lift<'tcx>> Lift<'tcx> for OutlivesPredicate<A, B> {
-    type Lifted = OutlivesPredicate<A::Lifted, B::Lifted>;
-    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(&(self.0, self.1)).map(|(a, b)| OutlivesPredicate(a, b))
-    }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for ProjectionPredicate<'a> {
-    type Lifted = ProjectionPredicate<'tcx>;
-    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<ProjectionPredicate<'tcx>> {
-        tcx.lift(&(self.projection_ty.trait_ref, self.ty)).map(|(trait_ref, ty)| {
-            ProjectionPredicate {
-                projection_ty: ProjectionTy {
-                    trait_ref: trait_ref,
-                    item_name: self.projection_ty.item_name
-                },
-                ty: ty
-            }
-        })
-    }
-}
-
-impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Binder<T> {
-    type Lifted = Binder<T::Lifted>;
-    fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(&self.0).map(|x| Binder(x))
-    }
-}
-
-pub mod tls {
-    use middle::ty;
-    use session::Session;
-
-    use std::fmt;
-    use syntax::codemap;
-
-    /// Marker type used for the scoped TLS slot.
-    /// The type context cannot be used directly because the scoped TLS
-    /// in libstd doesn't allow types generic over lifetimes.
-    struct ThreadLocalTyCx;
-
-    scoped_thread_local!(static TLS_TCX: ThreadLocalTyCx);
-
-    fn span_debug(span: codemap::Span, f: &mut fmt::Formatter) -> fmt::Result {
-        with(|tcx| {
-            write!(f, "{}", tcx.sess.codemap().span_to_string(span))
-        })
-    }
-
-    pub fn enter<'tcx, F: FnOnce(&ty::ctxt<'tcx>) -> R, R>(tcx: ty::ctxt<'tcx>, f: F)
-                                                           -> (Session, R) {
-        let result = codemap::SPAN_DEBUG.with(|span_dbg| {
-            let original_span_debug = span_dbg.get();
-            span_dbg.set(span_debug);
-            let tls_ptr = &tcx as *const _ as *const ThreadLocalTyCx;
-            let result = TLS_TCX.set(unsafe { &*tls_ptr }, || f(&tcx));
-            span_dbg.set(original_span_debug);
-            result
-        });
-        (tcx.sess, result)
-    }
-
-    pub fn with<F: FnOnce(&ty::ctxt) -> R, R>(f: F) -> R {
-        TLS_TCX.with(|tcx| f(unsafe { &*(tcx as *const _ as *const ty::ctxt) }))
-    }
-
-    pub fn with_opt<F: FnOnce(Option<&ty::ctxt>) -> R, R>(f: F) -> R {
-        if TLS_TCX.is_set() {
-            with(|v| f(Some(v)))
-        } else {
-            f(None)
-        }
-    }
-}
-
 // Flags that we track on types. These flags are propagated upwards
 // through the type during type construction, so that we can quickly
 // check whether the type has various kinds of types in it without
@@ -1190,82 +677,6 @@ pub fn with_opt<F: FnOnce(Option<&ty::ctxt>) -> R, R>(f: F) -> R {
     }
 }
 
-macro_rules! sty_debug_print {
-    ($ctxt: expr, $($variant: ident),*) => {{
-        // curious inner module to allow variant names to be used as
-        // variable names.
-        #[allow(non_snake_case)]
-        mod inner {
-            use middle::ty;
-            #[derive(Copy, Clone)]
-            struct DebugStat {
-                total: usize,
-                region_infer: usize,
-                ty_infer: usize,
-                both_infer: usize,
-            }
-
-            pub fn go(tcx: &ty::ctxt) {
-                let mut total = DebugStat {
-                    total: 0,
-                    region_infer: 0, ty_infer: 0, both_infer: 0,
-                };
-                $(let mut $variant = total;)*
-
-
-                for (_, t) in tcx.interner.borrow().iter() {
-                    let variant = match t.sty {
-                        ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) |
-                            ty::TyFloat(..) | ty::TyStr => continue,
-                        ty::TyError => /* unimportant */ continue,
-                        $(ty::$variant(..) => &mut $variant,)*
-                    };
-                    let region = t.flags.get().intersects(ty::TypeFlags::HAS_RE_INFER);
-                    let ty = t.flags.get().intersects(ty::TypeFlags::HAS_TY_INFER);
-
-                    variant.total += 1;
-                    total.total += 1;
-                    if region { total.region_infer += 1; variant.region_infer += 1 }
-                    if ty { total.ty_infer += 1; variant.ty_infer += 1 }
-                    if region && ty { total.both_infer += 1; variant.both_infer += 1 }
-                }
-                println!("Ty interner             total           ty region  both");
-                $(println!("    {:18}: {uses:6} {usespc:4.1}%, \
-{ty:4.1}% {region:5.1}% {both:4.1}%",
-                           stringify!($variant),
-                           uses = $variant.total,
-                           usespc = $variant.total as f64 * 100.0 / total.total as f64,
-                           ty = $variant.ty_infer as f64 * 100.0  / total.total as f64,
-                           region = $variant.region_infer as f64 * 100.0  / total.total as f64,
-                           both = $variant.both_infer as f64 * 100.0  / total.total as f64);
-                  )*
-                println!("                  total {uses:6}        \
-{ty:4.1}% {region:5.1}% {both:4.1}%",
-                         uses = total.total,
-                         ty = total.ty_infer as f64 * 100.0  / total.total as f64,
-                         region = total.region_infer as f64 * 100.0  / total.total as f64,
-                         both = total.both_infer as f64 * 100.0  / total.total as f64)
-            }
-        }
-
-        inner::go($ctxt)
-    }}
-}
-
-impl<'tcx> ctxt<'tcx> {
-    pub fn print_debug_stats(&self) {
-        sty_debug_print!(
-            self,
-            TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyBareFn, TyTrait,
-            TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection);
-
-        println!("Substs interner: #{}", self.substs_interner.borrow().len());
-        println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len());
-        println!("Region interner: #{}", self.region_interner.borrow().len());
-        println!("Stability interner: #{}", self.stability_interner.borrow().len());
-    }
-}
-
 pub struct TyS<'tcx> {
     pub sty: TypeVariants<'tcx>,
     pub flags: Cell<TypeFlags>,
@@ -1274,12 +685,6 @@ pub struct TyS<'tcx> {
     region_depth: u32,
 }
 
-impl fmt::Debug for TypeFlags {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", self.bits)
-    }
-}
-
 impl<'tcx> PartialEq for TyS<'tcx> {
     #[inline]
     fn eq(&self, other: &TyS<'tcx>) -> bool {
@@ -1297,323 +702,6 @@ fn hash<H: Hasher>(&self, s: &mut H) {
 
 pub type Ty<'tcx> = &'tcx TyS<'tcx>;
 
-/// An IVar that contains a Ty. 'lt is a (reverse-variant) upper bound
-/// on the lifetime of the IVar. This is required because of variance
-/// problems: the IVar needs to be variant with respect to 'tcx (so
-/// it can be referred to from Ty) but can only be modified if its
-/// lifetime is exactly 'tcx.
-///
-/// Safety invariants:
-///     (A) self.0, if fulfilled, is a valid Ty<'tcx>
-///     (B) no aliases to this value with a 'tcx longer than this
-///         value's 'lt exist
-///
-/// NonZero is used rather than Unique because Unique isn't Copy.
-pub struct TyIVar<'tcx, 'lt: 'tcx>(ivar::Ivar<NonZero<*const TyS<'static>>>,
-                                   PhantomData<fn(TyS<'lt>)->TyS<'tcx>>);
-
-impl<'tcx, 'lt> TyIVar<'tcx, 'lt> {
-    #[inline]
-    pub fn new() -> Self {
-        // Invariant (A) satisfied because the IVar is unfulfilled
-        // Invariant (B) because 'lt : 'tcx
-        TyIVar(ivar::Ivar::new(), PhantomData)
-    }
-
-    #[inline]
-    pub fn get(&self) -> Option<Ty<'tcx>> {
-        match self.0.get() {
-            None => None,
-            // valid because of invariant (A)
-            Some(v) => Some(unsafe { &*(*v as *const TyS<'tcx>) })
-        }
-    }
-    #[inline]
-    pub fn unwrap(&self) -> Ty<'tcx> {
-        self.get().unwrap()
-    }
-
-    pub fn fulfill(&self, value: Ty<'lt>) {
-        // Invariant (A) is fulfilled, because by (B), every alias
-        // of this has a 'tcx longer than 'lt.
-        let value: *const TyS<'lt> = value;
-        // FIXME(27214): unneeded [as *const ()]
-        let value = value as *const () as *const TyS<'static>;
-        self.0.fulfill(unsafe { NonZero::new(value) })
-    }
-}
-
-impl<'tcx, 'lt> fmt::Debug for TyIVar<'tcx, 'lt> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match self.get() {
-            Some(val) => write!(f, "TyIVar({:?})", val),
-            None => f.write_str("TyIVar(<unfulfilled>)")
-        }
-    }
-}
-
-/// An entry in the type interner.
-pub struct InternedTy<'tcx> {
-    ty: Ty<'tcx>
-}
-
-// NB: An InternedTy compares and hashes as a sty.
-impl<'tcx> PartialEq for InternedTy<'tcx> {
-    fn eq(&self, other: &InternedTy<'tcx>) -> bool {
-        self.ty.sty == other.ty.sty
-    }
-}
-
-impl<'tcx> Eq for InternedTy<'tcx> {}
-
-impl<'tcx> Hash for InternedTy<'tcx> {
-    fn hash<H: Hasher>(&self, s: &mut H) {
-        self.ty.sty.hash(s)
-    }
-}
-
-impl<'tcx> Borrow<TypeVariants<'tcx>> for InternedTy<'tcx> {
-    fn borrow<'a>(&'a self) -> &'a TypeVariants<'tcx> {
-        &self.ty.sty
-    }
-}
-
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
-pub struct BareFnTy<'tcx> {
-    pub unsafety: hir::Unsafety,
-    pub abi: abi::Abi,
-    pub sig: PolyFnSig<'tcx>,
-}
-
-#[derive(Clone, PartialEq, Eq, Hash)]
-pub struct ClosureTy<'tcx> {
-    pub unsafety: hir::Unsafety,
-    pub abi: abi::Abi,
-    pub sig: PolyFnSig<'tcx>,
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
-pub enum FnOutput<'tcx> {
-    FnConverging(Ty<'tcx>),
-    FnDiverging
-}
-
-impl<'tcx> FnOutput<'tcx> {
-    pub fn diverges(&self) -> bool {
-        *self == FnDiverging
-    }
-
-    pub fn unwrap(self) -> Ty<'tcx> {
-        match self {
-            ty::FnConverging(t) => t,
-            ty::FnDiverging => unreachable!()
-        }
-    }
-
-    pub fn unwrap_or(self, def: Ty<'tcx>) -> Ty<'tcx> {
-        match self {
-            ty::FnConverging(t) => t,
-            ty::FnDiverging => def
-        }
-    }
-}
-
-pub type PolyFnOutput<'tcx> = Binder<FnOutput<'tcx>>;
-
-impl<'tcx> PolyFnOutput<'tcx> {
-    pub fn diverges(&self) -> bool {
-        self.0.diverges()
-    }
-}
-
-/// Signature of a function type, which I have arbitrarily
-/// decided to use to refer to the input/output types.
-///
-/// - `inputs` is the list of arguments and their modes.
-/// - `output` is the return type.
-/// - `variadic` indicates whether this is a variadic function. (only true for foreign fns)
-#[derive(Clone, PartialEq, Eq, Hash)]
-pub struct FnSig<'tcx> {
-    pub inputs: Vec<Ty<'tcx>>,
-    pub output: FnOutput<'tcx>,
-    pub variadic: bool
-}
-
-pub type PolyFnSig<'tcx> = Binder<FnSig<'tcx>>;
-
-impl<'tcx> PolyFnSig<'tcx> {
-    pub fn inputs(&self) -> ty::Binder<Vec<Ty<'tcx>>> {
-        self.map_bound_ref(|fn_sig| fn_sig.inputs.clone())
-    }
-    pub fn input(&self, index: usize) -> ty::Binder<Ty<'tcx>> {
-        self.map_bound_ref(|fn_sig| fn_sig.inputs[index])
-    }
-    pub fn output(&self) -> ty::Binder<FnOutput<'tcx>> {
-        self.map_bound_ref(|fn_sig| fn_sig.output.clone())
-    }
-    pub fn variadic(&self) -> bool {
-        self.skip_binder().variadic
-    }
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
-pub struct ParamTy {
-    pub space: subst::ParamSpace,
-    pub idx: u32,
-    pub name: Name,
-}
-
-/// A [De Bruijn index][dbi] is a standard means of representing
-/// regions (and perhaps later types) in a higher-ranked setting. In
-/// particular, imagine a type like this:
-///
-///     for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
-///     ^          ^            |        |         |
-///     |          |            |        |         |
-///     |          +------------+ 1      |         |
-///     |                                |         |
-///     +--------------------------------+ 2       |
-///     |                                          |
-///     +------------------------------------------+ 1
-///
-/// In this type, there are two binders (the outer fn and the inner
-/// fn). We need to be able to determine, for any given region, which
-/// fn type it is bound by, the inner or the outer one. There are
-/// various ways you can do this, but a De Bruijn index is one of the
-/// more convenient and has some nice properties. The basic idea is to
-/// count the number of binders, inside out. Some examples should help
-/// clarify what I mean.
-///
-/// Let's start with the reference type `&'b isize` that is the first
-/// argument to the inner function. This region `'b` is assigned a De
-/// Bruijn index of 1, meaning "the innermost binder" (in this case, a
-/// fn). The region `'a` that appears in the second argument type (`&'a
-/// isize`) would then be assigned a De Bruijn index of 2, meaning "the
-/// second-innermost binder". (These indices are written on the arrays
-/// in the diagram).
-///
-/// What is interesting is that De Bruijn index attached to a particular
-/// variable will vary depending on where it appears. For example,
-/// the final type `&'a char` also refers to the region `'a` declared on
-/// the outermost fn. But this time, this reference is not nested within
-/// any other binders (i.e., it is not an argument to the inner fn, but
-/// rather the outer one). Therefore, in this case, it is assigned a
-/// De Bruijn index of 1, because the innermost binder in that location
-/// is the outer fn.
-///
-/// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index
-#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, Copy)]
-pub struct DebruijnIndex {
-    // We maintain the invariant that this is never 0. So 1 indicates
-    // the innermost binder. To ensure this, create with `DebruijnIndex::new`.
-    pub depth: u32,
-}
-
-/// Representation of regions.
-///
-/// Unlike types, most region variants are "fictitious", not concrete,
-/// regions. Among these, `ReStatic`, `ReEmpty` and `ReScope` are the only
-/// ones representing concrete regions.
-///
-/// ## Bound Regions
-///
-/// These are regions that are stored behind a binder and must be substituted
-/// with some concrete region before being used. There are 2 kind of
-/// bound regions: early-bound, which are bound in a TypeScheme/TraitDef,
-/// and are substituted by a Substs,  and late-bound, which are part of
-/// higher-ranked types (e.g. `for<'a> fn(&'a ())`) and are substituted by
-/// the likes of `liberate_late_bound_regions`. The distinction exists
-/// because higher-ranked lifetimes aren't supported in all places. See [1][2].
-///
-/// Unlike TyParam-s, bound regions are not supposed to exist "in the wild"
-/// outside their binder, e.g. in types passed to type inference, and
-/// should first be substituted (by skolemized regions, free regions,
-/// or region variables).
-///
-/// ## Skolemized and Free Regions
-///
-/// One often wants to work with bound regions without knowing their precise
-/// identity. For example, when checking a function, the lifetime of a borrow
-/// can end up being assigned to some region parameter. In these cases,
-/// it must be ensured that bounds on the region can't be accidentally
-/// assumed without being checked.
-///
-/// The process of doing that is called "skolemization". The bound regions
-/// are replaced by skolemized markers, which don't satisfy any relation
-/// not explicity provided.
-///
-/// There are 2 kinds of skolemized regions in rustc: `ReFree` and
-/// `ReSkolemized`. When checking an item's body, `ReFree` is supposed
-/// to be used. These also support explicit bounds: both the internally-stored
-/// *scope*, which the region is assumed to outlive, as well as other
-/// relations stored in the `FreeRegionMap`. Note that these relations
-/// aren't checked when you `make_subregion` (or `mk_eqty`), only by
-/// `resolve_regions_and_report_errors`.
-///
-/// When working with higher-ranked types, some region relations aren't
-/// yet known, so you can't just call `resolve_regions_and_report_errors`.
-/// `ReSkolemized` is designed for this purpose. In these contexts,
-/// there's also the risk that some inference variable laying around will
-/// get unified with your skolemized region: if you want to check whether
-/// `for<'a> Foo<'_>: 'a`, and you substitute your bound region `'a`
-/// with a skolemized region `'%a`, the variable `'_` would just be
-/// instantiated to the skolemized region `'%a`, which is wrong because
-/// the inference variable is supposed to satisfy the relation
-/// *for every value of the skolemized region*. To ensure that doesn't
-/// happen, you can use `leak_check`. This is more clearly explained
-/// by infer/higher_ranked/README.md.
-///
-/// [1] http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
-/// [2] http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
-#[derive(Clone, PartialEq, Eq, Hash, Copy)]
-pub enum Region {
-    // Region bound in a type or fn declaration which will be
-    // substituted 'early' -- that is, at the same time when type
-    // parameters are substituted.
-    ReEarlyBound(EarlyBoundRegion),
-
-    // Region bound in a function scope, which will be substituted when the
-    // function is called.
-    ReLateBound(DebruijnIndex, BoundRegion),
-
-    /// When checking a function body, the types of all arguments and so forth
-    /// that refer to bound region parameters are modified to refer to free
-    /// region parameters.
-    ReFree(FreeRegion),
-
-    /// A concrete region naming some statically determined extent
-    /// (e.g. an expression or sequence of statements) within the
-    /// current function.
-    ReScope(region::CodeExtent),
-
-    /// Static data that has an "infinite" lifetime. Top in the region lattice.
-    ReStatic,
-
-    /// A region variable.  Should not exist after typeck.
-    ReVar(RegionVid),
-
-    /// A skolemized region - basically the higher-ranked version of ReFree.
-    /// Should not exist after typeck.
-    ReSkolemized(SkolemizedRegionVid, BoundRegion),
-
-    /// Empty lifetime is for data that is never accessed.
-    /// Bottom in the region lattice. We treat ReEmpty somewhat
-    /// specially; at least right now, we do not generate instances of
-    /// it during the GLB computations, but rather
-    /// generate an error instead. This is to improve error messages.
-    /// The only way to get an instance of ReEmpty is to have a region
-    /// variable with no constraints.
-    ReEmpty,
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
-pub struct EarlyBoundRegion {
-    pub param_id: NodeId,
-    pub space: subst::ParamSpace,
-    pub index: u32,
-    pub name: Name,
-}
-
 /// Upvars do not get their own node-id. Instead, we use the pair of
 /// the original var id (that is, the root variable that is referenced
 /// by the upvar) and the id of the closure expression.
@@ -1702,628 +790,12 @@ pub struct ClosureUpvar<'tcx> {
     pub ty: Ty<'tcx>,
 }
 
-impl Region {
-    pub fn is_bound(&self) -> bool {
-        match *self {
-            ty::ReEarlyBound(..) => true,
-            ty::ReLateBound(..) => true,
-            _ => false
-        }
-    }
-
-    pub fn needs_infer(&self) -> bool {
-        match *self {
-            ty::ReVar(..) | ty::ReSkolemized(..) => true,
-            _ => false
-        }
-    }
-
-    pub fn escapes_depth(&self, depth: u32) -> bool {
-        match *self {
-            ty::ReLateBound(debruijn, _) => debruijn.depth > depth,
-            _ => false,
-        }
-    }
-
-    /// Returns the depth of `self` from the (1-based) binding level `depth`
-    pub fn from_depth(&self, depth: u32) -> Region {
-        match *self {
-            ty::ReLateBound(debruijn, r) => ty::ReLateBound(DebruijnIndex {
-                depth: debruijn.depth - (depth - 1)
-            }, r),
-            r => r
-        }
-    }
-}
-
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash,
-         RustcEncodable, RustcDecodable, Copy)]
-/// A "free" region `fr` can be interpreted as "some region
-/// at least as big as the scope `fr.scope`".
-pub struct FreeRegion {
-    pub scope: region::CodeExtent,
-    pub bound_region: BoundRegion
-}
-
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash,
-         RustcEncodable, RustcDecodable, Copy)]
-pub enum BoundRegion {
-    /// An anonymous region parameter for a given fn (&T)
-    BrAnon(u32),
-
-    /// Named region parameters for functions (a in &'a T)
-    ///
-    /// The def-id is needed to distinguish free regions in
-    /// the event of shadowing.
-    BrNamed(DefId, Name),
-
-    /// Fresh bound identifiers created during GLB computations.
-    BrFresh(u32),
-
-    // Anonymous region for the implicit env pointer parameter
-    // to a closure
-    BrEnv
-}
-
-// NB: If you change this, you'll probably want to change the corresponding
-// AST structure in libsyntax/ast.rs as well.
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
-pub enum TypeVariants<'tcx> {
-    /// The primitive boolean type. Written as `bool`.
-    TyBool,
-
-    /// The primitive character type; holds a Unicode scalar value
-    /// (a non-surrogate code point).  Written as `char`.
-    TyChar,
-
-    /// A primitive signed integer type. For example, `i32`.
-    TyInt(hir::IntTy),
-
-    /// A primitive unsigned integer type. For example, `u32`.
-    TyUint(hir::UintTy),
-
-    /// A primitive floating-point type. For example, `f64`.
-    TyFloat(hir::FloatTy),
-
-    /// An enumerated type, defined with `enum`.
-    ///
-    /// Substs here, possibly against intuition, *may* contain `TyParam`s.
-    /// That is, even after substitution it is possible that there are type
-    /// variables. This happens when the `TyEnum` corresponds to an enum
-    /// definition and not a concrete use of it. To get the correct `TyEnum`
-    /// from the tcx, use the `NodeId` from the `hir::Ty` and look it up in
-    /// the `ast_ty_to_ty_cache`. This is probably true for `TyStruct` as
-    /// well.
-    TyEnum(AdtDef<'tcx>, &'tcx Substs<'tcx>),
-
-    /// A structure type, defined with `struct`.
-    ///
-    /// See warning about substitutions for enumerated types.
-    TyStruct(AdtDef<'tcx>, &'tcx Substs<'tcx>),
-
-    /// `Box<T>`; this is nominally a struct in the documentation, but is
-    /// special-cased internally. For example, it is possible to implicitly
-    /// move the contents of a box out of that box, and methods of any type
-    /// can have type `Box<Self>`.
-    TyBox(Ty<'tcx>),
-
-    /// The pointee of a string slice. Written as `str`.
-    TyStr,
-
-    /// An array with the given length. Written as `[T; n]`.
-    TyArray(Ty<'tcx>, usize),
-
-    /// The pointee of an array slice.  Written as `[T]`.
-    TySlice(Ty<'tcx>),
-
-    /// A raw pointer. Written as `*mut T` or `*const T`
-    TyRawPtr(TypeAndMut<'tcx>),
-
-    /// A reference; a pointer with an associated lifetime. Written as
-    /// `&a mut T` or `&'a T`.
-    TyRef(&'tcx Region, TypeAndMut<'tcx>),
-
-    /// If the def-id is Some(_), then this is the type of a specific
-    /// fn item. Otherwise, if None(_), it a fn pointer type.
-    ///
-    /// FIXME: Conflating function pointers and the type of a
-    /// function is probably a terrible idea; a function pointer is a
-    /// value with a specific type, but a function can be polymorphic
-    /// or dynamically dispatched.
-    TyBareFn(Option<DefId>, &'tcx BareFnTy<'tcx>),
-
-    /// A trait, defined with `trait`.
-    TyTrait(Box<TraitTy<'tcx>>),
-
-    /// The anonymous type of a closure. Used to represent the type of
-    /// `|a| a`.
-    TyClosure(DefId, Box<ClosureSubsts<'tcx>>),
-
-    /// A tuple type.  For example, `(i32, bool)`.
-    TyTuple(Vec<Ty<'tcx>>),
-
-    /// The projection of an associated type.  For example,
-    /// `<T as Trait<..>>::N`.
-    TyProjection(ProjectionTy<'tcx>),
-
-    /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
-    TyParam(ParamTy),
-
-    /// A type variable used during type-checking.
-    TyInfer(InferTy),
-
-    /// A placeholder for a type which could not be computed; this is
-    /// propagated to avoid useless error messages.
-    TyError,
-}
-
-/// A closure can be modeled as a struct that looks like:
-///
-///     struct Closure<'l0...'li, T0...Tj, U0...Uk> {
-///         upvar0: U0,
-///         ...
-///         upvark: Uk
-///     }
-///
-/// where 'l0...'li and T0...Tj are the lifetime and type parameters
-/// in scope on the function that defined the closure, and U0...Uk are
-/// type parameters representing the types of its upvars (borrowed, if
-/// appropriate).
-///
-/// So, for example, given this function:
-///
-///     fn foo<'a, T>(data: &'a mut T) {
-///          do(|| data.count += 1)
-///     }
-///
-/// the type of the closure would be something like:
-///
-///     struct Closure<'a, T, U0> {
-///         data: U0
-///     }
-///
-/// Note that the type of the upvar is not specified in the struct.
-/// You may wonder how the impl would then be able to use the upvar,
-/// if it doesn't know it's type? The answer is that the impl is
-/// (conceptually) not fully generic over Closure but rather tied to
-/// instances with the expected upvar types:
-///
-///     impl<'b, 'a, T> FnMut() for Closure<'a, T, &'b mut &'a mut T> {
-///         ...
-///     }
-///
-/// You can see that the *impl* fully specified the type of the upvar
-/// and thus knows full well that `data` has type `&'b mut &'a mut T`.
-/// (Here, I am assuming that `data` is mut-borrowed.)
-///
-/// Now, the last question you may ask is: Why include the upvar types
-/// as extra type parameters? The reason for this design is that the
-/// upvar types can reference lifetimes that are internal to the
-/// creating function. In my example above, for example, the lifetime
-/// `'b` represents the extent of the closure itself; this is some
-/// subset of `foo`, probably just the extent of the call to the to
-/// `do()`. If we just had the lifetime/type parameters from the
-/// enclosing function, we couldn't name this lifetime `'b`. Note that
-/// there can also be lifetimes in the types of the upvars themselves,
-/// if one of them happens to be a reference to something that the
-/// creating fn owns.
-///
-/// OK, you say, so why not create a more minimal set of parameters
-/// that just includes the extra lifetime parameters? The answer is
-/// primarily that it would be hard --- we don't know at the time when
-/// we create the closure type what the full types of the upvars are,
-/// nor do we know which are borrowed and which are not. In this
-/// design, we can just supply a fresh type parameter and figure that
-/// out later.
-///
-/// All right, you say, but why include the type parameters from the
-/// original function then? The answer is that trans may need them
-/// when monomorphizing, and they may not appear in the upvars.  A
-/// closure could capture no variables but still make use of some
-/// in-scope type parameter with a bound (e.g., if our example above
-/// had an extra `U: Default`, and the closure called `U::default()`).
-///
-/// There is another reason. This design (implicitly) prohibits
-/// closures from capturing themselves (except via a trait
-/// object). This simplifies closure inference considerably, since it
-/// means that when we infer the kind of a closure or its upvars, we
-/// don't have to handle cycles where the decisions we make for
-/// closure C wind up influencing the decisions we ought to make for
-/// closure C (which would then require fixed point iteration to
-/// handle). Plus it fixes an ICE. :P
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
-pub struct ClosureSubsts<'tcx> {
-    /// Lifetime and type parameters from the enclosing function.
-    /// These are separated out because trans wants to pass them around
-    /// when monomorphizing.
-    pub func_substs: &'tcx Substs<'tcx>,
-
-    /// The types of the upvars. The list parallels the freevars and
-    /// `upvar_borrows` lists. These are kept distinct so that we can
-    /// easily index into them.
-    pub upvar_tys: Vec<Ty<'tcx>>
-}
-
-#[derive(Clone, PartialEq, Eq, Hash)]
-pub struct TraitTy<'tcx> {
-    pub principal: ty::PolyTraitRef<'tcx>,
-    pub bounds: ExistentialBounds<'tcx>,
-}
-
-impl<'tcx> TraitTy<'tcx> {
-    pub fn principal_def_id(&self) -> DefId {
-        self.principal.0.def_id
-    }
-
-    /// Object types don't have a self-type specified. Therefore, when
-    /// we convert the principal trait-ref into a normal trait-ref,
-    /// you must give *some* self-type. A common choice is `mk_err()`
-    /// or some skolemized type.
-    pub fn principal_trait_ref_with_self_ty(&self,
-                                            tcx: &ctxt<'tcx>,
-                                            self_ty: Ty<'tcx>)
-                                            -> ty::PolyTraitRef<'tcx>
-    {
-        // otherwise the escaping regions would be captured by the binder
-        assert!(!self_ty.has_escaping_regions());
-
-        ty::Binder(TraitRef {
-            def_id: self.principal.0.def_id,
-            substs: tcx.mk_substs(self.principal.0.substs.with_self_ty(self_ty)),
-        })
-    }
-
-    pub fn projection_bounds_with_self_ty(&self,
-                                          tcx: &ctxt<'tcx>,
-                                          self_ty: Ty<'tcx>)
-                                          -> Vec<ty::PolyProjectionPredicate<'tcx>>
-    {
-        // otherwise the escaping regions would be captured by the binders
-        assert!(!self_ty.has_escaping_regions());
-
-        self.bounds.projection_bounds.iter()
-            .map(|in_poly_projection_predicate| {
-                let in_projection_ty = &in_poly_projection_predicate.0.projection_ty;
-                let substs = tcx.mk_substs(in_projection_ty.trait_ref.substs.with_self_ty(self_ty));
-                let trait_ref = ty::TraitRef::new(in_projection_ty.trait_ref.def_id,
-                                              substs);
-                let projection_ty = ty::ProjectionTy {
-                    trait_ref: trait_ref,
-                    item_name: in_projection_ty.item_name
-                };
-                ty::Binder(ty::ProjectionPredicate {
-                    projection_ty: projection_ty,
-                    ty: in_poly_projection_predicate.0.ty
-                })
-            })
-            .collect()
-    }
-}
-
-/// A complete reference to a trait. These take numerous guises in syntax,
-/// but perhaps the most recognizable form is in a where clause:
-///
-///     T : Foo<U>
-///
-/// This would be represented by a trait-reference where the def-id is the
-/// def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the
-/// `SelfSpace` and `U` as parameter 0 in the `TypeSpace`.
-///
-/// Trait references also appear in object types like `Foo<U>`, but in
-/// that case the `Self` parameter is absent from the substitutions.
-///
-/// Note that a `TraitRef` introduces a level of region binding, to
-/// account for higher-ranked trait bounds like `T : for<'a> Foo<&'a
-/// U>` or higher-ranked object types.
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub struct TraitRef<'tcx> {
-    pub def_id: DefId,
-    pub substs: &'tcx Substs<'tcx>,
-}
-
-pub type PolyTraitRef<'tcx> = Binder<TraitRef<'tcx>>;
-
-impl<'tcx> PolyTraitRef<'tcx> {
-    pub fn self_ty(&self) -> Ty<'tcx> {
-        self.0.self_ty()
-    }
-
-    pub fn def_id(&self) -> DefId {
-        self.0.def_id
-    }
-
-    pub fn substs(&self) -> &'tcx Substs<'tcx> {
-        // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<>
-        self.0.substs
-    }
-
-    pub fn input_types(&self) -> &[Ty<'tcx>] {
-        // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<>
-        self.0.input_types()
-    }
-
-    pub fn to_poly_trait_predicate(&self) -> PolyTraitPredicate<'tcx> {
-        // Note that we preserve binding levels
-        Binder(TraitPredicate { trait_ref: self.0.clone() })
-    }
-}
-
-/// Binder is a binder for higher-ranked lifetimes. It is part of the
-/// compiler's representation for things like `for<'a> Fn(&'a isize)`
-/// (which would be represented by the type `PolyTraitRef ==
-/// Binder<TraitRef>`). Note that when we skolemize, instantiate,
-/// erase, or otherwise "discharge" these bound regions, we change the
-/// type from `Binder<T>` to just `T` (see
-/// e.g. `liberate_late_bound_regions`).
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub struct Binder<T>(pub T);
-
-impl<T> Binder<T> {
-    /// Skips the binder and returns the "bound" value. This is a
-    /// risky thing to do because it's easy to get confused about
-    /// debruijn indices and the like. It is usually better to
-    /// discharge the binder using `no_late_bound_regions` or
-    /// `replace_late_bound_regions` or something like
-    /// that. `skip_binder` is only valid when you are either
-    /// extracting data that has nothing to do with bound regions, you
-    /// are doing some sort of test that does not involve bound
-    /// regions, or you are being very careful about your depth
-    /// accounting.
-    ///
-    /// Some examples where `skip_binder` is reasonable:
-    /// - extracting the def-id from a PolyTraitRef;
-    /// - comparing the self type of a PolyTraitRef to see if it is equal to
-    ///   a type parameter `X`, since the type `X`  does not reference any regions
-    pub fn skip_binder(&self) -> &T {
-        &self.0
-    }
-
-    pub fn as_ref(&self) -> Binder<&T> {
-        ty::Binder(&self.0)
-    }
-
-    pub fn map_bound_ref<F,U>(&self, f: F) -> Binder<U>
-        where F: FnOnce(&T) -> U
-    {
-        self.as_ref().map_bound(f)
-    }
-
-    pub fn map_bound<F,U>(self, f: F) -> Binder<U>
-        where F: FnOnce(T) -> U
-    {
-        ty::Binder(f(self.0))
-    }
-}
-
 #[derive(Clone, Copy, PartialEq)]
 pub enum IntVarValue {
     IntType(hir::IntTy),
     UintType(hir::UintTy),
 }
 
-#[derive(Clone, Copy, Debug)]
-pub struct ExpectedFound<T> {
-    pub expected: T,
-    pub found: T
-}
-
-// Data structures used in type unification
-#[derive(Clone, Debug)]
-pub enum TypeError<'tcx> {
-    Mismatch,
-    UnsafetyMismatch(ExpectedFound<hir::Unsafety>),
-    AbiMismatch(ExpectedFound<abi::Abi>),
-    Mutability,
-    BoxMutability,
-    PtrMutability,
-    RefMutability,
-    VecMutability,
-    TupleSize(ExpectedFound<usize>),
-    FixedArraySize(ExpectedFound<usize>),
-    TyParamSize(ExpectedFound<usize>),
-    ArgCount,
-    RegionsDoesNotOutlive(Region, Region),
-    RegionsNotSame(Region, Region),
-    RegionsNoOverlap(Region, Region),
-    RegionsInsufficientlyPolymorphic(BoundRegion, Region),
-    RegionsOverlyPolymorphic(BoundRegion, Region),
-    Sorts(ExpectedFound<Ty<'tcx>>),
-    IntegerAsChar,
-    IntMismatch(ExpectedFound<IntVarValue>),
-    FloatMismatch(ExpectedFound<hir::FloatTy>),
-    Traits(ExpectedFound<DefId>),
-    BuiltinBoundsMismatch(ExpectedFound<BuiltinBounds>),
-    VariadicMismatch(ExpectedFound<bool>),
-    CyclicTy,
-    ConvergenceMismatch(ExpectedFound<bool>),
-    ProjectionNameMismatched(ExpectedFound<Name>),
-    ProjectionBoundsLength(ExpectedFound<usize>),
-    TyParamDefaultMismatch(ExpectedFound<type_variable::Default<'tcx>>)
-}
-
-/// Bounds suitable for an existentially quantified type parameter
-/// such as those that appear in object types or closure types.
-#[derive(PartialEq, Eq, Hash, Clone)]
-pub struct ExistentialBounds<'tcx> {
-    pub region_bound: ty::Region,
-    pub builtin_bounds: BuiltinBounds,
-    pub projection_bounds: Vec<PolyProjectionPredicate<'tcx>>,
-}
-
-impl<'tcx> ExistentialBounds<'tcx> {
-    pub fn new(region_bound: ty::Region,
-               builtin_bounds: BuiltinBounds,
-               projection_bounds: Vec<PolyProjectionPredicate<'tcx>>)
-               -> Self {
-        let mut projection_bounds = projection_bounds;
-        ty::sort_bounds_list(&mut projection_bounds);
-        ExistentialBounds {
-            region_bound: region_bound,
-            builtin_bounds: builtin_bounds,
-            projection_bounds: projection_bounds
-        }
-    }
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
-pub struct BuiltinBounds(EnumSet<BuiltinBound>);
-
-impl BuiltinBounds {
-    pub fn empty() -> BuiltinBounds {
-        BuiltinBounds(EnumSet::new())
-    }
-
-    pub fn iter(&self) -> enum_set::Iter<BuiltinBound> {
-        self.into_iter()
-    }
-
-    pub fn to_predicates<'tcx>(&self,
-                               tcx: &ty::ctxt<'tcx>,
-                               self_ty: Ty<'tcx>) -> Vec<Predicate<'tcx>> {
-        self.iter().filter_map(|builtin_bound|
-            match traits::trait_ref_for_builtin_bound(tcx, builtin_bound, self_ty) {
-                Ok(trait_ref) => Some(trait_ref.to_predicate()),
-                Err(ErrorReported) => { None }
-            }
-        ).collect()
-    }
-}
-
-impl ops::Deref for BuiltinBounds {
-    type Target = EnumSet<BuiltinBound>;
-    fn deref(&self) -> &Self::Target { &self.0 }
-}
-
-impl ops::DerefMut for BuiltinBounds {
-    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
-}
-
-impl<'a> IntoIterator for &'a BuiltinBounds {
-    type Item = BuiltinBound;
-    type IntoIter = enum_set::Iter<BuiltinBound>;
-    fn into_iter(self) -> Self::IntoIter {
-        (**self).into_iter()
-    }
-}
-
-#[derive(Clone, RustcEncodable, PartialEq, Eq, RustcDecodable, Hash,
-           Debug, Copy)]
-#[repr(usize)]
-pub enum BuiltinBound {
-    Send,
-    Sized,
-    Copy,
-    Sync,
-}
-
-impl CLike for BuiltinBound {
-    fn to_usize(&self) -> usize {
-        *self as usize
-    }
-    fn from_usize(v: usize) -> BuiltinBound {
-        unsafe { mem::transmute(v) }
-    }
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
-pub struct TyVid {
-    pub index: u32
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
-pub struct IntVid {
-    pub index: u32
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
-pub struct FloatVid {
-    pub index: u32
-}
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
-pub struct RegionVid {
-    pub index: u32
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
-pub struct SkolemizedRegionVid {
-    pub index: u32
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
-pub enum InferTy {
-    TyVar(TyVid),
-    IntVar(IntVid),
-    FloatVar(FloatVid),
-
-    /// A `FreshTy` is one that is generated as a replacement for an
-    /// unbound type variable. This is convenient for caching etc. See
-    /// `middle::infer::freshen` for more details.
-    FreshTy(u32),
-    FreshIntTy(u32),
-    FreshFloatTy(u32)
-}
-
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
-pub enum UnconstrainedNumeric {
-    UnconstrainedFloat,
-    UnconstrainedInt,
-    Neither,
-}
-
-
-impl fmt::Debug for TyVid {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "_#{}t", self.index)
-    }
-}
-
-impl fmt::Debug for IntVid {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "_#{}i", self.index)
-    }
-}
-
-impl fmt::Debug for FloatVid {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "_#{}f", self.index)
-    }
-}
-
-impl fmt::Debug for RegionVid {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "'_#{}r", self.index)
-    }
-}
-
-impl<'tcx> fmt::Debug for FnSig<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "({:?}; variadic: {})->{:?}", self.inputs, self.variadic, self.output)
-    }
-}
-
-impl fmt::Debug for InferTy {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            TyVar(ref v) => v.fmt(f),
-            IntVar(ref v) => v.fmt(f),
-            FloatVar(ref v) => v.fmt(f),
-            FreshTy(v) => write!(f, "FreshTy({:?})", v),
-            FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v),
-            FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v)
-        }
-    }
-}
-
-impl fmt::Debug for IntVarValue {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            IntType(ref v) => v.fmt(f),
-            UintType(ref v) => v.fmt(f),
-        }
-    }
-}
-
 /// Default region to use for the bound of objects that are
 /// supplied as the value for this type parameter. This is derived
 /// from `T:'a` annotations appearing in the type definition.  If
@@ -2620,23 +1092,6 @@ pub fn sort_key(&self) -> (DefId, Name) {
     }
 }
 
-/// Represents the projection of an associated type. In explicit UFCS
-/// form this would be written `<T as Trait<..>>::N`.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub struct ProjectionTy<'tcx> {
-    /// The trait reference `T as Trait<..>`.
-    pub trait_ref: ty::TraitRef<'tcx>,
-
-    /// The name `N` of the associated type.
-    pub item_name: Name,
-}
-
-impl<'tcx> ProjectionTy<'tcx> {
-    pub fn sort_key(&self) -> (DefId, Name) {
-        (self.trait_ref.def_id, self.item_name)
-    }
-}
-
 pub trait ToPolyTraitRef<'tcx> {
     fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
 }
@@ -3314,7 +1769,7 @@ pub struct FieldDefData<'tcx, 'container: 'tcx> {
     pub vis: hir::Visibility,
     /// TyIVar is used here to allow for variance (see the doc at
     /// AdtDefData).
-    ty: TyIVar<'tcx, 'container>
+    ty: ivar::TyIVar<'tcx, 'container>
 }
 
 /// The definition of an abstract data type - a struct or enum.
@@ -3572,7 +2027,7 @@ pub fn new(did: DefId,
             did: did,
             name: name,
             vis: vis,
-            ty: TyIVar::new()
+            ty: ivar::TyIVar::new()
         }
     }
 
@@ -3638,656 +2093,64 @@ pub fn extends(self, other: ty::ClosureKind) -> bool {
     }
 }
 
-impl<'tcx> CommonTypes<'tcx> {
-    fn new(arena: &'tcx TypedArena<TyS<'tcx>>,
-           interner: &RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>)
-           -> CommonTypes<'tcx>
-    {
-        let mk = |sty| ctxt::intern_ty(arena, interner, sty);
-        CommonTypes {
-            bool: mk(TyBool),
-            char: mk(TyChar),
-            err: mk(TyError),
-            isize: mk(TyInt(hir::TyIs)),
-            i8: mk(TyInt(hir::TyI8)),
-            i16: mk(TyInt(hir::TyI16)),
-            i32: mk(TyInt(hir::TyI32)),
-            i64: mk(TyInt(hir::TyI64)),
-            usize: mk(TyUint(hir::TyUs)),
-            u8: mk(TyUint(hir::TyU8)),
-            u16: mk(TyUint(hir::TyU16)),
-            u32: mk(TyUint(hir::TyU32)),
-            u64: mk(TyUint(hir::TyU64)),
-            f32: mk(TyFloat(hir::TyF32)),
-            f64: mk(TyFloat(hir::TyF64)),
-        }
+impl<'tcx> ctxt<'tcx> {
+    pub fn pat_contains_ref_binding(&self, pat: &hir::Pat) -> Option<hir::Mutability> {
+        pat_util::pat_contains_ref_binding(&self.def_map, pat)
     }
-}
-
-struct FlagComputation {
-    flags: TypeFlags,
-
-    // maximum depth of any bound region that we have seen thus far
-    depth: u32,
-}
 
-impl FlagComputation {
-    fn new() -> FlagComputation {
-        FlagComputation { flags: TypeFlags::empty(), depth: 0 }
+    pub fn arm_contains_ref_binding(&self, arm: &hir::Arm) -> Option<hir::Mutability> {
+        pat_util::arm_contains_ref_binding(&self.def_map, arm)
     }
+}
 
-    fn for_sty(st: &TypeVariants) -> FlagComputation {
-        let mut result = FlagComputation::new();
-        result.add_sty(st);
-        result
+impl<'tcx> TyS<'tcx> {
+    /// Iterator that walks `self` and any types reachable from
+    /// `self`, in depth-first order. Note that just walks the types
+    /// that appear in `self`, it does not descend into the fields of
+    /// structs or variants. For example:
+    ///
+    /// ```notrust
+    /// isize => { isize }
+    /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
+    /// [isize] => { [isize], isize }
+    /// ```
+    pub fn walk(&'tcx self) -> TypeWalker<'tcx> {
+        TypeWalker::new(self)
     }
 
-    fn add_flags(&mut self, flags: TypeFlags) {
-        self.flags = self.flags | (flags & TypeFlags::NOMINAL_FLAGS);
+    /// Iterator that walks the immediate children of `self`.  Hence
+    /// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]`
+    /// (but not `i32`, like `walk`).
+    pub fn walk_shallow(&'tcx self) -> IntoIter<Ty<'tcx>> {
+        walk::walk_shallow(self)
     }
 
-    fn add_depth(&mut self, depth: u32) {
-        if depth > self.depth {
-            self.depth = depth;
+    pub fn as_opt_param_ty(&self) -> Option<ty::ParamTy> {
+        match self.sty {
+            ty::TyParam(ref d) => Some(d.clone()),
+            _ => None,
         }
     }
 
-    /// Adds the flags/depth from a set of types that appear within the current type, but within a
-    /// region binder.
-    fn add_bound_computation(&mut self, computation: &FlagComputation) {
-        self.add_flags(computation.flags);
-
-        // The types that contributed to `computation` occurred within
-        // a region binder, so subtract one from the region depth
-        // within when adding the depth to `self`.
-        let depth = computation.depth;
-        if depth > 0 {
-            self.add_depth(depth - 1);
+    pub fn is_param(&self, space: ParamSpace, index: u32) -> bool {
+        match self.sty {
+            ty::TyParam(ref data) => data.space == space && data.idx == index,
+            _ => false,
         }
     }
 
-    fn add_sty(&mut self, st: &TypeVariants) {
-        match st {
-            &TyBool |
-            &TyChar |
-            &TyInt(_) |
-            &TyFloat(_) |
-            &TyUint(_) |
-            &TyStr => {
-            }
-
-            // You might think that we could just return TyError for
-            // any type containing TyError as a component, and get
-            // rid of the TypeFlags::HAS_TY_ERR flag -- likewise for ty_bot (with
-            // the exception of function types that return bot).
-            // But doing so caused sporadic memory corruption, and
-            // neither I (tjc) nor nmatsakis could figure out why,
-            // so we're doing it this way.
-            &TyError => {
-                self.add_flags(TypeFlags::HAS_TY_ERR)
+    /// Returns the regions directly referenced from this type (but
+    /// not types reachable from this type via `walk_tys`). This
+    /// ignores late-bound regions binders.
+    pub fn regions(&self) -> Vec<ty::Region> {
+        match self.sty {
+            TyRef(region, _) => {
+                vec![*region]
             }
-
-            &TyParam(ref p) => {
-                self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
-                if p.space == subst::SelfSpace {
-                    self.add_flags(TypeFlags::HAS_SELF);
-                } else {
-                    self.add_flags(TypeFlags::HAS_PARAMS);
-                }
-            }
-
-            &TyClosure(_, ref substs) => {
-                self.add_flags(TypeFlags::HAS_TY_CLOSURE);
-                self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
-                self.add_substs(&substs.func_substs);
-                self.add_tys(&substs.upvar_tys);
-            }
-
-            &TyInfer(_) => {
-                self.add_flags(TypeFlags::HAS_LOCAL_NAMES); // it might, right?
-                self.add_flags(TypeFlags::HAS_TY_INFER)
-            }
-
-            &TyEnum(_, substs) | &TyStruct(_, substs) => {
-                self.add_substs(substs);
-            }
-
-            &TyProjection(ref data) => {
-                self.add_flags(TypeFlags::HAS_PROJECTION);
-                self.add_projection_ty(data);
-            }
-
-            &TyTrait(box TraitTy { ref principal, ref bounds }) => {
-                let mut computation = FlagComputation::new();
-                computation.add_substs(principal.0.substs);
-                for projection_bound in &bounds.projection_bounds {
-                    let mut proj_computation = FlagComputation::new();
-                    proj_computation.add_projection_predicate(&projection_bound.0);
-                    self.add_bound_computation(&proj_computation);
-                }
-                self.add_bound_computation(&computation);
-
-                self.add_bounds(bounds);
-            }
-
-            &TyBox(tt) | &TyArray(tt, _) | &TySlice(tt) => {
-                self.add_ty(tt)
-            }
-
-            &TyRawPtr(ref m) => {
-                self.add_ty(m.ty);
-            }
-
-            &TyRef(r, ref m) => {
-                self.add_region(*r);
-                self.add_ty(m.ty);
-            }
-
-            &TyTuple(ref ts) => {
-                self.add_tys(&ts[..]);
-            }
-
-            &TyBareFn(_, ref f) => {
-                self.add_fn_sig(&f.sig);
-            }
-        }
-    }
-
-    fn add_ty(&mut self, ty: Ty) {
-        self.add_flags(ty.flags.get());
-        self.add_depth(ty.region_depth);
-    }
-
-    fn add_tys(&mut self, tys: &[Ty]) {
-        for &ty in tys {
-            self.add_ty(ty);
-        }
-    }
-
-    fn add_fn_sig(&mut self, fn_sig: &PolyFnSig) {
-        let mut computation = FlagComputation::new();
-
-        computation.add_tys(&fn_sig.0.inputs);
-
-        if let ty::FnConverging(output) = fn_sig.0.output {
-            computation.add_ty(output);
-        }
-
-        self.add_bound_computation(&computation);
-    }
-
-    fn add_region(&mut self, r: Region) {
-        match r {
-            ty::ReVar(..) |
-            ty::ReSkolemized(..) => { self.add_flags(TypeFlags::HAS_RE_INFER); }
-            ty::ReLateBound(debruijn, _) => { self.add_depth(debruijn.depth); }
-            ty::ReEarlyBound(..) => { self.add_flags(TypeFlags::HAS_RE_EARLY_BOUND); }
-            ty::ReStatic => {}
-            _ => { self.add_flags(TypeFlags::HAS_FREE_REGIONS); }
-        }
-
-        if !r.is_global() {
-            self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
-        }
-    }
-
-    fn add_projection_predicate(&mut self, projection_predicate: &ProjectionPredicate) {
-        self.add_projection_ty(&projection_predicate.projection_ty);
-        self.add_ty(projection_predicate.ty);
-    }
-
-    fn add_projection_ty(&mut self, projection_ty: &ProjectionTy) {
-        self.add_substs(projection_ty.trait_ref.substs);
-    }
-
-    fn add_substs(&mut self, substs: &Substs) {
-        self.add_tys(substs.types.as_slice());
-        match substs.regions {
-            subst::ErasedRegions => {}
-            subst::NonerasedRegions(ref regions) => {
-                for &r in regions {
-                    self.add_region(r);
-                }
-            }
-        }
-    }
-
-    fn add_bounds(&mut self, bounds: &ExistentialBounds) {
-        self.add_region(bounds.region_bound);
-    }
-}
-
-impl<'tcx> ctxt<'tcx> {
-    /// Create a type context and call the closure with a `&ty::ctxt` reference
-    /// to the context. The closure enforces that the type context and any interned
-    /// value (types, substs, etc.) can only be used while `ty::tls` has a valid
-    /// reference to the context, to allow formatting values that need it.
-    pub fn create_and_enter<F, R>(s: Session,
-                                 arenas: &'tcx CtxtArenas<'tcx>,
-                                 def_map: DefMap,
-                                 named_region_map: resolve_lifetime::NamedRegionMap,
-                                 map: ast_map::Map<'tcx>,
-                                 freevars: RefCell<FreevarMap>,
-                                 region_maps: RegionMaps,
-                                 lang_items: middle::lang_items::LanguageItems,
-                                 stability: stability::Index<'tcx>,
-                                 f: F) -> (Session, R)
-                                 where F: FnOnce(&ctxt<'tcx>) -> R
-    {
-        let interner = RefCell::new(FnvHashMap());
-        let common_types = CommonTypes::new(&arenas.type_, &interner);
-
-        tls::enter(ctxt {
-            arenas: arenas,
-            interner: interner,
-            substs_interner: RefCell::new(FnvHashMap()),
-            bare_fn_interner: RefCell::new(FnvHashMap()),
-            region_interner: RefCell::new(FnvHashMap()),
-            stability_interner: RefCell::new(FnvHashMap()),
-            types: common_types,
-            named_region_map: named_region_map,
-            region_maps: region_maps,
-            free_region_maps: RefCell::new(FnvHashMap()),
-            item_variance_map: RefCell::new(DefIdMap()),
-            variance_computed: Cell::new(false),
-            sess: s,
-            def_map: def_map,
-            tables: RefCell::new(Tables::empty()),
-            impl_trait_refs: RefCell::new(DefIdMap()),
-            trait_defs: RefCell::new(DefIdMap()),
-            adt_defs: RefCell::new(DefIdMap()),
-            predicates: RefCell::new(DefIdMap()),
-            super_predicates: RefCell::new(DefIdMap()),
-            fulfilled_predicates: RefCell::new(traits::FulfilledPredicates::new()),
-            map: map,
-            freevars: freevars,
-            tcache: RefCell::new(DefIdMap()),
-            rcache: RefCell::new(FnvHashMap()),
-            tc_cache: RefCell::new(FnvHashMap()),
-            ast_ty_to_ty_cache: RefCell::new(NodeMap()),
-            impl_or_trait_items: RefCell::new(DefIdMap()),
-            trait_item_def_ids: RefCell::new(DefIdMap()),
-            trait_items_cache: RefCell::new(DefIdMap()),
-            ty_param_defs: RefCell::new(NodeMap()),
-            normalized_cache: RefCell::new(FnvHashMap()),
-            lang_items: lang_items,
-            provided_method_sources: RefCell::new(DefIdMap()),
-            destructors: RefCell::new(DefIdSet()),
-            inherent_impls: RefCell::new(DefIdMap()),
-            impl_items: RefCell::new(DefIdMap()),
-            used_unsafe: RefCell::new(NodeSet()),
-            used_mut_nodes: RefCell::new(NodeSet()),
-            populated_external_types: RefCell::new(DefIdSet()),
-            populated_external_primitive_impls: RefCell::new(DefIdSet()),
-            extern_const_statics: RefCell::new(DefIdMap()),
-            extern_const_variants: RefCell::new(DefIdMap()),
-            extern_const_fns: RefCell::new(DefIdMap()),
-            node_lint_levels: RefCell::new(FnvHashMap()),
-            transmute_restrictions: RefCell::new(Vec::new()),
-            stability: RefCell::new(stability),
-            selection_cache: traits::SelectionCache::new(),
-            repr_hint_cache: RefCell::new(DefIdMap()),
-            const_qualif_map: RefCell::new(NodeMap()),
-            custom_coerce_unsized_kinds: RefCell::new(DefIdMap()),
-            cast_kinds: RefCell::new(NodeMap()),
-            fragment_infos: RefCell::new(DefIdMap()),
-       }, f)
-    }
-
-    // Type constructors
-
-    pub fn mk_substs(&self, substs: Substs<'tcx>) -> &'tcx Substs<'tcx> {
-        if let Some(substs) = self.substs_interner.borrow().get(&substs) {
-            return *substs;
-        }
-
-        let substs = self.arenas.substs.alloc(substs);
-        self.substs_interner.borrow_mut().insert(substs, substs);
-        substs
-    }
-
-    /// Create an unsafe fn ty based on a safe fn ty.
-    pub fn safe_to_unsafe_fn_ty(&self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> {
-        assert_eq!(bare_fn.unsafety, hir::Unsafety::Normal);
-        let unsafe_fn_ty_a = self.mk_bare_fn(ty::BareFnTy {
-            unsafety: hir::Unsafety::Unsafe,
-            abi: bare_fn.abi,
-            sig: bare_fn.sig.clone()
-        });
-        self.mk_fn(None, unsafe_fn_ty_a)
-    }
-
-    pub fn mk_bare_fn(&self, bare_fn: BareFnTy<'tcx>) -> &'tcx BareFnTy<'tcx> {
-        if let Some(bare_fn) = self.bare_fn_interner.borrow().get(&bare_fn) {
-            return *bare_fn;
-        }
-
-        let bare_fn = self.arenas.bare_fn.alloc(bare_fn);
-        self.bare_fn_interner.borrow_mut().insert(bare_fn, bare_fn);
-        bare_fn
-    }
-
-    pub fn mk_region(&self, region: Region) -> &'tcx Region {
-        if let Some(region) = self.region_interner.borrow().get(&region) {
-            return *region;
-        }
-
-        let region = self.arenas.region.alloc(region);
-        self.region_interner.borrow_mut().insert(region, region);
-        region
-    }
-
-    pub fn closure_kind(&self, def_id: DefId) -> ty::ClosureKind {
-        *self.tables.borrow().closure_kinds.get(&def_id).unwrap()
-    }
-
-    pub fn closure_type(&self,
-                        def_id: DefId,
-                        substs: &ClosureSubsts<'tcx>)
-                        -> ty::ClosureTy<'tcx>
-    {
-        self.tables.borrow().closure_tys.get(&def_id).unwrap().subst(self, &substs.func_substs)
-    }
-
-    pub fn type_parameter_def(&self,
-                              node_id: NodeId)
-                              -> TypeParameterDef<'tcx>
-    {
-        self.ty_param_defs.borrow().get(&node_id).unwrap().clone()
-    }
-
-    pub fn pat_contains_ref_binding(&self, pat: &hir::Pat) -> Option<hir::Mutability> {
-        pat_util::pat_contains_ref_binding(&self.def_map, pat)
-    }
-
-    pub fn arm_contains_ref_binding(&self, arm: &hir::Arm) -> Option<hir::Mutability> {
-        pat_util::arm_contains_ref_binding(&self.def_map, arm)
-    }
-
-    fn intern_ty(type_arena: &'tcx TypedArena<TyS<'tcx>>,
-                 interner: &RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>,
-                 st: TypeVariants<'tcx>)
-                 -> Ty<'tcx> {
-        let ty: Ty /* don't be &mut TyS */ = {
-            let mut interner = interner.borrow_mut();
-            match interner.get(&st) {
-                Some(ty) => return *ty,
-                _ => ()
-            }
-
-            let flags = FlagComputation::for_sty(&st);
-
-            let ty = match () {
-                () => type_arena.alloc(TyS { sty: st,
-                                             flags: Cell::new(flags.flags),
-                                             region_depth: flags.depth, }),
-            };
-
-            interner.insert(InternedTy { ty: ty }, ty);
-            ty
-        };
-
-        debug!("Interned type: {:?} Pointer: {:?}",
-            ty, ty as *const TyS);
-        ty
-    }
-
-    // Interns a type/name combination, stores the resulting box in cx.interner,
-    // and returns the box as cast to an unsafe ptr (see comments for Ty above).
-    pub fn mk_ty(&self, st: TypeVariants<'tcx>) -> Ty<'tcx> {
-        ctxt::intern_ty(&self.arenas.type_, &self.interner, st)
-    }
-
-    pub fn mk_mach_int(&self, tm: hir::IntTy) -> Ty<'tcx> {
-        match tm {
-            hir::TyIs   => self.types.isize,
-            hir::TyI8   => self.types.i8,
-            hir::TyI16  => self.types.i16,
-            hir::TyI32  => self.types.i32,
-            hir::TyI64  => self.types.i64,
-        }
-    }
-
-    pub fn mk_mach_uint(&self, tm: hir::UintTy) -> Ty<'tcx> {
-        match tm {
-            hir::TyUs   => self.types.usize,
-            hir::TyU8   => self.types.u8,
-            hir::TyU16  => self.types.u16,
-            hir::TyU32  => self.types.u32,
-            hir::TyU64  => self.types.u64,
-        }
-    }
-
-    pub fn mk_mach_float(&self, tm: hir::FloatTy) -> Ty<'tcx> {
-        match tm {
-            hir::TyF32  => self.types.f32,
-            hir::TyF64  => self.types.f64,
-        }
-    }
-
-    pub fn mk_str(&self) -> Ty<'tcx> {
-        self.mk_ty(TyStr)
-    }
-
-    pub fn mk_static_str(&self) -> Ty<'tcx> {
-        self.mk_imm_ref(self.mk_region(ty::ReStatic), self.mk_str())
-    }
-
-    pub fn mk_enum(&self, def: AdtDef<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
-        // take a copy of substs so that we own the vectors inside
-        self.mk_ty(TyEnum(def, substs))
-    }
-
-    pub fn mk_box(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ty(TyBox(ty))
-    }
-
-    pub fn mk_ptr(&self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
-        self.mk_ty(TyRawPtr(tm))
-    }
-
-    pub fn mk_ref(&self, r: &'tcx Region, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
-        self.mk_ty(TyRef(r, tm))
-    }
-
-    pub fn mk_mut_ref(&self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutMutable})
-    }
-
-    pub fn mk_imm_ref(&self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutImmutable})
-    }
-
-    pub fn mk_mut_ptr(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutMutable})
-    }
-
-    pub fn mk_imm_ptr(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutImmutable})
-    }
-
-    pub fn mk_nil_ptr(&self) -> Ty<'tcx> {
-        self.mk_imm_ptr(self.mk_nil())
-    }
-
-    pub fn mk_array(&self, ty: Ty<'tcx>, n: usize) -> Ty<'tcx> {
-        self.mk_ty(TyArray(ty, n))
-    }
-
-    pub fn mk_slice(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.mk_ty(TySlice(ty))
-    }
-
-    pub fn mk_tup(&self, ts: Vec<Ty<'tcx>>) -> Ty<'tcx> {
-        self.mk_ty(TyTuple(ts))
-    }
-
-    pub fn mk_nil(&self) -> Ty<'tcx> {
-        self.mk_tup(Vec::new())
-    }
-
-    pub fn mk_bool(&self) -> Ty<'tcx> {
-        self.mk_ty(TyBool)
-    }
-
-    pub fn mk_fn(&self,
-                 opt_def_id: Option<DefId>,
-                 fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> {
-        self.mk_ty(TyBareFn(opt_def_id, fty))
-    }
-
-    pub fn mk_ctor_fn(&self,
-                      def_id: DefId,
-                      input_tys: &[Ty<'tcx>],
-                      output: Ty<'tcx>) -> Ty<'tcx> {
-        let input_args = input_tys.iter().cloned().collect();
-        self.mk_fn(Some(def_id), self.mk_bare_fn(BareFnTy {
-            unsafety: hir::Unsafety::Normal,
-            abi: abi::Rust,
-            sig: ty::Binder(FnSig {
-                inputs: input_args,
-                output: ty::FnConverging(output),
-                variadic: false
-            })
-        }))
-    }
-
-    pub fn mk_trait(&self,
-                    principal: ty::PolyTraitRef<'tcx>,
-                    bounds: ExistentialBounds<'tcx>)
-                    -> Ty<'tcx>
-    {
-        assert!(bound_list_is_sorted(&bounds.projection_bounds));
-
-        let inner = box TraitTy {
-            principal: principal,
-            bounds: bounds
-        };
-        self.mk_ty(TyTrait(inner))
-    }
-
-    pub fn mk_projection(&self,
-                         trait_ref: TraitRef<'tcx>,
-                         item_name: Name)
-                         -> Ty<'tcx> {
-        // take a copy of substs so that we own the vectors inside
-        let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name };
-        self.mk_ty(TyProjection(inner))
-    }
-
-    pub fn mk_struct(&self, def: AdtDef<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
-        // take a copy of substs so that we own the vectors inside
-        self.mk_ty(TyStruct(def, substs))
-    }
-
-    pub fn mk_closure(&self,
-                      closure_id: DefId,
-                      substs: &'tcx Substs<'tcx>,
-                      tys: Vec<Ty<'tcx>>)
-                      -> Ty<'tcx> {
-        self.mk_closure_from_closure_substs(closure_id, Box::new(ClosureSubsts {
-            func_substs: substs,
-            upvar_tys: tys
-        }))
-    }
-
-    pub fn mk_closure_from_closure_substs(&self,
-                                          closure_id: DefId,
-                                          closure_substs: Box<ClosureSubsts<'tcx>>)
-                                          -> Ty<'tcx> {
-        self.mk_ty(TyClosure(closure_id, closure_substs))
-    }
-
-    pub fn mk_var(&self, v: TyVid) -> Ty<'tcx> {
-        self.mk_infer(TyVar(v))
-    }
-
-    pub fn mk_int_var(&self, v: IntVid) -> Ty<'tcx> {
-        self.mk_infer(IntVar(v))
-    }
-
-    pub fn mk_float_var(&self, v: FloatVid) -> Ty<'tcx> {
-        self.mk_infer(FloatVar(v))
-    }
-
-    pub fn mk_infer(&self, it: InferTy) -> Ty<'tcx> {
-        self.mk_ty(TyInfer(it))
-    }
-
-    pub fn mk_param(&self,
-                    space: subst::ParamSpace,
-                    index: u32,
-                    name: Name) -> Ty<'tcx> {
-        self.mk_ty(TyParam(ParamTy { space: space, idx: index, name: name }))
-    }
-
-    pub fn mk_self_type(&self) -> Ty<'tcx> {
-        self.mk_param(subst::SelfSpace, 0, special_idents::type_self.name)
-    }
-
-    pub fn mk_param_from_def(&self, def: &TypeParameterDef) -> Ty<'tcx> {
-        self.mk_param(def.space, def.index, def.name)
-    }
-}
-
-fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool {
-    bounds.is_empty() ||
-        bounds[1..].iter().enumerate().all(
-            |(index, bound)| bounds[index].sort_key() <= bound.sort_key())
-}
-
-pub fn sort_bounds_list(bounds: &mut [ty::PolyProjectionPredicate]) {
-    bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key()))
-}
-
-impl<'tcx> TyS<'tcx> {
-    /// Iterator that walks `self` and any types reachable from
-    /// `self`, in depth-first order. Note that just walks the types
-    /// that appear in `self`, it does not descend into the fields of
-    /// structs or variants. For example:
-    ///
-    /// ```notrust
-    /// isize => { isize }
-    /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
-    /// [isize] => { [isize], isize }
-    /// ```
-    pub fn walk(&'tcx self) -> TypeWalker<'tcx> {
-        TypeWalker::new(self)
-    }
-
-    /// Iterator that walks the immediate children of `self`.  Hence
-    /// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]`
-    /// (but not `i32`, like `walk`).
-    pub fn walk_shallow(&'tcx self) -> IntoIter<Ty<'tcx>> {
-        walk::walk_shallow(self)
-    }
-
-    pub fn as_opt_param_ty(&self) -> Option<ty::ParamTy> {
-        match self.sty {
-            ty::TyParam(ref d) => Some(d.clone()),
-            _ => None,
-        }
-    }
-
-    pub fn is_param(&self, space: ParamSpace, index: u32) -> bool {
-        match self.sty {
-            ty::TyParam(ref data) => data.space == space && data.idx == index,
-            _ => false,
-        }
-    }
-
-    /// Returns the regions directly referenced from this type (but
-    /// not types reachable from this type via `walk_tys`). This
-    /// ignores late-bound regions binders.
-    pub fn regions(&self) -> Vec<ty::Region> {
-        match self.sty {
-            TyRef(region, _) => {
-                vec![*region]
-            }
-            TyTrait(ref obj) => {
-                let mut v = vec![obj.bounds.region_bound];
-                v.push_all(obj.principal.skip_binder().substs.regions().as_slice());
-                v
+            TyTrait(ref obj) => {
+                let mut v = vec![obj.bounds.region_bound];
+                v.push_all(obj.principal.skip_binder().substs.regions().as_slice());
+                v
             }
             TyEnum(_, substs) |
             TyStruct(_, substs) => {
@@ -4315,457 +2178,63 @@ pub fn regions(&self) -> Vec<ty::Region> {
             TyInfer(_) |
             TyError => {
                 vec![]
-            }
-        }
-    }
-
-    /// Walks `ty` and any types appearing within `ty`, invoking the
-    /// callback `f` on each type. If the callback returns false, then the
-    /// children of the current type are ignored.
-    ///
-    /// Note: prefer `ty.walk()` where possible.
-    pub fn maybe_walk<F>(&'tcx self, mut f: F)
-        where F : FnMut(Ty<'tcx>) -> bool
-    {
-        let mut walker = self.walk();
-        while let Some(ty) = walker.next() {
-            if !f(ty) {
-                walker.skip_current_subtree();
-            }
-        }
-    }
-}
-
-impl ParamTy {
-    pub fn new(space: subst::ParamSpace,
-               index: u32,
-               name: Name)
-               -> ParamTy {
-        ParamTy { space: space, idx: index, name: name }
-    }
-
-    pub fn for_self() -> ParamTy {
-        ParamTy::new(subst::SelfSpace, 0, special_idents::type_self.name)
-    }
-
-    pub fn for_def(def: &TypeParameterDef) -> ParamTy {
-        ParamTy::new(def.space, def.index, def.name)
-    }
-
-    pub fn to_ty<'tcx>(self, tcx: &ctxt<'tcx>) -> Ty<'tcx> {
-        tcx.mk_param(self.space, self.idx, self.name)
-    }
-
-    pub fn is_self(&self) -> bool {
-        self.space == subst::SelfSpace && self.idx == 0
-    }
-}
-
-impl<'tcx> ItemSubsts<'tcx> {
-    pub fn empty() -> ItemSubsts<'tcx> {
-        ItemSubsts { substs: Substs::empty() }
-    }
-
-    pub fn is_noop(&self) -> bool {
-        self.substs.is_noop()
-    }
-}
-
-// Type utilities
-impl<'tcx> TyS<'tcx> {
-    pub fn is_nil(&self) -> bool {
-        match self.sty {
-            TyTuple(ref tys) => tys.is_empty(),
-            _ => false
-        }
-    }
-
-    pub fn is_empty(&self, _cx: &ctxt) -> bool {
-        // FIXME(#24885): be smarter here
-        match self.sty {
-            TyEnum(def, _) | TyStruct(def, _) => def.is_empty(),
-            _ => false
-        }
-    }
-
-    pub fn is_ty_var(&self) -> bool {
-        match self.sty {
-            TyInfer(TyVar(_)) => true,
-            _ => false
-        }
-    }
-
-    pub fn is_bool(&self) -> bool { self.sty == TyBool }
-
-    pub fn is_self(&self) -> bool {
-        match self.sty {
-            TyParam(ref p) => p.space == subst::SelfSpace,
-            _ => false
-        }
-    }
-
-    fn is_slice(&self) -> bool {
-        match self.sty {
-            TyRawPtr(mt) | TyRef(_, mt) => match mt.ty.sty {
-                TySlice(_) | TyStr => true,
-                _ => false,
-            },
-            _ => false
-        }
-    }
-
-    pub fn is_structural(&self) -> bool {
-        match self.sty {
-            TyStruct(..) | TyTuple(_) | TyEnum(..) |
-            TyArray(..) | TyClosure(..) => true,
-            _ => self.is_slice() | self.is_trait()
-        }
-    }
-
-    #[inline]
-    pub fn is_simd(&self) -> bool {
-        match self.sty {
-            TyStruct(def, _) => def.is_simd(),
-            _ => false
-        }
-    }
-
-    pub fn sequence_element_type(&self, cx: &ctxt<'tcx>) -> Ty<'tcx> {
-        match self.sty {
-            TyArray(ty, _) | TySlice(ty) => ty,
-            TyStr => cx.mk_mach_uint(hir::TyU8),
-            _ => cx.sess.bug(&format!("sequence_element_type called on non-sequence value: {}",
-                                      self)),
-        }
-    }
-
-    pub fn simd_type(&self, cx: &ctxt<'tcx>) -> Ty<'tcx> {
-        match self.sty {
-            TyStruct(def, substs) => {
-                def.struct_variant().fields[0].ty(cx, substs)
-            }
-            _ => panic!("simd_type called on invalid type")
-        }
-    }
-
-    pub fn simd_size(&self, _cx: &ctxt) -> usize {
-        match self.sty {
-            TyStruct(def, _) => def.struct_variant().fields.len(),
-            _ => panic!("simd_size called on invalid type")
-        }
-    }
-
-    pub fn is_region_ptr(&self) -> bool {
-        match self.sty {
-            TyRef(..) => true,
-            _ => false
-        }
-    }
-
-    pub fn is_unsafe_ptr(&self) -> bool {
-        match self.sty {
-            TyRawPtr(_) => return true,
-            _ => return false
-        }
-    }
-
-    pub fn is_unique(&self) -> bool {
-        match self.sty {
-            TyBox(_) => true,
-            _ => false
-        }
-    }
-
-    /*
-     A scalar type is one that denotes an atomic datum, with no sub-components.
-     (A TyRawPtr is scalar because it represents a non-managed pointer, so its
-     contents are abstract to rustc.)
-    */
-    pub fn is_scalar(&self) -> bool {
-        match self.sty {
-            TyBool | TyChar | TyInt(_) | TyFloat(_) | TyUint(_) |
-            TyInfer(IntVar(_)) | TyInfer(FloatVar(_)) |
-            TyBareFn(..) | TyRawPtr(_) => true,
-            _ => false
-        }
-    }
-
-    /// Returns true if this type is a floating point type and false otherwise.
-    pub fn is_floating_point(&self) -> bool {
-        match self.sty {
-            TyFloat(_) |
-            TyInfer(FloatVar(_)) => true,
-            _ => false,
-        }
-    }
-
-    pub fn ty_to_def_id(&self) -> Option<DefId> {
-        match self.sty {
-            TyTrait(ref tt) => Some(tt.principal_def_id()),
-            TyStruct(def, _) |
-            TyEnum(def, _) => Some(def.did),
-            TyClosure(id, _) => Some(id),
-            _ => None
-        }
-    }
-
-    pub fn ty_adt_def(&self) -> Option<AdtDef<'tcx>> {
-        match self.sty {
-            TyStruct(adt, _) | TyEnum(adt, _) => Some(adt),
-            _ => None
-        }
-    }
-}
-
-/// Type contents is how the type checker reasons about kinds.
-/// They track what kinds of things are found within a type.  You can
-/// think of them as kind of an "anti-kind".  They track the kinds of values
-/// and thinks that are contained in types.  Having a larger contents for
-/// a type tends to rule that type *out* from various kinds.  For example,
-/// a type that contains a reference is not sendable.
-///
-/// The reason we compute type contents and not kinds is that it is
-/// easier for me (nmatsakis) to think about what is contained within
-/// a type than to think about what is *not* contained within a type.
-#[derive(Clone, Copy)]
-pub struct TypeContents {
-    pub bits: u64
-}
-
-macro_rules! def_type_content_sets {
-    (mod $mname:ident { $($name:ident = $bits:expr),+ }) => {
-        #[allow(non_snake_case)]
-        mod $mname {
-            use middle::ty::TypeContents;
-            $(
-                #[allow(non_upper_case_globals)]
-                pub const $name: TypeContents = TypeContents { bits: $bits };
-             )+
+            }
         }
     }
-}
-
-def_type_content_sets! {
-    mod TC {
-        None                                = 0b0000_0000__0000_0000__0000,
-
-        // Things that are interior to the value (first nibble):
-        InteriorUnsafe                      = 0b0000_0000__0000_0000__0010,
-        InteriorParam                       = 0b0000_0000__0000_0000__0100,
-        // InteriorAll                         = 0b00000000__00000000__1111,
 
-        // Things that are owned by the value (second and third nibbles):
-        OwnsOwned                           = 0b0000_0000__0000_0001__0000,
-        OwnsDtor                            = 0b0000_0000__0000_0010__0000,
-        OwnsAll                             = 0b0000_0000__1111_1111__0000,
-
-        // Things that mean drop glue is necessary
-        NeedsDrop                           = 0b0000_0000__0000_0111__0000,
-
-        // All bits
-        All                                 = 0b1111_1111__1111_1111__1111
+    /// Walks `ty` and any types appearing within `ty`, invoking the
+    /// callback `f` on each type. If the callback returns false, then the
+    /// children of the current type are ignored.
+    ///
+    /// Note: prefer `ty.walk()` where possible.
+    pub fn maybe_walk<F>(&'tcx self, mut f: F)
+        where F : FnMut(Ty<'tcx>) -> bool
+    {
+        let mut walker = self.walk();
+        while let Some(ty) = walker.next() {
+            if !f(ty) {
+                walker.skip_current_subtree();
+            }
+        }
     }
 }
 
-impl TypeContents {
-    pub fn when(&self, cond: bool) -> TypeContents {
-        if cond {*self} else {TC::None}
-    }
-
-    pub fn intersects(&self, tc: TypeContents) -> bool {
-        (self.bits & tc.bits) != 0
-    }
-
-    pub fn owns_owned(&self) -> bool {
-        self.intersects(TC::OwnsOwned)
-    }
-
-    pub fn interior_param(&self) -> bool {
-        self.intersects(TC::InteriorParam)
-    }
-
-    pub fn interior_unsafe(&self) -> bool {
-        self.intersects(TC::InteriorUnsafe)
-    }
-
-    pub fn needs_drop(&self, _: &ctxt) -> bool {
-        self.intersects(TC::NeedsDrop)
-    }
-
-    /// Includes only those bits that still apply when indirected through a `Box` pointer
-    pub fn owned_pointer(&self) -> TypeContents {
-        TC::OwnsOwned | (*self & TC::OwnsAll)
+impl ParamTy {
+    pub fn new(space: subst::ParamSpace,
+               index: u32,
+               name: Name)
+               -> ParamTy {
+        ParamTy { space: space, idx: index, name: name }
     }
 
-    pub fn union<T, F>(v: &[T], mut f: F) -> TypeContents where
-        F: FnMut(&T) -> TypeContents,
-    {
-        v.iter().fold(TC::None, |tc, ty| tc | f(ty))
+    pub fn for_self() -> ParamTy {
+        ParamTy::new(subst::SelfSpace, 0, special_idents::type_self.name)
     }
 
-    pub fn has_dtor(&self) -> bool {
-        self.intersects(TC::OwnsDtor)
+    pub fn for_def(def: &TypeParameterDef) -> ParamTy {
+        ParamTy::new(def.space, def.index, def.name)
     }
-}
-
-impl ops::BitOr for TypeContents {
-    type Output = TypeContents;
 
-    fn bitor(self, other: TypeContents) -> TypeContents {
-        TypeContents {bits: self.bits | other.bits}
+    pub fn to_ty<'tcx>(self, tcx: &ctxt<'tcx>) -> Ty<'tcx> {
+        tcx.mk_param(self.space, self.idx, self.name)
     }
-}
-
-impl ops::BitAnd for TypeContents {
-    type Output = TypeContents;
 
-    fn bitand(self, other: TypeContents) -> TypeContents {
-        TypeContents {bits: self.bits & other.bits}
+    pub fn is_self(&self) -> bool {
+        self.space == subst::SelfSpace && self.idx == 0
     }
 }
 
-impl ops::Sub for TypeContents {
-    type Output = TypeContents;
-
-    fn sub(self, other: TypeContents) -> TypeContents {
-        TypeContents {bits: self.bits & !other.bits}
+impl<'tcx> ItemSubsts<'tcx> {
+    pub fn empty() -> ItemSubsts<'tcx> {
+        ItemSubsts { substs: Substs::empty() }
     }
-}
 
-impl fmt::Debug for TypeContents {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "TypeContents({:b})", self.bits)
+    pub fn is_noop(&self) -> bool {
+        self.substs.is_noop()
     }
 }
 
 impl<'tcx> TyS<'tcx> {
-    pub fn type_contents(&'tcx self, cx: &ctxt<'tcx>) -> TypeContents {
-        return memoized(&cx.tc_cache, self, |ty| {
-            tc_ty(cx, ty, &mut FnvHashMap())
-        });
-
-        fn tc_ty<'tcx>(cx: &ctxt<'tcx>,
-                       ty: Ty<'tcx>,
-                       cache: &mut FnvHashMap<Ty<'tcx>, TypeContents>) -> TypeContents
-        {
-            // Subtle: Note that we are *not* using cx.tc_cache here but rather a
-            // private cache for this walk.  This is needed in the case of cyclic
-            // types like:
-            //
-            //     struct List { next: Box<Option<List>>, ... }
-            //
-            // When computing the type contents of such a type, we wind up deeply
-            // recursing as we go.  So when we encounter the recursive reference
-            // to List, we temporarily use TC::None as its contents.  Later we'll
-            // patch up the cache with the correct value, once we've computed it
-            // (this is basically a co-inductive process, if that helps).  So in
-            // the end we'll compute TC::OwnsOwned, in this case.
-            //
-            // The problem is, as we are doing the computation, we will also
-            // compute an *intermediate* contents for, e.g., Option<List> of
-            // TC::None.  This is ok during the computation of List itself, but if
-            // we stored this intermediate value into cx.tc_cache, then later
-            // requests for the contents of Option<List> would also yield TC::None
-            // which is incorrect.  This value was computed based on the crutch
-            // value for the type contents of list.  The correct value is
-            // TC::OwnsOwned.  This manifested as issue #4821.
-            match cache.get(&ty) {
-                Some(tc) => { return *tc; }
-                None => {}
-            }
-            match cx.tc_cache.borrow().get(&ty) {    // Must check both caches!
-                Some(tc) => { return *tc; }
-                None => {}
-            }
-            cache.insert(ty, TC::None);
-
-            let result = match ty.sty {
-                // usize and isize are ffi-unsafe
-                TyUint(hir::TyUs) | TyInt(hir::TyIs) => {
-                    TC::None
-                }
-
-                // Scalar and unique types are sendable, and durable
-                TyInfer(ty::FreshIntTy(_)) | TyInfer(ty::FreshFloatTy(_)) |
-                TyBool | TyInt(_) | TyUint(_) | TyFloat(_) |
-                TyBareFn(..) | ty::TyChar => {
-                    TC::None
-                }
-
-                TyBox(typ) => {
-                    tc_ty(cx, typ, cache).owned_pointer()
-                }
-
-                TyTrait(_) => {
-                    TC::All - TC::InteriorParam
-                }
-
-                TyRawPtr(_) => {
-                    TC::None
-                }
-
-                TyRef(_, _) => {
-                    TC::None
-                }
-
-                TyArray(ty, _) => {
-                    tc_ty(cx, ty, cache)
-                }
-
-                TySlice(ty) => {
-                    tc_ty(cx, ty, cache)
-                }
-                TyStr => TC::None,
-
-                TyClosure(_, ref substs) => {
-                    TypeContents::union(&substs.upvar_tys, |ty| tc_ty(cx, &ty, cache))
-                }
-
-                TyTuple(ref tys) => {
-                    TypeContents::union(&tys[..],
-                                        |ty| tc_ty(cx, *ty, cache))
-                }
-
-                TyStruct(def, substs) | TyEnum(def, substs) => {
-                    let mut res =
-                        TypeContents::union(&def.variants, |v| {
-                            TypeContents::union(&v.fields, |f| {
-                                tc_ty(cx, f.ty(cx, substs), cache)
-                            })
-                        });
-
-                    if def.has_dtor() {
-                        res = res | TC::OwnsDtor;
-                    }
-
-                    apply_lang_items(cx, def.did, res)
-                }
-
-                TyProjection(..) |
-                TyParam(_) => {
-                    TC::All
-                }
-
-                TyInfer(_) |
-                TyError => {
-                    cx.sess.bug("asked to compute contents of error type");
-                }
-            };
-
-            cache.insert(ty, result);
-            result
-        }
-
-        fn apply_lang_items(cx: &ctxt, did: DefId, tc: TypeContents)
-                            -> TypeContents {
-            if Some(did) == cx.lang_items.unsafe_cell_type() {
-                tc | TC::InteriorUnsafe
-            } else {
-                tc
-            }
-        }
-    }
-
     fn impls_bound<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
                        bound: ty::BuiltinBound,
                        span: Span)
@@ -5037,143 +2506,6 @@ fn is_type_structurally_recursive<'tcx>(cx: &ctxt<'tcx>, sp: Span,
         r
     }
 
-    pub fn is_trait(&self) -> bool {
-        match self.sty {
-            TyTrait(..) => true,
-            _ => false
-        }
-    }
-
-    pub fn is_integral(&self) -> bool {
-        match self.sty {
-            TyInfer(IntVar(_)) | TyInt(_) | TyUint(_) => true,
-            _ => false
-        }
-    }
-
-    pub fn is_fresh(&self) -> bool {
-        match self.sty {
-            TyInfer(FreshTy(_)) => true,
-            TyInfer(FreshIntTy(_)) => true,
-            TyInfer(FreshFloatTy(_)) => true,
-            _ => false
-        }
-    }
-
-    pub fn is_uint(&self) -> bool {
-        match self.sty {
-            TyInfer(IntVar(_)) | TyUint(hir::TyUs) => true,
-            _ => false
-        }
-    }
-
-    pub fn is_char(&self) -> bool {
-        match self.sty {
-            TyChar => true,
-            _ => false
-        }
-    }
-
-    pub fn is_bare_fn(&self) -> bool {
-        match self.sty {
-            TyBareFn(..) => true,
-            _ => false
-        }
-    }
-
-    pub fn is_bare_fn_item(&self) -> bool {
-        match self.sty {
-            TyBareFn(Some(_), _) => true,
-            _ => false
-        }
-    }
-
-    pub fn is_fp(&self) -> bool {
-        match self.sty {
-            TyInfer(FloatVar(_)) | TyFloat(_) => true,
-            _ => false
-        }
-    }
-
-    pub fn is_numeric(&self) -> bool {
-        self.is_integral() || self.is_fp()
-    }
-
-    pub fn is_signed(&self) -> bool {
-        match self.sty {
-            TyInt(_) => true,
-            _ => false
-        }
-    }
-
-    pub fn is_machine(&self) -> bool {
-        match self.sty {
-            TyInt(hir::TyIs) | TyUint(hir::TyUs) => false,
-            TyInt(..) | TyUint(..) | TyFloat(..) => true,
-            _ => false
-        }
-    }
-
-    // Returns the type and mutability of *ty.
-    //
-    // The parameter `explicit` indicates if this is an *explicit* dereference.
-    // Some types---notably unsafe ptrs---can only be dereferenced explicitly.
-    pub fn builtin_deref(&self, explicit: bool, pref: LvaluePreference)
-        -> Option<TypeAndMut<'tcx>>
-    {
-        match self.sty {
-            TyBox(ty) => {
-                Some(TypeAndMut {
-                    ty: ty,
-                    mutbl:
-                        if pref == PreferMutLvalue { hir::MutMutable } else { hir::MutImmutable },
-                })
-            },
-            TyRef(_, mt) => Some(mt),
-            TyRawPtr(mt) if explicit => Some(mt),
-            _ => None
-        }
-    }
-
-    // Returns the type of ty[i]
-    pub fn builtin_index(&self) -> Option<Ty<'tcx>> {
-        match self.sty {
-            TyArray(ty, _) | TySlice(ty) => Some(ty),
-            _ => None
-        }
-    }
-
-    pub fn fn_sig(&self) -> &'tcx PolyFnSig<'tcx> {
-        match self.sty {
-            TyBareFn(_, ref f) => &f.sig,
-            _ => panic!("Ty::fn_sig() called on non-fn type: {:?}", self)
-        }
-    }
-
-    /// Returns the ABI of the given function.
-    pub fn fn_abi(&self) -> abi::Abi {
-        match self.sty {
-            TyBareFn(_, ref f) => f.abi,
-            _ => panic!("Ty::fn_abi() called on non-fn type"),
-        }
-    }
-
-    // Type accessors for substructures of types
-    pub fn fn_args(&self) -> ty::Binder<Vec<Ty<'tcx>>> {
-        self.fn_sig().inputs()
-    }
-
-    pub fn fn_ret(&self) -> Binder<FnOutput<'tcx>> {
-        self.fn_sig().output()
-    }
-
-    pub fn is_fn(&self) -> bool {
-        match self.sty {
-            TyBareFn(..) => true,
-            _ => false
-        }
-    }
-
     /// See `expr_ty_adjusted`
     pub fn adjust<F>(&'tcx self, cx: &ctxt<'tcx>,
                      span: Span,
@@ -5285,187 +2617,6 @@ pub fn adjust_for_autoref(&'tcx self, cx: &ctxt<'tcx>,
         }
     }
 
-    fn sort_string(&self, cx: &ctxt) -> String {
-
-        match self.sty {
-            TyBool | TyChar | TyInt(_) |
-            TyUint(_) | TyFloat(_) | TyStr => self.to_string(),
-            TyTuple(ref tys) if tys.is_empty() => self.to_string(),
-
-            TyEnum(def, _) => format!("enum `{}`", cx.item_path_str(def.did)),
-            TyBox(_) => "box".to_string(),
-            TyArray(_, n) => format!("array of {} elements", n),
-            TySlice(_) => "slice".to_string(),
-            TyRawPtr(_) => "*-ptr".to_string(),
-            TyRef(_, _) => "&-ptr".to_string(),
-            TyBareFn(Some(_), _) => format!("fn item"),
-            TyBareFn(None, _) => "fn pointer".to_string(),
-            TyTrait(ref inner) => {
-                format!("trait {}", cx.item_path_str(inner.principal_def_id()))
-            }
-            TyStruct(def, _) => {
-                format!("struct `{}`", cx.item_path_str(def.did))
-            }
-            TyClosure(..) => "closure".to_string(),
-            TyTuple(_) => "tuple".to_string(),
-            TyInfer(TyVar(_)) => "inferred type".to_string(),
-            TyInfer(IntVar(_)) => "integral variable".to_string(),
-            TyInfer(FloatVar(_)) => "floating-point variable".to_string(),
-            TyInfer(FreshTy(_)) => "skolemized type".to_string(),
-            TyInfer(FreshIntTy(_)) => "skolemized integral type".to_string(),
-            TyInfer(FreshFloatTy(_)) => "skolemized floating-point type".to_string(),
-            TyProjection(_) => "associated type".to_string(),
-            TyParam(ref p) => {
-                if p.space == subst::SelfSpace {
-                    "Self".to_string()
-                } else {
-                    "type parameter".to_string()
-                }
-            }
-            TyError => "type error".to_string(),
-        }
-    }
-}
-/// Explains the source of a type err in a short, human readable way. This is meant to be placed
-/// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
-/// afterwards to present additional details, particularly when it comes to lifetime-related
-/// errors.
-impl<'tcx> fmt::Display for TypeError<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        use self::TypeError::*;
-        fn report_maybe_different(f: &mut fmt::Formatter,
-                                  expected: String, found: String) -> fmt::Result {
-            // A naive approach to making sure that we're not reporting silly errors such as:
-            // (expected closure, found closure).
-            if expected == found {
-                write!(f, "expected {}, found a different {}", expected, found)
-            } else {
-                write!(f, "expected {}, found {}", expected, found)
-            }
-        }
-
-        match *self {
-            CyclicTy => write!(f, "cyclic type of infinite size"),
-            Mismatch => write!(f, "types differ"),
-            UnsafetyMismatch(values) => {
-                write!(f, "expected {} fn, found {} fn",
-                       values.expected,
-                       values.found)
-            }
-            AbiMismatch(values) => {
-                write!(f, "expected {} fn, found {} fn",
-                       values.expected,
-                       values.found)
-            }
-            Mutability => write!(f, "values differ in mutability"),
-            BoxMutability => {
-                write!(f, "boxed values differ in mutability")
-            }
-            VecMutability => write!(f, "vectors differ in mutability"),
-            PtrMutability => write!(f, "pointers differ in mutability"),
-            RefMutability => write!(f, "references differ in mutability"),
-            TyParamSize(values) => {
-                write!(f, "expected a type with {} type params, \
-                           found one with {} type params",
-                       values.expected,
-                       values.found)
-            }
-            FixedArraySize(values) => {
-                write!(f, "expected an array with a fixed size of {} elements, \
-                           found one with {} elements",
-                       values.expected,
-                       values.found)
-            }
-            TupleSize(values) => {
-                write!(f, "expected a tuple with {} elements, \
-                           found one with {} elements",
-                       values.expected,
-                       values.found)
-            }
-            ArgCount => {
-                write!(f, "incorrect number of function parameters")
-            }
-            RegionsDoesNotOutlive(..) => {
-                write!(f, "lifetime mismatch")
-            }
-            RegionsNotSame(..) => {
-                write!(f, "lifetimes are not the same")
-            }
-            RegionsNoOverlap(..) => {
-                write!(f, "lifetimes do not intersect")
-            }
-            RegionsInsufficientlyPolymorphic(br, _) => {
-                write!(f, "expected bound lifetime parameter {}, \
-                           found concrete lifetime", br)
-            }
-            RegionsOverlyPolymorphic(br, _) => {
-                write!(f, "expected concrete lifetime, \
-                           found bound lifetime parameter {}", br)
-            }
-            Sorts(values) => tls::with(|tcx| {
-                report_maybe_different(f, values.expected.sort_string(tcx),
-                                       values.found.sort_string(tcx))
-            }),
-            Traits(values) => tls::with(|tcx| {
-                report_maybe_different(f,
-                                       format!("trait `{}`",
-                                               tcx.item_path_str(values.expected)),
-                                       format!("trait `{}`",
-                                               tcx.item_path_str(values.found)))
-            }),
-            BuiltinBoundsMismatch(values) => {
-                if values.expected.is_empty() {
-                    write!(f, "expected no bounds, found `{}`",
-                           values.found)
-                } else if values.found.is_empty() {
-                    write!(f, "expected bounds `{}`, found no bounds",
-                           values.expected)
-                } else {
-                    write!(f, "expected bounds `{}`, found bounds `{}`",
-                           values.expected,
-                           values.found)
-                }
-            }
-            IntegerAsChar => {
-                write!(f, "expected an integral type, found `char`")
-            }
-            IntMismatch(ref values) => {
-                write!(f, "expected `{:?}`, found `{:?}`",
-                       values.expected,
-                       values.found)
-            }
-            FloatMismatch(ref values) => {
-                write!(f, "expected `{:?}`, found `{:?}`",
-                       values.expected,
-                       values.found)
-            }
-            VariadicMismatch(ref values) => {
-                write!(f, "expected {} fn, found {} function",
-                       if values.expected { "variadic" } else { "non-variadic" },
-                       if values.found { "variadic" } else { "non-variadic" })
-            }
-            ConvergenceMismatch(ref values) => {
-                write!(f, "expected {} fn, found {} function",
-                       if values.expected { "converging" } else { "diverging" },
-                       if values.found { "converging" } else { "diverging" })
-            }
-            ProjectionNameMismatched(ref values) => {
-                write!(f, "expected {}, found {}",
-                       values.expected,
-                       values.found)
-            }
-            ProjectionBoundsLength(ref values) => {
-                write!(f, "expected {} associated type bindings, found {}",
-                       values.expected,
-                       values.found)
-            },
-            TyParamDefaultMismatch(ref values) => {
-                write!(f, "conflicting type parameter defaults `{}` and `{}`",
-                       values.expected.ty,
-                       values.found.ty)
-            }
-        }
-    }
 }
 
 /// Helper for looking things up in the various maps that are populated during
@@ -5724,102 +2875,14 @@ pub fn expr_is_lval(&self, expr: &hir::Expr) -> bool {
             hir::ExprAssignOp(..) |
             hir::ExprLit(_) |
             hir::ExprUnary(..) |
-            hir::ExprBox(..) |
-            hir::ExprAddrOf(..) |
-            hir::ExprBinary(..) |
-            hir::ExprCast(..) => {
-                false
-            }
-
-            hir::ExprParen(ref e) => self.expr_is_lval(e),
-        }
-    }
-
-    pub fn note_and_explain_type_err(&self, err: &TypeError<'tcx>, sp: Span) {
-        use self::TypeError::*;
-
-        match err.clone() {
-            RegionsDoesNotOutlive(subregion, superregion) => {
-                self.note_and_explain_region("", subregion, "...");
-                self.note_and_explain_region("...does not necessarily outlive ",
-                                           superregion, "");
-            }
-            RegionsNotSame(region1, region2) => {
-                self.note_and_explain_region("", region1, "...");
-                self.note_and_explain_region("...is not the same lifetime as ",
-                                           region2, "");
-            }
-            RegionsNoOverlap(region1, region2) => {
-                self.note_and_explain_region("", region1, "...");
-                self.note_and_explain_region("...does not overlap ",
-                                           region2, "");
-            }
-            RegionsInsufficientlyPolymorphic(_, conc_region) => {
-                self.note_and_explain_region("concrete lifetime that was found is ",
-                                           conc_region, "");
-            }
-            RegionsOverlyPolymorphic(_, ty::ReVar(_)) => {
-                // don't bother to print out the message below for
-                // inference variables, it's not very illuminating.
-            }
-            RegionsOverlyPolymorphic(_, conc_region) => {
-                self.note_and_explain_region("expected concrete lifetime is ",
-                                           conc_region, "");
-            }
-            Sorts(values) => {
-                let expected_str = values.expected.sort_string(self);
-                let found_str = values.found.sort_string(self);
-                if expected_str == found_str && expected_str == "closure" {
-                    self.sess.span_note(sp,
-                        &format!("no two closures, even if identical, have the same type"));
-                    self.sess.span_help(sp,
-                        &format!("consider boxing your closure and/or \
-                                  using it as a trait object"));
-                }
-            },
-            TyParamDefaultMismatch(values) => {
-                let expected = values.expected;
-                let found = values.found;
-                self.sess.span_note(sp,
-                                    &format!("conflicting type parameter defaults `{}` and `{}`",
-                                             expected.ty,
-                                             found.ty));
-
-                match (expected.def_id.is_local(),
-                       self.map.opt_span(expected.def_id.node)) {
-                    (true, Some(span)) => {
-                        self.sess.span_note(span,
-                                            &format!("a default was defined here..."));
-                    }
-                    (_, _) => {
-                        self.sess.note(
-                            &format!("a default is defined on `{}`",
-                                     self.item_path_str(expected.def_id)));
-                    }
-                }
-
-                self.sess.span_note(
-                    expected.origin_span,
-                    &format!("...that was applied to an unconstrained type variable here"));
-
-                match (found.def_id.is_local(),
-                       self.map.opt_span(found.def_id.node)) {
-                    (true, Some(span)) => {
-                        self.sess.span_note(span,
-                                            &format!("a second default was defined here..."));
-                    }
-                    (_, _) => {
-                        self.sess.note(
-                            &format!("a second default is defined on `{}`",
-                                     self.item_path_str(found.def_id)));
-                    }
-                }
-
-                self.sess.span_note(
-                    found.origin_span,
-                    &format!("...that also applies to the same type variable here"));
+            hir::ExprBox(..) |
+            hir::ExprAddrOf(..) |
+            hir::ExprBinary(..) |
+            hir::ExprCast(..) => {
+                false
             }
-            _ => {}
+
+            hir::ExprParen(ref e) => self.expr_is_lval(e),
         }
     }
 
@@ -5986,22 +3049,6 @@ pub fn trait_ref_to_def_id(&self, tr: &hir::TraitRef) -> DefId {
         self.def_map.borrow().get(&tr.ref_id).expect("no def-map entry for trait").def_id()
     }
 
-    pub fn try_add_builtin_trait(&self,
-                                 trait_def_id: DefId,
-                                 builtin_bounds: &mut EnumSet<BuiltinBound>)
-                                 -> bool
-    {
-        //! Checks whether `trait_ref` refers to one of the builtin
-        //! traits, like `Send`, and adds the corresponding
-        //! bound to the set `builtin_bounds` if so. Returns true if `trait_ref`
-        //! is a builtin trait.
-
-        match self.lang_items.to_builtin_kind(trait_def_id) {
-            Some(bound) => { builtin_bounds.insert(bound); true }
-            None => false
-        }
-    }
-
     pub fn item_path_str(&self, id: DefId) -> String {
         self.with_path(id, |path| ast_map::path_to_string(path))
     }
@@ -6070,7 +3117,7 @@ pub fn lookup_item_type(&self, did: DefId) -> TypeScheme<'tcx> {
     pub fn lookup_trait_def(&self, did: DefId) -> &'tcx TraitDef<'tcx> {
         lookup_locally_or_in_crate_store(
             "trait_defs", did, &self.trait_defs,
-            || self.arenas.trait_defs.alloc(csearch::get_trait_def(self, did))
+            || self.alloc_trait_def(csearch::get_trait_def(self, did))
         )
     }
 
@@ -6878,78 +3925,6 @@ pub fn with_freevars<T, F>(&self, fid: NodeId, f: F) -> T where
         }
     }
 
-    /// Replace any late-bound regions bound in `value` with free variants attached to scope-id
-    /// `scope_id`.
-    pub fn liberate_late_bound_regions<T>(&self,
-        all_outlive_scope: region::CodeExtent,
-        value: &Binder<T>)
-        -> T
-        where T : TypeFoldable<'tcx>
-    {
-        fold::replace_late_bound_regions(
-            self, value,
-            |br| ty::ReFree(ty::FreeRegion{scope: all_outlive_scope, bound_region: br})).0
-    }
-
-    /// Flattens two binding levels into one. So `for<'a> for<'b> Foo`
-    /// becomes `for<'a,'b> Foo`.
-    pub fn flatten_late_bound_regions<T>(&self, bound2_value: &Binder<Binder<T>>)
-                                         -> Binder<T>
-        where T: TypeFoldable<'tcx>
-    {
-        let bound0_value = bound2_value.skip_binder().skip_binder();
-        let value = fold::fold_regions(self, bound0_value, &mut false,
-                                       |region, current_depth| {
-            match region {
-                ty::ReLateBound(debruijn, br) if debruijn.depth >= current_depth => {
-                    // should be true if no escaping regions from bound2_value
-                    assert!(debruijn.depth - current_depth <= 1);
-                    ty::ReLateBound(DebruijnIndex::new(current_depth), br)
-                }
-                _ => {
-                    region
-                }
-            }
-        });
-        Binder(value)
-    }
-
-    pub fn no_late_bound_regions<T>(&self, value: &Binder<T>) -> Option<T>
-        where T : TypeFoldable<'tcx> + RegionEscape
-    {
-        if value.0.has_escaping_regions() {
-            None
-        } else {
-            Some(value.0.clone())
-        }
-    }
-
-    /// Replace any late-bound regions bound in `value` with `'static`. Useful in trans but also
-    /// method lookup and a few other places where precise region relationships are not required.
-    pub fn erase_late_bound_regions<T>(&self, value: &Binder<T>) -> T
-        where T : TypeFoldable<'tcx>
-    {
-        fold::replace_late_bound_regions(self, value, |_| ty::ReStatic).0
-    }
-
-    /// Rewrite any late-bound regions so that they are anonymous.  Region numbers are
-    /// assigned starting at 1 and increasing monotonically in the order traversed
-    /// by the fold operation.
-    ///
-    /// The chief purpose of this function is to canonicalize regions so that two
-    /// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become
-    /// structurally identical.  For example, `for<'a, 'b> fn(&'a isize, &'b isize)` and
-    /// `for<'a, 'b> fn(&'b isize, &'a isize)` will become identical after anonymization.
-    pub fn anonymize_late_bound_regions<T>(&self, sig: &Binder<T>) -> Binder<T>
-        where T : TypeFoldable<'tcx>,
-    {
-        let mut counter = 0;
-        ty::Binder(fold::replace_late_bound_regions(self, sig, |_| {
-            counter += 1;
-            ReLateBound(ty::DebruijnIndex::new(1), BrAnon(counter))
-        }).0)
-    }
-
     pub fn make_substs_for_receiver_types(&self,
                                           trait_ref: &ty::TraitRef<'tcx>,
                                           method: &ty::Method<'tcx>)
@@ -6975,67 +3950,6 @@ pub fn make_substs_for_receiver_types(&self,
     }
 }
 
-impl DebruijnIndex {
-    pub fn new(depth: u32) -> DebruijnIndex {
-        assert!(depth > 0);
-        DebruijnIndex { depth: depth }
-    }
-
-    pub fn shifted(&self, amount: u32) -> DebruijnIndex {
-        DebruijnIndex { depth: self.depth + amount }
-    }
-}
-
-impl<'tcx> fmt::Debug for AutoAdjustment<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            AdjustReifyFnPointer => {
-                write!(f, "AdjustReifyFnPointer")
-            }
-            AdjustUnsafeFnPointer => {
-                write!(f, "AdjustUnsafeFnPointer")
-            }
-            AdjustDerefRef(ref data) => {
-                write!(f, "{:?}", data)
-            }
-        }
-    }
-}
-
-impl<'tcx> fmt::Debug for AutoDerefRef<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "AutoDerefRef({}, unsize={:?}, {:?})",
-               self.autoderefs, self.unsize, self.autoref)
-    }
-}
-
-impl<'tcx> fmt::Debug for TraitTy<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "TraitTy({:?},{:?})",
-               self.principal,
-               self.bounds)
-    }
-}
-
-impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            Predicate::Trait(ref a) => write!(f, "{:?}", a),
-            Predicate::Equate(ref pair) => write!(f, "{:?}", pair),
-            Predicate::RegionOutlives(ref pair) => write!(f, "{:?}", pair),
-            Predicate::TypeOutlives(ref pair) => write!(f, "{:?}", pair),
-            Predicate::Projection(ref pair) => write!(f, "{:?}", pair),
-            Predicate::WellFormed(ty) => write!(f, "WF({:?})", ty),
-            Predicate::ObjectSafe(trait_def_id) => write!(f, "ObjectSafe({:?})", trait_def_id),
-        }
-    }
-}
-
-// FIXME(#20298) -- all of these traits basically walk various
-// structures to test whether types/regions are reachable with various
-// properties. It should be possible to express them in terms of one
-// common "walker" trait or something.
-
 /// An "escaping region" is a bound region whose binder is not part of `t`.
 ///
 /// So, for example, consider a type like the following, which has two binders:
@@ -7066,167 +3980,6 @@ fn has_escaping_regions(&self) -> bool {
     fn has_regions_escaping_depth(&self, depth: u32) -> bool;
 }
 
-impl<'tcx> RegionEscape for Ty<'tcx> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.region_depth > depth
-    }
-}
-
-impl<'tcx> RegionEscape for TraitTy<'tcx> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.principal.has_regions_escaping_depth(depth) ||
-            self.bounds.has_regions_escaping_depth(depth)
-    }
-}
-
-impl<'tcx> RegionEscape for ExistentialBounds<'tcx> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.region_bound.has_regions_escaping_depth(depth) ||
-            self.projection_bounds.has_regions_escaping_depth(depth)
-    }
-}
-
-impl<'tcx> RegionEscape for Substs<'tcx> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.types.has_regions_escaping_depth(depth) ||
-            self.regions.has_regions_escaping_depth(depth)
-    }
-}
-
-impl<'tcx> RegionEscape for ClosureSubsts<'tcx> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.func_substs.has_regions_escaping_depth(depth) ||
-            self.upvar_tys.iter().any(|t| t.has_regions_escaping_depth(depth))
-    }
-}
-
-impl<T:RegionEscape> RegionEscape for Vec<T> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.iter().any(|t| t.has_regions_escaping_depth(depth))
-    }
-}
-
-impl<'tcx> RegionEscape for FnSig<'tcx> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.inputs.has_regions_escaping_depth(depth) ||
-            self.output.has_regions_escaping_depth(depth)
-    }
-}
-
-impl<'tcx,T:RegionEscape> RegionEscape for VecPerParamSpace<T> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.iter_enumerated().any(|(space, _, t)| {
-            if space == subst::FnSpace {
-                t.has_regions_escaping_depth(depth+1)
-            } else {
-                t.has_regions_escaping_depth(depth)
-            }
-        })
-    }
-}
-
-impl<'tcx> RegionEscape for TypeScheme<'tcx> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.ty.has_regions_escaping_depth(depth)
-    }
-}
-
-impl RegionEscape for Region {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.escapes_depth(depth)
-    }
-}
-
-impl<'tcx> RegionEscape for GenericPredicates<'tcx> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.predicates.has_regions_escaping_depth(depth)
-    }
-}
-
-impl<'tcx> RegionEscape for Predicate<'tcx> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        match *self {
-            Predicate::Trait(ref data) => data.has_regions_escaping_depth(depth),
-            Predicate::Equate(ref data) => data.has_regions_escaping_depth(depth),
-            Predicate::RegionOutlives(ref data) => data.has_regions_escaping_depth(depth),
-            Predicate::TypeOutlives(ref data) => data.has_regions_escaping_depth(depth),
-            Predicate::Projection(ref data) => data.has_regions_escaping_depth(depth),
-            Predicate::WellFormed(ty) => ty.has_regions_escaping_depth(depth),
-            Predicate::ObjectSafe(_trait_def_id) => false,
-        }
-    }
-}
-
-impl<'tcx,P:RegionEscape> RegionEscape for traits::Obligation<'tcx,P> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.predicate.has_regions_escaping_depth(depth)
-    }
-}
-
-impl<'tcx> RegionEscape for TraitRef<'tcx> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.substs.types.iter().any(|t| t.has_regions_escaping_depth(depth)) ||
-            self.substs.regions.has_regions_escaping_depth(depth)
-    }
-}
-
-impl<'tcx> RegionEscape for subst::RegionSubsts {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        match *self {
-            subst::ErasedRegions => false,
-            subst::NonerasedRegions(ref r) => {
-                r.iter().any(|t| t.has_regions_escaping_depth(depth))
-            }
-        }
-    }
-}
-
-impl<'tcx,T:RegionEscape> RegionEscape for Binder<T> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.0.has_regions_escaping_depth(depth + 1)
-    }
-}
-
-impl<'tcx> RegionEscape for FnOutput<'tcx> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        match *self {
-            FnConverging(t) => t.has_regions_escaping_depth(depth),
-            FnDiverging => false
-        }
-    }
-}
-
-impl<'tcx> RegionEscape for EquatePredicate<'tcx> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.0.has_regions_escaping_depth(depth) || self.1.has_regions_escaping_depth(depth)
-    }
-}
-
-impl<'tcx> RegionEscape for TraitPredicate<'tcx> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.trait_ref.has_regions_escaping_depth(depth)
-    }
-}
-
-impl<T:RegionEscape,U:RegionEscape> RegionEscape for OutlivesPredicate<T,U> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.0.has_regions_escaping_depth(depth) || self.1.has_regions_escaping_depth(depth)
-    }
-}
-
-impl<'tcx> RegionEscape for ProjectionPredicate<'tcx> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.projection_ty.has_regions_escaping_depth(depth) ||
-            self.ty.has_regions_escaping_depth(depth)
-    }
-}
-
-impl<'tcx> RegionEscape for ProjectionTy<'tcx> {
-    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.trait_ref.has_regions_escaping_depth(depth)
-    }
-}
-
 pub trait HasTypeFlags {
     fn has_type_flags(&self, flags: TypeFlags) -> bool;
     fn has_projection_types(&self) -> bool {
@@ -7266,254 +4019,3 @@ fn is_global(&self) -> bool {
         !self.has_type_flags(TypeFlags::HAS_LOCAL_NAMES)
     }
 }
-
-impl<'tcx,T:HasTypeFlags> HasTypeFlags for Vec<T> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self[..].has_type_flags(flags)
-    }
-}
-
-impl<'tcx,T:HasTypeFlags> HasTypeFlags for [T] {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.iter().any(|p| p.has_type_flags(flags))
-    }
-}
-
-impl<'tcx,T:HasTypeFlags> HasTypeFlags for VecPerParamSpace<T> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.iter().any(|p| p.has_type_flags(flags))
-    }
-}
-
-impl HasTypeFlags for abi::Abi {
-    fn has_type_flags(&self, _flags: TypeFlags) -> bool {
-        false
-    }
-}
-
-impl HasTypeFlags for hir::Unsafety {
-    fn has_type_flags(&self, _flags: TypeFlags) -> bool {
-        false
-    }
-}
-
-impl HasTypeFlags for BuiltinBounds {
-    fn has_type_flags(&self, _flags: TypeFlags) -> bool {
-        false
-    }
-}
-
-impl<'tcx> HasTypeFlags for ClosureTy<'tcx> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.sig.has_type_flags(flags)
-    }
-}
-
-impl<'tcx> HasTypeFlags for ClosureUpvar<'tcx> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.ty.has_type_flags(flags)
-    }
-}
-
-impl<'tcx> HasTypeFlags for ExistentialBounds<'tcx> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.projection_bounds.has_type_flags(flags)
-    }
-}
-
-impl<'tcx> HasTypeFlags for ty::InstantiatedPredicates<'tcx> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.predicates.has_type_flags(flags)
-    }
-}
-
-impl<'tcx> HasTypeFlags for Predicate<'tcx> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        match *self {
-            Predicate::Trait(ref data) => data.has_type_flags(flags),
-            Predicate::Equate(ref data) => data.has_type_flags(flags),
-            Predicate::RegionOutlives(ref data) => data.has_type_flags(flags),
-            Predicate::TypeOutlives(ref data) => data.has_type_flags(flags),
-            Predicate::Projection(ref data) => data.has_type_flags(flags),
-            Predicate::WellFormed(data) => data.has_type_flags(flags),
-            Predicate::ObjectSafe(_trait_def_id) => false,
-        }
-    }
-}
-
-impl<'tcx> HasTypeFlags for TraitPredicate<'tcx> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.trait_ref.has_type_flags(flags)
-    }
-}
-
-impl<'tcx> HasTypeFlags for EquatePredicate<'tcx> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.0.has_type_flags(flags) || self.1.has_type_flags(flags)
-    }
-}
-
-impl HasTypeFlags for Region {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        if flags.intersects(TypeFlags::HAS_LOCAL_NAMES) {
-            // does this represent a region that cannot be named in a global
-            // way? used in fulfillment caching.
-            match *self {
-                ty::ReStatic | ty::ReEmpty => {}
-                _ => return true
-            }
-        }
-        if flags.intersects(TypeFlags::HAS_RE_INFER) {
-            match *self {
-                ty::ReVar(_) | ty::ReSkolemized(..) => { return true }
-                _ => {}
-            }
-        }
-        false
-    }
-}
-
-impl<T:HasTypeFlags,U:HasTypeFlags> HasTypeFlags for OutlivesPredicate<T,U> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.0.has_type_flags(flags) || self.1.has_type_flags(flags)
-    }
-}
-
-impl<'tcx> HasTypeFlags for ProjectionPredicate<'tcx> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.projection_ty.has_type_flags(flags) || self.ty.has_type_flags(flags)
-    }
-}
-
-impl<'tcx> HasTypeFlags for ProjectionTy<'tcx> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.trait_ref.has_type_flags(flags)
-    }
-}
-
-impl<'tcx> HasTypeFlags for Ty<'tcx> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.flags.get().intersects(flags)
-    }
-}
-
-impl<'tcx> HasTypeFlags for TypeAndMut<'tcx> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.ty.has_type_flags(flags)
-    }
-}
-
-impl<'tcx> HasTypeFlags for TraitRef<'tcx> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.substs.has_type_flags(flags)
-    }
-}
-
-impl<'tcx> HasTypeFlags for subst::Substs<'tcx> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.types.has_type_flags(flags) || match self.regions {
-            subst::ErasedRegions => false,
-            subst::NonerasedRegions(ref r) => r.has_type_flags(flags)
-        }
-    }
-}
-
-impl<'tcx,T> HasTypeFlags for Option<T>
-    where T : HasTypeFlags
-{
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.iter().any(|t| t.has_type_flags(flags))
-    }
-}
-
-impl<'tcx,T> HasTypeFlags for Rc<T>
-    where T : HasTypeFlags
-{
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        (**self).has_type_flags(flags)
-    }
-}
-
-impl<'tcx,T> HasTypeFlags for Box<T>
-    where T : HasTypeFlags
-{
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        (**self).has_type_flags(flags)
-    }
-}
-
-impl<T> HasTypeFlags for Binder<T>
-    where T : HasTypeFlags
-{
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.0.has_type_flags(flags)
-    }
-}
-
-impl<'tcx> HasTypeFlags for FnOutput<'tcx> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        match *self {
-            FnConverging(t) => t.has_type_flags(flags),
-            FnDiverging => false,
-        }
-    }
-}
-
-impl<'tcx> HasTypeFlags for FnSig<'tcx> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.inputs.iter().any(|t| t.has_type_flags(flags)) ||
-            self.output.has_type_flags(flags)
-    }
-}
-
-impl<'tcx> HasTypeFlags for BareFnTy<'tcx> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.sig.has_type_flags(flags)
-    }
-}
-
-impl<'tcx> HasTypeFlags for ClosureSubsts<'tcx> {
-    fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.func_substs.has_type_flags(flags) ||
-            self.upvar_tys.iter().any(|t| t.has_type_flags(flags))
-    }
-}
-
-impl<'tcx> fmt::Debug for ClosureTy<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "ClosureTy({},{:?},{})",
-               self.unsafety,
-               self.sig,
-               self.abi)
-    }
-}
-
-impl<'tcx> fmt::Debug for ClosureUpvar<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "ClosureUpvar({:?},{:?})",
-               self.def,
-               self.ty)
-    }
-}
-
-impl<'a, 'tcx> fmt::Debug for ParameterEnvironment<'a, 'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "ParameterEnvironment(\
-            free_substs={:?}, \
-            implicit_region_bound={:?}, \
-            caller_bounds={:?})",
-            self.free_substs,
-            self.implicit_region_bound,
-            self.caller_bounds)
-    }
-}
-
-impl<'tcx> fmt::Debug for ObjectLifetimeDefault {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            ObjectLifetimeDefault::Ambiguous => write!(f, "Ambiguous"),
-            ObjectLifetimeDefault::BaseDefault => write!(f, "BaseDefault"),
-            ObjectLifetimeDefault::Specific(ref r) => write!(f, "{:?}", r),
-        }
-    }
-}
index 7baf075cc69ba0d56738469305e0c0f20e3cbac5..ff0a9789cf1f8cad49abd0d1654c9a1a7ec40b82 100644 (file)
 
 use middle::def_id::DefId;
 use middle::subst::{ErasedRegions, NonerasedRegions, ParamSpace, Substs};
-use middle::ty::{self, HasTypeFlags, Ty, TypeError};
+use middle::ty::{self, HasTypeFlags, Ty};
+use middle::ty::error::{ExpectedFound, TypeError};
 use middle::ty::fold::TypeFoldable;
 use std::rc::Rc;
 use syntax::abi;
 use rustc_front::hir as ast;
 
-pub type RelateResult<'tcx, T> = Result<T, ty::TypeError<'tcx>>;
+pub type RelateResult<'tcx, T> = Result<T, TypeError<'tcx>>;
 
 #[derive(Clone, Debug)]
 pub enum Cause {
@@ -662,7 +663,7 @@ fn relate<R>(relation: &mut R,
 pub fn expected_found<'a,'tcx:'a,R,T>(relation: &mut R,
                                       a: &T,
                                       b: &T)
-                                      -> ty::ExpectedFound<T>
+                                      -> ExpectedFound<T>
     where R: TypeRelation<'a,'tcx>, T: Clone
 {
     expected_found_bool(relation.a_is_expected(), a, b)
@@ -671,14 +672,14 @@ pub fn expected_found<'a,'tcx:'a,R,T>(relation: &mut R,
 pub fn expected_found_bool<T>(a_is_expected: bool,
                               a: &T,
                               b: &T)
-                              -> ty::ExpectedFound<T>
+                              -> ExpectedFound<T>
     where T: Clone
 {
     let a = a.clone();
     let b = b.clone();
     if a_is_expected {
-        ty::ExpectedFound {expected: a, found: b}
+        ExpectedFound {expected: a, found: b}
     } else {
-        ty::ExpectedFound {expected: b, found: a}
+        ExpectedFound {expected: b, found: a}
     }
 }
diff --git a/src/librustc/middle/ty/structural_impls.rs b/src/librustc/middle/ty/structural_impls.rs
new file mode 100644 (file)
index 0000000..55d0648
--- /dev/null
@@ -0,0 +1,895 @@
+// 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 middle::subst::{self, VecPerParamSpace};
+use middle::traits;
+use middle::ty::{self, TraitRef, Ty, TypeAndMut};
+use middle::ty::{HasTypeFlags, Lift, TypeFlags, RegionEscape};
+use middle::ty::fold::{TypeFoldable, TypeFolder};
+
+use std::rc::Rc;
+use syntax::abi;
+use syntax::owned_slice::OwnedSlice;
+
+use rustc_front::hir;
+
+// FIXME(#20298) -- all of these traits basically walk various
+// structures to test whether types/regions are reachable with various
+// properties. It should be possible to express them in terms of one
+// common "walker" trait or something.
+
+impl<'tcx> RegionEscape for Ty<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.region_depth > depth
+    }
+}
+
+impl<'tcx> RegionEscape for ty::TraitTy<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.principal.has_regions_escaping_depth(depth) ||
+            self.bounds.has_regions_escaping_depth(depth)
+    }
+}
+
+impl<'tcx> RegionEscape for ty::ExistentialBounds<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.region_bound.has_regions_escaping_depth(depth) ||
+            self.projection_bounds.has_regions_escaping_depth(depth)
+    }
+}
+
+impl<'tcx> RegionEscape for subst::Substs<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.types.has_regions_escaping_depth(depth) ||
+            self.regions.has_regions_escaping_depth(depth)
+    }
+}
+
+impl<'tcx> RegionEscape for ty::ClosureSubsts<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.func_substs.has_regions_escaping_depth(depth) ||
+            self.upvar_tys.iter().any(|t| t.has_regions_escaping_depth(depth))
+    }
+}
+
+impl<T:RegionEscape> RegionEscape for Vec<T> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.iter().any(|t| t.has_regions_escaping_depth(depth))
+    }
+}
+
+impl<'tcx> RegionEscape for ty::FnSig<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.inputs.has_regions_escaping_depth(depth) ||
+            self.output.has_regions_escaping_depth(depth)
+    }
+}
+
+impl<'tcx,T:RegionEscape> RegionEscape for VecPerParamSpace<T> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.iter_enumerated().any(|(space, _, t)| {
+            if space == subst::FnSpace {
+                t.has_regions_escaping_depth(depth+1)
+            } else {
+                t.has_regions_escaping_depth(depth)
+            }
+        })
+    }
+}
+
+impl<'tcx> RegionEscape for ty::TypeScheme<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.ty.has_regions_escaping_depth(depth)
+    }
+}
+
+impl RegionEscape for ty::Region {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.escapes_depth(depth)
+    }
+}
+
+impl<'tcx> RegionEscape for ty::GenericPredicates<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.predicates.has_regions_escaping_depth(depth)
+    }
+}
+
+impl<'tcx> RegionEscape for ty::Predicate<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        match *self {
+            ty::Predicate::Trait(ref data) => data.has_regions_escaping_depth(depth),
+            ty::Predicate::Equate(ref data) => data.has_regions_escaping_depth(depth),
+            ty::Predicate::RegionOutlives(ref data) => data.has_regions_escaping_depth(depth),
+            ty::Predicate::TypeOutlives(ref data) => data.has_regions_escaping_depth(depth),
+            ty::Predicate::Projection(ref data) => data.has_regions_escaping_depth(depth),
+            ty::Predicate::WellFormed(ty) => ty.has_regions_escaping_depth(depth),
+            ty::Predicate::ObjectSafe(_trait_def_id) => false,
+        }
+    }
+}
+
+impl<'tcx,P:RegionEscape> RegionEscape for traits::Obligation<'tcx,P> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.predicate.has_regions_escaping_depth(depth)
+    }
+}
+
+impl<'tcx> RegionEscape for TraitRef<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.substs.types.iter().any(|t| t.has_regions_escaping_depth(depth)) ||
+            self.substs.regions.has_regions_escaping_depth(depth)
+    }
+}
+
+impl<'tcx> RegionEscape for subst::RegionSubsts {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        match *self {
+            subst::ErasedRegions => false,
+            subst::NonerasedRegions(ref r) => {
+                r.iter().any(|t| t.has_regions_escaping_depth(depth))
+            }
+        }
+    }
+}
+
+impl<'tcx,T:RegionEscape> RegionEscape for ty::Binder<T> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.0.has_regions_escaping_depth(depth + 1)
+    }
+}
+
+impl<'tcx> RegionEscape for ty::FnOutput<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        match *self {
+            ty::FnConverging(t) => t.has_regions_escaping_depth(depth),
+            ty::FnDiverging => false
+        }
+    }
+}
+
+impl<'tcx> RegionEscape for ty::EquatePredicate<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.0.has_regions_escaping_depth(depth) || self.1.has_regions_escaping_depth(depth)
+    }
+}
+
+impl<'tcx> RegionEscape for ty::TraitPredicate<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.trait_ref.has_regions_escaping_depth(depth)
+    }
+}
+
+impl<T:RegionEscape,U:RegionEscape> RegionEscape for ty::OutlivesPredicate<T,U> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.0.has_regions_escaping_depth(depth) || self.1.has_regions_escaping_depth(depth)
+    }
+}
+
+impl<'tcx> RegionEscape for ty::ProjectionPredicate<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.projection_ty.has_regions_escaping_depth(depth) ||
+            self.ty.has_regions_escaping_depth(depth)
+    }
+}
+
+impl<'tcx> RegionEscape for ty::ProjectionTy<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.trait_ref.has_regions_escaping_depth(depth)
+    }
+}
+impl<'tcx,T:HasTypeFlags> HasTypeFlags for Vec<T> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self[..].has_type_flags(flags)
+    }
+}
+
+impl<'tcx,T:HasTypeFlags> HasTypeFlags for [T] {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.iter().any(|p| p.has_type_flags(flags))
+    }
+}
+
+impl<'tcx,T:HasTypeFlags> HasTypeFlags for VecPerParamSpace<T> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.iter().any(|p| p.has_type_flags(flags))
+    }
+}
+
+impl HasTypeFlags for abi::Abi {
+    fn has_type_flags(&self, _flags: TypeFlags) -> bool {
+        false
+    }
+}
+
+impl HasTypeFlags for hir::Unsafety {
+    fn has_type_flags(&self, _flags: TypeFlags) -> bool {
+        false
+    }
+}
+
+impl HasTypeFlags for ty::BuiltinBounds {
+    fn has_type_flags(&self, _flags: TypeFlags) -> bool {
+        false
+    }
+}
+
+impl<'tcx> HasTypeFlags for ty::ClosureTy<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.sig.has_type_flags(flags)
+    }
+}
+
+impl<'tcx> HasTypeFlags for ty::ClosureUpvar<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.ty.has_type_flags(flags)
+    }
+}
+
+impl<'tcx> HasTypeFlags for ty::ExistentialBounds<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.projection_bounds.has_type_flags(flags)
+    }
+}
+
+impl<'tcx> HasTypeFlags for ty::InstantiatedPredicates<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.predicates.has_type_flags(flags)
+    }
+}
+
+impl<'tcx> HasTypeFlags for ty::Predicate<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        match *self {
+            ty::Predicate::Trait(ref data) => data.has_type_flags(flags),
+            ty::Predicate::Equate(ref data) => data.has_type_flags(flags),
+            ty::Predicate::RegionOutlives(ref data) => data.has_type_flags(flags),
+            ty::Predicate::TypeOutlives(ref data) => data.has_type_flags(flags),
+            ty::Predicate::Projection(ref data) => data.has_type_flags(flags),
+            ty::Predicate::WellFormed(data) => data.has_type_flags(flags),
+            ty::Predicate::ObjectSafe(_trait_def_id) => false,
+        }
+    }
+}
+
+impl<'tcx> HasTypeFlags for ty::TraitPredicate<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.trait_ref.has_type_flags(flags)
+    }
+}
+
+impl<'tcx> HasTypeFlags for ty::EquatePredicate<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.0.has_type_flags(flags) || self.1.has_type_flags(flags)
+    }
+}
+
+impl HasTypeFlags for ty::Region {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        if flags.intersects(TypeFlags::HAS_LOCAL_NAMES) {
+            // does this represent a region that cannot be named in a global
+            // way? used in fulfillment caching.
+            match *self {
+                ty::ReStatic | ty::ReEmpty => {}
+                _ => return true
+            }
+        }
+        if flags.intersects(TypeFlags::HAS_RE_INFER) {
+            match *self {
+                ty::ReVar(_) | ty::ReSkolemized(..) => { return true }
+                _ => {}
+            }
+        }
+        false
+    }
+}
+
+impl<T:HasTypeFlags,U:HasTypeFlags> HasTypeFlags for ty::OutlivesPredicate<T,U> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.0.has_type_flags(flags) || self.1.has_type_flags(flags)
+    }
+}
+
+impl<'tcx> HasTypeFlags for ty::ProjectionPredicate<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.projection_ty.has_type_flags(flags) || self.ty.has_type_flags(flags)
+    }
+}
+
+impl<'tcx> HasTypeFlags for ty::ProjectionTy<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.trait_ref.has_type_flags(flags)
+    }
+}
+
+impl<'tcx> HasTypeFlags for Ty<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.flags.get().intersects(flags)
+    }
+}
+
+impl<'tcx> HasTypeFlags for TypeAndMut<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.ty.has_type_flags(flags)
+    }
+}
+
+impl<'tcx> HasTypeFlags for TraitRef<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.substs.has_type_flags(flags)
+    }
+}
+
+impl<'tcx> HasTypeFlags for subst::Substs<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.types.has_type_flags(flags) || match self.regions {
+            subst::ErasedRegions => false,
+            subst::NonerasedRegions(ref r) => r.has_type_flags(flags)
+        }
+    }
+}
+
+impl<'tcx,T> HasTypeFlags for Option<T>
+    where T : HasTypeFlags
+{
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.iter().any(|t| t.has_type_flags(flags))
+    }
+}
+
+impl<'tcx,T> HasTypeFlags for Rc<T>
+    where T : HasTypeFlags
+{
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        (**self).has_type_flags(flags)
+    }
+}
+
+impl<'tcx,T> HasTypeFlags for Box<T>
+    where T : HasTypeFlags
+{
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        (**self).has_type_flags(flags)
+    }
+}
+
+impl<T> HasTypeFlags for ty::Binder<T>
+    where T : HasTypeFlags
+{
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.0.has_type_flags(flags)
+    }
+}
+
+impl<'tcx> HasTypeFlags for ty::FnOutput<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        match *self {
+            ty::FnConverging(t) => t.has_type_flags(flags),
+            ty::FnDiverging => false,
+        }
+    }
+}
+
+impl<'tcx> HasTypeFlags for ty::FnSig<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.inputs.iter().any(|t| t.has_type_flags(flags)) ||
+            self.output.has_type_flags(flags)
+    }
+}
+
+impl<'tcx> HasTypeFlags for ty::BareFnTy<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.sig.has_type_flags(flags)
+    }
+}
+
+impl<'tcx> HasTypeFlags for ty::ClosureSubsts<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.func_substs.has_type_flags(flags) ||
+            self.upvar_tys.iter().any(|t| t.has_type_flags(flags))
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Lift implementations
+
+impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>> Lift<'tcx> for (A, B) {
+    type Lifted = (A::Lifted, B::Lifted);
+    fn lift_to_tcx(&self, tcx: &ty::ctxt<'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.0).and_then(|a| tcx.lift(&self.1).map(|b| (a, b)))
+    }
+}
+
+impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for [T] {
+    type Lifted = Vec<T::Lifted>;
+    fn lift_to_tcx(&self, tcx: &ty::ctxt<'tcx>) -> Option<Self::Lifted> {
+        let mut result = Vec::with_capacity(self.len());
+        for x in self {
+            if let Some(value) = tcx.lift(x) {
+                result.push(value);
+            } else {
+                return None;
+            }
+        }
+        Some(result)
+    }
+}
+
+impl<'tcx> Lift<'tcx> for ty::Region {
+    type Lifted = Self;
+    fn lift_to_tcx(&self, _: &ty::ctxt<'tcx>) -> Option<ty::Region> {
+        Some(*self)
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for TraitRef<'a> {
+    type Lifted = TraitRef<'tcx>;
+    fn lift_to_tcx(&self, tcx: &ty::ctxt<'tcx>) -> Option<TraitRef<'tcx>> {
+        tcx.lift(&self.substs).map(|substs| TraitRef {
+            def_id: self.def_id,
+            substs: substs
+        })
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> {
+    type Lifted = ty::TraitPredicate<'tcx>;
+    fn lift_to_tcx(&self, tcx: &ty::ctxt<'tcx>) -> Option<ty::TraitPredicate<'tcx>> {
+        tcx.lift(&self.trait_ref).map(|trait_ref| ty::TraitPredicate {
+            trait_ref: trait_ref
+        })
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for ty::EquatePredicate<'a> {
+    type Lifted = ty::EquatePredicate<'tcx>;
+    fn lift_to_tcx(&self, tcx: &ty::ctxt<'tcx>) -> Option<ty::EquatePredicate<'tcx>> {
+        tcx.lift(&(self.0, self.1)).map(|(a, b)| ty::EquatePredicate(a, b))
+    }
+}
+
+impl<'tcx, A: Copy+Lift<'tcx>, B: Copy+Lift<'tcx>> Lift<'tcx> for ty::OutlivesPredicate<A, B> {
+    type Lifted = ty::OutlivesPredicate<A::Lifted, B::Lifted>;
+    fn lift_to_tcx(&self, tcx: &ty::ctxt<'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&(self.0, self.1)).map(|(a, b)| ty::OutlivesPredicate(a, b))
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionPredicate<'a> {
+    type Lifted = ty::ProjectionPredicate<'tcx>;
+    fn lift_to_tcx(&self, tcx: &ty::ctxt<'tcx>) -> Option<ty::ProjectionPredicate<'tcx>> {
+        tcx.lift(&(self.projection_ty.trait_ref, self.ty)).map(|(trait_ref, ty)| {
+            ty::ProjectionPredicate {
+                projection_ty: ty::ProjectionTy {
+                    trait_ref: trait_ref,
+                    item_name: self.projection_ty.item_name
+                },
+                ty: ty
+            }
+        })
+    }
+}
+
+impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder<T> {
+    type Lifted = ty::Binder<T::Lifted>;
+    fn lift_to_tcx(&self, tcx: &ty::ctxt<'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.0).map(|x| ty::Binder(x))
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// TypeFoldable implementations.
+//
+// Ideally, each type should invoke `folder.fold_foo(self)` and
+// nothing else. In some cases, though, we haven't gotten around to
+// adding methods on the `folder` yet, and thus the folding is
+// hard-coded here. This is less-flexible, because folders cannot
+// override the behavior, but there are a lot of random types and one
+// can easily refactor the folding into the TypeFolder trait as
+// needed.
+
+macro_rules! CopyImpls {
+    ($($ty:ty),+) => {
+        $(
+            impl<'tcx> TypeFoldable<'tcx> for $ty {
+                fn fold_with<F:TypeFolder<'tcx>>(&self, _: &mut F) -> $ty {
+                    *self
+                }
+            }
+        )+
+    }
+}
+
+CopyImpls! { (), hir::Unsafety, abi::Abi }
+
+impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> (T, U) {
+        (self.0.fold_with(folder), self.1.fold_with(folder))
+    }
+}
+
+impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Option<T> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Option<T> {
+        self.as_ref().map(|t| t.fold_with(folder))
+    }
+}
+
+impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Rc<T> {
+        Rc::new((**self).fold_with(folder))
+    }
+}
+
+impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Box<T> {
+        let content: T = (**self).fold_with(folder);
+        box content
+    }
+}
+
+impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Vec<T> {
+        self.iter().map(|t| t.fold_with(folder)).collect()
+    }
+}
+
+impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Binder<T> {
+        folder.fold_binder(self)
+    }
+}
+
+impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for OwnedSlice<T> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> OwnedSlice<T> {
+        self.iter().map(|t| t.fold_with(folder)).collect()
+    }
+}
+
+impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for VecPerParamSpace<T> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> VecPerParamSpace<T> {
+
+        // Things in the Fn space take place under an additional level
+        // of region binding relative to the other spaces. This is
+        // because those entries are attached to a method, and methods
+        // always introduce a level of region binding.
+
+        let result = self.map_enumerated(|(space, index, elem)| {
+            if space == subst::FnSpace && index == 0 {
+                // enter new level when/if we reach the first thing in fn space
+                folder.enter_region_binder();
+            }
+            elem.fold_with(folder)
+        });
+        if result.len(subst::FnSpace) > 0 {
+            // if there was anything in fn space, exit the region binding level
+            folder.exit_region_binder();
+        }
+        result
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Ty<'tcx> {
+        folder.fold_ty(*self)
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::BareFnTy<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::BareFnTy<'tcx> {
+        folder.fold_bare_fn_ty(self)
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::ClosureTy<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ClosureTy<'tcx> {
+        folder.fold_closure_ty(self)
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::TypeAndMut<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TypeAndMut<'tcx> {
+        folder.fold_mt(self)
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::FnOutput<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::FnOutput<'tcx> {
+        folder.fold_output(self)
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::FnSig<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::FnSig<'tcx> {
+        folder.fold_fn_sig(self)
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::TraitRef<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TraitRef<'tcx> {
+        folder.fold_trait_ref(self)
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::Region {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Region {
+        folder.fold_region(*self)
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for subst::Substs<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> subst::Substs<'tcx> {
+        folder.fold_substs(self)
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::ClosureSubsts<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ClosureSubsts<'tcx> {
+        let func_substs = self.func_substs.fold_with(folder);
+        ty::ClosureSubsts {
+            func_substs: folder.tcx().mk_substs(func_substs),
+            upvar_tys: self.upvar_tys.fold_with(folder),
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::ItemSubsts<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ItemSubsts<'tcx> {
+        ty::ItemSubsts {
+            substs: self.substs.fold_with(folder),
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::AutoRef<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::AutoRef<'tcx> {
+        folder.fold_autoref(self)
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::BuiltinBounds {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, _folder: &mut F) -> ty::BuiltinBounds {
+        *self
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ExistentialBounds<'tcx> {
+        folder.fold_existential_bounds(self)
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TypeParameterDef<'tcx> {
+        ty::TypeParameterDef {
+            name: self.name,
+            def_id: self.def_id,
+            space: self.space,
+            index: self.index,
+            default: self.default.fold_with(folder),
+            default_def_id: self.default_def_id,
+            object_lifetime_default: self.object_lifetime_default.fold_with(folder),
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::ObjectLifetimeDefault {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ObjectLifetimeDefault {
+        match *self {
+            ty::ObjectLifetimeDefault::Ambiguous =>
+                ty::ObjectLifetimeDefault::Ambiguous,
+
+            ty::ObjectLifetimeDefault::BaseDefault =>
+                ty::ObjectLifetimeDefault::BaseDefault,
+
+            ty::ObjectLifetimeDefault::Specific(r) =>
+                ty::ObjectLifetimeDefault::Specific(r.fold_with(folder)),
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::RegionParameterDef {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::RegionParameterDef {
+        ty::RegionParameterDef {
+            name: self.name,
+            def_id: self.def_id,
+            space: self.space,
+            index: self.index,
+            bounds: self.bounds.fold_with(folder)
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::Generics<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Generics<'tcx> {
+        ty::Generics {
+            types: self.types.fold_with(folder),
+            regions: self.regions.fold_with(folder),
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::GenericPredicates<'tcx> {
+        ty::GenericPredicates {
+            predicates: self.predicates.fold_with(folder),
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Predicate<'tcx> {
+        match *self {
+            ty::Predicate::Trait(ref a) =>
+                ty::Predicate::Trait(a.fold_with(folder)),
+            ty::Predicate::Equate(ref binder) =>
+                ty::Predicate::Equate(binder.fold_with(folder)),
+            ty::Predicate::RegionOutlives(ref binder) =>
+                ty::Predicate::RegionOutlives(binder.fold_with(folder)),
+            ty::Predicate::TypeOutlives(ref binder) =>
+                ty::Predicate::TypeOutlives(binder.fold_with(folder)),
+            ty::Predicate::Projection(ref binder) =>
+                ty::Predicate::Projection(binder.fold_with(folder)),
+            ty::Predicate::WellFormed(data) =>
+                ty::Predicate::WellFormed(data.fold_with(folder)),
+            ty::Predicate::ObjectSafe(trait_def_id) =>
+                ty::Predicate::ObjectSafe(trait_def_id),
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionPredicate<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ProjectionPredicate<'tcx> {
+        ty::ProjectionPredicate {
+            projection_ty: self.projection_ty.fold_with(folder),
+            ty: self.ty.fold_with(folder),
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ProjectionTy<'tcx> {
+        ty::ProjectionTy {
+            trait_ref: self.trait_ref.fold_with(folder),
+            item_name: self.item_name,
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::InstantiatedPredicates<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::InstantiatedPredicates<'tcx> {
+        ty::InstantiatedPredicates {
+            predicates: self.predicates.fold_with(folder),
+        }
+    }
+}
+
+impl<'tcx,O> TypeFoldable<'tcx> for traits::Obligation<'tcx,O>
+    where O : TypeFoldable<'tcx>
+{
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Obligation<'tcx, O> {
+        traits::Obligation {
+            cause: self.cause.clone(),
+            recursion_depth: self.recursion_depth,
+            predicate: self.predicate.fold_with(folder),
+        }
+    }
+}
+
+impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableImplData<'tcx, N> {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableImplData<'tcx, N> {
+        traits::VtableImplData {
+            impl_def_id: self.impl_def_id,
+            substs: self.substs.fold_with(folder),
+            nested: self.nested.fold_with(folder),
+        }
+    }
+}
+
+impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableClosureData<'tcx, N> {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableClosureData<'tcx, N> {
+        traits::VtableClosureData {
+            closure_def_id: self.closure_def_id,
+            substs: self.substs.fold_with(folder),
+            nested: self.nested.fold_with(folder),
+        }
+    }
+}
+
+impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableDefaultImplData<N> {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableDefaultImplData<N> {
+        traits::VtableDefaultImplData {
+            trait_def_id: self.trait_def_id,
+            nested: self.nested.fold_with(folder),
+        }
+    }
+}
+
+impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableBuiltinData<N> {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableBuiltinData<N> {
+        traits::VtableBuiltinData {
+            nested: self.nested.fold_with(folder),
+        }
+    }
+}
+
+impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Vtable<'tcx, N> {
+        match *self {
+            traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)),
+            traits::VtableDefaultImpl(ref t) => traits::VtableDefaultImpl(t.fold_with(folder)),
+            traits::VtableClosure(ref d) => {
+                traits::VtableClosure(d.fold_with(folder))
+            }
+            traits::VtableFnPointer(ref d) => {
+                traits::VtableFnPointer(d.fold_with(folder))
+            }
+            traits::VtableParam(ref n) => traits::VtableParam(n.fold_with(folder)),
+            traits::VtableBuiltin(ref d) => traits::VtableBuiltin(d.fold_with(folder)),
+            traits::VtableObject(ref d) => traits::VtableObject(d.fold_with(folder)),
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx> {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableObjectData<'tcx> {
+        traits::VtableObjectData {
+            upcast_trait_ref: self.upcast_trait_ref.fold_with(folder),
+            vtable_base: self.vtable_base
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::EquatePredicate<'tcx> {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::EquatePredicate<'tcx> {
+        ty::EquatePredicate(self.0.fold_with(folder),
+                            self.1.fold_with(folder))
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::TraitPredicate<'tcx> {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TraitPredicate<'tcx> {
+        ty::TraitPredicate {
+            trait_ref: self.trait_ref.fold_with(folder)
+        }
+    }
+}
+
+impl<'tcx,T,U> TypeFoldable<'tcx> for ty::OutlivesPredicate<T,U>
+    where T : TypeFoldable<'tcx>,
+          U : TypeFoldable<'tcx>,
+{
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::OutlivesPredicate<T,U> {
+        ty::OutlivesPredicate(self.0.fold_with(folder),
+                              self.1.fold_with(folder))
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::ClosureUpvar<'tcx> {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ClosureUpvar<'tcx> {
+        ty::ClosureUpvar {
+            def: self.def,
+            span: self.span,
+            ty: self.ty.fold_with(folder),
+        }
+    }
+}
+
+impl<'a, 'tcx> TypeFoldable<'tcx> for ty::ParameterEnvironment<'a, 'tcx> where 'tcx: 'a {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ParameterEnvironment<'a, 'tcx> {
+        ty::ParameterEnvironment {
+            tcx: self.tcx,
+            free_substs: self.free_substs.fold_with(folder),
+            implicit_region_bound: self.implicit_region_bound.fold_with(folder),
+            caller_bounds: self.caller_bounds.fold_with(folder),
+            selection_cache: traits::SelectionCache::new(),
+            free_id: self.free_id,
+        }
+    }
+}
diff --git a/src/librustc/middle/ty/sty.rs b/src/librustc/middle/ty/sty.rs
new file mode 100644 (file)
index 0000000..a04cc89
--- /dev/null
@@ -0,0 +1,1129 @@
+// 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.
+
+//! This module contains TypeVariants and its major components
+
+use middle::def_id::DefId;
+use middle::region;
+use middle::subst::{self, Substs};
+use middle::traits;
+use middle::ty::{self, AdtDef, TypeFlags, Ty, TyS};
+use middle::ty::{RegionEscape, ToPredicate};
+use util::common::ErrorReported;
+
+use collections::enum_set::{self, EnumSet, CLike};
+use std::fmt;
+use std::ops;
+use std::mem;
+use syntax::abi;
+use syntax::ast::{Name, NodeId};
+
+use rustc_front::hir;
+
+use self::FnOutput::*;
+use self::InferTy::*;
+use self::TypeVariants::*;
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+pub struct TypeAndMut<'tcx> {
+    pub ty: Ty<'tcx>,
+    pub mutbl: hir::Mutability,
+}
+
+#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash,
+         RustcEncodable, RustcDecodable, Copy)]
+/// A "free" region `fr` can be interpreted as "some region
+/// at least as big as the scope `fr.scope`".
+pub struct FreeRegion {
+    pub scope: region::CodeExtent,
+    pub bound_region: BoundRegion
+}
+
+#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash,
+         RustcEncodable, RustcDecodable, Copy)]
+pub enum BoundRegion {
+    /// An anonymous region parameter for a given fn (&T)
+    BrAnon(u32),
+
+    /// Named region parameters for functions (a in &'a T)
+    ///
+    /// The def-id is needed to distinguish free regions in
+    /// the event of shadowing.
+    BrNamed(DefId, Name),
+
+    /// Fresh bound identifiers created during GLB computations.
+    BrFresh(u32),
+
+    // Anonymous region for the implicit env pointer parameter
+    // to a closure
+    BrEnv
+}
+
+// NB: If you change this, you'll probably want to change the corresponding
+// AST structure in libsyntax/ast.rs as well.
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub enum TypeVariants<'tcx> {
+    /// The primitive boolean type. Written as `bool`.
+    TyBool,
+
+    /// The primitive character type; holds a Unicode scalar value
+    /// (a non-surrogate code point).  Written as `char`.
+    TyChar,
+
+    /// A primitive signed integer type. For example, `i32`.
+    TyInt(hir::IntTy),
+
+    /// A primitive unsigned integer type. For example, `u32`.
+    TyUint(hir::UintTy),
+
+    /// A primitive floating-point type. For example, `f64`.
+    TyFloat(hir::FloatTy),
+
+    /// An enumerated type, defined with `enum`.
+    ///
+    /// Substs here, possibly against intuition, *may* contain `TyParam`s.
+    /// That is, even after substitution it is possible that there are type
+    /// variables. This happens when the `TyEnum` corresponds to an enum
+    /// definition and not a concrete use of it. To get the correct `TyEnum`
+    /// from the tcx, use the `NodeId` from the `hir::Ty` and look it up in
+    /// the `ast_ty_to_ty_cache`. This is probably true for `TyStruct` as
+    /// well.
+    TyEnum(AdtDef<'tcx>, &'tcx Substs<'tcx>),
+
+    /// A structure type, defined with `struct`.
+    ///
+    /// See warning about substitutions for enumerated types.
+    TyStruct(AdtDef<'tcx>, &'tcx Substs<'tcx>),
+
+    /// `Box<T>`; this is nominally a struct in the documentation, but is
+    /// special-cased internally. For example, it is possible to implicitly
+    /// move the contents of a box out of that box, and methods of any type
+    /// can have type `Box<Self>`.
+    TyBox(Ty<'tcx>),
+
+    /// The pointee of a string slice. Written as `str`.
+    TyStr,
+
+    /// An array with the given length. Written as `[T; n]`.
+    TyArray(Ty<'tcx>, usize),
+
+    /// The pointee of an array slice.  Written as `[T]`.
+    TySlice(Ty<'tcx>),
+
+    /// A raw pointer. Written as `*mut T` or `*const T`
+    TyRawPtr(TypeAndMut<'tcx>),
+
+    /// A reference; a pointer with an associated lifetime. Written as
+    /// `&a mut T` or `&'a T`.
+    TyRef(&'tcx Region, TypeAndMut<'tcx>),
+
+    /// If the def-id is Some(_), then this is the type of a specific
+    /// fn item. Otherwise, if None(_), it a fn pointer type.
+    ///
+    /// FIXME: Conflating function pointers and the type of a
+    /// function is probably a terrible idea; a function pointer is a
+    /// value with a specific type, but a function can be polymorphic
+    /// or dynamically dispatched.
+    TyBareFn(Option<DefId>, &'tcx BareFnTy<'tcx>),
+
+    /// A trait, defined with `trait`.
+    TyTrait(Box<TraitTy<'tcx>>),
+
+    /// The anonymous type of a closure. Used to represent the type of
+    /// `|a| a`.
+    TyClosure(DefId, Box<ClosureSubsts<'tcx>>),
+
+    /// A tuple type.  For example, `(i32, bool)`.
+    TyTuple(Vec<Ty<'tcx>>),
+
+    /// The projection of an associated type.  For example,
+    /// `<T as Trait<..>>::N`.
+    TyProjection(ProjectionTy<'tcx>),
+
+    /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
+    TyParam(ParamTy),
+
+    /// A type variable used during type-checking.
+    TyInfer(InferTy),
+
+    /// A placeholder for a type which could not be computed; this is
+    /// propagated to avoid useless error messages.
+    TyError,
+}
+
+/// A closure can be modeled as a struct that looks like:
+///
+///     struct Closure<'l0...'li, T0...Tj, U0...Uk> {
+///         upvar0: U0,
+///         ...
+///         upvark: Uk
+///     }
+///
+/// where 'l0...'li and T0...Tj are the lifetime and type parameters
+/// in scope on the function that defined the closure, and U0...Uk are
+/// type parameters representing the types of its upvars (borrowed, if
+/// appropriate).
+///
+/// So, for example, given this function:
+///
+///     fn foo<'a, T>(data: &'a mut T) {
+///          do(|| data.count += 1)
+///     }
+///
+/// the type of the closure would be something like:
+///
+///     struct Closure<'a, T, U0> {
+///         data: U0
+///     }
+///
+/// Note that the type of the upvar is not specified in the struct.
+/// You may wonder how the impl would then be able to use the upvar,
+/// if it doesn't know it's type? The answer is that the impl is
+/// (conceptually) not fully generic over Closure but rather tied to
+/// instances with the expected upvar types:
+///
+///     impl<'b, 'a, T> FnMut() for Closure<'a, T, &'b mut &'a mut T> {
+///         ...
+///     }
+///
+/// You can see that the *impl* fully specified the type of the upvar
+/// and thus knows full well that `data` has type `&'b mut &'a mut T`.
+/// (Here, I am assuming that `data` is mut-borrowed.)
+///
+/// Now, the last question you may ask is: Why include the upvar types
+/// as extra type parameters? The reason for this design is that the
+/// upvar types can reference lifetimes that are internal to the
+/// creating function. In my example above, for example, the lifetime
+/// `'b` represents the extent of the closure itself; this is some
+/// subset of `foo`, probably just the extent of the call to the to
+/// `do()`. If we just had the lifetime/type parameters from the
+/// enclosing function, we couldn't name this lifetime `'b`. Note that
+/// there can also be lifetimes in the types of the upvars themselves,
+/// if one of them happens to be a reference to something that the
+/// creating fn owns.
+///
+/// OK, you say, so why not create a more minimal set of parameters
+/// that just includes the extra lifetime parameters? The answer is
+/// primarily that it would be hard --- we don't know at the time when
+/// we create the closure type what the full types of the upvars are,
+/// nor do we know which are borrowed and which are not. In this
+/// design, we can just supply a fresh type parameter and figure that
+/// out later.
+///
+/// All right, you say, but why include the type parameters from the
+/// original function then? The answer is that trans may need them
+/// when monomorphizing, and they may not appear in the upvars.  A
+/// closure could capture no variables but still make use of some
+/// in-scope type parameter with a bound (e.g., if our example above
+/// had an extra `U: Default`, and the closure called `U::default()`).
+///
+/// There is another reason. This design (implicitly) prohibits
+/// closures from capturing themselves (except via a trait
+/// object). This simplifies closure inference considerably, since it
+/// means that when we infer the kind of a closure or its upvars, we
+/// don't have to handle cycles where the decisions we make for
+/// closure C wind up influencing the decisions we ought to make for
+/// closure C (which would then require fixed point iteration to
+/// handle). Plus it fixes an ICE. :P
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub struct ClosureSubsts<'tcx> {
+    /// Lifetime and type parameters from the enclosing function.
+    /// These are separated out because trans wants to pass them around
+    /// when monomorphizing.
+    pub func_substs: &'tcx Substs<'tcx>,
+
+    /// The types of the upvars. The list parallels the freevars and
+    /// `upvar_borrows` lists. These are kept distinct so that we can
+    /// easily index into them.
+    pub upvar_tys: Vec<Ty<'tcx>>
+}
+
+#[derive(Clone, PartialEq, Eq, Hash)]
+pub struct TraitTy<'tcx> {
+    pub principal: ty::PolyTraitRef<'tcx>,
+    pub bounds: ExistentialBounds<'tcx>,
+}
+
+impl<'tcx> TraitTy<'tcx> {
+    pub fn principal_def_id(&self) -> DefId {
+        self.principal.0.def_id
+    }
+
+    /// Object types don't have a self-type specified. Therefore, when
+    /// we convert the principal trait-ref into a normal trait-ref,
+    /// you must give *some* self-type. A common choice is `mk_err()`
+    /// or some skolemized type.
+    pub fn principal_trait_ref_with_self_ty(&self,
+                                            tcx: &ty::ctxt<'tcx>,
+                                            self_ty: Ty<'tcx>)
+                                            -> ty::PolyTraitRef<'tcx>
+    {
+        // otherwise the escaping regions would be captured by the binder
+        assert!(!self_ty.has_escaping_regions());
+
+        ty::Binder(TraitRef {
+            def_id: self.principal.0.def_id,
+            substs: tcx.mk_substs(self.principal.0.substs.with_self_ty(self_ty)),
+        })
+    }
+
+    pub fn projection_bounds_with_self_ty(&self,
+                                          tcx: &ty::ctxt<'tcx>,
+                                          self_ty: Ty<'tcx>)
+                                          -> Vec<ty::PolyProjectionPredicate<'tcx>>
+    {
+        // otherwise the escaping regions would be captured by the binders
+        assert!(!self_ty.has_escaping_regions());
+
+        self.bounds.projection_bounds.iter()
+            .map(|in_poly_projection_predicate| {
+                let in_projection_ty = &in_poly_projection_predicate.0.projection_ty;
+                let substs = tcx.mk_substs(in_projection_ty.trait_ref.substs.with_self_ty(self_ty));
+                let trait_ref = ty::TraitRef::new(in_projection_ty.trait_ref.def_id,
+                                              substs);
+                let projection_ty = ty::ProjectionTy {
+                    trait_ref: trait_ref,
+                    item_name: in_projection_ty.item_name
+                };
+                ty::Binder(ty::ProjectionPredicate {
+                    projection_ty: projection_ty,
+                    ty: in_poly_projection_predicate.0.ty
+                })
+            })
+            .collect()
+    }
+}
+
+/// A complete reference to a trait. These take numerous guises in syntax,
+/// but perhaps the most recognizable form is in a where clause:
+///
+///     T : Foo<U>
+///
+/// This would be represented by a trait-reference where the def-id is the
+/// def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the
+/// `SelfSpace` and `U` as parameter 0 in the `TypeSpace`.
+///
+/// Trait references also appear in object types like `Foo<U>`, but in
+/// that case the `Self` parameter is absent from the substitutions.
+///
+/// Note that a `TraitRef` introduces a level of region binding, to
+/// account for higher-ranked trait bounds like `T : for<'a> Foo<&'a
+/// U>` or higher-ranked object types.
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+pub struct TraitRef<'tcx> {
+    pub def_id: DefId,
+    pub substs: &'tcx Substs<'tcx>,
+}
+
+pub type PolyTraitRef<'tcx> = Binder<TraitRef<'tcx>>;
+
+impl<'tcx> PolyTraitRef<'tcx> {
+    pub fn self_ty(&self) -> Ty<'tcx> {
+        self.0.self_ty()
+    }
+
+    pub fn def_id(&self) -> DefId {
+        self.0.def_id
+    }
+
+    pub fn substs(&self) -> &'tcx Substs<'tcx> {
+        // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<>
+        self.0.substs
+    }
+
+    pub fn input_types(&self) -> &[Ty<'tcx>] {
+        // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<>
+        self.0.input_types()
+    }
+
+    pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> {
+        // Note that we preserve binding levels
+        Binder(ty::TraitPredicate { trait_ref: self.0.clone() })
+    }
+}
+
+/// Binder is a binder for higher-ranked lifetimes. It is part of the
+/// compiler's representation for things like `for<'a> Fn(&'a isize)`
+/// (which would be represented by the type `PolyTraitRef ==
+/// Binder<TraitRef>`). Note that when we skolemize, instantiate,
+/// erase, or otherwise "discharge" these bound regions, we change the
+/// type from `Binder<T>` to just `T` (see
+/// e.g. `liberate_late_bound_regions`).
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub struct Binder<T>(pub T);
+
+impl<T> Binder<T> {
+    /// Skips the binder and returns the "bound" value. This is a
+    /// risky thing to do because it's easy to get confused about
+    /// debruijn indices and the like. It is usually better to
+    /// discharge the binder using `no_late_bound_regions` or
+    /// `replace_late_bound_regions` or something like
+    /// that. `skip_binder` is only valid when you are either
+    /// extracting data that has nothing to do with bound regions, you
+    /// are doing some sort of test that does not involve bound
+    /// regions, or you are being very careful about your depth
+    /// accounting.
+    ///
+    /// Some examples where `skip_binder` is reasonable:
+    /// - extracting the def-id from a PolyTraitRef;
+    /// - comparing the self type of a PolyTraitRef to see if it is equal to
+    ///   a type parameter `X`, since the type `X`  does not reference any regions
+    pub fn skip_binder(&self) -> &T {
+        &self.0
+    }
+
+    pub fn as_ref(&self) -> Binder<&T> {
+        ty::Binder(&self.0)
+    }
+
+    pub fn map_bound_ref<F,U>(&self, f: F) -> Binder<U>
+        where F: FnOnce(&T) -> U
+    {
+        self.as_ref().map_bound(f)
+    }
+
+    pub fn map_bound<F,U>(self, f: F) -> Binder<U>
+        where F: FnOnce(T) -> U
+    {
+        ty::Binder(f(self.0))
+    }
+}
+
+impl fmt::Debug for TypeFlags {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self.bits)
+    }
+}
+
+/// Represents the projection of an associated type. In explicit UFCS
+/// form this would be written `<T as Trait<..>>::N`.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub struct ProjectionTy<'tcx> {
+    /// The trait reference `T as Trait<..>`.
+    pub trait_ref: ty::TraitRef<'tcx>,
+
+    /// The name `N` of the associated type.
+    pub item_name: Name,
+}
+
+impl<'tcx> ProjectionTy<'tcx> {
+    pub fn sort_key(&self) -> (DefId, Name) {
+        (self.trait_ref.def_id, self.item_name)
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub struct BareFnTy<'tcx> {
+    pub unsafety: hir::Unsafety,
+    pub abi: abi::Abi,
+    pub sig: PolyFnSig<'tcx>,
+}
+
+#[derive(Clone, PartialEq, Eq, Hash)]
+pub struct ClosureTy<'tcx> {
+    pub unsafety: hir::Unsafety,
+    pub abi: abi::Abi,
+    pub sig: PolyFnSig<'tcx>,
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+pub enum FnOutput<'tcx> {
+    FnConverging(Ty<'tcx>),
+    FnDiverging
+}
+
+impl<'tcx> FnOutput<'tcx> {
+    pub fn diverges(&self) -> bool {
+        *self == FnDiverging
+    }
+
+    pub fn unwrap(self) -> Ty<'tcx> {
+        match self {
+            ty::FnConverging(t) => t,
+            ty::FnDiverging => unreachable!()
+        }
+    }
+
+    pub fn unwrap_or(self, def: Ty<'tcx>) -> Ty<'tcx> {
+        match self {
+            ty::FnConverging(t) => t,
+            ty::FnDiverging => def
+        }
+    }
+}
+
+pub type PolyFnOutput<'tcx> = Binder<FnOutput<'tcx>>;
+
+impl<'tcx> PolyFnOutput<'tcx> {
+    pub fn diverges(&self) -> bool {
+        self.0.diverges()
+    }
+}
+
+/// Signature of a function type, which I have arbitrarily
+/// decided to use to refer to the input/output types.
+///
+/// - `inputs` is the list of arguments and their modes.
+/// - `output` is the return type.
+/// - `variadic` indicates whether this is a variadic function. (only true for foreign fns)
+#[derive(Clone, PartialEq, Eq, Hash)]
+pub struct FnSig<'tcx> {
+    pub inputs: Vec<Ty<'tcx>>,
+    pub output: FnOutput<'tcx>,
+    pub variadic: bool
+}
+
+pub type PolyFnSig<'tcx> = Binder<FnSig<'tcx>>;
+
+impl<'tcx> PolyFnSig<'tcx> {
+    pub fn inputs(&self) -> ty::Binder<Vec<Ty<'tcx>>> {
+        self.map_bound_ref(|fn_sig| fn_sig.inputs.clone())
+    }
+    pub fn input(&self, index: usize) -> ty::Binder<Ty<'tcx>> {
+        self.map_bound_ref(|fn_sig| fn_sig.inputs[index])
+    }
+    pub fn output(&self) -> ty::Binder<FnOutput<'tcx>> {
+        self.map_bound_ref(|fn_sig| fn_sig.output.clone())
+    }
+    pub fn variadic(&self) -> bool {
+        self.skip_binder().variadic
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+pub struct ParamTy {
+    pub space: subst::ParamSpace,
+    pub idx: u32,
+    pub name: Name,
+}
+
+/// A [De Bruijn index][dbi] is a standard means of representing
+/// regions (and perhaps later types) in a higher-ranked setting. In
+/// particular, imagine a type like this:
+///
+///     for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
+///     ^          ^            |        |         |
+///     |          |            |        |         |
+///     |          +------------+ 1      |         |
+///     |                                |         |
+///     +--------------------------------+ 2       |
+///     |                                          |
+///     +------------------------------------------+ 1
+///
+/// In this type, there are two binders (the outer fn and the inner
+/// fn). We need to be able to determine, for any given region, which
+/// fn type it is bound by, the inner or the outer one. There are
+/// various ways you can do this, but a De Bruijn index is one of the
+/// more convenient and has some nice properties. The basic idea is to
+/// count the number of binders, inside out. Some examples should help
+/// clarify what I mean.
+///
+/// Let's start with the reference type `&'b isize` that is the first
+/// argument to the inner function. This region `'b` is assigned a De
+/// Bruijn index of 1, meaning "the innermost binder" (in this case, a
+/// fn). The region `'a` that appears in the second argument type (`&'a
+/// isize`) would then be assigned a De Bruijn index of 2, meaning "the
+/// second-innermost binder". (These indices are written on the arrays
+/// in the diagram).
+///
+/// What is interesting is that De Bruijn index attached to a particular
+/// variable will vary depending on where it appears. For example,
+/// the final type `&'a char` also refers to the region `'a` declared on
+/// the outermost fn. But this time, this reference is not nested within
+/// any other binders (i.e., it is not an argument to the inner fn, but
+/// rather the outer one). Therefore, in this case, it is assigned a
+/// De Bruijn index of 1, because the innermost binder in that location
+/// is the outer fn.
+///
+/// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index
+#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, Copy)]
+pub struct DebruijnIndex {
+    // We maintain the invariant that this is never 0. So 1 indicates
+    // the innermost binder. To ensure this, create with `DebruijnIndex::new`.
+    pub depth: u32,
+}
+
+/// Representation of regions.
+///
+/// Unlike types, most region variants are "fictitious", not concrete,
+/// regions. Among these, `ReStatic`, `ReEmpty` and `ReScope` are the only
+/// ones representing concrete regions.
+///
+/// ## Bound Regions
+///
+/// These are regions that are stored behind a binder and must be substituted
+/// with some concrete region before being used. There are 2 kind of
+/// bound regions: early-bound, which are bound in a TypeScheme/TraitDef,
+/// and are substituted by a Substs,  and late-bound, which are part of
+/// higher-ranked types (e.g. `for<'a> fn(&'a ())`) and are substituted by
+/// the likes of `liberate_late_bound_regions`. The distinction exists
+/// because higher-ranked lifetimes aren't supported in all places. See [1][2].
+///
+/// Unlike TyParam-s, bound regions are not supposed to exist "in the wild"
+/// outside their binder, e.g. in types passed to type inference, and
+/// should first be substituted (by skolemized regions, free regions,
+/// or region variables).
+///
+/// ## Skolemized and Free Regions
+///
+/// One often wants to work with bound regions without knowing their precise
+/// identity. For example, when checking a function, the lifetime of a borrow
+/// can end up being assigned to some region parameter. In these cases,
+/// it must be ensured that bounds on the region can't be accidentally
+/// assumed without being checked.
+///
+/// The process of doing that is called "skolemization". The bound regions
+/// are replaced by skolemized markers, which don't satisfy any relation
+/// not explicity provided.
+///
+/// There are 2 kinds of skolemized regions in rustc: `ReFree` and
+/// `ReSkolemized`. When checking an item's body, `ReFree` is supposed
+/// to be used. These also support explicit bounds: both the internally-stored
+/// *scope*, which the region is assumed to outlive, as well as other
+/// relations stored in the `FreeRegionMap`. Note that these relations
+/// aren't checked when you `make_subregion` (or `mk_eqty`), only by
+/// `resolve_regions_and_report_errors`.
+///
+/// When working with higher-ranked types, some region relations aren't
+/// yet known, so you can't just call `resolve_regions_and_report_errors`.
+/// `ReSkolemized` is designed for this purpose. In these contexts,
+/// there's also the risk that some inference variable laying around will
+/// get unified with your skolemized region: if you want to check whether
+/// `for<'a> Foo<'_>: 'a`, and you substitute your bound region `'a`
+/// with a skolemized region `'%a`, the variable `'_` would just be
+/// instantiated to the skolemized region `'%a`, which is wrong because
+/// the inference variable is supposed to satisfy the relation
+/// *for every value of the skolemized region*. To ensure that doesn't
+/// happen, you can use `leak_check`. This is more clearly explained
+/// by infer/higher_ranked/README.md.
+///
+/// [1] http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
+/// [2] http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
+#[derive(Clone, PartialEq, Eq, Hash, Copy)]
+pub enum Region {
+    // Region bound in a type or fn declaration which will be
+    // substituted 'early' -- that is, at the same time when type
+    // parameters are substituted.
+    ReEarlyBound(EarlyBoundRegion),
+
+    // Region bound in a function scope, which will be substituted when the
+    // function is called.
+    ReLateBound(DebruijnIndex, BoundRegion),
+
+    /// When checking a function body, the types of all arguments and so forth
+    /// that refer to bound region parameters are modified to refer to free
+    /// region parameters.
+    ReFree(FreeRegion),
+
+    /// A concrete region naming some statically determined extent
+    /// (e.g. an expression or sequence of statements) within the
+    /// current function.
+    ReScope(region::CodeExtent),
+
+    /// Static data that has an "infinite" lifetime. Top in the region lattice.
+    ReStatic,
+
+    /// A region variable.  Should not exist after typeck.
+    ReVar(RegionVid),
+
+    /// A skolemized region - basically the higher-ranked version of ReFree.
+    /// Should not exist after typeck.
+    ReSkolemized(SkolemizedRegionVid, BoundRegion),
+
+    /// Empty lifetime is for data that is never accessed.
+    /// Bottom in the region lattice. We treat ReEmpty somewhat
+    /// specially; at least right now, we do not generate instances of
+    /// it during the GLB computations, but rather
+    /// generate an error instead. This is to improve error messages.
+    /// The only way to get an instance of ReEmpty is to have a region
+    /// variable with no constraints.
+    ReEmpty,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
+pub struct EarlyBoundRegion {
+    pub param_id: NodeId,
+    pub space: subst::ParamSpace,
+    pub index: u32,
+    pub name: Name,
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+pub struct TyVid {
+    pub index: u32
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+pub struct IntVid {
+    pub index: u32
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+pub struct FloatVid {
+    pub index: u32
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
+pub struct RegionVid {
+    pub index: u32
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+pub struct SkolemizedRegionVid {
+    pub index: u32
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+pub enum InferTy {
+    TyVar(TyVid),
+    IntVar(IntVid),
+    FloatVar(FloatVid),
+
+    /// A `FreshTy` is one that is generated as a replacement for an
+    /// unbound type variable. This is convenient for caching etc. See
+    /// `middle::infer::freshen` for more details.
+    FreshTy(u32),
+    FreshIntTy(u32),
+    FreshFloatTy(u32)
+}
+
+/// Bounds suitable for an existentially quantified type parameter
+/// such as those that appear in object types or closure types.
+#[derive(PartialEq, Eq, Hash, Clone)]
+pub struct ExistentialBounds<'tcx> {
+    pub region_bound: ty::Region,
+    pub builtin_bounds: BuiltinBounds,
+    pub projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
+}
+
+impl<'tcx> ExistentialBounds<'tcx> {
+    pub fn new(region_bound: ty::Region,
+               builtin_bounds: BuiltinBounds,
+               projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>)
+               -> Self {
+        let mut projection_bounds = projection_bounds;
+        projection_bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key()));
+        ExistentialBounds {
+            region_bound: region_bound,
+            builtin_bounds: builtin_bounds,
+            projection_bounds: projection_bounds
+        }
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+pub struct BuiltinBounds(EnumSet<BuiltinBound>);
+
+impl BuiltinBounds {
+    pub fn empty() -> BuiltinBounds {
+        BuiltinBounds(EnumSet::new())
+    }
+
+    pub fn iter(&self) -> enum_set::Iter<BuiltinBound> {
+        self.into_iter()
+    }
+
+    pub fn to_predicates<'tcx>(&self,
+                               tcx: &ty::ctxt<'tcx>,
+                               self_ty: Ty<'tcx>) -> Vec<ty::Predicate<'tcx>> {
+        self.iter().filter_map(|builtin_bound|
+            match traits::trait_ref_for_builtin_bound(tcx, builtin_bound, self_ty) {
+                Ok(trait_ref) => Some(trait_ref.to_predicate()),
+                Err(ErrorReported) => { None }
+            }
+        ).collect()
+    }
+}
+
+impl ops::Deref for BuiltinBounds {
+    type Target = EnumSet<BuiltinBound>;
+    fn deref(&self) -> &Self::Target { &self.0 }
+}
+
+impl ops::DerefMut for BuiltinBounds {
+    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
+}
+
+impl<'a> IntoIterator for &'a BuiltinBounds {
+    type Item = BuiltinBound;
+    type IntoIter = enum_set::Iter<BuiltinBound>;
+    fn into_iter(self) -> Self::IntoIter {
+        (**self).into_iter()
+    }
+}
+
+#[derive(Clone, RustcEncodable, PartialEq, Eq, RustcDecodable, Hash,
+           Debug, Copy)]
+#[repr(usize)]
+pub enum BuiltinBound {
+    Send,
+    Sized,
+    Copy,
+    Sync,
+}
+
+impl CLike for BuiltinBound {
+    fn to_usize(&self) -> usize {
+        *self as usize
+    }
+    fn from_usize(v: usize) -> BuiltinBound {
+        unsafe { mem::transmute(v) }
+    }
+}
+
+impl<'tcx> ty::ctxt<'tcx> {
+    pub fn try_add_builtin_trait(&self,
+                                 trait_def_id: DefId,
+                                 builtin_bounds: &mut EnumSet<BuiltinBound>)
+                                 -> bool
+    {
+        //! Checks whether `trait_ref` refers to one of the builtin
+        //! traits, like `Send`, and adds the corresponding
+        //! bound to the set `builtin_bounds` if so. Returns true if `trait_ref`
+        //! is a builtin trait.
+
+        match self.lang_items.to_builtin_kind(trait_def_id) {
+            Some(bound) => { builtin_bounds.insert(bound); true }
+            None => false
+        }
+    }
+}
+
+impl DebruijnIndex {
+    pub fn new(depth: u32) -> DebruijnIndex {
+        assert!(depth > 0);
+        DebruijnIndex { depth: depth }
+    }
+
+    pub fn shifted(&self, amount: u32) -> DebruijnIndex {
+        DebruijnIndex { depth: self.depth + amount }
+    }
+}
+
+// Region utilities
+impl Region {
+    pub fn is_bound(&self) -> bool {
+        match *self {
+            ty::ReEarlyBound(..) => true,
+            ty::ReLateBound(..) => true,
+            _ => false
+        }
+    }
+
+    pub fn needs_infer(&self) -> bool {
+        match *self {
+            ty::ReVar(..) | ty::ReSkolemized(..) => true,
+            _ => false
+        }
+    }
+
+    pub fn escapes_depth(&self, depth: u32) -> bool {
+        match *self {
+            ty::ReLateBound(debruijn, _) => debruijn.depth > depth,
+            _ => false,
+        }
+    }
+
+    /// Returns the depth of `self` from the (1-based) binding level `depth`
+    pub fn from_depth(&self, depth: u32) -> Region {
+        match *self {
+            ty::ReLateBound(debruijn, r) => ty::ReLateBound(DebruijnIndex {
+                depth: debruijn.depth - (depth - 1)
+            }, r),
+            r => r
+        }
+    }
+}
+
+// Type utilities
+impl<'tcx> TyS<'tcx> {
+    pub fn is_nil(&self) -> bool {
+        match self.sty {
+            TyTuple(ref tys) => tys.is_empty(),
+            _ => false
+        }
+    }
+
+    pub fn is_empty(&self, _cx: &ty::ctxt) -> bool {
+        // FIXME(#24885): be smarter here
+        match self.sty {
+            TyEnum(def, _) | TyStruct(def, _) => def.is_empty(),
+            _ => false
+        }
+    }
+
+    pub fn is_ty_var(&self) -> bool {
+        match self.sty {
+            TyInfer(TyVar(_)) => true,
+            _ => false
+        }
+    }
+
+    pub fn is_bool(&self) -> bool { self.sty == TyBool }
+
+    pub fn is_self(&self) -> bool {
+        match self.sty {
+            TyParam(ref p) => p.space == subst::SelfSpace,
+            _ => false
+        }
+    }
+
+    fn is_slice(&self) -> bool {
+        match self.sty {
+            TyRawPtr(mt) | TyRef(_, mt) => match mt.ty.sty {
+                TySlice(_) | TyStr => true,
+                _ => false,
+            },
+            _ => false
+        }
+    }
+
+    pub fn is_structural(&self) -> bool {
+        match self.sty {
+            TyStruct(..) | TyTuple(_) | TyEnum(..) |
+            TyArray(..) | TyClosure(..) => true,
+            _ => self.is_slice() | self.is_trait()
+        }
+    }
+
+    #[inline]
+    pub fn is_simd(&self) -> bool {
+        match self.sty {
+            TyStruct(def, _) => def.is_simd(),
+            _ => false
+        }
+    }
+
+    pub fn sequence_element_type(&self, cx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
+        match self.sty {
+            TyArray(ty, _) | TySlice(ty) => ty,
+            TyStr => cx.mk_mach_uint(hir::TyU8),
+            _ => cx.sess.bug(&format!("sequence_element_type called on non-sequence value: {}",
+                                      self)),
+        }
+    }
+
+    pub fn simd_type(&self, cx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
+        match self.sty {
+            TyStruct(def, substs) => {
+                def.struct_variant().fields[0].ty(cx, substs)
+            }
+            _ => panic!("simd_type called on invalid type")
+        }
+    }
+
+    pub fn simd_size(&self, _cx: &ty::ctxt) -> usize {
+        match self.sty {
+            TyStruct(def, _) => def.struct_variant().fields.len(),
+            _ => panic!("simd_size called on invalid type")
+        }
+    }
+
+    pub fn is_region_ptr(&self) -> bool {
+        match self.sty {
+            TyRef(..) => true,
+            _ => false
+        }
+    }
+
+    pub fn is_unsafe_ptr(&self) -> bool {
+        match self.sty {
+            TyRawPtr(_) => return true,
+            _ => return false
+        }
+    }
+
+    pub fn is_unique(&self) -> bool {
+        match self.sty {
+            TyBox(_) => true,
+            _ => false
+        }
+    }
+
+    /*
+     A scalar type is one that denotes an atomic datum, with no sub-components.
+     (A TyRawPtr is scalar because it represents a non-managed pointer, so its
+     contents are abstract to rustc.)
+    */
+    pub fn is_scalar(&self) -> bool {
+        match self.sty {
+            TyBool | TyChar | TyInt(_) | TyFloat(_) | TyUint(_) |
+            TyInfer(IntVar(_)) | TyInfer(FloatVar(_)) |
+            TyBareFn(..) | TyRawPtr(_) => true,
+            _ => false
+        }
+    }
+
+    /// Returns true if this type is a floating point type and false otherwise.
+    pub fn is_floating_point(&self) -> bool {
+        match self.sty {
+            TyFloat(_) |
+            TyInfer(FloatVar(_)) => true,
+            _ => false,
+        }
+    }
+
+    pub fn is_trait(&self) -> bool {
+        match self.sty {
+            TyTrait(..) => true,
+            _ => false
+        }
+    }
+
+    pub fn is_integral(&self) -> bool {
+        match self.sty {
+            TyInfer(IntVar(_)) | TyInt(_) | TyUint(_) => true,
+            _ => false
+        }
+    }
+
+    pub fn is_fresh(&self) -> bool {
+        match self.sty {
+            TyInfer(FreshTy(_)) => true,
+            TyInfer(FreshIntTy(_)) => true,
+            TyInfer(FreshFloatTy(_)) => true,
+            _ => false
+        }
+    }
+
+    pub fn is_uint(&self) -> bool {
+        match self.sty {
+            TyInfer(IntVar(_)) | TyUint(hir::TyUs) => true,
+            _ => false
+        }
+    }
+
+    pub fn is_char(&self) -> bool {
+        match self.sty {
+            TyChar => true,
+            _ => false
+        }
+    }
+
+    pub fn is_bare_fn(&self) -> bool {
+        match self.sty {
+            TyBareFn(..) => true,
+            _ => false
+        }
+    }
+
+    pub fn is_bare_fn_item(&self) -> bool {
+        match self.sty {
+            TyBareFn(Some(_), _) => true,
+            _ => false
+        }
+    }
+
+    pub fn is_fp(&self) -> bool {
+        match self.sty {
+            TyInfer(FloatVar(_)) | TyFloat(_) => true,
+            _ => false
+        }
+    }
+
+    pub fn is_numeric(&self) -> bool {
+        self.is_integral() || self.is_fp()
+    }
+
+    pub fn is_signed(&self) -> bool {
+        match self.sty {
+            TyInt(_) => true,
+            _ => false
+        }
+    }
+
+    pub fn is_machine(&self) -> bool {
+        match self.sty {
+            TyInt(hir::TyIs) | TyUint(hir::TyUs) => false,
+            TyInt(..) | TyUint(..) | TyFloat(..) => true,
+            _ => false
+        }
+    }
+
+    // Returns the type and mutability of *ty.
+    //
+    // The parameter `explicit` indicates if this is an *explicit* dereference.
+    // Some types---notably unsafe ptrs---can only be dereferenced explicitly.
+    pub fn builtin_deref(&self, explicit: bool, pref: ty::LvaluePreference)
+        -> Option<TypeAndMut<'tcx>>
+    {
+        match self.sty {
+            TyBox(ty) => {
+                Some(TypeAndMut {
+                    ty: ty,
+                    mutbl: if pref == ty::PreferMutLvalue {
+                        hir::MutMutable
+                    } else {
+                        hir::MutImmutable
+                    },
+                })
+            },
+            TyRef(_, mt) => Some(mt),
+            TyRawPtr(mt) if explicit => Some(mt),
+            _ => None
+        }
+    }
+
+    // Returns the type of ty[i]
+    pub fn builtin_index(&self) -> Option<Ty<'tcx>> {
+        match self.sty {
+            TyArray(ty, _) | TySlice(ty) => Some(ty),
+            _ => None
+        }
+    }
+
+    pub fn fn_sig(&self) -> &'tcx PolyFnSig<'tcx> {
+        match self.sty {
+            TyBareFn(_, ref f) => &f.sig,
+            _ => panic!("Ty::fn_sig() called on non-fn type: {:?}", self)
+        }
+    }
+
+    /// Returns the ABI of the given function.
+    pub fn fn_abi(&self) -> abi::Abi {
+        match self.sty {
+            TyBareFn(_, ref f) => f.abi,
+            _ => panic!("Ty::fn_abi() called on non-fn type"),
+        }
+    }
+
+    // Type accessors for substructures of types
+    pub fn fn_args(&self) -> ty::Binder<Vec<Ty<'tcx>>> {
+        self.fn_sig().inputs()
+    }
+
+    pub fn fn_ret(&self) -> Binder<FnOutput<'tcx>> {
+        self.fn_sig().output()
+    }
+
+    pub fn is_fn(&self) -> bool {
+        match self.sty {
+            TyBareFn(..) => true,
+            _ => false
+        }
+    }
+
+    pub fn ty_to_def_id(&self) -> Option<DefId> {
+        match self.sty {
+            TyTrait(ref tt) => Some(tt.principal_def_id()),
+            TyStruct(def, _) |
+            TyEnum(def, _) => Some(def.did),
+            TyClosure(id, _) => Some(id),
+            _ => None
+        }
+    }
+
+    pub fn ty_adt_def(&self) -> Option<AdtDef<'tcx>> {
+        match self.sty {
+            TyStruct(adt, _) | TyEnum(adt, _) => Some(adt),
+            _ => None
+        }
+    }
+}
index 222de426432975b72f120bd1fc10a1b975d9017c..99e41bd22b8bb9b250ed054dde519e6941dc509f 100644 (file)
@@ -21,7 +21,7 @@
 use middle::ty::TyClosure;
 use middle::ty::{TyBox, TyTrait, TyInt, TyUint, TyInfer};
 use middle::ty::{self, TypeAndMut, Ty, HasTypeFlags};
-use middle::ty::fold::{self, TypeFoldable};
+use middle::ty::fold::TypeFoldable;
 
 use std::fmt;
 use syntax::abi;
@@ -219,7 +219,7 @@ fn in_binder<'tcx, T, U>(f: &mut fmt::Formatter,
         }
     };
 
-    let new_value = fold::replace_late_bound_regions(tcx, &value, |br| {
+    let new_value = tcx.replace_late_bound_regions(&value, |br| {
         let _ = start_or_continue(f, "for<", ", ");
         ty::ReLateBound(ty::DebruijnIndex::new(1), match br {
             ty::BrNamed(_, name) => {
@@ -255,7 +255,7 @@ fn in_binder<'tcx, T, U>(f: &mut fmt::Formatter,
 struct TraitAndProjections<'tcx>(ty::TraitRef<'tcx>, Vec<ty::ProjectionPredicate<'tcx>>);
 
 impl<'tcx> TypeFoldable<'tcx> for TraitAndProjections<'tcx> {
-    fn fold_with<F: fold::TypeFolder<'tcx>>(&self, folder: &mut F)
+    fn fold_with<F:ty::fold::TypeFolder<'tcx>>(&self, folder: &mut F)
                                               -> TraitAndProjections<'tcx> {
         TraitAndProjections(self.0.fold_with(folder), self.1.fold_with(folder))
     }
@@ -388,6 +388,53 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+impl<'tcx> fmt::Debug for ty::AutoAdjustment<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            ty::AdjustReifyFnPointer => {
+                write!(f, "AdjustReifyFnPointer")
+            }
+            ty::AdjustUnsafeFnPointer => {
+                write!(f, "AdjustUnsafeFnPointer")
+            }
+            ty::AdjustDerefRef(ref data) => {
+                write!(f, "{:?}", data)
+            }
+        }
+    }
+}
+
+impl<'tcx> fmt::Debug for ty::AutoDerefRef<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "AutoDerefRef({}, unsize={:?}, {:?})",
+               self.autoderefs, self.unsize, self.autoref)
+    }
+}
+
+impl<'tcx> fmt::Debug for ty::TraitTy<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "TraitTy({:?},{:?})",
+               self.principal,
+               self.bounds)
+    }
+}
+
+impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            ty::Predicate::Trait(ref a) => write!(f, "{:?}", a),
+            ty::Predicate::Equate(ref pair) => write!(f, "{:?}", pair),
+            ty::Predicate::RegionOutlives(ref pair) => write!(f, "{:?}", pair),
+            ty::Predicate::TypeOutlives(ref pair) => write!(f, "{:?}", pair),
+            ty::Predicate::Projection(ref pair) => write!(f, "{:?}", pair),
+            ty::Predicate::WellFormed(ty) => write!(f, "WF({:?})", ty),
+            ty::Predicate::ObjectSafe(trait_def_id) => {
+                write!(f, "ObjectSafe({:?})", trait_def_id)
+            }
+        }
+    }
+}
+
 impl fmt::Display for ty::BoundRegion {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         if verbose() {
@@ -452,6 +499,45 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+impl<'tcx> fmt::Debug for ty::ClosureTy<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "ClosureTy({},{:?},{})",
+               self.unsafety,
+               self.sig,
+               self.abi)
+    }
+}
+
+impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "ClosureUpvar({:?},{:?})",
+               self.def,
+               self.ty)
+    }
+}
+
+impl<'a, 'tcx> fmt::Debug for ty::ParameterEnvironment<'a, 'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "ParameterEnvironment(\
+            free_substs={:?}, \
+            implicit_region_bound={:?}, \
+            caller_bounds={:?})",
+            self.free_substs,
+            self.implicit_region_bound,
+            self.caller_bounds)
+    }
+}
+
+impl<'tcx> fmt::Debug for ty::ObjectLifetimeDefault {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            ty::ObjectLifetimeDefault::Ambiguous => write!(f, "Ambiguous"),
+            ty::ObjectLifetimeDefault::BaseDefault => write!(f, "BaseDefault"),
+            ty::ObjectLifetimeDefault::Specific(ref r) => write!(f, "{:?}", r),
+        }
+    }
+}
+
 impl fmt::Display for ty::Region {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         if verbose() {
@@ -486,6 +572,17 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+impl fmt::Debug for ty::Variance {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str(match *self {
+            ty::Covariant => "+",
+            ty::Contravariant => "-",
+            ty::Invariant => "o",
+            ty::Bivariant => "*",
+        })
+    }
+}
+
 impl fmt::Debug for ty::ItemVariances {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "ItemVariances(types={:?}, regions={:?})",
@@ -570,6 +667,58 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+impl fmt::Debug for ty::TyVid {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "_#{}t", self.index)
+    }
+}
+
+impl fmt::Debug for ty::IntVid {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "_#{}i", self.index)
+    }
+}
+
+impl fmt::Debug for ty::FloatVid {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "_#{}f", self.index)
+    }
+}
+
+impl fmt::Debug for ty::RegionVid {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "'_#{}r", self.index)
+    }
+}
+
+impl<'tcx> fmt::Debug for ty::FnSig<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "({:?}; variadic: {})->{:?}", self.inputs, self.variadic, self.output)
+    }
+}
+
+impl fmt::Debug for ty::InferTy {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            ty::TyVar(ref v) => v.fmt(f),
+            ty::IntVar(ref v) => v.fmt(f),
+            ty::FloatVar(ref v) => v.fmt(f),
+            ty::FreshTy(v) => write!(f, "FreshTy({:?})", v),
+            ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v),
+            ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v)
+        }
+    }
+}
+
+impl fmt::Debug for ty::IntVarValue {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            ty::IntType(ref v) => v.fmt(f),
+            ty::UintType(ref v) => v.fmt(f),
+        }
+    }
+}
+
 // The generic impl doesn't work yet because projections are not
 // normalized under HRTB.
 /*impl<T> fmt::Display for ty::Binder<T>
index e6f9b1f9d6dec4808b6c438616b9cab914033e73..a9322bf2197b0b1c58f671e27668e5f0c0129783 100644 (file)
@@ -534,9 +534,7 @@ fn find_implied_output_region<'tcx>(tcx: &ty::ctxt<'tcx>,
 
     for (input_type, input_pat) in input_tys.iter().zip(input_pats) {
         let mut regions = FnvHashSet();
-        let have_bound_regions = ty::fold::collect_regions(tcx,
-                                                           input_type,
-                                                           &mut regions);
+        let have_bound_regions = tcx.collect_regions(input_type, &mut regions);
 
         debug!("find_implied_output_regions: collected {:?} from {:?} \
                 have_bound_regions={:?}", &regions, input_type, have_bound_regions);
index d3a292676c5ef7f30b5ccfb607107f98f741e614..cde188fa41e48f353d877bf383516227afc0adb9 100644 (file)
@@ -66,7 +66,8 @@
 use middle::traits::{self, ObligationCause};
 use middle::traits::{predicate_for_trait_def, report_selection_error};
 use middle::ty::{AutoDerefRef, AdjustDerefRef};
-use middle::ty::{self, LvaluePreference, TypeAndMut, Ty, TypeError};
+use middle::ty::{self, LvaluePreference, TypeAndMut, Ty};
+use middle::ty::error::TypeError;
 use middle::ty::relate::RelateResult;
 use util::common::indent;
 
index c16892d07416325cc965ae5077f5c131a32e8983..fe822138c9b5be3eb958110350190b26affd44fe 100644 (file)
@@ -32,7 +32,7 @@ pub fn suptype_with_fn<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                     ty_a: Ty<'tcx>,
                                     ty_b: Ty<'tcx>,
                                     handle_err: F) where
-    F: FnOnce(Span, Ty<'tcx>, Ty<'tcx>, &ty::TypeError<'tcx>),
+    F: FnOnce(Span, Ty<'tcx>, Ty<'tcx>, &ty::error::TypeError<'tcx>),
 {
     // n.b.: order of actual, expected is reversed
     match infer::mk_subty(fcx.infcx(), b_is_expected, infer::Misc(sp),
index dc433786ae4d63f509786ff4c51281327ca27d39..3160ed3502578f10e870e594f143ce268a5a8af4 100644 (file)
@@ -97,6 +97,7 @@
 use middle::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
 use middle::ty::{self, HasTypeFlags, RegionEscape, ToPolyTraitRef, Ty};
 use middle::ty::{MethodCall, MethodCallee};
+use middle::ty::error::TypeError;
 use middle::ty::fold::{TypeFolder, TypeFoldable};
 use require_c_abi_if_variadic;
 use rscope::{ElisionFailureInfo, RegionScope};
@@ -1627,7 +1628,7 @@ pub fn mk_subty(&self,
                     origin: infer::TypeOrigin,
                     sub: Ty<'tcx>,
                     sup: Ty<'tcx>)
-                    -> Result<(), ty::TypeError<'tcx>> {
+                    -> Result<(), TypeError<'tcx>> {
         infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
     }
 
@@ -1636,7 +1637,7 @@ pub fn mk_eqty(&self,
                    origin: infer::TypeOrigin,
                    sub: Ty<'tcx>,
                    sup: Ty<'tcx>)
-                   -> Result<(), ty::TypeError<'tcx>> {
+                   -> Result<(), TypeError<'tcx>> {
         infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
     }
 
@@ -1651,7 +1652,7 @@ pub fn type_error_message<M>(&self,
                                  sp: Span,
                                  mk_msg: M,
                                  actual_ty: Ty<'tcx>,
-                                 err: Option<&ty::TypeError<'tcx>>) where
+                                 err: Option<&TypeError<'tcx>>) where
         M: FnOnce(String) -> String,
     {
         self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
@@ -1661,7 +1662,7 @@ pub fn report_mismatched_types(&self,
                                    sp: Span,
                                    e: Ty<'tcx>,
                                    a: Ty<'tcx>,
-                                   err: &ty::TypeError<'tcx>) {
+                                   err: &TypeError<'tcx>) {
         self.infcx().report_mismatched_types(sp, e, a, err)
     }
 
@@ -1766,7 +1767,8 @@ fn check_casts(&self) {
     /// Apply "fallbacks" to some types
     /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
     fn default_type_parameters(&self) {
-        use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
+        use middle::ty::error::UnconstrainedNumeric::Neither;
+        use middle::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
         for ty in &self.infcx().unsolved_variables() {
             let resolved = self.infcx().resolve_type_vars_if_possible(ty);
             if self.infcx().type_var_diverges(resolved) {
@@ -1801,9 +1803,10 @@ fn old_select_all_obligations_and_apply_defaults(&self) {
     }
 
     fn new_select_all_obligations_and_apply_defaults(&self) {
-        use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
+        use middle::ty::error::UnconstrainedNumeric::Neither;
+        use middle::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
 
-            // For the time being this errs on the side of being memory wasteful but provides better
+        // For the time being this errs on the side of being memory wasteful but provides better
         // error reporting.
         // let type_variables = self.infcx().type_variables.clone();
 
@@ -1973,7 +1976,8 @@ fn find_conflicting_default(&self,
                                 default_map: &FnvHashMap<&Ty<'tcx>, type_variable::Default<'tcx>>,
                                 conflict: Ty<'tcx>)
                                 -> Option<type_variable::Default<'tcx>> {
-        use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
+        use middle::ty::error::UnconstrainedNumeric::Neither;
+        use middle::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
 
         // Ensure that we apply the conflicting default first
         let mut unbound_tyvars = Vec::with_capacity(unbound_vars.len() + 1);
index 8683afe44735a4f8c13e338e6f55b5c939d0e393..8048c302f2c78ff17abfec3fd2a06c093c44b518 100644 (file)
@@ -446,7 +446,7 @@ fn check_implementations_of_coerce_unsized(&self) {
                                mk_ptr: &Fn(Ty<'tcx>) -> Ty<'tcx>| {
                 if (mt_a.mutbl, mt_b.mutbl) == (hir::MutImmutable, hir::MutMutable) {
                     infcx.report_mismatched_types(span, mk_ptr(mt_b.ty),
-                                                  target, &ty::TypeError::Mutability);
+                                                  target, &ty::error::TypeError::Mutability);
                 }
                 (mt_a.ty, mt_b.ty, unsize_trait, None)
             };
index 930eb431f4957fdca3dd1af7e0de10baebb77d91..0f71c4d8ceb5608df065c4f3f95f533bceea9c4a 100644 (file)
@@ -2374,7 +2374,7 @@ fn liberate_early_bound_regions<'tcx,T>(
          * before we really have a `ParameterEnvironment` to check.
          */
 
-        ty::fold::fold_regions(tcx, value, &mut false, |region, _| {
+        tcx.fold_regions(value, &mut false, |region, _| {
             match region {
                 ty::ReEarlyBound(data) => {
                     let def_id = DefId::local(data.param_id);