]> git.lizzy.rs Git - rust.git/commitdiff
split ty::util and ty::adjustment
authorAriel Ben-Yehuda <ariel.byd@gmail.com>
Mon, 14 Sep 2015 11:55:56 +0000 (14:55 +0300)
committerAriel Ben-Yehuda <ariel.byd@gmail.com>
Mon, 14 Sep 2015 11:55:56 +0000 (14:55 +0300)
27 files changed:
src/librustc/metadata/csearch.rs
src/librustc/metadata/decoder.rs
src/librustc/middle/astencode.rs
src/librustc/middle/check_const.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/infer/mod.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/ty/adjustment.rs [new file with mode: 0644]
src/librustc/middle/ty/context.rs
src/librustc/middle/ty/fold.rs
src/librustc/middle/ty/mod.rs
src/librustc/middle/ty/structural_impls.rs
src/librustc/middle/ty/sty.rs
src/librustc/middle/ty/util.rs [new file with mode: 0644]
src/librustc/util/ppaux.rs
src/librustc_lint/builtin.rs
src/librustc_mir/tcx/expr.rs
src/librustc_trans/trans/consts.rs
src/librustc_trans/trans/expr.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/collect.rs

index c539bfc596413a78cccb156027fde7626bdc4369..e1cb9bd0e77cf60db4317ad998cae8d564355d64 100644 (file)
@@ -247,9 +247,11 @@ pub fn get_impl_polarity<'tcx>(tcx: &ty::ctxt<'tcx>,
     decoder::get_impl_polarity(&*cdata, def.node)
 }
 
-pub fn get_custom_coerce_unsized_kind<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                            def: DefId)
-                                            -> Option<ty::CustomCoerceUnsized> {
+pub fn get_custom_coerce_unsized_kind<'tcx>(
+    tcx: &ty::ctxt<'tcx>,
+    def: DefId)
+    -> Option<ty::adjustment::CustomCoerceUnsized>
+{
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_custom_coerce_unsized_kind(&*cdata, def.node)
index 309a18feb9aad123750e0467b7715a61f4ef0567..e2cf50cf30ad0b4a768c510eb25bf12a150f62c6 100644 (file)
@@ -540,9 +540,11 @@ pub fn get_impl_polarity<'tcx>(cdata: Cmd,
     }
 }
 
-pub fn get_custom_coerce_unsized_kind<'tcx>(cdata: Cmd,
-                                            id: ast::NodeId)
-                                            -> Option<ty::CustomCoerceUnsized> {
+pub fn get_custom_coerce_unsized_kind<'tcx>(
+    cdata: Cmd,
+    id: ast::NodeId)
+    -> Option<ty::adjustment::CustomCoerceUnsized>
+{
     let item_doc = cdata.lookup_item(id);
     reader::maybe_get_doc(item_doc, tag_impl_coerce_unsized_kind).map(|kind_doc| {
         let mut decoder = reader::Decoder::new(kind_doc);
index ac2dd54598253d888ef1e404e09209548fb5a3c2..0bd4434857abd50ca1d6d989b05ad0d8c449e6fa 100644 (file)
@@ -27,6 +27,7 @@
 use metadata::tydecode::{DefIdSource, NominalType, TypeWithId};
 use metadata::tydecode::{RegionParameter, ClosureSource};
 use metadata::tyencode;
+use middle::ty::adjustment;
 use middle::ty::cast;
 use middle::check_const::ConstQualif;
 use middle::def;
@@ -646,11 +647,11 @@ fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>,
     fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds);
     fn emit_upvar_capture(&mut self, ecx: &e::EncodeContext, capture: &ty::UpvarCapture);
     fn emit_auto_adjustment<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
-                                adj: &ty::AutoAdjustment<'tcx>);
+                                adj: &adjustment::AutoAdjustment<'tcx>);
     fn emit_autoref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
-                        autoref: &ty::AutoRef<'tcx>);
+                        autoref: &adjustment::AutoRef<'tcx>);
     fn emit_auto_deref_ref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
-                               auto_deref_ref: &ty::AutoDerefRef<'tcx>);
+                               auto_deref_ref: &adjustment::AutoDerefRef<'tcx>);
 }
 
 impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
@@ -771,22 +772,22 @@ fn emit_substs<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
     }
 
     fn emit_auto_adjustment<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
