]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/ty/util.rs
move projection mode into parameter environment
[rust.git] / src / librustc / ty / util.rs
index 01fed11fc97affd7e8ad22cb0f275e7b5ec1faef..31c099c661df05d9a80a4f4ae3c90599e8c48324 100644 (file)
@@ -150,20 +150,32 @@ pub enum Representability {
 impl<'tcx> ty::ParamEnv<'tcx> {
     /// Construct a trait environment suitable for contexts where
     /// there are no where clauses in scope.
-    pub fn empty() -> Self {
-        Self::new(ty::Slice::empty())
+    pub fn empty(reveal: Reveal) -> Self {
+        Self::new(ty::Slice::empty(), reveal)
     }
 
     /// Construct a trait environment with the given set of predicates.
-    pub fn new(caller_bounds: &'tcx ty::Slice<ty::Predicate<'tcx>>) -> Self {
-        ty::ParamEnv { caller_bounds }
+    pub fn new(caller_bounds: &'tcx ty::Slice<ty::Predicate<'tcx>>,
+               reveal: Reveal)
+               -> Self {
+        ty::ParamEnv { caller_bounds, reveal }
+    }
+
+    /// Returns a new parameter environment with the same clauses, but
+    /// which "reveals" the true results of projections in all cases
+    /// (even for associated types that are specializable).  This is
+    /// the desired behavior during trans and certain other special
+    /// contexts; normally though we want to use `Reveal::UserFacing`,
+    /// which is the default.
+    pub fn reveal_all(self) -> Self {
+        ty::ParamEnv { reveal: Reveal::All, ..self }
     }
 
     pub fn can_type_implement_copy<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                        self_type: Ty<'tcx>, span: Span)
                                        -> Result<(), CopyImplementationError> {
         // FIXME: (@jroesch) float this code up
-        tcx.infer_ctxt(self.clone(), Reveal::UserFacing).enter(|infcx| {
+        tcx.infer_ctxt(self.clone()).enter(|infcx| {
             let (adt, substs) = match self_type.sty {
                 ty::TyAdt(adt, substs) => (adt, substs),
                 _ => return Err(CopyImplementationError::NotAnAdt),
@@ -266,13 +278,29 @@ pub fn named_element_ty(self,
     /// 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 TyAdt(def, substs) = ty.sty {
-            if !def.is_struct() {
-                break;
-            }
-            match def.struct_variant().fields.last() {
-                Some(f) => ty = f.ty(self, substs),
-                None => break,
+        loop {
+            match ty.sty {
+                ty::TyAdt(def, substs) => {
+                    if !def.is_struct() {
+                        break;
+                    }
+                    match def.struct_variant().fields.last() {
+                        Some(f) => ty = f.ty(self, substs),
+                        None => break,
+                    }
+                }
+
+                ty::TyTuple(tys, _) => {
+                    if let Some((&last_ty, _)) = tys.split_last() {
+                        ty = last_ty;
+                    } else {
+                        break;
+                    }
+                }
+
+                _ => {
+                    break;
+                }
             }
         }
         ty
@@ -584,6 +612,15 @@ pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> &'tcx ty::Substs<'tc
             bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id)
         })
     }
+
+    pub fn const_usize(&self, val: u16) -> ConstInt {
+        match self.sess.target.uint_type {
+            ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16(val as u16)),
+            ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32(val as u32)),
+            ast::UintTy::U64 => ConstInt::Usize(ConstUsize::Us64(val as u64)),
+            _ => bug!(),
+        }
+    }
 }
 
 pub struct TypeIdHasher<'a, 'gcx: 'a+'tcx, 'tcx: 'a, W> {
@@ -666,8 +703,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
                 self.hash(p.name.as_str());
             }
             TyProjection(ref data) => {
-                self.def_id(data.trait_ref.def_id);
-                self.hash(data.item_name.as_str());
+                self.def_id(data.item_def_id);
             }
             TyNever |
             TyBool |
@@ -946,7 +982,7 @@ fn is_copy_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 {
     let (param_env, ty) = query.into_parts();
     let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem);
-    tcx.infer_ctxt(param_env, Reveal::UserFacing)
+    tcx.infer_ctxt(param_env)
        .enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
 }
 
@@ -956,7 +992,7 @@ fn is_sized_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 {
     let (param_env, ty) = query.into_parts();
     let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem);
-    tcx.infer_ctxt(param_env, Reveal::UserFacing)
+    tcx.infer_ctxt(param_env)
        .enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
 }
 
@@ -966,7 +1002,7 @@ fn is_freeze_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 {
     let (param_env, ty) = query.into_parts();
     let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem);
-    tcx.infer_ctxt(param_env, Reveal::UserFacing)
+    tcx.infer_ctxt(param_env)
        .enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
 }