-                                adj: &ty::AutoAdjustment<'tcx>) {
+                                adj: &adjustment::AutoAdjustment<'tcx>) {
         use serialize::Encoder;
 
         self.emit_enum("AutoAdjustment", |this| {
             match *adj {
-                ty::AdjustReifyFnPointer=> {
+                adjustment::AdjustReifyFnPointer=> {
                     this.emit_enum_variant("AdjustReifyFnPointer", 1, 0, |_| Ok(()))
                 }
 
-                ty::AdjustUnsafeFnPointer => {
+                adjustment::AdjustUnsafeFnPointer => {
                     this.emit_enum_variant("AdjustUnsafeFnPointer", 2, 0, |_| {
                         Ok(())
                     })
                 }
 
-                ty::AdjustDerefRef(ref auto_deref_ref) => {
+                adjustment::AdjustDerefRef(ref auto_deref_ref) => {
                     this.emit_enum_variant("AdjustDerefRef", 3, 2, |this| {
                         this.emit_enum_variant_arg(0,
                             |this| Ok(this.emit_auto_deref_ref(ecx, auto_deref_ref)))
@@ -797,19 +798,19 @@ fn emit_auto_adjustment<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
     }
 
     fn emit_autoref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
-                        autoref: &ty::AutoRef<'tcx>) {
+                        autoref: &adjustment::AutoRef<'tcx>) {
         use serialize::Encoder;
 
         self.emit_enum("AutoRef", |this| {
             match autoref {
-                &ty::AutoPtr(r, m) => {
+                &adjustment::AutoPtr(r, m) => {
                     this.emit_enum_variant("AutoPtr", 0, 2, |this| {
                         this.emit_enum_variant_arg(0,
                             |this| Ok(this.emit_region(ecx, *r)));
                         this.emit_enum_variant_arg(1, |this| m.encode(this))
                     })
                 }
-                &ty::AutoUnsafe(m) => {
+                &adjustment::AutoUnsafe(m) => {
                     this.emit_enum_variant("AutoUnsafe", 1, 1, |this| {
                         this.emit_enum_variant_arg(0, |this| m.encode(this))
                     })
@@ -819,7 +820,7 @@ fn emit_autoref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
     }
 
     fn emit_auto_deref_ref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
-                               auto_deref_ref: &ty::AutoDerefRef<'tcx>) {
+                               auto_deref_ref: &adjustment::AutoDerefRef<'tcx>) {
         use serialize::Encoder;
 
         self.emit_struct("AutoDerefRef", 2, |this| {
@@ -974,7 +975,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
 
     if let Some(adjustment) = tcx.tables.borrow().adjustments.get(&id) {
         match *adjustment {
-            ty::AdjustDerefRef(ref adj) => {
+            adjustment::AdjustDerefRef(ref adj) => {
                 for autoderef in 0..adj.autoderefs {
                     let method_call = ty::MethodCall::autoderef(id, autoderef as u32);
                     if let Some(method) = tcx.tables.borrow().method_map.get(&method_call) {
@@ -1063,7 +1064,7 @@ fn read_substs<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
     fn read_upvar_capture(&mut self, dcx: &DecodeContext)
                           -> ty::UpvarCapture;
     fn read_auto_adjustment<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-                                    -> ty::AutoAdjustment<'tcx>;
+                                    -> adjustment::AutoAdjustment<'tcx>;
     fn read_cast_kind<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
                                  -> cast::CastKind;
     fn read_closure_kind<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
@@ -1071,9 +1072,9 @@ fn read_closure_kind<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
     fn read_closure_ty<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
                                -> ty::ClosureTy<'tcx>;
     fn read_auto_deref_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-                                   -> ty::AutoDerefRef<'tcx>;
+                                   -> adjustment::AutoDerefRef<'tcx>;
     fn read_autoref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-                            -> ty::AutoRef<'tcx>;
+                            -> adjustment::AutoRef<'tcx>;
     fn convert_def_id(&mut self,
                       dcx: &DecodeContext,
                       source: DefIdSource,
@@ -1246,30 +1247,30 @@ fn read_upvar_capture(&mut self, dcx: &DecodeContext) -> ty::UpvarCapture {
         }).unwrap()
     }
     fn read_auto_adjustment<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-                                    -> ty::AutoAdjustment<'tcx> {
+                                    -> adjustment::AutoAdjustment<'tcx> {
         self.read_enum("AutoAdjustment", |this| {
             let variants = ["AdjustReifyFnPointer", "AdjustUnsafeFnPointer", "AdjustDerefRef"];
             this.read_enum_variant(&variants, |this, i| {
                 Ok(match i {
-                    1 => ty::AdjustReifyFnPointer,
-                    2 => ty::AdjustUnsafeFnPointer,
+                    1 => adjustment::AdjustReifyFnPointer,
+                    2 => adjustment::AdjustUnsafeFnPointer,
                     3 => {
-                        let auto_deref_ref: ty::AutoDerefRef =
+                        let auto_deref_ref: adjustment::AutoDerefRef =
                             this.read_enum_variant_arg(0,
                                 |this| Ok(this.read_auto_deref_ref(dcx))).unwrap();
 
-                        ty::AdjustDerefRef(auto_deref_ref)
+                        adjustment::AdjustDerefRef(auto_deref_ref)
                     }
-                    _ => panic!("bad enum variant for ty::AutoAdjustment")
+                    _ => panic!("bad enum variant for adjustment::AutoAdjustment")
                 })
             })
         }).unwrap()
     }
 
     fn read_auto_deref_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-                                   -> ty::AutoDerefRef<'tcx> {
+                                   -> adjustment::AutoDerefRef<'tcx> {
         self.read_struct("AutoDerefRef", 2, |this| {
-            Ok(ty::AutoDerefRef {
+            Ok(adjustment::AutoDerefRef {
                 autoderefs: this.read_struct_field("autoderefs", 0, |this| {
                     Decodable::decode(this)
                 }).unwrap(),
@@ -1296,7 +1297,7 @@ fn read_auto_deref_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
     }
 
     fn read_autoref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-                            -> ty::AutoRef<'tcx> {
+                            -> adjustment::AutoRef<'tcx> {
         self.read_enum("AutoRef", |this| {
             let variants = ["AutoPtr", "AutoUnsafe"];
             this.read_enum_variant(&variants, |this, i| {
@@ -1311,15 +1312,15 @@ fn read_autoref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
                                 Decodable::decode(this)
                             }).unwrap();
 
-                        ty::AutoPtr(dcx.tcx.mk_region(r), m)
+                        adjustment::AutoPtr(dcx.tcx.mk_region(r), m)
                     }
                     1 => {
                         let m: hir::Mutability =
                             this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap();
 
-                        ty::AutoUnsafe(m)
+                        adjustment::AutoUnsafe(m)
                     }
-                    _ => panic!("bad enum variant for ty::AutoRef")
+                    _ => panic!("bad enum variant for adjustment::AutoRef")
                 })
             })
         }).unwrap()
@@ -1467,7 +1468,8 @@ fn decode_side_tables(dcx: &DecodeContext,
                         dcx.tcx.tables.borrow_mut().method_map.insert(method_call, method);
                     }
                     c::tag_table_adjustments => {
-                        let adj: ty::AutoAdjustment = val_dsr.read_auto_adjustment(dcx);
+                        let adj =
+                            val_dsr.read_auto_adjustment(dcx);
                         dcx.tcx.tables.borrow_mut().adjustments.insert(id, adj);
                     }
                     c::tag_table_closure_tys => {
index 48c8cca76b0564e8904a5d8a88478e565bf4bf7e..661299cd7f3fc0aec502bee21c5ae89e2a0331f9 100644 (file)
@@ -798,8 +798,13 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
 /// Check the adjustments of an expression
 fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr) {
     match v.tcx.tables.borrow().adjustments.get(&e.id) {
-        None | Some(&ty::AdjustReifyFnPointer) | Some(&ty::AdjustUnsafeFnPointer) => {}
-        Some(&ty::AdjustDerefRef(ty::AutoDerefRef { autoderefs, .. })) => {
+        None |
+        Some(&ty::adjustment::AdjustReifyFnPointer) |
+        Some(&ty::adjustment::AdjustUnsafeFnPointer) => {}
+
+        Some(&ty::adjustment::AdjustDerefRef(
+            ty::adjustment::AutoDerefRef { autoderefs, .. }
+        )) => {
             if (0..autoderefs as u32).any(|autoderef| {
                     v.tcx.is_overloaded_autoderef(e.id, autoderef)
             }) {
index d2bb31f10bd14025a1e93ff532589cbf349e21d9..a8fed5eab16bef2d690c90f5ac9b3cd4d9b153ff 100644 (file)
@@ -25,6 +25,7 @@
 use middle::infer;
 use middle::mem_categorization as mc;
 use middle::ty;
+use middle::ty::adjustment;
 
 use rustc_front::hir;
 
@@ -726,8 +727,8 @@ fn walk_adjustment(&mut self, expr: &hir::Expr) {
         let adj = typer.adjustments().get(&expr.id).map(|x| x.clone());
         if let Some(adjustment) = adj {
             match adjustment {
-                ty::AdjustReifyFnPointer |
-                ty::AdjustUnsafeFnPointer => {
+                adjustment::AdjustReifyFnPointer |
+                adjustment::AdjustUnsafeFnPointer => {
                     // Creating a closure/fn-pointer or unsizing consumes
                     // the input and stores it into the resulting rvalue.
                     debug!("walk_adjustment(AdjustReifyFnPointer|AdjustUnsafeFnPointer)");
@@ -735,7 +736,7 @@ fn walk_adjustment(&mut self, expr: &hir::Expr) {
                         return_if_err!(self.mc.cat_expr_unadjusted(expr));
                     self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
                 }
-                ty::AdjustDerefRef(ref adj) => {
+                adjustment::AdjustDerefRef(ref adj) => {
                     self.walk_autoderefref(expr, adj);
                 }
             }
@@ -778,7 +779,7 @@ fn walk_autoderefs(&mut self,
 
     fn walk_autoderefref(&mut self,
                          expr: &hir::Expr,
-                         adj: &ty::AutoDerefRef<'tcx>) {
+                         adj: &adjustment::AutoDerefRef<'tcx>) {
         debug!("walk_autoderefref expr={:?} adj={:?}",
                expr,
                adj);
@@ -809,7 +810,7 @@ fn walk_autoderefref(&mut self,
     fn walk_autoref(&mut self,
                     expr: &hir::Expr,
                     cmt_base: mc::cmt<'tcx>,
-                    opt_autoref: Option<ty::AutoRef<'tcx>>)
+                    opt_autoref: Option<adjustment::AutoRef<'tcx>>)
                     -> mc::cmt<'tcx>
     {
         debug!("walk_autoref(expr.id={} cmt_derefd={:?} opt_autoref={:?})",
@@ -828,7 +829,7 @@ fn walk_autoref(&mut self,
         };
 
         match *autoref {
-            ty::AutoPtr(r, m) => {
+            adjustment::AutoPtr(r, m) => {
                 self.delegate.borrow(expr.id,
                                      expr.span,
                                      cmt_base,
@@ -837,7 +838,7 @@ fn walk_autoref(&mut self,
                                      AutoRef);
             }
 
-            ty::AutoUnsafe(m) => {
+            adjustment::AutoUnsafe(m) => {
                 debug!("walk_autoref: expr.id={} cmt_base={:?}",
                        expr.id,
                        cmt_base);
index b9e9ee5e2449732dc7c469459ecbcef6d52c93b2..ffb631e105b3a0bf05895ed4201ff67b4c76b6cb 100644 (file)
@@ -30,6 +30,7 @@
 use middle::subst::Subst;
 use middle::traits::{self, FulfillmentContext, Normalized,
                      SelectionContext, ObligationCause};
+use middle::ty::adjustment;
 use middle::ty::{TyVid, IntVid, FloatVid, RegionVid};
 use middle::ty::{self, Ty, HasTypeFlags};
 use middle::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
@@ -1151,7 +1152,7 @@ pub fn fresh_bound_region(&self, debruijn: ty::DebruijnIndex) -> ty::Region {
     /// Apply `adjustment` to the type of `expr`
     pub fn adjust_expr_ty(&self,
                           expr: &hir::Expr,
-                          adjustment: Option<&ty::AutoAdjustment<'tcx>>)
+                          adjustment: Option<&adjustment::AutoAdjustment<'tcx>>)
                           -> Ty<'tcx>
     {
         let raw_ty = self.expr_ty(expr);
@@ -1485,9 +1486,9 @@ pub fn node_method_id(&self, method_call: ty::MethodCall)
             .map(|method| method.def_id)
     }
 
-    pub fn adjustments(&self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>> {
+    pub fn adjustments(&self) -> Ref<NodeMap<adjustment::AutoAdjustment<'tcx>>> {
         fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>)
-                                        -> &'a NodeMap<ty::AutoAdjustment<'tcx>> {
+                                        -> &'a NodeMap<adjustment::AutoAdjustment<'tcx>> {
             &tables.adjustments
         }
 
index 51005ef8b97704c2c2b71846df9359cc52a38b18..dd2f48d25b4b0c6cc00c69dbd56b508fa824e141 100644 (file)
@@ -77,6 +77,7 @@
 use middle::infer;
 use middle::check_const;
 use middle::def;
+use middle::ty::adjustment;
 use middle::ty::{self, Ty};
 
 use rustc_front::hir::{MutImmutable, MutMutable};
@@ -421,16 +422,16 @@ pub fn cat_expr(&self, expr: &hir::Expr) -> McResult<cmt<'tcx>> {
 
             Some(adjustment) => {
                 match *adjustment {
-                    ty::AdjustDerefRef(
-                        ty::AutoDerefRef {
+                    adjustment::AdjustDerefRef(
+                        adjustment::AutoDerefRef {
                             autoref: None, unsize: None, autoderefs, ..}) => {
                         // Equivalent to *expr or something similar.
                         self.cat_expr_autoderefd(expr, autoderefs)
                     }
 
-                    ty::AdjustReifyFnPointer |
-                    ty::AdjustUnsafeFnPointer |
-                    ty::AdjustDerefRef(_) => {
+                    adjustment::AdjustReifyFnPointer |
+                    adjustment::AdjustUnsafeFnPointer |
+                    adjustment::AdjustDerefRef(_) => {
                         debug!("cat_expr({:?}): {:?}",
                                adjustment,
                                expr);
diff --git a/src/librustc/middle/ty/adjustment.rs b/src/librustc/middle/ty/adjustment.rs
new file mode 100644 (file)
index 0000000..cadab49
--- /dev/null
@@ -0,0 +1,249 @@
+// 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.
+
+pub use self::AutoAdjustment::*;
+pub use self::AutoRef::*;
+
+use middle::ty::{self, Ty, TypeAndMut};
+use middle::ty::HasTypeFlags;
+use middle::ty::LvaluePreference::{NoPreference};
+
+use syntax::ast;
+use syntax::codemap::Span;
+
+use rustc_front::hir;
+
+#[derive(Copy, Clone)]
+pub enum AutoAdjustment<'tcx> {
+    AdjustReifyFnPointer,   // go from a fn-item type to a fn-pointer type
+    AdjustUnsafeFnPointer,  // go from a safe fn pointer to an unsafe fn pointer
+    AdjustDerefRef(AutoDerefRef<'tcx>),
+}
+
+/// Represents coercing a pointer to a different kind of pointer - where 'kind'
+/// here means either or both of raw vs borrowed vs unique and fat vs thin.
+///
+/// We transform pointers by following the following steps in order:
+/// 1. Deref the pointer `self.autoderefs` times (may be 0).
+/// 2. If `autoref` is `Some(_)`, then take the address and produce either a
+///    `&` or `*` pointer.
+/// 3. If `unsize` is `Some(_)`, then apply the unsize transformation,
+///    which will do things like convert thin pointers to fat
+///    pointers, or convert structs containing thin pointers to
+///    structs containing fat pointers, or convert between fat
+///    pointers.  We don't store the details of how the transform is
+///    done (in fact, we don't know that, because it might depend on
+///    the precise type parameters). We just store the target
+///    type. Trans figures out what has to be done at monomorphization
+///    time based on the precise source/target type at hand.
+///
+/// To make that more concrete, here are some common scenarios:
+///
+/// 1. The simplest cases are where the pointer is not adjusted fat vs thin.
+/// Here the pointer will be dereferenced N times (where a dereference can
+/// happen to to raw or borrowed pointers or any smart pointer which implements
+/// Deref, including Box<_>). The number of dereferences is given by
+/// `autoderefs`.  It can then be auto-referenced zero or one times, indicated
+/// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is
+/// None.
+///
+/// 2. A thin-to-fat coercon involves unsizing the underlying data. We start
+/// with a thin pointer, deref a number of times, unsize the underlying data,
+/// then autoref. The 'unsize' phase may change a fixed length array to a
+/// dynamically sized one, a concrete object to a trait object, or statically
+/// sized struct to a dyncamically sized one. E.g., &[i32; 4] -> &[i32] is
+/// represented by:
+///
+/// ```
+/// AutoDerefRef {
+///     autoderefs: 1,          // &[i32; 4] -> [i32; 4]
+///     autoref: Some(AutoPtr), // [i32] -> &[i32]
+///     unsize: Some([i32]),    // [i32; 4] -> [i32]
+/// }
+/// ```
+///
+/// Note that for a struct, the 'deep' unsizing of the struct is not recorded.
+/// E.g., `struct Foo<T> { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>
+/// The autoderef and -ref are the same as in the above example, but the type
+/// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about
+/// the underlying conversions from `[i32; 4]` to `[i32]`.
+///
+/// 3. Coercing a `Box<T>` to `Box<Trait>` is an interesting special case.  In
+/// that case, we have the pointer we need coming in, so there are no
+/// autoderefs, and no autoref. Instead we just do the `Unsize` transformation.
+/// At some point, of course, `Box` should move out of the compiler, in which
+/// case this is analogous to transformating a struct. E.g., Box<[i32; 4]> ->
+/// Box<[i32]> is represented by:
+///
+/// ```
+/// AutoDerefRef {
+///     autoderefs: 0,
+///     autoref: None,
+///     unsize: Some(Box<[i32]>),
+/// }
+/// ```
+#[derive(Copy, Clone)]
+pub struct AutoDerefRef<'tcx> {
+    /// Step 1. Apply a number of dereferences, producing an lvalue.
+    pub autoderefs: usize,
+
+    /// Step 2. Optionally produce a pointer/reference from the value.
+    pub autoref: Option<AutoRef<'tcx>>,
+
+    /// Step 3. Unsize a pointer/reference value, e.g. `&[T; n]` to
+    /// `&[T]`. The stored type is the target pointer type. Note that
+    /// the source could be a thin or fat pointer.
+    pub unsize: Option<Ty<'tcx>>,
+}
+
+impl<'tcx> AutoAdjustment<'tcx> {
+    pub fn is_identity(&self) -> bool {
+        match *self {
+            AdjustReifyFnPointer |
+            AdjustUnsafeFnPointer => false,
+            AdjustDerefRef(ref r) => r.is_identity(),
+        }
+    }
+}
+impl<'tcx> AutoDerefRef<'tcx> {
+    pub fn is_identity(&self) -> bool {
+        self.autoderefs == 0 && self.unsize.is_none() && self.autoref.is_none()
+    }
+}
+
+
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub enum AutoRef<'tcx> {
+    /// Convert from T to &T.
+    AutoPtr(&'tcx ty::Region, hir::Mutability),
+
+    /// Convert from T to *T.
+    /// Value to thin pointer.
+    AutoUnsafe(hir::Mutability),
+}
+
+#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
+pub enum CustomCoerceUnsized {
+    /// Records the index of the field being coerced.
+    Struct(usize)
+}
+
+impl<'tcx> ty::TyS<'tcx> {
+    /// See `expr_ty_adjusted`
+    pub fn adjust<F>(&'tcx self, cx: &ty::ctxt<'tcx>,
+                     span: Span,
+                     expr_id: ast::NodeId,
+                     adjustment: Option<&AutoAdjustment<'tcx>>,
+                     mut method_type: F)
+                     -> Ty<'tcx> where
+        F: FnMut(ty::MethodCall) -> Option<Ty<'tcx>>,
+    {
+        if let ty::TyError = self.sty {
+            return self;
+        }
+
+        return match adjustment {
+            Some(adjustment) => {
+                match *adjustment {
+                   AdjustReifyFnPointer => {
+                        match self.sty {
+                            ty::TyBareFn(Some(_), b) => {
+                                cx.mk_fn(None, b)
+                            }
+                            _ => {
+                                cx.sess.bug(
+                                    &format!("AdjustReifyFnPointer adjustment on non-fn-item: \
+                                              {:?}", self));
+                            }
+                        }
+                    }
+
+                   AdjustUnsafeFnPointer => {
+                        match self.sty {
+                            ty::TyBareFn(None, b) => cx.safe_to_unsafe_fn_ty(b),
+                            ref b => {
+                                cx.sess.bug(
+                                    &format!("AdjustReifyFnPointer adjustment on non-fn-item: \
+                                             {:?}",
+                                            b));
+                            }
+                        }
+                   }
+
+                    AdjustDerefRef(ref adj) => {
+                        let mut adjusted_ty = self;
+
+                        if !adjusted_ty.references_error() {
+                            for i in 0..adj.autoderefs {
+                                adjusted_ty =
+                                    adjusted_ty.adjust_for_autoderef(cx,
+                                                                     expr_id,
+                                                                     span,
+                                                                     i as u32,
+                                                                     &mut method_type);
+                            }
+                        }
+
+                        if let Some(target) = adj.unsize {
+                            target
+                        } else {
+                            adjusted_ty.adjust_for_autoref(cx, adj.autoref)
+                        }
+                    }
+                }
+            }
+            None => self
+        };
+    }
+
+    pub fn adjust_for_autoderef<F>(&'tcx self,
+                                   cx: &ty::ctxt<'tcx>,
+                                   expr_id: ast::NodeId,
+                                   expr_span: Span,
+                                   autoderef: u32, // how many autoderefs so far?
+                                   mut method_type: F)
+                                   -> Ty<'tcx> where
+        F: FnMut(ty::MethodCall) -> Option<Ty<'tcx>>,
+    {
+        let method_call = ty::MethodCall::autoderef(expr_id, autoderef);
+        let mut adjusted_ty = self;
+        if let Some(method_ty) = method_type(method_call) {
+            // Method calls always have all late-bound regions
+            // fully instantiated.
+            let fn_ret = cx.no_late_bound_regions(&method_ty.fn_ret()).unwrap();
+            adjusted_ty = fn_ret.unwrap();
+        }
+        match adjusted_ty.builtin_deref(true, NoPreference) {
+            Some(mt) => mt.ty,
+            None => {
+                cx.sess.span_bug(
+                    expr_span,
+                    &format!("the {}th autoderef failed: {}",
+                             autoderef,
+                             adjusted_ty)
+                        );
+            }
+        }
+    }
+
+    pub fn adjust_for_autoref(&'tcx self, cx: &ty::ctxt<'tcx>,
+                              autoref: Option<AutoRef<'tcx>>)
+                              -> Ty<'tcx> {
+        match autoref {
+            None => self,
+            Some(AutoPtr(r, m)) => {
+                cx.mk_ref(r, TypeAndMut { ty: self, mutbl: m })
+            }
+            Some(AutoUnsafe(m)) => {
+                cx.mk_ptr(TypeAndMut { ty: self, mutbl: m })
+            }
+        }
+    }
+}
index 4d57e0980ef542446f1186d23e2c2293e2e327c8..e3b6da56680da303b5657aec0a52ecfe4cd93a81 100644 (file)
@@ -106,7 +106,7 @@ pub struct Tables<'tcx> {
     /// other items.
     pub item_substs: NodeMap<ty::ItemSubsts<'tcx>>,
 
-    pub adjustments: NodeMap<ty::AutoAdjustment<'tcx>>,
+    pub adjustments: NodeMap<ty::adjustment::AutoAdjustment<'tcx>>,
 
     pub method_map: ty::MethodMap<'tcx>,
 
@@ -308,7 +308,7 @@ pub struct ctxt<'tcx> {
     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>>,
+    pub custom_coerce_unsized_kinds: RefCell<DefIdMap<ty::adjustment::CustomCoerceUnsized>>,
 
     /// Maps a cast expression to its kind. This is keyed on the
     /// *from* expression of the cast, not the cast itself.
index 9de58369a63f8c68cff6276b6cb7f91261b1bd0b..751bac28ce4c2aa7c0037bd897ef2a24c64bd03c 100644 (file)
@@ -36,6 +36,7 @@
 
 use middle::region;
 use middle::subst;
+use middle::ty::adjustment;
 use middle::ty::{self, Binder, Ty, HasTypeFlags, RegionEscape};
 
 use std::fmt;
@@ -128,7 +129,8 @@ fn fold_existential_bounds(&mut self, s: &ty::ExistentialBounds<'tcx>)
         super_fold_existential_bounds(self, s)
     }
 
-    fn fold_autoref(&mut self, ar: &ty::AutoRef<'tcx>) -> ty::AutoRef<'tcx> {
+    fn fold_autoref(&mut self, ar: &adjustment::AutoRef<'tcx>)
+                    -> adjustment::AutoRef<'tcx> {
         super_fold_autoref(self, ar)
     }
 
@@ -296,15 +298,15 @@ pub fn super_fold_existential_bounds<'tcx, T: TypeFolder<'tcx>>(
 }
 
 pub fn super_fold_autoref<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
-                                                     autoref: &ty::AutoRef<'tcx>)
-                                                     -> ty::AutoRef<'tcx>
+                                                     autoref: &adjustment::AutoRef<'tcx>)
+                                                     -> adjustment::AutoRef<'tcx>
 {
     match *autoref {
-        ty::AutoPtr(r, m) => {
+        adjustment::AutoPtr(r, m) => {
             let r = r.fold_with(this);
-            ty::AutoPtr(this.tcx().mk_region(r), m)
+            adjustment::AutoPtr(this.tcx().mk_region(r), m)
         }
-        ty::AutoUnsafe(m) => ty::AutoUnsafe(m)
+        adjustment::AutoUnsafe(m) => adjustment::AutoUnsafe(m)
     }
 }
 
index ab1160d7deb02292d1a7c4bc57713c29e21feea7..dff423b35dd0a59c5799a6aafdab8146c0adccc5 100644 (file)
 pub use self::ImplOrTraitItemId::*;
 pub use self::ClosureKind::*;
 pub use self::Variance::*;
-pub use self::AutoAdjustment::*;
-pub use self::Representability::*;
-pub use self::AutoRef::*;
 pub use self::DtorKind::*;
 pub use self::ExplicitSelfCategory::*;
 pub use self::ImplOrTraitItemContainer::*;
 pub use self::BorrowKind::*;
 pub use self::ImplOrTraitItem::*;
 pub use self::IntVarValue::*;
-pub use self::CopyImplementationError::*;
 pub use self::LvaluePreference::*;
 
-use back::svh::Svh;
 use front::map as ast_map;
 use front::map::LinkedPath;
 use metadata::csearch;
 use middle;
-use middle::const_eval::{self, ConstVal, ErrKind};
-use middle::const_eval::EvalHint::UncheckedExprHint;
 use middle::def::{self, ExportMap};
 use middle::def_id::{DefId, LOCAL_CRATE};
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
-use middle::infer;
-use middle::pat_util;
 use middle::subst::{self, ParamSpace, Subst, Substs, VecPerParamSpace};
 use middle::traits;
 use middle::ty;
 use util::common::memoized;
 use util::nodemap::{NodeMap, NodeSet, DefIdMap};
 use util::nodemap::FnvHashMap;
-use util::num::ToPrimitive;
 
 use std::borrow::{Borrow, Cow};
 use std::cell::{Cell, RefCell};
-use std::cmp;
-use std::hash::{Hash, SipHasher, Hasher};
+use std::hash::{Hash, Hasher};
 use std::iter;
 use std::rc::Rc;
 use std::slice;
@@ -61,7 +50,7 @@
 use rustc_front::hir;
 use rustc_front::hir::{ItemImpl, ItemTrait};
 use rustc_front::hir::{MutImmutable, MutMutable, Visibility};
-use rustc_front::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt};
+use rustc_front::attr::{self, AttrMetaMethods};
 
 pub use self::sty::{Binder, DebruijnIndex};
 pub use self::sty::{BuiltinBound, BuiltinBounds, ExistentialBounds};
@@ -86,6 +75,7 @@
 pub use self::context::{ctxt, tls};
 pub use self::context::{CtxtArenas, Lift, Tables};
 
+pub mod adjustment;
 pub mod cast;
 pub mod error;
 pub mod fast_reject;
@@ -95,6 +85,7 @@
 pub mod relate;
 pub mod walk;
 pub mod wf;
+pub mod util;
 
 mod contents;
 mod context;
 mod sty;
 
 pub type Disr = u64;
-
 pub const INITIAL_DISCRIMINANT_VALUE: Disr = 0;
 
 // Data types
@@ -143,126 +133,6 @@ pub fn has_drop_flag(&self) -> bool {
     }
 }
 
-pub trait IntTypeExt {
-    fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx>;
-    fn i64_to_disr(&self, val: i64) -> Option<Disr>;
-    fn u64_to_disr(&self, val: u64) -> Option<Disr>;
-    fn disr_incr(&self, val: Disr) -> Option<Disr>;
-    fn disr_string(&self, val: Disr) -> String;
-    fn disr_wrap_incr(&self, val: Option<Disr>) -> Disr;
-}
-
-impl IntTypeExt for attr::IntType {
-    fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx> {
-        match *self {
-            SignedInt(hir::TyI8)      => cx.types.i8,
-            SignedInt(hir::TyI16)     => cx.types.i16,
-            SignedInt(hir::TyI32)     => cx.types.i32,
-            SignedInt(hir::TyI64)     => cx.types.i64,
-            SignedInt(hir::TyIs)   => cx.types.isize,
-            UnsignedInt(hir::TyU8)    => cx.types.u8,
-            UnsignedInt(hir::TyU16)   => cx.types.u16,
-            UnsignedInt(hir::TyU32)   => cx.types.u32,
-            UnsignedInt(hir::TyU64)   => cx.types.u64,
-            UnsignedInt(hir::TyUs) => cx.types.usize,
-        }
-    }
-
-    fn i64_to_disr(&self, val: i64) -> Option<Disr> {
-        match *self {
-            SignedInt(hir::TyI8)    => val.to_i8()  .map(|v| v as Disr),
-            SignedInt(hir::TyI16)   => val.to_i16() .map(|v| v as Disr),
-            SignedInt(hir::TyI32)   => val.to_i32() .map(|v| v as Disr),
-            SignedInt(hir::TyI64)   => val.to_i64() .map(|v| v as Disr),
-            UnsignedInt(hir::TyU8)  => val.to_u8()  .map(|v| v as Disr),
-            UnsignedInt(hir::TyU16) => val.to_u16() .map(|v| v as Disr),
-            UnsignedInt(hir::TyU32) => val.to_u32() .map(|v| v as Disr),
-            UnsignedInt(hir::TyU64) => val.to_u64() .map(|v| v as Disr),
-
-            UnsignedInt(hir::TyUs) |
-            SignedInt(hir::TyIs) => unreachable!(),
-        }
-    }
-
-    fn u64_to_disr(&self, val: u64) -> Option<Disr> {
-        match *self {
-            SignedInt(hir::TyI8)    => val.to_i8()  .map(|v| v as Disr),
-            SignedInt(hir::TyI16)   => val.to_i16() .map(|v| v as Disr),
-            SignedInt(hir::TyI32)   => val.to_i32() .map(|v| v as Disr),
-            SignedInt(hir::TyI64)   => val.to_i64() .map(|v| v as Disr),
-            UnsignedInt(hir::TyU8)  => val.to_u8()  .map(|v| v as Disr),
-            UnsignedInt(hir::TyU16) => val.to_u16() .map(|v| v as Disr),
-            UnsignedInt(hir::TyU32) => val.to_u32() .map(|v| v as Disr),
-            UnsignedInt(hir::TyU64) => val.to_u64() .map(|v| v as Disr),
-
-            UnsignedInt(hir::TyUs) |
-            SignedInt(hir::TyIs) => unreachable!(),
-        }
-    }
-
-    fn disr_incr(&self, val: Disr) -> Option<Disr> {
-        macro_rules! add1 {
-            ($e:expr) => { $e.and_then(|v|v.checked_add(1)).map(|v| v as Disr) }
-        }
-        match *self {
-            // SignedInt repr means we *want* to reinterpret the bits
-            // treating the highest bit of Disr as a sign-bit, so
-            // cast to i64 before range-checking.
-            SignedInt(hir::TyI8)    => add1!((val as i64).to_i8()),
-            SignedInt(hir::TyI16)   => add1!((val as i64).to_i16()),
-            SignedInt(hir::TyI32)   => add1!((val as i64).to_i32()),
-            SignedInt(hir::TyI64)   => add1!(Some(val as i64)),
-
-            UnsignedInt(hir::TyU8)  => add1!(val.to_u8()),
-            UnsignedInt(hir::TyU16) => add1!(val.to_u16()),
-            UnsignedInt(hir::TyU32) => add1!(val.to_u32()),
-            UnsignedInt(hir::TyU64) => add1!(Some(val)),
-
-            UnsignedInt(hir::TyUs) |
-            SignedInt(hir::TyIs) => unreachable!(),
-        }
-    }
-
-    // This returns a String because (1.) it is only used for
-    // rendering an error message and (2.) a string can represent the
-    // full range from `i64::MIN` through `u64::MAX`.
-    fn disr_string(&self, val: Disr) -> String {
-        match *self {
-            SignedInt(hir::TyI8)    => format!("{}", val as i8 ),
-            SignedInt(hir::TyI16)   => format!("{}", val as i16),
-            SignedInt(hir::TyI32)   => format!("{}", val as i32),
-            SignedInt(hir::TyI64)   => format!("{}", val as i64),
-            UnsignedInt(hir::TyU8)  => format!("{}", val as u8 ),
-            UnsignedInt(hir::TyU16) => format!("{}", val as u16),
-            UnsignedInt(hir::TyU32) => format!("{}", val as u32),
-            UnsignedInt(hir::TyU64) => format!("{}", val as u64),
-
-            UnsignedInt(hir::TyUs) |
-            SignedInt(hir::TyIs) => unreachable!(),
-        }
-    }
-
-    fn disr_wrap_incr(&self, val: Option<Disr>) -> Disr {
-        macro_rules! add1 {
-            ($e:expr) => { ($e).wrapping_add(1) as Disr }
-        }
-        let val = val.unwrap_or(ty::INITIAL_DISCRIMINANT_VALUE);
-        match *self {
-            SignedInt(hir::TyI8)    => add1!(val as i8 ),
-            SignedInt(hir::TyI16)   => add1!(val as i16),
-            SignedInt(hir::TyI32)   => add1!(val as i32),
-            SignedInt(hir::TyI64)   => add1!(val as i64),
-            UnsignedInt(hir::TyU8)  => add1!(val as u8 ),
-            UnsignedInt(hir::TyU16) => add1!(val as u16),
-            UnsignedInt(hir::TyU32) => add1!(val as u32),
-            UnsignedInt(hir::TyU64) => add1!(val as u64),
-
-            UnsignedInt(hir::TyUs) |
-            SignedInt(hir::TyIs) => unreachable!(),
-        }
-    }
-}
-
 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub enum ImplOrTraitItemContainer {
     TraitContainer(DefId),
@@ -435,105 +305,6 @@ pub enum Variance {
     Bivariant,      // T<A> <: T<B>            -- e.g., unused type parameter
 }
 
-#[derive(Copy, Clone)]
-pub enum AutoAdjustment<'tcx> {
-    AdjustReifyFnPointer,   // go from a fn-item type to a fn-pointer type
-    AdjustUnsafeFnPointer,  // go from a safe fn pointer to an unsafe fn pointer
-    AdjustDerefRef(AutoDerefRef<'tcx>),
-}
-
-/// Represents coercing a pointer to a different kind of pointer - where 'kind'
-/// here means either or both of raw vs borrowed vs unique and fat vs thin.
-///
-/// We transform pointers by following the following steps in order:
-/// 1. Deref the pointer `self.autoderefs` times (may be 0).
-/// 2. If `autoref` is `Some(_)`, then take the address and produce either a
-///    `&` or `*` pointer.
-/// 3. If `unsize` is `Some(_)`, then apply the unsize transformation,
-///    which will do things like convert thin pointers to fat
-///    pointers, or convert structs containing thin pointers to
-///    structs containing fat pointers, or convert between fat
-///    pointers.  We don't store the details of how the transform is
-///    done (in fact, we don't know that, because it might depend on
-///    the precise type parameters). We just store the target
-///    type. Trans figures out what has to be done at monomorphization
-///    time based on the precise source/target type at hand.
-///
-/// To make that more concrete, here are some common scenarios:
-///
-/// 1. The simplest cases are where the pointer is not adjusted fat vs thin.
-/// Here the pointer will be dereferenced N times (where a dereference can
-/// happen to to raw or borrowed pointers or any smart pointer which implements
-/// Deref, including Box<_>). The number of dereferences is given by
-/// `autoderefs`.  It can then be auto-referenced zero or one times, indicated
-/// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is
-/// None.
-///
-/// 2. A thin-to-fat coercon involves unsizing the underlying data. We start
-/// with a thin pointer, deref a number of times, unsize the underlying data,
-/// then autoref. The 'unsize' phase may change a fixed length array to a
-/// dynamically sized one, a concrete object to a trait object, or statically
-/// sized struct to a dyncamically sized one. E.g., &[i32; 4] -> &[i32] is
-/// represented by:
-///
-/// ```
-/// AutoDerefRef {
-///     autoderefs: 1,          // &[i32; 4] -> [i32; 4]
-///     autoref: Some(AutoPtr), // [i32] -> &[i32]
-///     unsize: Some([i32]),    // [i32; 4] -> [i32]
-/// }
-/// ```
-///
-/// Note that for a struct, the 'deep' unsizing of the struct is not recorded.
-/// E.g., `struct Foo<T> { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>
-/// The autoderef and -ref are the same as in the above example, but the type
-/// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about
-/// the underlying conversions from `[i32; 4]` to `[i32]`.
-///
-/// 3. Coercing a `Box<T>` to `Box<Trait>` is an interesting special case.  In
-/// that case, we have the pointer we need coming in, so there are no
-/// autoderefs, and no autoref. Instead we just do the `Unsize` transformation.
-/// At some point, of course, `Box` should move out of the compiler, in which
-/// case this is analogous to transformating a struct. E.g., Box<[i32; 4]> ->
-/// Box<[i32]> is represented by:
-///
-/// ```
-/// AutoDerefRef {
-///     autoderefs: 0,
-///     autoref: None,
-///     unsize: Some(Box<[i32]>),
-/// }
-/// ```
-#[derive(Copy, Clone)]
-pub struct AutoDerefRef<'tcx> {
-    /// Step 1. Apply a number of dereferences, producing an lvalue.
-    pub autoderefs: usize,
-
-    /// Step 2. Optionally produce a pointer/reference from the value.
-    pub autoref: Option<AutoRef<'tcx>>,
-
-    /// Step 3. Unsize a pointer/reference value, e.g. `&[T; n]` to
-    /// `&[T]`. The stored type is the target pointer type. Note that
-    /// the source could be a thin or fat pointer.
-    pub unsize: Option<Ty<'tcx>>,
-}
-
-#[derive(Copy, Clone, PartialEq, Debug)]
-pub enum AutoRef<'tcx> {
-    /// Convert from T to &T.
-    AutoPtr(&'tcx Region, hir::Mutability),
-
-    /// Convert from T to *T.
-    /// Value to thin pointer.
-    AutoUnsafe(hir::Mutability),
-}
-
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
-pub enum CustomCoerceUnsized {
-    /// Records the index of the field being coerced.
-    Struct(usize)
-}
-
 #[derive(Clone, Copy, Debug)]
 pub struct MethodCallee<'tcx> {
     /// Impl method ID, for inherent methods, or trait method ID, otherwise.
@@ -1502,52 +1273,6 @@ pub fn for_item(cx: &'a ctxt<'tcx>, id: NodeId) -> ParameterEnvironment<'a, 'tcx
             }
         }
     }
-
-    pub fn can_type_implement_copy(&self, self_type: Ty<'tcx>, span: Span)
-                                   -> Result<(),CopyImplementationError> {
-        let tcx = self.tcx;
-
-        // FIXME: (@jroesch) float this code up
-        let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(self.clone()), false);
-
-        let adt = match self_type.sty {
-            ty::TyStruct(struct_def, substs) => {
-                for field in struct_def.all_fields() {
-                    let field_ty = field.ty(tcx, substs);
-                    if infcx.type_moves_by_default(field_ty, span) {
-                        return Err(FieldDoesNotImplementCopy(field.name))
-                    }
-                }
-                struct_def
-            }
-            ty::TyEnum(enum_def, substs) => {
-                for variant in &enum_def.variants {
-                    for field in &variant.fields {
-                        let field_ty = field.ty(tcx, substs);
-                        if infcx.type_moves_by_default(field_ty, span) {
-                            return Err(VariantDoesNotImplementCopy(variant.name))
-                        }
-                    }
-                }
-                enum_def
-            }
-            _ => return Err(TypeIsStructural),
-        };
-
-        if adt.has_dtor() {
-            return Err(TypeHasDestructor)
-        }
-
-        Ok(())
-    }
-}
-
-#[derive(Copy, Clone)]
-pub enum CopyImplementationError {
-    FieldDoesNotImplementCopy(Name),
-    VariantDoesNotImplementCopy(Name),
-    TypeIsStructural,
-    TypeHasDestructor,
 }
 
 /// A "type scheme", in ML terminology, is a type combined with some
@@ -2093,16 +1818,6 @@ pub fn extends(self, other: ty::ClosureKind) -> bool {
     }
 }
 
-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)
-    }
-
-    pub fn arm_contains_ref_binding(&self, arm: &hir::Arm) -> Option<hir::Mutability> {
-        pat_util::arm_contains_ref_binding(&self.def_map, arm)
-    }
-}
-
 impl<'tcx> TyS<'tcx> {
     /// Iterator that walks `self` and any types reachable from
     /// `self`, in depth-first order. Note that just walks the types
@@ -2125,63 +1840,6 @@ 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
-            }
-            TyEnum(_, substs) |
-            TyStruct(_, substs) => {
-                substs.regions().as_slice().to_vec()
-            }
-            TyClosure(_, ref substs) => {
-                substs.func_substs.regions().as_slice().to_vec()
-            }
-            TyProjection(ref data) => {
-                data.trait_ref.substs.regions().as_slice().to_vec()
-            }
-            TyBareFn(..) |
-            TyBool |
-            TyChar |
-            TyInt(_) |
-            TyUint(_) |
-            TyFloat(_) |
-            TyBox(_) |
-            TyStr |
-            TyArray(_, _) |
-            TySlice(_) |
-            TyRawPtr(_) |
-            TyTuple(_) |
-            TyParam(_) |
-            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.
@@ -2199,31 +1857,6 @@ pub fn maybe_walk<F>(&'tcx self, mut f: F)
     }
 }
 
-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() }
@@ -2234,99 +1867,6 @@ pub fn is_noop(&self) -> bool {
     }
 }
 
-impl<'tcx> TyS<'tcx> {
-    fn impls_bound<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
-                       bound: ty::BuiltinBound,
-                       span: Span)
-                       -> bool
-    {
-        let tcx = param_env.tcx;
-        let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env.clone()), false);
-
-        let is_impld = traits::type_known_to_meet_builtin_bound(&infcx,
-                                                                self, bound, span);
-
-        debug!("Ty::impls_bound({:?}, {:?}) = {:?}",
-               self, bound, is_impld);
-
-        is_impld
-    }
-
-    // FIXME (@jroesch): I made this public to use it, not sure if should be private
-    pub fn moves_by_default<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
-                           span: Span) -> bool {
-        if self.flags.get().intersects(TypeFlags::MOVENESS_CACHED) {
-            return self.flags.get().intersects(TypeFlags::MOVES_BY_DEFAULT);
-        }
-
-        assert!(!self.needs_infer());
-
-        // Fast-path for primitive types
-        let result = match self.sty {
-            TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
-            TyRawPtr(..) | TyBareFn(..) | TyRef(_, TypeAndMut {
-                mutbl: hir::MutImmutable, ..
-            }) => Some(false),
-
-            TyStr | TyBox(..) | TyRef(_, TypeAndMut {
-                mutbl: hir::MutMutable, ..
-            }) => Some(true),
-
-            TyArray(..) | TySlice(_) | TyTrait(..) | TyTuple(..) |
-            TyClosure(..) | TyEnum(..) | TyStruct(..) |
-            TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
-        }.unwrap_or_else(|| !self.impls_bound(param_env, ty::BoundCopy, span));
-
-        if !self.has_param_types() && !self.has_self_ty() {
-            self.flags.set(self.flags.get() | if result {
-                TypeFlags::MOVENESS_CACHED | TypeFlags::MOVES_BY_DEFAULT
-            } else {
-                TypeFlags::MOVENESS_CACHED
-            });
-        }
-
-        result
-    }
-
-    #[inline]
-    pub fn is_sized<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
-                        span: Span) -> bool
-    {
-        if self.flags.get().intersects(TypeFlags::SIZEDNESS_CACHED) {
-            return self.flags.get().intersects(TypeFlags::IS_SIZED);
-        }
-
-        self.is_sized_uncached(param_env, span)
-    }
-
-    fn is_sized_uncached<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
-                             span: Span) -> bool {
-        assert!(!self.needs_infer());
-
-        // Fast-path for primitive types
-        let result = match self.sty {
-            TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
-            TyBox(..) | TyRawPtr(..) | TyRef(..) | TyBareFn(..) |
-            TyArray(..) | TyTuple(..) | TyClosure(..) => Some(true),
-
-            TyStr | TyTrait(..) | TySlice(_) => Some(false),
-
-            TyEnum(..) | TyStruct(..) | TyProjection(..) | TyParam(..) |
-            TyInfer(..) | TyError => None
-        }.unwrap_or_else(|| self.impls_bound(param_env, ty::BoundSized, span));
-
-        if !self.has_param_types() && !self.has_self_ty() {
-            self.flags.set(self.flags.get() | if result {
-                TypeFlags::SIZEDNESS_CACHED | TypeFlags::IS_SIZED
-            } else {
-                TypeFlags::SIZEDNESS_CACHED
-            });
-        }
-
-        result
-    }
-}
-
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub enum LvaluePreference {
     PreferMutLvalue,
@@ -2342,283 +1882,6 @@ pub fn from_mutbl(m: hir::Mutability) -> Self {
     }
 }
 
-/// Describes whether a type is representable. For types that are not
-/// representable, 'SelfRecursive' and 'ContainsRecursive' are used to
-/// distinguish between types that are recursive with themselves and types that
-/// contain a different recursive type. These cases can therefore be treated
-/// differently when reporting errors.
-///
-/// The ordering of the cases is significant. They are sorted so that cmp::max
-/// will keep the "more erroneous" of two values.
-#[derive(Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Debug)]
-pub enum Representability {
-    Representable,
-    ContainsRecursive,
-    SelfRecursive,
-}
-
-impl<'tcx> TyS<'tcx> {
-    /// Check whether a type is representable. This means it cannot contain unboxed
-    /// structural recursion. This check is needed for structs and enums.
-    pub fn is_representable(&'tcx self, cx: &ctxt<'tcx>, sp: Span) -> Representability {
-
-        // Iterate until something non-representable is found
-        fn find_nonrepresentable<'tcx, It: Iterator<Item=Ty<'tcx>>>(cx: &ctxt<'tcx>, sp: Span,
-                                                                    seen: &mut Vec<Ty<'tcx>>,
-                                                                    iter: It)
-                                                                    -> Representability {
-            iter.fold(Representable,
-                      |r, ty| cmp::max(r, is_type_structurally_recursive(cx, sp, seen, ty)))
-        }
-
-        fn are_inner_types_recursive<'tcx>(cx: &ctxt<'tcx>, sp: Span,
-                                           seen: &mut Vec<Ty<'tcx>>, ty: Ty<'tcx>)
-                                           -> Representability {
-            match ty.sty {
-                TyTuple(ref ts) => {
-                    find_nonrepresentable(cx, sp, seen, ts.iter().cloned())
-                }
-                // Fixed-length vectors.
-                // FIXME(#11924) Behavior undecided for zero-length vectors.
-                TyArray(ty, _) => {
-                    is_type_structurally_recursive(cx, sp, seen, ty)
-                }
-                TyStruct(def, substs) | TyEnum(def, substs) => {
-                    find_nonrepresentable(cx,
-                                          sp,
-                                          seen,
-                                          def.all_fields().map(|f| f.ty(cx, substs)))
-                }
-                TyClosure(..) => {
-                    // this check is run on type definitions, so we don't expect
-                    // to see closure types
-                    cx.sess.bug(&format!("requires check invoked on inapplicable type: {:?}", ty))
-                }
-                _ => Representable,
-            }
-        }
-
-        fn same_struct_or_enum<'tcx>(ty: Ty<'tcx>, def: AdtDef<'tcx>) -> bool {
-            match ty.sty {
-                TyStruct(ty_def, _) | TyEnum(ty_def, _) => {
-                     ty_def == def
-                }
-                _ => false
-            }
-        }
-
-        fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
-            match (&a.sty, &b.sty) {
-                (&TyStruct(did_a, ref substs_a), &TyStruct(did_b, ref substs_b)) |
-                (&TyEnum(did_a, ref substs_a), &TyEnum(did_b, ref substs_b)) => {
-                    if did_a != did_b {
-                        return false;
-                    }
-
-                    let types_a = substs_a.types.get_slice(subst::TypeSpace);
-                    let types_b = substs_b.types.get_slice(subst::TypeSpace);
-
-                    let mut pairs = types_a.iter().zip(types_b);
-
-                    pairs.all(|(&a, &b)| same_type(a, b))
-                }
-                _ => {
-                    a == b
-                }
-            }
-        }
-
-        // Does the type `ty` directly (without indirection through a pointer)
-        // contain any types on stack `seen`?
-        fn is_type_structurally_recursive<'tcx>(cx: &ctxt<'tcx>, sp: Span,
-                                                seen: &mut Vec<Ty<'tcx>>,
-                                                ty: Ty<'tcx>) -> Representability {
-            debug!("is_type_structurally_recursive: {:?}", ty);
-
-            match ty.sty {
-                TyStruct(def, _) | TyEnum(def, _) => {
-                    {
-                        // Iterate through stack of previously seen types.
-                        let mut iter = seen.iter();
-
-                        // The first item in `seen` is the type we are actually curious about.
-                        // We want to return SelfRecursive if this type contains itself.
-                        // It is important that we DON'T take generic parameters into account
-                        // for this check, so that Bar<T> in this example counts as SelfRecursive:
-                        //
-                        // struct Foo;
-                        // struct Bar<T> { x: Bar<Foo> }
-
-                        match iter.next() {
-                            Some(&seen_type) => {
-                                if same_struct_or_enum(seen_type, def) {
-                                    debug!("SelfRecursive: {:?} contains {:?}",
-                                           seen_type,
-                                           ty);
-                                    return SelfRecursive;
-                                }
-                            }
-                            None => {}
-                        }
-
-                        // We also need to know whether the first item contains other types
-                        // that are structurally recursive. If we don't catch this case, we
-                        // will recurse infinitely for some inputs.
-                        //
-                        // It is important that we DO take generic parameters into account
-                        // here, so that code like this is considered SelfRecursive, not
-                        // ContainsRecursive:
-                        //
-                        // struct Foo { Option<Option<Foo>> }
-
-                        for &seen_type in iter {
-                            if same_type(ty, seen_type) {
-                                debug!("ContainsRecursive: {:?} contains {:?}",
-                                       seen_type,
-                                       ty);
-                                return ContainsRecursive;
-                            }
-                        }
-                    }
-
-                    // For structs and enums, track all previously seen types by pushing them
-                    // onto the 'seen' stack.
-                    seen.push(ty);
-                    let out = are_inner_types_recursive(cx, sp, seen, ty);
-                    seen.pop();
-                    out
-                }
-                _ => {
-                    // No need to push in other cases.
-                    are_inner_types_recursive(cx, sp, seen, ty)
-                }
-            }
-        }
-
-        debug!("is_type_representable: {:?}", self);
-
-        // To avoid a stack overflow when checking an enum variant or struct that
-        // contains a different, structurally recursive type, maintain a stack
-        // of seen types and check recursion for each of them (issues #3008, #3779).
-        let mut seen: Vec<Ty> = Vec::new();
-        let r = is_type_structurally_recursive(cx, sp, &mut seen, self);
-        debug!("is_type_representable: {:?} is {:?}", self, r);
-        r
-    }
-
-    /// See `expr_ty_adjusted`
-    pub fn adjust<F>(&'tcx self, cx: &ctxt<'tcx>,
-                     span: Span,
-                     expr_id: NodeId,
-                     adjustment: Option<&AutoAdjustment<'tcx>>,
-                     mut method_type: F)
-                     -> Ty<'tcx> where
-        F: FnMut(MethodCall) -> Option<Ty<'tcx>>,
-    {
-        if let TyError = self.sty {
-            return self;
-        }
-
-        return match adjustment {
-            Some(adjustment) => {
-                match *adjustment {
-                   AdjustReifyFnPointer => {
-                        match self.sty {
-                            ty::TyBareFn(Some(_), b) => {
-                                cx.mk_fn(None, b)
-                            }
-                            _ => {
-                                cx.sess.bug(
-                                    &format!("AdjustReifyFnPointer adjustment on non-fn-item: \
-                                              {:?}", self));
-                            }
-                        }
-                    }
-
-                   AdjustUnsafeFnPointer => {
-                        match self.sty {
-                            ty::TyBareFn(None, b) => cx.safe_to_unsafe_fn_ty(b),
-                            ref b => {
-                                cx.sess.bug(
-                                    &format!("AdjustReifyFnPointer adjustment on non-fn-item: \
-                                             {:?}",
-                                            b));
-                            }
-                        }
-                   }
-
-                    AdjustDerefRef(ref adj) => {
-                        let mut adjusted_ty = self;
-
-                        if !adjusted_ty.references_error() {
-                            for i in 0..adj.autoderefs {
-                                adjusted_ty =
-                                    adjusted_ty.adjust_for_autoderef(cx,
-                                                                     expr_id,
-                                                                     span,
-                                                                     i as u32,
-                                                                     &mut method_type);
-                            }
-                        }
-
-                        if let Some(target) = adj.unsize {
-                            target
-                        } else {
-                            adjusted_ty.adjust_for_autoref(cx, adj.autoref)
-                        }
-                    }
-                }
-            }
-            None => self
-        };
-    }
-
-    pub fn adjust_for_autoderef<F>(&'tcx self,
-                                   cx: &ctxt<'tcx>,
-                                   expr_id: ast::NodeId,
-                                   expr_span: Span,
-                                   autoderef: u32, // how many autoderefs so far?
-                                   mut method_type: F)
-                                   -> Ty<'tcx> where
-        F: FnMut(MethodCall) -> Option<Ty<'tcx>>,
-    {
-        let method_call = MethodCall::autoderef(expr_id, autoderef);
-        let mut adjusted_ty = self;
-        if let Some(method_ty) = method_type(method_call) {
-            // Method calls always have all late-bound regions
-            // fully instantiated.
-            let fn_ret = cx.no_late_bound_regions(&method_ty.fn_ret()).unwrap();
-            adjusted_ty = fn_ret.unwrap();
-        }
-        match adjusted_ty.builtin_deref(true, NoPreference) {
-            Some(mt) => mt.ty,
-            None => {
-                cx.sess.span_bug(
-                    expr_span,
-                    &format!("the {}th autoderef failed: {}",
-                             autoderef,
-                             adjusted_ty)
-                        );
-            }
-        }
-    }
-
-    pub fn adjust_for_autoref(&'tcx self, cx: &ctxt<'tcx>,
-                              autoref: Option<AutoRef<'tcx>>)
-                              -> Ty<'tcx> {
-        match autoref {
-            None => self,
-            Some(AutoPtr(r, m)) => {
-                cx.mk_ref(r, TypeAndMut { ty: self, mutbl: m })
-            }
-            Some(AutoUnsafe(m)) => {
-                cx.mk_ptr(TypeAndMut { ty: self, mutbl: m })
-            }
-        }
-    }
-
-}
-
 /// Helper for looking things up in the various maps that are populated during
 /// typeck::collect (e.g., `cx.impl_or_trait_items`, `cx.tcache`, etc).  All of
 /// these share the pattern that if the id is local, it should have been loaded
@@ -2679,45 +1942,6 @@ pub fn to_user_str(&self) -> &'static str {
 }
 
 impl<'tcx> ctxt<'tcx> {
-    /// Returns the type of element at index `i` in tuple or tuple-like type `t`.
-    /// For an enum `t`, `variant` is None only if `t` is a univariant enum.
-    pub fn positional_element_ty(&self,
-                                 ty: Ty<'tcx>,
-                                 i: usize,
-                                 variant: Option<DefId>) -> Option<Ty<'tcx>> {
-        match (&ty.sty, variant) {
-            (&TyStruct(def, substs), None) => {
-                def.struct_variant().fields.get(i).map(|f| f.ty(self, substs))
-            }
-            (&TyEnum(def, substs), Some(vid)) => {
-                def.variant_with_id(vid).fields.get(i).map(|f| f.ty(self, substs))
-            }
-            (&TyEnum(def, substs), None) => {
-                assert!(def.is_univariant());
-                def.variants[0].fields.get(i).map(|f| f.ty(self, substs))
-            }
-            (&TyTuple(ref v), None) => v.get(i).cloned(),
-            _ => None
-        }
-    }
-
-    /// Returns the type of element at field `n` in struct or struct-like type `t`.
-    /// For an enum `t`, `variant` must be some def id.
-    pub fn named_element_ty(&self,
-                            ty: Ty<'tcx>,
-                            n: Name,
-                            variant: Option<DefId>) -> Option<Ty<'tcx>> {
-        match (&ty.sty, variant) {
-            (&TyStruct(def, substs), None) => {
-                def.struct_variant().find_field_named(n).map(|f| f.ty(self, substs))
-            }
-            (&TyEnum(def, substs), Some(vid)) => {
-                def.variant_with_id(vid).find_field_named(n).map(|f| f.ty(self, substs))
-            }
-            _ => return None
-        }
-    }
-
     pub fn node_id_to_type(&self, id: NodeId) -> Ty<'tcx> {
         match self.node_id_to_type_opt(id) {
            Some(ty) => ty,
@@ -2992,7 +2216,7 @@ pub fn trait_impl_polarity(&self, id: DefId) -> Option<hir::ImplPolarity> {
         }
     }
 
-    pub fn custom_coerce_unsized_kind(&self, did: DefId) -> CustomCoerceUnsized {
+    pub fn custom_coerce_unsized_kind(&self, did: DefId) -> adjustment::CustomCoerceUnsized {
         memoized(&self.custom_coerce_unsized_kinds, did, |did: DefId| {
             let (kind, src) = if did.krate != LOCAL_CRATE {
                 (csearch::get_custom_coerce_unsized_kind(self, did), "external")
@@ -3071,35 +2295,6 @@ pub fn item_name(&self, id: DefId) -> ast::Name {
         }
     }
 
-    /// Returns `(normalized_type, ty)`, where `normalized_type` is the
-    /// IntType representation of one of {i64,i32,i16,i8,u64,u32,u16,u8},
-    /// and `ty` is the original type (i.e. may include `isize` or
-    /// `usize`).
-    pub fn enum_repr_type(&self, opt_hint: Option<&attr::ReprAttr>)
-                          -> (attr::IntType, Ty<'tcx>) {
-        let repr_type = match opt_hint {
-            // Feed in the given type
-            Some(&attr::ReprInt(_, int_t)) => int_t,
-            // ... but provide sensible default if none provided
-            //
-            // NB. Historically `fn enum_variants` generate i64 here, while
-            // rustc_typeck::check would generate isize.
-            _ => SignedInt(hir::TyIs),
-        };
-
-        let repr_type_ty = repr_type.to_ty(self);
-        let repr_type = match repr_type {
-            SignedInt(hir::TyIs) =>
-                SignedInt(self.sess.target.int_type),
-            UnsignedInt(hir::TyUs) =>
-                UnsignedInt(self.sess.target.uint_type),
-            other => other
-        };
-
-        (repr_type, repr_type_ty)
-    }
-
-
     // Register a given item type
     pub fn register_item_type(&self, did: DefId, ty: TypeScheme<'tcx>) {
         self.tcache.borrow_mut().insert(did, ty);
@@ -3195,155 +2390,6 @@ pub fn lookup_repr_hints(&self, did: DefId) -> Rc<Vec<attr::ReprAttr>> {
         })
     }
 
-
-    /// Returns the deeply last field of nested structures, or the same type,
-    /// if not a structure at all. Corresponds to the only possible unsized
-    /// field, and its type can be used to determine unsizing strategy.
-    pub fn struct_tail(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
-        while let TyStruct(def, substs) = ty.sty {
-            match def.struct_variant().fields.last() {
-                Some(f) => ty = f.ty(self, substs),
-                None => break
-            }
-        }
-        ty
-    }
-
-    /// Same as applying struct_tail on `source` and `target`, but only
-    /// keeps going as long as the two types are instances of the same
-    /// structure definitions.
-    /// For `(Foo<Foo<T>>, Foo<Trait>)`, the result will be `(Foo<T>, Trait)`,
-    /// whereas struct_tail produces `T`, and `Trait`, respectively.
-    pub fn struct_lockstep_tails(&self,
-                                 source: Ty<'tcx>,
-                                 target: Ty<'tcx>)
-                                 -> (Ty<'tcx>, Ty<'tcx>) {
-        let (mut a, mut b) = (source, target);
-        while let (&TyStruct(a_def, a_substs), &TyStruct(b_def, b_substs)) = (&a.sty, &b.sty) {
-            if a_def != b_def {
-                break;
-            }
-            if let Some(f) = a_def.struct_variant().fields.last() {
-                a = f.ty(self, a_substs);
-                b = f.ty(self, b_substs);
-            } else {
-                break;
-            }
-        }
-        (a, b)
-    }
-
-    // Returns the repeat count for a repeating vector expression.
-    pub fn eval_repeat_count(&self, count_expr: &hir::Expr) -> usize {
-        let hint = UncheckedExprHint(self.types.usize);
-        match const_eval::eval_const_expr_partial(self, count_expr, hint) {
-            Ok(val) => {
-                let found = match val {
-                    ConstVal::Uint(count) => return count as usize,
-                    ConstVal::Int(count) if count >= 0 => return count as usize,
-                    const_val => const_val.description(),
-                };
-                span_err!(self.sess, count_expr.span, E0306,
-                    "expected positive integer for repeat count, found {}",
-                    found);
-            }
-            Err(err) => {
-                let err_msg = match count_expr.node {
-                    hir::ExprPath(None, hir::Path {
-                        global: false,
-                        ref segments,
-                        ..
-                    }) if segments.len() == 1 =>
-                        format!("found variable"),
-                    _ => match err.kind {
-                        ErrKind::MiscCatchAll => format!("but found {}", err.description()),
-                        _ => format!("but {}", err.description())
-                    }
-                };
-                span_err!(self.sess, count_expr.span, E0307,
-                    "expected constant integer for repeat count, {}", err_msg);
-            }
-        }
-        0
-    }
-
-    // Iterate over a type parameter's bounded traits and any supertraits
-    // of those traits, ignoring kinds.
-    // Here, the supertraits are the transitive closure of the supertrait
-    // relation on the supertraits from each bounded trait's constraint
-    // list.
-    pub fn each_bound_trait_and_supertraits<F>(&self,
-                                               bounds: &[PolyTraitRef<'tcx>],
-                                               mut f: F)
-                                               -> bool where
-        F: FnMut(PolyTraitRef<'tcx>) -> bool,
-    {
-        for bound_trait_ref in traits::transitive_bounds(self, bounds) {
-            if !f(bound_trait_ref) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /// Given a set of predicates that apply to an object type, returns
-    /// the region bounds that the (erased) `Self` type must
-    /// outlive. Precisely *because* the `Self` type is erased, the
-    /// parameter `erased_self_ty` must be supplied to indicate what type
-    /// has been used to represent `Self` in the predicates
-    /// themselves. This should really be a unique type; `FreshTy(0)` is a
-    /// popular choice.
-    ///
-    /// NB: in some cases, particularly around higher-ranked bounds,
-    /// this function returns a kind of conservative approximation.
-    /// That is, all regions returned by this function are definitely
-    /// required, but there may be other region bounds that are not
-    /// returned, as well as requirements like `for<'a> T: 'a`.
-    ///
-    /// Requires that trait definitions have been processed so that we can
-    /// elaborate predicates and walk supertraits.
-    pub fn required_region_bounds(&self,
-                                  erased_self_ty: Ty<'tcx>,
-                                  predicates: Vec<ty::Predicate<'tcx>>)
-                                  -> Vec<ty::Region>    {
-        debug!("required_region_bounds(erased_self_ty={:?}, predicates={:?})",
-               erased_self_ty,
-               predicates);
-
-        assert!(!erased_self_ty.has_escaping_regions());
-
-        traits::elaborate_predicates(self, predicates)
-            .filter_map(|predicate| {
-                match predicate {
-                    ty::Predicate::Projection(..) |
-                    ty::Predicate::Trait(..) |
-                    ty::Predicate::Equate(..) |
-                    ty::Predicate::WellFormed(..) |
-                    ty::Predicate::ObjectSafe(..) |
-                    ty::Predicate::RegionOutlives(..) => {
-                        None
-                    }
-                    ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t, r))) => {
-                        // Search for a bound of the form `erased_self_ty
-                        // : 'a`, but be wary of something like `for<'a>
-                        // erased_self_ty : 'a` (we interpret a
-                        // higher-ranked bound like that as 'static,
-                        // though at present the code in `fulfill.rs`
-                        // considers such bounds to be unsatisfiable, so
-                        // it's kind of a moot point since you could never
-                        // construct such an object, but this seems
-                        // correct even if that code changes).
-                        if t == erased_self_ty && !r.has_escaping_regions() {
-                            Some(r)
-                        } else {
-                            None
-                        }
-                    }
-                }
-            })
-            .collect()
-    }
-
     pub fn item_variances(&self, item_id: DefId) -> Rc<ItemVariances> {
         lookup_locally_or_in_crate_store(
             "item_variance_map", item_id, &self.item_variance_map,
@@ -3527,148 +2573,6 @@ pub fn trait_item_of_item(&self, def_id: DefId) -> Option<ImplOrTraitItemId> {
         }
     }
 
-    /// Creates a hash of the type `Ty` which will be the same no matter what crate
-    /// context it's calculated within. This is used by the `type_id` intrinsic.
-    pub fn hash_crate_independent(&self, ty: Ty<'tcx>, svh: &Svh) -> u64 {
-        let mut state = SipHasher::new();
-        helper(self, ty, svh, &mut state);
-        return state.finish();
-
-        fn helper<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh,
-                        state: &mut SipHasher) {
-            macro_rules! byte { ($b:expr) => { ($b as u8).hash(state) } }
-            macro_rules! hash { ($e:expr) => { $e.hash(state) }  }
-
-            let region = |state: &mut SipHasher, r: Region| {
-                match r {
-                    ReStatic => {}
-                    ReLateBound(db, BrAnon(i)) => {
-                        db.hash(state);
-                        i.hash(state);
-                    }
-                    ReEmpty |
-                    ReEarlyBound(..) |
-                    ReLateBound(..) |
-                    ReFree(..) |
-                    ReScope(..) |
-                    ReVar(..) |
-                    ReSkolemized(..) => {
-                        tcx.sess.bug("unexpected region found when hashing a type")
-                    }
-                }
-            };
-            let did = |state: &mut SipHasher, did: DefId| {
-                let h = if did.is_local() {
-                    svh.clone()
-                } else {
-                    tcx.sess.cstore.get_crate_hash(did.krate)
-                };
-                h.as_str().hash(state);
-                did.node.hash(state);
-            };
-            let mt = |state: &mut SipHasher, mt: TypeAndMut| {
-                mt.mutbl.hash(state);
-            };
-            let fn_sig = |state: &mut SipHasher, sig: &Binder<FnSig<'tcx>>| {
-                let sig = tcx.anonymize_late_bound_regions(sig).0;
-                for a in &sig.inputs { helper(tcx, *a, svh, state); }
-                if let ty::FnConverging(output) = sig.output {
-                    helper(tcx, output, svh, state);
-                }
-            };
-            ty.maybe_walk(|ty| {
-                match ty.sty {
-                    TyBool => byte!(2),
-                    TyChar => byte!(3),
-                    TyInt(i) => {
-                        byte!(4);
-                        hash!(i);
-                    }
-                    TyUint(u) => {
-                        byte!(5);
-                        hash!(u);
-                    }
-                    TyFloat(f) => {
-                        byte!(6);
-                        hash!(f);
-                    }
-                    TyStr => {
-                        byte!(7);
-                    }
-                    TyEnum(d, _) => {
-                        byte!(8);
-                        did(state, d.did);
-                    }
-                    TyBox(_) => {
-                        byte!(9);
-                    }
-                    TyArray(_, n) => {
-                        byte!(10);
-                        n.hash(state);
-                    }
-                    TySlice(_) => {
-                        byte!(11);
-                    }
-                    TyRawPtr(m) => {
-                        byte!(12);
-                        mt(state, m);
-                    }
-                    TyRef(r, m) => {
-                        byte!(13);
-                        region(state, *r);
-                        mt(state, m);
-                    }
-                    TyBareFn(opt_def_id, ref b) => {
-                        byte!(14);
-                        hash!(opt_def_id);
-                        hash!(b.unsafety);
-                        hash!(b.abi);
-                        fn_sig(state, &b.sig);
-                        return false;
-                    }
-                    TyTrait(ref data) => {
-                        byte!(17);
-                        did(state, data.principal_def_id());
-                        hash!(data.bounds);
-
-                        let principal = tcx.anonymize_late_bound_regions(&data.principal).0;
-                        for subty in &principal.substs.types {
-                            helper(tcx, subty, svh, state);
-                        }
-
-                        return false;
-                    }
-                    TyStruct(d, _) => {
-                        byte!(18);
-                        did(state, d.did);
-                    }
-                    TyTuple(ref inner) => {
-                        byte!(19);
-                        hash!(inner.len());
-                    }
-                    TyParam(p) => {
-                        byte!(20);
-                        hash!(p.space);
-                        hash!(p.idx);
-                        hash!(p.name.as_str());
-                    }
-                    TyInfer(_) => unreachable!(),
-                    TyError => byte!(21),
-                    TyClosure(d, _) => {
-                        byte!(22);
-                        did(state, d);
-                    }
-                    TyProjection(ref data) => {
-                        byte!(23);
-                        did(state, data.trait_ref.def_id);
-                        hash!(data.item_name.as_str());
-                    }
-                }
-                true
-            });
-        }
-    }
-
     /// Construct a parameter environment suitable for static contexts or other contexts where there
     /// are no free type/lifetime parameters in scope.
     pub fn empty_parameter_environment<'a>(&'a self)
@@ -3786,87 +2690,6 @@ pub fn is_overloaded_autoderef(&self, expr_id: NodeId, autoderefs: u32) -> bool
     pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
         Some(self.tables.borrow().upvar_capture_map.get(&upvar_id).unwrap().clone())
     }
-
-
-    /// Returns true if this ADT is a dtorck type, i.e. whether it being
-    /// safe for destruction requires it to be alive
-    fn is_adt_dtorck(&self, adt: AdtDef<'tcx>) -> bool {
-        let dtor_method = match adt.destructor() {
-            Some(dtor) => dtor,
-            None => return false
-        };
-        let impl_did = self.impl_of_method(dtor_method).unwrap_or_else(|| {
-            self.sess.bug(&format!("no Drop impl for the dtor of `{:?}`", adt))
-        });
-        let generics = adt.type_scheme(self).generics;
-
-        // In `impl<'a> Drop ...`, we automatically assume
-        // `'a` is meaningful and thus represents a bound
-        // through which we could reach borrowed data.
-        //
-        // FIXME (pnkfelix): In the future it would be good to
-        // extend the language to allow the user to express,
-        // in the impl signature, that a lifetime is not
-        // actually used (something like `where 'a: ?Live`).
-        if generics.has_region_params(subst::TypeSpace) {
-            debug!("typ: {:?} has interesting dtor due to region params",
-                   adt);
-            return true;
-        }
-
-        let mut seen_items = Vec::new();
-        let mut items_to_inspect = vec![impl_did];
-        while let Some(item_def_id) = items_to_inspect.pop() {
-            if seen_items.contains(&item_def_id) {
-                continue;
-            }
-
-            for pred in self.lookup_predicates(item_def_id).predicates {
-                let result = match pred {
-                    ty::Predicate::Equate(..) |
-                    ty::Predicate::RegionOutlives(..) |
-                    ty::Predicate::TypeOutlives(..) |
-                    ty::Predicate::WellFormed(..) |
-                    ty::Predicate::ObjectSafe(..) |
-                    ty::Predicate::Projection(..) => {
-                        // For now, assume all these where-clauses
-                        // may give drop implementation capabilty
-                        // to access borrowed data.
-                        true
-                    }
-
-                    ty::Predicate::Trait(ty::Binder(ref t_pred)) => {
-                        let def_id = t_pred.trait_ref.def_id;
-                        if self.trait_items(def_id).len() != 0 {
-                            // If trait has items, assume it adds
-                            // capability to access borrowed data.
-                            true
-                        } else {
-                            // Trait without items is itself
-                            // uninteresting from POV of dropck.
-                            //
-                            // However, may have parent w/ items;
-                            // so schedule checking of predicates,
-                            items_to_inspect.push(def_id);
-                            // and say "no capability found" for now.
-                            false
-                        }
-                    }
-                };
-
-                if result {
-                    debug!("typ: {:?} has interesting dtor due to generic preds, e.g. {:?}",
-                           adt, pred);
-                    return true;
-                }
-            }
-
-            seen_items.push(item_def_id);
-        }
-
-        debug!("typ: {:?} is dtorck-safe", adt);
-        false
-    }
 }
 
 /// The category of explicit self.
@@ -3899,22 +2722,6 @@ pub struct Freevar {
 // imported.
 pub type GlobMap = HashMap<NodeId, HashSet<Name>>;
 
-impl<'tcx> AutoAdjustment<'tcx> {
-    pub fn is_identity(&self) -> bool {
-        match *self {
-            AdjustReifyFnPointer |
-            AdjustUnsafeFnPointer => false,
-            AdjustDerefRef(ref r) => r.is_identity(),
-        }
-    }
-}
-
-impl<'tcx> AutoDerefRef<'tcx> {
-    pub fn is_identity(&self) -> bool {
-        self.autoderefs == 0 && self.unsize.is_none() && self.autoref.is_none()
-    }
-}
-
 impl<'tcx> ctxt<'tcx> {
     pub fn with_freevars<T, F>(&self, fid: NodeId, f: F) -> T where
         F: FnOnce(&[Freevar]) -> T,
index 94e4672ea9710e850f87fd0c4192464ed2c46557..0058ccbce3b19da27543afb5f50536069dbdd490 100644 (file)
@@ -641,8 +641,8 @@ fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ItemSubsts<'tcx>
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for ty::AutoRef<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::AutoRef<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoRef<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::adjustment::AutoRef<'tcx> {
         folder.fold_autoref(self)
     }
 }
index a04cc89ee18a0940106f6b965510ade70bd59035..3969738a22e86b94278bb4042612ff9065ddd506 100644 (file)
@@ -24,6 +24,7 @@
 use std::mem;
 use syntax::abi;
 use syntax::ast::{Name, NodeId};
+use syntax::parse::token::special_idents;
 
 use rustc_front::hir;
 
@@ -504,6 +505,31 @@ pub struct ParamTy {
     pub name: Name,
 }
 
+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: &ty::TypeParameterDef) -> ParamTy {
+        ParamTy::new(def.space, def.index, def.name)
+    }
+
+    pub fn to_ty<'tcx>(self, tcx: &ty::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
+    }
+}
+
 /// 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:
@@ -844,6 +870,13 @@ pub fn from_depth(&self, depth: u32) -> Region {
 
 // Type utilities
 impl<'tcx> TyS<'tcx> {
+    pub fn as_opt_param_ty(&self) -> Option<ty::ParamTy> {
+        match self.sty {
+            ty::TyParam(ref d) => Some(d.clone()),
+            _ => None,
+        }
+    }
+
     pub fn is_nil(&self) -> bool {
         match self.sty {
             TyTuple(ref tys) => tys.is_empty(),
@@ -868,6 +901,13 @@ pub fn is_ty_var(&self) -> bool {
 
     pub fn is_bool(&self) -> bool { self.sty == TyBool }
 
+    pub fn is_param(&self, space: subst::ParamSpace, index: u32) -> bool {
+        match self.sty {
+            ty::TyParam(ref data) => data.space == space && data.idx == index,
+            _ => false,
+        }
+    }
+
     pub fn is_self(&self) -> bool {
         match self.sty {
             TyParam(ref p) => p.space == subst::SelfSpace,
@@ -1126,4 +1166,47 @@ pub fn ty_adt_def(&self) -> Option<AdtDef<'tcx>> {
             _ => None
         }
     }
+
+    /// 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
+            }
+            TyEnum(_, substs) |
+            TyStruct(_, substs) => {
+                substs.regions().as_slice().to_vec()
+            }
+            TyClosure(_, ref substs) => {
+                substs.func_substs.regions().as_slice().to_vec()
+            }
+            TyProjection(ref data) => {
+                data.trait_ref.substs.regions().as_slice().to_vec()
+            }
+            TyBareFn(..) |
+            TyBool |
+            TyChar |
+            TyInt(_) |
+            TyUint(_) |
+            TyFloat(_) |
+            TyBox(_) |
+            TyStr |
+            TyArray(_, _) |
+            TySlice(_) |
+            TyRawPtr(_) |
+            TyTuple(_) |
+            TyParam(_) |
+            TyInfer(_) |
+            TyError => {
+                vec![]
+            }
+        }
+    }
 }
diff --git a/src/librustc/middle/ty/util.rs b/src/librustc/middle/ty/util.rs
new file mode 100644 (file)
index 0000000..8831461
--- /dev/null
@@ -0,0 +1,891 @@
+// 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.
+
+//! misc. type-system utilities too small to deserve their own file
+
+use back::svh::Svh;
+use middle::const_eval::{self, ConstVal, ErrKind};
+use middle::const_eval::EvalHint::UncheckedExprHint;
+use middle::def_id::DefId;
+use middle::subst;
+use middle::infer;
+use middle::pat_util;
+use middle::traits;
+use middle::ty::{self, Ty, TypeAndMut, TypeFlags};
+use middle::ty::{Disr, ParameterEnvironment};
+use middle::ty::{HasTypeFlags, RegionEscape};
+use middle::ty::TypeVariants::*;
+use util::num::ToPrimitive;
+
+use std::cmp;
+use std::hash::{Hash, SipHasher, Hasher};
+use syntax::ast::Name;
+use syntax::codemap::Span;
+
+use rustc_front::hir;
+use rustc_front::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt};
+
+pub trait IntTypeExt {
+    fn to_ty<'tcx>(&self, cx: &ty::ctxt<'tcx>) -> Ty<'tcx>;
+    fn i64_to_disr(&self, val: i64) -> Option<Disr>;
+    fn u64_to_disr(&self, val: u64) -> Option<Disr>;
+    fn disr_incr(&self, val: Disr) -> Option<Disr>;
+    fn disr_string(&self, val: Disr) -> String;
+    fn disr_wrap_incr(&self, val: Option<Disr>) -> Disr;
+}
+
+impl IntTypeExt for attr::IntType {
+    fn to_ty<'tcx>(&self, cx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
+        match *self {
+            SignedInt(hir::TyI8)      => cx.types.i8,
+            SignedInt(hir::TyI16)     => cx.types.i16,
+            SignedInt(hir::TyI32)     => cx.types.i32,
+            SignedInt(hir::TyI64)     => cx.types.i64,
+            SignedInt(hir::TyIs)   => cx.types.isize,
+            UnsignedInt(hir::TyU8)    => cx.types.u8,
+            UnsignedInt(hir::TyU16)   => cx.types.u16,
+            UnsignedInt(hir::TyU32)   => cx.types.u32,
+            UnsignedInt(hir::TyU64)   => cx.types.u64,
+            UnsignedInt(hir::TyUs) => cx.types.usize,
+        }
+    }
+
+    fn i64_to_disr(&self, val: i64) -> Option<Disr> {
+        match *self {
+            SignedInt(hir::TyI8)    => val.to_i8()  .map(|v| v as Disr),
+            SignedInt(hir::TyI16)   => val.to_i16() .map(|v| v as Disr),
+            SignedInt(hir::TyI32)   => val.to_i32() .map(|v| v as Disr),
+            SignedInt(hir::TyI64)   => val.to_i64() .map(|v| v as Disr),
+            UnsignedInt(hir::TyU8)  => val.to_u8()  .map(|v| v as Disr),
+            UnsignedInt(hir::TyU16) => val.to_u16() .map(|v| v as Disr),
+            UnsignedInt(hir::TyU32) => val.to_u32() .map(|v| v as Disr),
+            UnsignedInt(hir::TyU64) => val.to_u64() .map(|v| v as Disr),
+
+            UnsignedInt(hir::TyUs) |
+            SignedInt(hir::TyIs) => unreachable!(),
+        }
+    }
+
+    fn u64_to_disr(&self, val: u64) -> Option<Disr> {
+        match *self {
+            SignedInt(hir::TyI8)    => val.to_i8()  .map(|v| v as Disr),
+            SignedInt(hir::TyI16)   => val.to_i16() .map(|v| v as Disr),
+            SignedInt(hir::TyI32)   => val.to_i32() .map(|v| v as Disr),
+            SignedInt(hir::TyI64)   => val.to_i64() .map(|v| v as Disr),
+            UnsignedInt(hir::TyU8)  => val.to_u8()  .map(|v| v as Disr),
+            UnsignedInt(hir::TyU16) => val.to_u16() .map(|v| v as Disr),
+            UnsignedInt(hir::TyU32) => val.to_u32() .map(|v| v as Disr),
+            UnsignedInt(hir::TyU64) => val.to_u64() .map(|v| v as Disr),
+
+            UnsignedInt(hir::TyUs) |
+            SignedInt(hir::TyIs) => unreachable!(),
+        }
+    }
+
+    fn disr_incr(&self, val: Disr) -> Option<Disr> {
+        macro_rules! add1 {
+            ($e:expr) => { $e.and_then(|v|v.checked_add(1)).map(|v| v as Disr) }
+        }
+        match *self {
+            // SignedInt repr means we *want* to reinterpret the bits
+            // treating the highest bit of Disr as a sign-bit, so
+            // cast to i64 before range-checking.
+            SignedInt(hir::TyI8)    => add1!((val as i64).to_i8()),
+            SignedInt(hir::TyI16)   => add1!((val as i64).to_i16()),
+            SignedInt(hir::TyI32)   => add1!((val as i64).to_i32()),
+            SignedInt(hir::TyI64)   => add1!(Some(val as i64)),
+
+            UnsignedInt(hir::TyU8)  => add1!(val.to_u8()),
+            UnsignedInt(hir::TyU16) => add1!(val.to_u16()),
+            UnsignedInt(hir::TyU32) => add1!(val.to_u32()),
+            UnsignedInt(hir::TyU64) => add1!(Some(val)),
+
+            UnsignedInt(hir::TyUs) |
+            SignedInt(hir::TyIs) => unreachable!(),
+        }
+    }
+
+    // This returns a String because (1.) it is only used for
+    // rendering an error message and (2.) a string can represent the
+    // full range from `i64::MIN` through `u64::MAX`.
+    fn disr_string(&self, val: Disr) -> String {
+        match *self {
+            SignedInt(hir::TyI8)    => format!("{}", val as i8 ),
+            SignedInt(hir::TyI16)   => format!("{}", val as i16),
+            SignedInt(hir::TyI32)   => format!("{}", val as i32),
+            SignedInt(hir::TyI64)   => format!("{}", val as i64),
+            UnsignedInt(hir::TyU8)  => format!("{}", val as u8 ),
+            UnsignedInt(hir::TyU16) => format!("{}", val as u16),
+            UnsignedInt(hir::TyU32) => format!("{}", val as u32),
+            UnsignedInt(hir::TyU64) => format!("{}", val as u64),
+
+            UnsignedInt(hir::TyUs) |
+            SignedInt(hir::TyIs) => unreachable!(),
+        }
+    }
+
+    fn disr_wrap_incr(&self, val: Option<Disr>) -> Disr {
+        macro_rules! add1 {
+            ($e:expr) => { ($e).wrapping_add(1) as Disr }
+        }
+        let val = val.unwrap_or(ty::INITIAL_DISCRIMINANT_VALUE);
+        match *self {
+            SignedInt(hir::TyI8)    => add1!(val as i8 ),
+            SignedInt(hir::TyI16)   => add1!(val as i16),
+            SignedInt(hir::TyI32)   => add1!(val as i32),
+            SignedInt(hir::TyI64)   => add1!(val as i64),
+            UnsignedInt(hir::TyU8)  => add1!(val as u8 ),
+            UnsignedInt(hir::TyU16) => add1!(val as u16),
+            UnsignedInt(hir::TyU32) => add1!(val as u32),
+            UnsignedInt(hir::TyU64) => add1!(val as u64),
+
+            UnsignedInt(hir::TyUs) |
+            SignedInt(hir::TyIs) => unreachable!(),
+        }
+    }
+}
+
+
+#[derive(Copy, Clone)]
+pub enum CopyImplementationError {
+    InfrigingField(Name),
+    InfrigingVariant(Name),
+    NotAnAdt,
+    HasDestructor
+}
+
+/// Describes whether a type is representable. For types that are not
+/// representable, 'SelfRecursive' and 'ContainsRecursive' are used to
+/// distinguish between types that are recursive with themselves and types that
+/// contain a different recursive type. These cases can therefore be treated
+/// differently when reporting errors.
+///
+/// The ordering of the cases is significant. They are sorted so that cmp::max
+/// will keep the "more erroneous" of two values.
+#[derive(Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Debug)]
+pub enum Representability {
+    Representable,
+    ContainsRecursive,
+    SelfRecursive,
+}
+
+impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
+    pub fn can_type_implement_copy(&self, self_type: Ty<'tcx>, span: Span)
+                                   -> Result<(),CopyImplementationError> {
+        let tcx = self.tcx;
+
+        // FIXME: (@jroesch) float this code up
+        let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(self.clone()), false);
+
+        let adt = match self_type.sty {
+            ty::TyStruct(struct_def, substs) => {
+                for field in struct_def.all_fields() {
+                    let field_ty = field.ty(tcx, substs);
+                    if infcx.type_moves_by_default(field_ty, span) {
+                        return Err(CopyImplementationError::InfrigingField(
+                            field.name))
+                    }
+                }
+                struct_def
+            }
+            ty::TyEnum(enum_def, substs) => {
+                for variant in &enum_def.variants {
+                    for field in &variant.fields {
+                        let field_ty = field.ty(tcx, substs);
+                        if infcx.type_moves_by_default(field_ty, span) {
+                            return Err(CopyImplementationError::InfrigingVariant(
+                                variant.name))
+                        }
+                    }
+                }
+                enum_def
+            }
+            _ => return Err(CopyImplementationError::NotAnAdt),
+        };
+
+        if adt.has_dtor() {
+            return Err(CopyImplementationError::HasDestructor)
+        }
+
+        Ok(())
+    }
+}
+
+impl<'tcx> ty::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)
+    }
+
+    pub fn arm_contains_ref_binding(&self, arm: &hir::Arm) -> Option<hir::Mutability> {
+        pat_util::arm_contains_ref_binding(&self.def_map, arm)
+    }
+
+    /// Returns the type of element at index `i` in tuple or tuple-like type `t`.
+    /// For an enum `t`, `variant` is None only if `t` is a univariant enum.
+    pub fn positional_element_ty(&self,
+                                 ty: Ty<'tcx>,
+                                 i: usize,
+                                 variant: Option<DefId>) -> Option<Ty<'tcx>> {
+        match (&ty.sty, variant) {
+            (&TyStruct(def, substs), None) => {
+                def.struct_variant().fields.get(i).map(|f| f.ty(self, substs))
+            }
+            (&TyEnum(def, substs), Some(vid)) => {
+                def.variant_with_id(vid).fields.get(i).map(|f| f.ty(self, substs))
+            }
+            (&TyEnum(def, substs), None) => {
+                assert!(def.is_univariant());
+                def.variants[0].fields.get(i).map(|f| f.ty(self, substs))
+            }
+            (&TyTuple(ref v), None) => v.get(i).cloned(),
+            _ => None
+        }
+    }
+
+    /// Returns the type of element at field `n` in struct or struct-like type `t`.
+    /// For an enum `t`, `variant` must be some def id.
+    pub fn named_element_ty(&self,
+                            ty: Ty<'tcx>,
+                            n: Name,
+                            variant: Option<DefId>) -> Option<Ty<'tcx>> {
+        match (&ty.sty, variant) {
+            (&TyStruct(def, substs), None) => {
+                def.struct_variant().find_field_named(n).map(|f| f.ty(self, substs))
+            }
+            (&TyEnum(def, substs), Some(vid)) => {
+                def.variant_with_id(vid).find_field_named(n).map(|f| f.ty(self, substs))
+            }
+            _ => return None
+        }
+    }
+
+    /// Returns `(normalized_type, ty)`, where `normalized_type` is the
+    /// IntType representation of one of {i64,i32,i16,i8,u64,u32,u16,u8},
+    /// and `ty` is the original type (i.e. may include `isize` or
+    /// `usize`).
+    pub fn enum_repr_type(&self, opt_hint: Option<&attr::ReprAttr>)
+                          -> (attr::IntType, Ty<'tcx>) {
+        let repr_type = match opt_hint {
+            // Feed in the given type
+            Some(&attr::ReprInt(_, int_t)) => int_t,
+            // ... but provide sensible default if none provided
+            //
+            // NB. Historically `fn enum_variants` generate i64 here, while
+            // rustc_typeck::check would generate isize.
+            _ => SignedInt(hir::TyIs),
+        };
+
+        let repr_type_ty = repr_type.to_ty(self);
+        let repr_type = match repr_type {
+            SignedInt(hir::TyIs) =>
+                SignedInt(self.sess.target.int_type),
+            UnsignedInt(hir::TyUs) =>
+                UnsignedInt(self.sess.target.uint_type),
+            other => other
+        };
+
+        (repr_type, repr_type_ty)
+    }
+
+    /// Returns the deeply last field of nested structures, or the same type,
+    /// if not a structure at all. Corresponds to the only possible unsized
+    /// field, and its type can be used to determine unsizing strategy.
+    pub fn struct_tail(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
+        while let TyStruct(def, substs) = ty.sty {
+            match def.struct_variant().fields.last() {
+                Some(f) => ty = f.ty(self, substs),
+                None => break
+            }
+        }
+        ty
+    }
+
+    /// Same as applying struct_tail on `source` and `target`, but only
+    /// keeps going as long as the two types are instances of the same
+    /// structure definitions.
+    /// For `(Foo<Foo<T>>, Foo<Trait>)`, the result will be `(Foo<T>, Trait)`,
+    /// whereas struct_tail produces `T`, and `Trait`, respectively.
+    pub fn struct_lockstep_tails(&self,
+                                 source: Ty<'tcx>,
+                                 target: Ty<'tcx>)
+                                 -> (Ty<'tcx>, Ty<'tcx>) {
+        let (mut a, mut b) = (source, target);
+        while let (&TyStruct(a_def, a_substs), &TyStruct(b_def, b_substs)) = (&a.sty, &b.sty) {
+            if a_def != b_def {
+                break;
+            }
+            if let Some(f) = a_def.struct_variant().fields.last() {
+                a = f.ty(self, a_substs);
+                b = f.ty(self, b_substs);
+            } else {
+                break;
+            }
+        }
+        (a, b)
+    }
+
+    /// Returns the repeat count for a repeating vector expression.
+    pub fn eval_repeat_count(&self, count_expr: &hir::Expr) -> usize {
+        let hint = UncheckedExprHint(self.types.usize);
+        match const_eval::eval_const_expr_partial(self, count_expr, hint) {
+            Ok(val) => {
+                let found = match val {
+                    ConstVal::Uint(count) => return count as usize,
+                    ConstVal::Int(count) if count >= 0 => return count as usize,
+                    const_val => const_val.description(),
+                };
+                span_err!(self.sess, count_expr.span, E0306,
+                    "expected positive integer for repeat count, found {}",
+                    found);
+            }
+            Err(err) => {
+                let err_msg = match count_expr.node {
+                    hir::ExprPath(None, hir::Path {
+                        global: false,
+                        ref segments,
+                        ..
+                    }) if segments.len() == 1 =>
+                        format!("found variable"),
+                    _ => match err.kind {
+                        ErrKind::MiscCatchAll => format!("but found {}", err.description()),
+                        _ => format!("but {}", err.description())
+                    }
+                };
+                span_err!(self.sess, count_expr.span, E0307,
+                    "expected constant integer for repeat count, {}", err_msg);
+            }
+        }
+        0
+    }
+
+    /// Given a set of predicates that apply to an object type, returns
+    /// the region bounds that the (erased) `Self` type must
+    /// outlive. Precisely *because* the `Self` type is erased, the
+    /// parameter `erased_self_ty` must be supplied to indicate what type
+    /// has been used to represent `Self` in the predicates
+    /// themselves. This should really be a unique type; `FreshTy(0)` is a
+    /// popular choice.
+    ///
+    /// NB: in some cases, particularly around higher-ranked bounds,
+    /// this function returns a kind of conservative approximation.
+    /// That is, all regions returned by this function are definitely
+    /// required, but there may be other region bounds that are not
+    /// returned, as well as requirements like `for<'a> T: 'a`.
+    ///
+    /// Requires that trait definitions have been processed so that we can
+    /// elaborate predicates and walk supertraits.
+    pub fn required_region_bounds(&self,
+                                  erased_self_ty: Ty<'tcx>,
+                                  predicates: Vec<ty::Predicate<'tcx>>)
+                                  -> Vec<ty::Region>    {
+        debug!("required_region_bounds(erased_self_ty={:?}, predicates={:?})",
+               erased_self_ty,
+               predicates);
+
+        assert!(!erased_self_ty.has_escaping_regions());
+
+        traits::elaborate_predicates(self, predicates)
+            .filter_map(|predicate| {
+                match predicate {
+                    ty::Predicate::Projection(..) |
+                    ty::Predicate::Trait(..) |
+                    ty::Predicate::Equate(..) |
+                    ty::Predicate::WellFormed(..) |
+                    ty::Predicate::ObjectSafe(..) |
+                    ty::Predicate::RegionOutlives(..) => {
+                        None
+                    }
+                    ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t, r))) => {
+                        // Search for a bound of the form `erased_self_ty
+                        // : 'a`, but be wary of something like `for<'a>
+                        // erased_self_ty : 'a` (we interpret a
+                        // higher-ranked bound like that as 'static,
+                        // though at present the code in `fulfill.rs`
+                        // considers such bounds to be unsatisfiable, so
+                        // it's kind of a moot point since you could never
+                        // construct such an object, but this seems
+                        // correct even if that code changes).
+                        if t == erased_self_ty && !r.has_escaping_regions() {
+                            Some(r)
+                        } else {
+                            None
+                        }
+                    }
+                }
+            })
+            .collect()
+    }
+
+    /// Creates a hash of the type `Ty` which will be the same no matter what crate
+    /// context it's calculated within. This is used by the `type_id` intrinsic.
+    pub fn hash_crate_independent(&self, ty: Ty<'tcx>, svh: &Svh) -> u64 {
+        let mut state = SipHasher::new();
+        helper(self, ty, svh, &mut state);
+        return state.finish();
+
+        fn helper<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh,
+                        state: &mut SipHasher) {
+            macro_rules! byte { ($b:expr) => { ($b as u8).hash(state) } }
+            macro_rules! hash { ($e:expr) => { $e.hash(state) }  }
+
+            let region = |state: &mut SipHasher, r: ty::Region| {
+                match r {
+                    ty::ReStatic => {}
+                    ty::ReLateBound(db, ty::BrAnon(i)) => {
+                        db.hash(state);
+                        i.hash(state);
+                    }
+                    ty::ReEmpty |
+                    ty::ReEarlyBound(..) |
+                    ty::ReLateBound(..) |
+                    ty::ReFree(..) |
+                    ty::ReScope(..) |
+                    ty::ReVar(..) |
+                    ty::ReSkolemized(..) => {
+                        tcx.sess.bug("unexpected region found when hashing a type")
+                    }
+                }
+            };
+            let did = |state: &mut SipHasher, did: DefId| {
+                let h = if did.is_local() {
+                    svh.clone()
+                } else {
+                    tcx.sess.cstore.get_crate_hash(did.krate)
+                };
+                h.as_str().hash(state);
+                did.node.hash(state);
+            };
+            let mt = |state: &mut SipHasher, mt: TypeAndMut| {
+                mt.mutbl.hash(state);
+            };
+            let fn_sig = |state: &mut SipHasher, sig: &ty::Binder<ty::FnSig<'tcx>>| {
+                let sig = tcx.anonymize_late_bound_regions(sig).0;
+                for a in &sig.inputs { helper(tcx, *a, svh, state); }
+                if let ty::FnConverging(output) = sig.output {
+                    helper(tcx, output, svh, state);
+                }
+            };
+            ty.maybe_walk(|ty| {
+                match ty.sty {
+                    TyBool => byte!(2),
+                    TyChar => byte!(3),
+                    TyInt(i) => {
+                        byte!(4);
+                        hash!(i);
+                    }
+                    TyUint(u) => {
+                        byte!(5);
+                        hash!(u);
+                    }
+                    TyFloat(f) => {
+                        byte!(6);
+                        hash!(f);
+                    }
+                    TyStr => {
+                        byte!(7);
+                    }
+                    TyEnum(d, _) => {
+                        byte!(8);
+                        did(state, d.did);
+                    }
+                    TyBox(_) => {
+                        byte!(9);
+                    }
+                    TyArray(_, n) => {
+                        byte!(10);
+                        n.hash(state);
+                    }
+                    TySlice(_) => {
+                        byte!(11);
+                    }
+                    TyRawPtr(m) => {
+                        byte!(12);
+                        mt(state, m);
+                    }
+                    TyRef(r, m) => {
+                        byte!(13);
+                        region(state, *r);
+                        mt(state, m);
+                    }
+                    TyBareFn(opt_def_id, ref b) => {
+                        byte!(14);
+                        hash!(opt_def_id);
+                        hash!(b.unsafety);
+                        hash!(b.abi);
+                        fn_sig(state, &b.sig);
+                        return false;
+                    }
+                    TyTrait(ref data) => {
+                        byte!(17);
+                        did(state, data.principal_def_id());
+                        hash!(data.bounds);
+
+                        let principal = tcx.anonymize_late_bound_regions(&data.principal).0;
+                        for subty in &principal.substs.types {
+                            helper(tcx, subty, svh, state);
+                        }
+
+                        return false;
+                    }
+                    TyStruct(d, _) => {
+                        byte!(18);
+                        did(state, d.did);
+                    }
+                    TyTuple(ref inner) => {
+                        byte!(19);
+                        hash!(inner.len());
+                    }
+                    TyParam(p) => {
+                        byte!(20);
+                        hash!(p.space);
+                        hash!(p.idx);
+                        hash!(p.name.as_str());
+                    }
+                    TyInfer(_) => unreachable!(),
+                    TyError => byte!(21),
+                    TyClosure(d, _) => {
+                        byte!(22);
+                        did(state, d);
+                    }
+                    TyProjection(ref data) => {
+                        byte!(23);
+                        did(state, data.trait_ref.def_id);
+                        hash!(data.item_name.as_str());
+                    }
+                }
+                true
+            });
+        }
+    }
+
+    /// Returns true if this ADT is a dtorck type, i.e. whether it being
+    /// safe for destruction requires it to be alive
+    pub fn is_adt_dtorck(&self, adt: ty::AdtDef<'tcx>) -> bool {
+        let dtor_method = match adt.destructor() {
+            Some(dtor) => dtor,
+            None => return false
+        };
+        let impl_did = self.impl_of_method(dtor_method).unwrap_or_else(|| {
+            self.sess.bug(&format!("no Drop impl for the dtor of `{:?}`", adt))
+        });
+        let generics = adt.type_scheme(self).generics;
+
+        // In `impl<'a> Drop ...`, we automatically assume
+        // `'a` is meaningful and thus represents a bound
+        // through which we could reach borrowed data.
+        //
+        // FIXME (pnkfelix): In the future it would be good to
+        // extend the language to allow the user to express,
+        // in the impl signature, that a lifetime is not
+        // actually used (something like `where 'a: ?Live`).
+        if generics.has_region_params(subst::TypeSpace) {
+            debug!("typ: {:?} has interesting dtor due to region params",
+                   adt);
+            return true;
+        }
+
+        let mut seen_items = Vec::new();
+        let mut items_to_inspect = vec![impl_did];
+        while let Some(item_def_id) = items_to_inspect.pop() {
+            if seen_items.contains(&item_def_id) {
+                continue;
+            }
+
+            for pred in self.lookup_predicates(item_def_id).predicates {
+                let result = match pred {
+                    ty::Predicate::Equate(..) |
+                    ty::Predicate::RegionOutlives(..) |
+                    ty::Predicate::TypeOutlives(..) |
+                    ty::Predicate::WellFormed(..) |
+                    ty::Predicate::ObjectSafe(..) |
+                    ty::Predicate::Projection(..) => {
+                        // For now, assume all these where-clauses
+                        // may give drop implementation capabilty
+                        // to access borrowed data.
+                        true
+                    }
+
+                    ty::Predicate::Trait(ty::Binder(ref t_pred)) => {
+                        let def_id = t_pred.trait_ref.def_id;
+                        if self.trait_items(def_id).len() != 0 {
+                            // If trait has items, assume it adds
+                            // capability to access borrowed data.
+                            true
+                        } else {
+                            // Trait without items is itself
+                            // uninteresting from POV of dropck.
+                            //
+                            // However, may have parent w/ items;
+                            // so schedule checking of predicates,
+                            items_to_inspect.push(def_id);
+                            // and say "no capability found" for now.
+                            false
+                        }
+                    }
+                };
+
+                if result {
+                    debug!("typ: {:?} has interesting dtor due to generic preds, e.g. {:?}",
+                           adt, pred);
+                    return true;
+                }
+            }
+
+            seen_items.push(item_def_id);
+        }
+
+        debug!("typ: {:?} is dtorck-safe", adt);
+        false
+    }
+}
+
+impl<'tcx> ty::TyS<'tcx> {
+    fn impls_bound<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
+                       bound: ty::BuiltinBound,
+                       span: Span)
+                       -> bool
+    {
+        let tcx = param_env.tcx;
+        let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env.clone()), false);
+
+        let is_impld = traits::type_known_to_meet_builtin_bound(&infcx,
+                                                                self, bound, span);
+
+        debug!("Ty::impls_bound({:?}, {:?}) = {:?}",
+               self, bound, is_impld);
+
+        is_impld
+    }
+
+    // FIXME (@jroesch): I made this public to use it, not sure if should be private
+    pub fn moves_by_default<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
+                           span: Span) -> bool {
+        if self.flags.get().intersects(TypeFlags::MOVENESS_CACHED) {
+            return self.flags.get().intersects(TypeFlags::MOVES_BY_DEFAULT);
+        }
+
+        assert!(!self.needs_infer());
+
+        // Fast-path for primitive types
+        let result = match self.sty {
+            TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
+            TyRawPtr(..) | TyBareFn(..) | TyRef(_, TypeAndMut {
+                mutbl: hir::MutImmutable, ..
+            }) => Some(false),
+
+            TyStr | TyBox(..) | TyRef(_, TypeAndMut {
+                mutbl: hir::MutMutable, ..
+            }) => Some(true),
+
+            TyArray(..) | TySlice(_) | TyTrait(..) | TyTuple(..) |
+            TyClosure(..) | TyEnum(..) | TyStruct(..) |
+            TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
+        }.unwrap_or_else(|| !self.impls_bound(param_env, ty::BoundCopy, span));
+
+        if !self.has_param_types() && !self.has_self_ty() {
+            self.flags.set(self.flags.get() | if result {
+                TypeFlags::MOVENESS_CACHED | TypeFlags::MOVES_BY_DEFAULT
+            } else {
+                TypeFlags::MOVENESS_CACHED
+            });
+        }
+
+        result
+    }
+
+    #[inline]
+    pub fn is_sized<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
+                        span: Span) -> bool
+    {
+        if self.flags.get().intersects(TypeFlags::SIZEDNESS_CACHED) {
+            return self.flags.get().intersects(TypeFlags::IS_SIZED);
+        }
+
+        self.is_sized_uncached(param_env, span)
+    }
+
+    fn is_sized_uncached<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
+                             span: Span) -> bool {
+        assert!(!self.needs_infer());
+
+        // Fast-path for primitive types
+        let result = match self.sty {
+            TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
+            TyBox(..) | TyRawPtr(..) | TyRef(..) | TyBareFn(..) |
+            TyArray(..) | TyTuple(..) | TyClosure(..) => Some(true),
+
+            TyStr | TyTrait(..) | TySlice(_) => Some(false),
+
+            TyEnum(..) | TyStruct(..) | TyProjection(..) | TyParam(..) |
+            TyInfer(..) | TyError => None
+        }.unwrap_or_else(|| self.impls_bound(param_env, ty::BoundSized, span));
+
+        if !self.has_param_types() && !self.has_self_ty() {
+            self.flags.set(self.flags.get() | if result {
+                TypeFlags::SIZEDNESS_CACHED | TypeFlags::IS_SIZED
+            } else {
+                TypeFlags::SIZEDNESS_CACHED
+            });
+        }
+
+        result
+    }
+
+
+    /// Check whether a type is representable. This means it cannot contain unboxed
+    /// structural recursion. This check is needed for structs and enums.
+    pub fn is_representable(&'tcx self, cx: &ty::ctxt<'tcx>, sp: Span) -> Representability {
+
+        // Iterate until something non-representable is found
+        fn find_nonrepresentable<'tcx, It: Iterator<Item=Ty<'tcx>>>(cx: &ty::ctxt<'tcx>,
+                                                                    sp: Span,
+                                                                    seen: &mut Vec<Ty<'tcx>>,
+                                                                    iter: It)
+                                                                    -> Representability {
+            iter.fold(Representability::Representable,
+                      |r, ty| cmp::max(r, is_type_structurally_recursive(cx, sp, seen, ty)))
+        }
+
+        fn are_inner_types_recursive<'tcx>(cx: &ty::ctxt<'tcx>, sp: Span,
+                                           seen: &mut Vec<Ty<'tcx>>, ty: Ty<'tcx>)
+                                           -> Representability {
+            match ty.sty {
+                TyTuple(ref ts) => {
+                    find_nonrepresentable(cx, sp, seen, ts.iter().cloned())
+                }
+                // Fixed-length vectors.
+                // FIXME(#11924) Behavior undecided for zero-length vectors.
+                TyArray(ty, _) => {
+                    is_type_structurally_recursive(cx, sp, seen, ty)
+                }
+                TyStruct(def, substs) | TyEnum(def, substs) => {
+                    find_nonrepresentable(cx,
+                                          sp,
+                                          seen,
+                                          def.all_fields().map(|f| f.ty(cx, substs)))
+                }
+                TyClosure(..) => {
+                    // this check is run on type definitions, so we don't expect
+                    // to see closure types
+                    cx.sess.bug(&format!("requires check invoked on inapplicable type: {:?}", ty))
+                }
+                _ => Representability::Representable,
+            }
+        }
+
+        fn same_struct_or_enum<'tcx>(ty: Ty<'tcx>, def: ty::AdtDef<'tcx>) -> bool {
+            match ty.sty {
+                TyStruct(ty_def, _) | TyEnum(ty_def, _) => {
+                     ty_def == def
+                }
+                _ => false
+            }
+        }
+
+        fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
+            match (&a.sty, &b.sty) {
+                (&TyStruct(did_a, ref substs_a), &TyStruct(did_b, ref substs_b)) |
+                (&TyEnum(did_a, ref substs_a), &TyEnum(did_b, ref substs_b)) => {
+                    if did_a != did_b {
+                        return false;
+                    }
+
+                    let types_a = substs_a.types.get_slice(subst::TypeSpace);
+                    let types_b = substs_b.types.get_slice(subst::TypeSpace);
+
+                    let mut pairs = types_a.iter().zip(types_b);
+
+                    pairs.all(|(&a, &b)| same_type(a, b))
+                }
+                _ => {
+                    a == b
+                }
+            }
+        }
+
+        // Does the type `ty` directly (without indirection through a pointer)
+        // contain any types on stack `seen`?
+        fn is_type_structurally_recursive<'tcx>(cx: &ty::ctxt<'tcx>,
+                                                sp: Span,
+                                                seen: &mut Vec<Ty<'tcx>>,
+                                                ty: Ty<'tcx>) -> Representability {
+            debug!("is_type_structurally_recursive: {:?}", ty);
+
+            match ty.sty {
+                TyStruct(def, _) | TyEnum(def, _) => {
+                    {
+                        // Iterate through stack of previously seen types.
+                        let mut iter = seen.iter();
+
+                        // The first item in `seen` is the type we are actually curious about.
+                        // We want to return SelfRecursive if this type contains itself.
+                        // It is important that we DON'T take generic parameters into account
+                        // for this check, so that Bar<T> in this example counts as SelfRecursive:
+                        //
+                        // struct Foo;
+                        // struct Bar<T> { x: Bar<Foo> }
+
+                        match iter.next() {
+                            Some(&seen_type) => {
+                                if same_struct_or_enum(seen_type, def) {
+                                    debug!("SelfRecursive: {:?} contains {:?}",
+                                           seen_type,
+                                           ty);
+                                    return Representability::SelfRecursive;
+                                }
+                            }
+                            None => {}
+                        }
+
+                        // We also need to know whether the first item contains other types
+                        // that are structurally recursive. If we don't catch this case, we
+                        // will recurse infinitely for some inputs.
+                        //
+                        // It is important that we DO take generic parameters into account
+                        // here, so that code like this is considered SelfRecursive, not
+                        // ContainsRecursive:
+                        //
+                        // struct Foo { Option<Option<Foo>> }
+
+                        for &seen_type in iter {
+                            if same_type(ty, seen_type) {
+                                debug!("ContainsRecursive: {:?} contains {:?}",
+                                       seen_type,
+                                       ty);
+                                return Representability::ContainsRecursive;
+                            }
+                        }
+                    }
+
+                    // For structs and enums, track all previously seen types by pushing them
+                    // onto the 'seen' stack.
+                    seen.push(ty);
+                    let out = are_inner_types_recursive(cx, sp, seen, ty);
+                    seen.pop();
+                    out
+                }
+                _ => {
+                    // No need to push in other cases.
+                    are_inner_types_recursive(cx, sp, seen, ty)
+                }
+            }
+        }
+
+        debug!("is_type_representable: {:?}", self);
+
+        // To avoid a stack overflow when checking an enum variant or struct that
+        // contains a different, structurally recursive type, maintain a stack
+        // of seen types and check recursion for each of them (issues #3008, #3779).
+        let mut seen: Vec<Ty> = Vec::new();
+        let r = is_type_structurally_recursive(cx, sp, &mut seen, self);
+        debug!("is_type_representable: {:?} is {:?}", self, r);
+        r
+    }
+}
index 99e41bd22b8bb9b250ed054dde519e6941dc509f..fee60d46dc0019b7436f4986015124092c2e74d8 100644 (file)
@@ -388,23 +388,23 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-impl<'tcx> fmt::Debug for ty::AutoAdjustment<'tcx> {
+impl<'tcx> fmt::Debug for ty::adjustment::AutoAdjustment<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            ty::AdjustReifyFnPointer => {
+            ty::adjustment::AdjustReifyFnPointer => {
                 write!(f, "AdjustReifyFnPointer")
             }
-            ty::AdjustUnsafeFnPointer => {
+            ty::adjustment::AdjustUnsafeFnPointer => {
                 write!(f, "AdjustUnsafeFnPointer")
             }
-            ty::AdjustDerefRef(ref data) => {
+            ty::adjustment::AdjustDerefRef(ref data) => {
                 write!(f, "{:?}", data)
             }
         }
     }
 }
 
-impl<'tcx> fmt::Debug for ty::AutoDerefRef<'tcx> {
+impl<'tcx> fmt::Debug for ty::adjustment::AutoDerefRef<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "AutoDerefRef({}, unsize={:?}, {:?})",
                self.autoderefs, self.unsize, self.autoref)
index c8ffe0766061114d63e7aaa745e9100d93e7713b..4084f13e818f226fe0b8d965f62f1340b7edefae 100644 (file)
@@ -33,6 +33,7 @@
 use middle::def_id::DefId;
 use middle::subst::Substs;
 use middle::ty::{self, Ty};
+use middle::ty::adjustment;
 use middle::const_eval::{eval_const_expr_partial, ConstVal};
 use middle::const_eval::EvalHint::ExprTypeChecked;
 use rustc::front::map as hir_map;
@@ -1722,13 +1723,15 @@ fn check_expr(&mut self, cx: &Context, e: &hir::Expr) {
         }
 
         if let Some(adjustment) = cx.tcx.tables.borrow().adjustments.get(&e.id) {
-            if let ty::AdjustDerefRef(ty::AutoDerefRef { ref autoref, .. }) = *adjustment {
+            if let adjustment::AdjustDerefRef(adjustment::AutoDerefRef {
+                ref autoref, ..
+            }) = *adjustment {
                 match autoref {
-                    &Some(ty::AutoPtr(_, hir::MutImmutable)) => {
+                    &Some(adjustment::AutoPtr(_, hir::MutImmutable)) => {
                         cx.span_lint(UNUSED_ALLOCATION, e.span,
                                      "unnecessary allocation, use & instead");
                     }
-                    &Some(ty::AutoPtr(_, hir::MutMutable)) => {
+                    &Some(adjustment::AutoPtr(_, hir::MutMutable)) => {
                         cx.span_lint(UNUSED_ALLOCATION, e.span,
                                      "unnecessary allocation, use &mut instead");
                     }
@@ -2297,7 +2300,7 @@ fn expr_refers_to_this_method(tcx: &ty::ctxt,
             }
 
             // Check for overloaded autoderef method calls.
-            if let Some(&ty::AdjustDerefRef(ref adj)) = tables.adjustments.get(&id) {
+            if let Some(&adjustment::AdjustDerefRef(ref adj)) = tables.adjustments.get(&id) {
                 for i in 0..adj.autoderefs {
                     let method_call = ty::MethodCall::autoderef(id, i as u32);
                     if let Some(m) = tables.method_map.get(&method_call) {
index 6352af39f1489b75d64e93e826cb7e9d061abcc0..f15470e7851d41b133e5470748154e94506888ab 100644 (file)
@@ -320,7 +320,7 @@ fn make_mirror(self, cx: &mut Cx<'a,'tcx>) -> Expr<Cx<'a,'tcx>> {
         // Now apply adjustments, if any.
         match cx.tcx.tables.borrow().adjustments.get(&self.id) {
             None => { }
-            Some(&ty::AdjustReifyFnPointer) => {
+            Some(&ty::adjustment::AdjustReifyFnPointer) => {
                 let adjusted_ty = cx.tcx.expr_ty_adjusted(self);
                 expr = Expr {
                     temp_lifetime: temp_lifetime,
@@ -329,7 +329,7 @@ fn make_mirror(self, cx: &mut Cx<'a,'tcx>) -> Expr<Cx<'a,'tcx>> {
                     kind: ExprKind::ReifyFnPointer { source: expr.to_ref() },
                 };
             }
-            Some(&ty::AdjustUnsafeFnPointer) => {
+            Some(&ty::adjustment::AdjustUnsafeFnPointer) => {
                 let adjusted_ty = cx.tcx.expr_ty_adjusted(self);
                 expr = Expr {
                     temp_lifetime: temp_lifetime,
@@ -338,7 +338,7 @@ fn make_mirror(self, cx: &mut Cx<'a,'tcx>) -> Expr<Cx<'a,'tcx>> {
                     kind: ExprKind::UnsafeFnPointer { source: expr.to_ref() },
                 };
             }
-            Some(&ty::AdjustDerefRef(ref adj)) => {
+            Some(&ty::adjustment::AdjustDerefRef(ref adj)) => {
                 for i in 0..adj.autoderefs {
                     let i = i as u32;
                     let adjusted_ty =
@@ -372,7 +372,7 @@ fn make_mirror(self, cx: &mut Cx<'a,'tcx>) -> Expr<Cx<'a,'tcx>> {
                 } else if let Some(autoref) = adj.autoref {
                     let adjusted_ty = expr.ty.adjust_for_autoref(cx.tcx, Some(autoref));
                     match autoref {
-                        ty::AutoPtr(r, m) => {
+                        ty::adjustment::AutoPtr(r, m) => {
                             expr = Expr {
                                 temp_lifetime: temp_lifetime,
                                 ty: adjusted_ty,
@@ -382,7 +382,7 @@ fn make_mirror(self, cx: &mut Cx<'a,'tcx>) -> Expr<Cx<'a,'tcx>> {
                                                          arg: expr.to_ref() }
                             };
                         }
-                        ty::AutoUnsafe(m) => {
+                        ty::adjustment::AutoUnsafe(m) => {
                             // Convert this to a suitable `&foo` and
                             // then an unsafe coercion. Limit the region to be just this
                             // expression.
index c98760ce02a269f8f617dcf7e52d712ca173b904..a2d74635b5e1ce6f2a54ae350fde781565392256 100644 (file)
@@ -34,6 +34,8 @@
 use trans::type_::Type;
 use trans::type_of;
 use middle::subst::Substs;
+use middle::ty::adjustment::{AdjustDerefRef, AdjustReifyFnPointer};
+use middle::ty::adjustment::AdjustUnsafeFnPointer;
 use middle::ty::{self, Ty};
 use middle::ty::cast::{CastTy,IntTy};
 use util::nodemap::NodeMap;
@@ -289,14 +291,14 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                                             &cx.tcx().expr_ty_adjusted(e));
     let opt_adj = cx.tcx().tables.borrow().adjustments.get(&e.id).cloned();
     match opt_adj {
-        Some(ty::AdjustReifyFnPointer) => {
+        Some(AdjustReifyFnPointer) => {
             // FIXME(#19925) once fn item types are
             // zero-sized, we'll need to do something here
         }
-        Some(ty::AdjustUnsafeFnPointer) => {
+        Some(AdjustUnsafeFnPointer) => {
             // purely a type-level thing
         }
-        Some(ty::AdjustDerefRef(adj)) => {
+        Some(AdjustDerefRef(adj)) => {
             let mut ty = ety;
             // Save the last autoderef in case we can avoid it.
             if adj.autoderefs > 0 {
index 59040b9cafef51d7e5269bf5af64ad2d81211bcc..7d8996867c016ff4138ec8425502ad2d6f49aeab 100644 (file)
@@ -71,7 +71,8 @@
 use trans::meth;
 use trans::tvec;
 use trans::type_of;
-use middle::ty::{AdjustDerefRef, AdjustReifyFnPointer, AdjustUnsafeFnPointer};
+use middle::ty::adjustment::{AdjustDerefRef, AdjustReifyFnPointer};
+use middle::ty::adjustment::{AdjustUnsafeFnPointer, CustomCoerceUnsized};
 use middle::ty::{self, Ty};
 use middle::ty::MethodCall;
 use middle::ty::cast::{CastKind, CastTy};
@@ -514,7 +515,7 @@ fn coerce_unsized<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             };
 
             let coerce_index = match kind {
-                ty::CustomCoerceUnsized::Struct(i) => i
+                CustomCoerceUnsized::Struct(i) => i
             };
             assert!(coerce_index < src_fields.len() && src_fields.len() == target_fields.len());
 
index cde188fa41e48f353d877bf383516227afc0adb9..69efaa792fe053e7356d0ccddea67aeb8bcebdc0 100644 (file)
@@ -65,7 +65,9 @@
 use middle::infer::{self, Coercion};
 use middle::traits::{self, ObligationCause};
 use middle::traits::{predicate_for_trait_def, report_selection_error};
-use middle::ty::{AutoDerefRef, AdjustDerefRef};
+use middle::ty::adjustment::{AutoAdjustment, AutoDerefRef, AdjustDerefRef};
+use middle::ty::adjustment::{AutoPtr, AutoUnsafe, AdjustReifyFnPointer};
+use middle::ty::adjustment::{AdjustUnsafeFnPointer};
 use middle::ty::{self, LvaluePreference, TypeAndMut, Ty};
 use middle::ty::error::TypeError;
 use middle::ty::relate::RelateResult;
@@ -81,7 +83,7 @@ struct Coerce<'a, 'tcx: 'a> {
     unsizing_obligations: RefCell<Vec<traits::PredicateObligation<'tcx>>>,
 }
 
-type CoerceResult<'tcx> = RelateResult<'tcx, Option<ty::AutoAdjustment<'tcx>>>;
+type CoerceResult<'tcx> = RelateResult<'tcx, Option<AutoAdjustment<'tcx>>>;
 
 impl<'f, 'tcx> Coerce<'f, 'tcx> {
     fn tcx(&self) -> &ty::ctxt<'tcx> {
@@ -186,7 +188,7 @@ fn coerce_borrowed_pointer(&self,
         let coercion = Coercion(self.origin.span());
         let r_borrow = self.fcx.infcx().next_region_var(coercion);
         let r_borrow = self.tcx().mk_region(r_borrow);
-        let autoref = Some(ty::AutoPtr(r_borrow, mutbl_b));
+        let autoref = Some(AutoPtr(r_borrow, mutbl_b));
 
         let lvalue_pref = LvaluePreference::from_mutbl(mutbl_b);
         let mut first_error = None;
@@ -264,11 +266,11 @@ fn coerce_unsized(&self,
                 let coercion = Coercion(self.origin.span());
                 let r_borrow = self.fcx.infcx().next_region_var(coercion);
                 let region = self.tcx().mk_region(r_borrow);
-                (mt_a.ty, Some(ty::AutoPtr(region, mt_b.mutbl)))
+                (mt_a.ty, Some(AutoPtr(region, mt_b.mutbl)))
             }
             (&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) => {
                 try!(coerce_mutbls(mt_a.mutbl, mt_b.mutbl));
-                (mt_a.ty, Some(ty::AutoUnsafe(mt_b.mutbl)))
+                (mt_a.ty, Some(AutoUnsafe(mt_b.mutbl)))
             }
             _ => (source, None)
         };
@@ -360,7 +362,7 @@ fn coerce_from_fn_pointer(&self,
                     (hir::Unsafety::Normal, hir::Unsafety::Unsafe) => {
                         let unsafe_a = self.tcx().safe_to_unsafe_fn_ty(fn_ty_a);
                         try!(self.subtype(unsafe_a, b));
-                        return Ok(Some(ty::AdjustUnsafeFnPointer));
+                        return Ok(Some(AdjustUnsafeFnPointer));
                     }
                     _ => {}
                 }
@@ -387,7 +389,7 @@ fn coerce_from_fn_item(&self,
                 ty::TyBareFn(None, _) => {
                     let a_fn_pointer = self.tcx().mk_fn(None, fn_ty_a);
                     try!(self.subtype(a_fn_pointer, b));
-                    Ok(Some(ty::AdjustReifyFnPointer))
+                    Ok(Some(AdjustReifyFnPointer))
                 }
                 _ => self.subtype(a, b)
             }
@@ -422,7 +424,7 @@ fn coerce_unsafe_ptr(&self,
         if is_ref {
             Ok(Some(AdjustDerefRef(AutoDerefRef {
                 autoderefs: 1,
-                autoref: Some(ty::AutoUnsafe(mutbl_b)),
+                autoref: Some(AutoUnsafe(mutbl_b)),
                 unsize: None
             })))
         } else {
index 048a2b62bcaa3fbc9e6dfb53b00845287e103a5d..572ba7a84871354ea543d78db2de580dfa62dc5b 100644 (file)
@@ -16,6 +16,7 @@
 use middle::subst::{self};
 use middle::traits;
 use middle::ty::{self, NoPreference, PreferMutLvalue, Ty};
+use middle::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr};
 use middle::ty::fold::TypeFoldable;
 use middle::infer;
 use middle::infer::InferCtxt;
@@ -136,7 +137,7 @@ fn adjust_self_ty(&mut self,
     {
         let (autoref, unsize) = if let Some(mutbl) = pick.autoref {
             let region = self.infcx().next_region_var(infer::Autoref(self.span));
-            let autoref = ty::AutoPtr(self.tcx().mk_region(region), mutbl);
+            let autoref = AutoPtr(self.tcx().mk_region(region), mutbl);
             (Some(autoref), pick.unsize.map(|target| {
                 target.adjust_for_autoref(self.tcx(), Some(autoref))
             }))
@@ -169,7 +170,7 @@ fn adjust_self_ty(&mut self,
 
         // Write out the final adjustment.
         self.fcx.write_adjustment(self.self_expr.id,
-                                  ty::AdjustDerefRef(ty::AutoDerefRef {
+                                  AdjustDerefRef(AutoDerefRef {
             autoderefs: pick.autoderefs,
             autoref: autoref,
             unsize: unsize
@@ -488,7 +489,7 @@ fn fixup_derefs_on_method_receiver_if_necessary(&self,
                                             .borrow()
                                             .adjustments
                                             .get(&expr.id) {
-                Some(&ty::AdjustDerefRef(ref adj)) => adj.autoderefs,
+                Some(&AdjustDerefRef(ref adj)) => adj.autoderefs,
                 Some(_) | None => 0,
             };
 
@@ -527,12 +528,12 @@ fn fixup_derefs_on_method_receiver_if_necessary(&self,
                         let adj = self.fcx.inh.tables.borrow().adjustments.get(&base_expr.id)
                                                                           .cloned();
                         let (autoderefs, unsize) = match adj {
-                            Some(ty::AdjustDerefRef(adr)) => match adr.autoref {
+                            Some(AdjustDerefRef(adr)) => match adr.autoref {
                                 None => {
                                     assert!(adr.unsize.is_none());
                                     (adr.autoderefs, None)
                                 }
-                                Some(ty::AutoPtr(_, _)) => {
+                                Some(AutoPtr(_, _)) => {
                                     (adr.autoderefs, adr.unsize.map(|target| {
                                         target.builtin_deref(false, NoPreference)
                                               .expect("fixup: AutoPtr is not &T").ty
@@ -557,7 +558,7 @@ fn fixup_derefs_on_method_receiver_if_necessary(&self,
                             (target, true)
                         } else {
                             (self.fcx.adjust_expr_ty(base_expr,
-                                Some(&ty::AdjustDerefRef(ty::AutoDerefRef {
+                                Some(&AdjustDerefRef(AutoDerefRef {
                                     autoderefs: autoderefs,
                                     autoref: None,
                                     unsize: None
index e319e37fa30981a5e429ee48693d77664b951a9a..1cfb495b36ed75a9e6dfb1b2c5384728e870e8e7 100644 (file)
@@ -18,6 +18,7 @@
 use middle::subst;
 use middle::traits;
 use middle::ty::{self, ToPredicate, ToPolyTraitRef, TraitRef};
+use middle::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr};
 use middle::infer;
 
 use syntax::ast;
@@ -282,9 +283,9 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     match transformed_self_ty.sty {
                         ty::TyRef(region, ty::TypeAndMut { mutbl, ty: _ }) => {
                             fcx.write_adjustment(self_expr.id,
-                                ty::AdjustDerefRef(ty::AutoDerefRef {
+                                AdjustDerefRef(AutoDerefRef {
                                     autoderefs: autoderefs,
-                                    autoref: Some(ty::AutoPtr(region, mutbl)),
+                                    autoref: Some(AutoPtr(region, mutbl)),
                                     unsize: if unsize {
                                         Some(transformed_self_ty)
                                     } else {
index 3160ed3502578f10e870e594f143ce268a5a8af4..656a740e9840e5f554cfe35ffbae2c57b57c52b6 100644 (file)
 use middle::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
 use middle::ty::{self, HasTypeFlags, RegionEscape, ToPolyTraitRef, Ty};
 use middle::ty::{MethodCall, MethodCallee};
+use middle::ty::adjustment;
 use middle::ty::error::TypeError;
 use middle::ty::fold::{TypeFolder, TypeFoldable};
+use middle::ty::util::Representability;
 use require_c_abi_if_variadic;
 use rscope::{ElisionFailureInfo, RegionScope};
 use session::Session;
@@ -1337,7 +1339,7 @@ pub fn write_autoderef_adjustment(&self,
                                       derefs: usize) {
         self.write_adjustment(
             node_id,
-            ty::AdjustDerefRef(ty::AutoDerefRef {
+            adjustment::AdjustDerefRef(adjustment::AutoDerefRef {
                 autoderefs: derefs,
                 autoref: None,
                 unsize: None
@@ -1347,7 +1349,7 @@ pub fn write_autoderef_adjustment(&self,
 
     pub fn write_adjustment(&self,
                             node_id: ast::NodeId,
-                            adj: ty::AutoAdjustment<'tcx>) {
+                            adj: adjustment::AutoAdjustment<'tcx>) {
         debug!("write_adjustment(node_id={}, adj={:?})", node_id, adj);
 
         if adj.is_identity() {
@@ -1576,7 +1578,7 @@ pub fn expr_ty(&self, ex: &hir::Expr) -> Ty<'tcx> {
     /// Apply `adjustment` to the type of `expr`
     pub fn adjust_expr_ty(&self,
                           expr: &hir::Expr,
-                          adjustment: Option<&ty::AutoAdjustment<'tcx>>)
+                          adjustment: Option<&adjustment::AutoAdjustment<'tcx>>)
                           -> Ty<'tcx>
     {
         let raw_ty = self.expr_ty(expr);
@@ -4170,12 +4172,13 @@ pub fn check_representable(tcx: &ty::ctxt,
     // contain themselves. For case 2, there must be an inner type that will be
     // caught by case 1.
     match rty.is_representable(tcx, sp) {
-      ty::SelfRecursive => {
-        span_err!(tcx.sess, sp, E0072, "invalid recursive {} type", designation);
-        tcx.sess.fileline_help(sp, "wrap the inner value in a box to make it representable");
-        return false
-      }
-      ty::Representable | ty::ContainsRecursive => (),
+        Representability::SelfRecursive => {
+            span_err!(tcx.sess, sp, E0072, "invalid recursive {} type", designation);
+            tcx.sess.fileline_help(
+                sp, "wrap the inner value in a box to make it representable");
+            return false
+        }
+        Representability::Representable | Representability::ContainsRecursive => (),
     }
     return true
 }
index b6ff7b529c556a6bacc7691597467f2f7afd28c4..155caaa8cb0fe2a7f4f1fac3b1d6bb3bde5540a2 100644 (file)
@@ -94,6 +94,7 @@
 use middle::ty::{self, RegionEscape, ReScope, Ty, MethodCall, HasTypeFlags};
 use middle::infer::{self, GenericKind, InferCtxt, SubregionOrigin, VerifyBound};
 use middle::pat_util;
+use middle::ty::adjustment;
 use middle::ty::wf::ImpliedBound;
 
 use std::mem;
@@ -598,7 +599,9 @@ fn visit_expr(rcx: &mut Rcx, expr: &hir::Expr) {
     if let Some(adjustment) = adjustment {
         debug!("adjustment={:?}", adjustment);
         match adjustment {
-            ty::AdjustDerefRef(ty::AutoDerefRef {autoderefs, ref autoref, ..}) => {
+            adjustment::AdjustDerefRef(adjustment::AutoDerefRef {
+                autoderefs, ref autoref, ..
+            }) => {
                 let expr_ty = rcx.resolve_node_type(expr.id);
                 constrain_autoderefs(rcx, expr, autoderefs, expr_ty);
                 if let Some(ref autoref) = *autoref {
@@ -614,7 +617,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &hir::Expr) {
                 }
             }
             /*
-            ty::AutoObject(_, ref bounds, _, _) => {
+            adjustment::AutoObject(_, ref bounds, _, _) => {
                 // Determine if we are casting `expr` to a trait
                 // instance. If so, we have to be sure that the type
                 // of the source obeys the new region bound.
@@ -1221,7 +1224,7 @@ fn link_pattern<'t, 'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
 fn link_autoref(rcx: &Rcx,
                 expr: &hir::Expr,
                 autoderefs: usize,
-                autoref: &ty::AutoRef)
+                autoref: &adjustment::AutoRef)
 {
     debug!("link_autoref(autoref={:?})", autoref);
     let mc = mc::MemCategorizationContext::new(rcx.fcx.infcx());
@@ -1229,12 +1232,12 @@ fn link_autoref(rcx: &Rcx,
     debug!("expr_cmt={:?}", expr_cmt);
 
     match *autoref {
-        ty::AutoPtr(r, m) => {
+        adjustment::AutoPtr(r, m) => {
             link_region(rcx, expr.span, r,
                 ty::BorrowKind::from_mutbl(m), expr_cmt);
         }
 
-        ty::AutoUnsafe(m) => {
+        adjustment::AutoUnsafe(m) => {
             let r = ty::ReScope(rcx.tcx().region_maps.node_extent(expr.id));
             link_region(rcx, expr.span, &r, ty::BorrowKind::from_mutbl(m), expr_cmt);
         }
index de841a0cc0022857311975ab1bf9fcb5840307ef..6f8e064c9d8195c3e98c83affec70b55b00a031c 100644 (file)
@@ -18,6 +18,7 @@
 use middle::def_id::DefId;
 use middle::pat_util;
 use middle::ty::{self, Ty, MethodCall, MethodCallee};
+use middle::ty::adjustment;
 use middle::ty::fold::{TypeFolder,TypeFoldable};
 use middle::infer;
 use write_substs_to_tcx;
@@ -268,19 +269,21 @@ fn visit_adjustments(&self, reason: ResolveReason, id: ast::NodeId) {
 
             Some(adjustment) => {
                 let resolved_adjustment = match adjustment {
-                    ty::AdjustReifyFnPointer => ty::AdjustReifyFnPointer,
+                    adjustment::AdjustReifyFnPointer => {
+                        adjustment::AdjustReifyFnPointer
+                    }
 
-                    ty::AdjustUnsafeFnPointer => {
-                        ty::AdjustUnsafeFnPointer
+                    adjustment::AdjustUnsafeFnPointer => {
+                        adjustment::AdjustUnsafeFnPointer
                     }
 
-                    ty::AdjustDerefRef(adj) => {
+                    adjustment::AdjustDerefRef(adj) => {
                         for autoderef in 0..adj.autoderefs {
                             let method_call = MethodCall::autoderef(id, autoderef as u32);
                             self.visit_method_map_entry(reason, method_call);
                         }
 
-                        ty::AdjustDerefRef(ty::AutoDerefRef {
+                        adjustment::AdjustDerefRef(adjustment::AutoDerefRef {
                             autoderefs: adj.autoderefs,
                             autoref: self.resolve(&adj.autoref, reason),
                             unsize: self.resolve(&adj.unsize, reason),
index 8048c302f2c78ff17abfec3fd2a06c093c44b518..9ba6f1398e47118fb84c708cbe83c80fcf12fde9 100644 (file)
@@ -20,6 +20,7 @@
 use middle::lang_items::UnsizeTraitLangItem;
 use middle::subst::{self, Subst};
 use middle::traits;
+use middle::ty;
 use middle::ty::RegionEscape;
 use middle::ty::{ImplContainer, ImplOrTraitItemId, ConstTraitItemId};
 use middle::ty::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment};
@@ -29,7 +30,7 @@
 use middle::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
 use middle::ty::{TyUint, TyClosure, TyBox, TyBareFn};
 use middle::ty::TyProjection;
-use middle::ty;
+use middle::ty::util::CopyImplementationError;
 use middle::free_region::FreeRegionMap;
 use CrateCtxt;
 use middle::infer::{self, InferCtxt, new_infer_ctxt};
@@ -370,27 +371,27 @@ fn check_implementations_of_copy(&self) {
 
             match param_env.can_type_implement_copy(self_type, span) {
                 Ok(()) => {}
-                Err(ty::FieldDoesNotImplementCopy(name)) => {
+                Err(CopyImplementationError::InfrigingField(name)) => {
                        span_err!(tcx.sess, span, E0204,
                                  "the trait `Copy` may not be \
                                           implemented for this type; field \
                                           `{}` does not implement `Copy`",
                                          name)
                 }
-                Err(ty::VariantDoesNotImplementCopy(name)) => {
+                Err(CopyImplementationError::InfrigingVariant(name)) => {
                        span_err!(tcx.sess, span, E0205,
                                  "the trait `Copy` may not be \
                                           implemented for this type; variant \
                                           `{}` does not implement `Copy`",
                                          name)
                 }
-                Err(ty::TypeIsStructural) => {
+                Err(CopyImplementationError::NotAnAdt) => {
                        span_err!(tcx.sess, span, E0206,
                                  "the trait `Copy` may not be implemented \
                                   for this type; type is not a structure or \
                                   enumeration")
                 }
-                Err(ty::TypeHasDestructor) => {
+                Err(CopyImplementationError::HasDestructor) => {
                     span_err!(tcx.sess, span, E0184,
                               "the trait `Copy` may not be implemented for this type; \
                                the type has a destructor");
@@ -510,7 +511,7 @@ fn check_implementations_of_coerce_unsized(&self) {
                     }
 
                     let (i, a, b) = diff_fields[0];
-                    let kind = ty::CustomCoerceUnsized::Struct(i);
+                    let kind = ty::adjustment::CustomCoerceUnsized::Struct(i);
                     (a, b, coerce_unsized_trait, Some(kind))
                 }
 
index 0f71c4d8ceb5608df065c4f3f95f533bceea9c4a..f7520ed54b77e3f153d8782fb9c1c29ccf29a190 100644 (file)
 use middle::const_eval::EvalHint::UncheckedExprHint;
 use middle::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace};
 use middle::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
-use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty, TypeScheme, IntTypeExt};
+use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty, TypeScheme};
 use middle::ty::{VariantKind};
 use middle::ty::fold::{TypeFolder, TypeFoldable};
+use middle::ty::util::IntTypeExt;
 use middle::infer;
 use rscope::*;
 use rustc::front::map as hir_map;