]> git.proxmox.com Git - rustc.git/blobdiff - src/librustc/middle/mem_categorization.rs
New upstream version 1.14.0+dfsg1
[rustc.git] / src / librustc / middle / mem_categorization.rs
index 676e456dcea94e2ecaf96fe984b50d1dec27dd47..e3ed13e1e40173501cab2d79040731b8d07b67e0 100644 (file)
@@ -67,7 +67,6 @@ pub use self::ElementKind::*;
 pub use self::MutabilityCategory::*;
 pub use self::AliasableReason::*;
 pub use self::Note::*;
-pub use self::deref_kind::*;
 
 use self::Aliasability::*;
 
@@ -75,7 +74,7 @@ use hir::def_id::DefId;
 use hir::map as ast_map;
 use infer::InferCtxt;
 use middle::const_qualif::ConstQualif;
-use hir::def::Def;
+use hir::def::{Def, CtorKind};
 use ty::adjustment;
 use ty::{self, Ty, TyCtxt};
 
@@ -90,11 +89,11 @@ use std::rc::Rc;
 
 #[derive(Clone, PartialEq)]
 pub enum Categorization<'tcx> {
-    Rvalue(ty::Region),                    // temporary val, argument is its scope
+    Rvalue(&'tcx ty::Region),                    // temporary val, argument is its scope
     StaticItem,
     Upvar(Upvar),                          // upvar referenced by closure env
     Local(ast::NodeId),                    // local variable
-    Deref(cmt<'tcx>, usize, PointerKind),  // deref of a ptr
+    Deref(cmt<'tcx>, usize, PointerKind<'tcx>),  // deref of a ptr
     Interior(cmt<'tcx>, InteriorKind),     // something interior: field, tuple, etc
     Downcast(cmt<'tcx>, DefId),            // selects a particular enum variant (*1)
 
@@ -110,18 +109,18 @@ pub struct Upvar {
 
 // different kinds of pointers:
 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
-pub enum PointerKind {
+pub enum PointerKind<'tcx> {
     /// `Box<T>`
     Unique,
 
     /// `&T`
-    BorrowedPtr(ty::BorrowKind, ty::Region),
+    BorrowedPtr(ty::BorrowKind, &'tcx ty::Region),
 
     /// `*T`
     UnsafePtr(hir::Mutability),
 
     /// Implicit deref of the `&T` that results from an overloaded index `[]`.
-    Implicit(ty::BorrowKind, ty::Region),
+    Implicit(ty::BorrowKind, &'tcx ty::Region),
 }
 
 // We use the term "interior" to mean "something reachable from the
@@ -195,52 +194,6 @@ pub struct cmt_<'tcx> {
 
 pub type cmt<'tcx> = Rc<cmt_<'tcx>>;
 
-// We pun on *T to mean both actual deref of a ptr as well
-// as accessing of components:
-#[derive(Copy, Clone)]
-pub enum deref_kind {
-    deref_ptr(PointerKind),
-    deref_interior(InteriorKind),
-}
-
-type DerefKindContext = Option<InteriorOffsetKind>;
-
-// Categorizes a derefable type.  Note that we include vectors and strings as
-// derefable (we model an index as the combination of a deref and then a
-// pointer adjustment).
-fn deref_kind(t: Ty, context: DerefKindContext) -> McResult<deref_kind> {
-    match t.sty {
-        ty::TyBox(_) => {
-            Ok(deref_ptr(Unique))
-        }
-
-        ty::TyRef(r, mt) => {
-            let kind = ty::BorrowKind::from_mutbl(mt.mutbl);
-            Ok(deref_ptr(BorrowedPtr(kind, *r)))
-        }
-
-        ty::TyRawPtr(ref mt) => {
-            Ok(deref_ptr(UnsafePtr(mt.mutbl)))
-        }
-
-        ty::TyEnum(..) |
-        ty::TyStruct(..) => { // newtype
-            Ok(deref_interior(InteriorField(PositionalField(0))))
-        }
-
-        ty::TyArray(_, _) | ty::TySlice(_) => {
-            // no deref of indexed content without supplying InteriorOffsetKind
-            if let Some(context) = context {
-                Ok(deref_interior(InteriorElement(context, ElementKind::VecElement)))
-            } else {
-                Err(())
-            }
-        }
-
-        _ => Err(()),
-    }
-}
-
 pub trait ast_node {
     fn id(&self) -> ast::NodeId;
     fn span(&self) -> Span;
@@ -318,7 +271,7 @@ impl MutabilityCategory {
     fn from_local(tcx: TyCtxt, id: ast::NodeId) -> MutabilityCategory {
         let ret = match tcx.map.get(id) {
             ast_map::NodeLocal(p) => match p.node {
-                PatKind::Binding(bind_mode, _, _) => {
+                PatKind::Binding(bind_mode, ..) => {
                     if bind_mode == hir::BindByValue(hir::MutMutable) {
                         McDeclared
                     } else {
@@ -401,11 +354,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
     }
 
     fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
-        let unadjusted_ty = self.expr_ty(expr)?;
-        Ok(unadjusted_ty.adjust(
-            self.tcx(), expr.span, expr.id,
-            self.infcx.adjustments().get(&expr.id),
-            |method_call| self.infcx.node_method_ty(method_call)))
+        self.infcx.expr_ty_adjusted(expr)
     }
 
     fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
@@ -419,7 +368,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         // *being borrowed* is.  But ideally we would put in a more
         // fundamental fix to this conflated use of the node id.
         let ret_ty = match pat.node {
-            PatKind::Binding(hir::BindByRef(_), _, _) => {
+            PatKind::Binding(hir::BindByRef(_), ..) => {
                 // a bind-by-ref means that the base_ty will be the type of the ident itself,
                 // but what we want here is the type of the underlying value being borrowed.
                 // So peel off one-level, turning the &T into T.
@@ -443,19 +392,21 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             }
 
             Some(adjustment) => {
-                match *adjustment {
-                    adjustment::AdjustDerefRef(
-                        adjustment::AutoDerefRef {
-                            autoref: None, unsize: None, autoderefs, ..}) => {
+                match adjustment.kind {
+                    adjustment::Adjust::DerefRef {
+                        autoderefs,
+                        autoref: None,
+                        unsize: false
+                    } => {
                         // Equivalent to *expr or something similar.
                         self.cat_expr_autoderefd(expr, autoderefs)
                     }
 
-                    adjustment::AdjustNeverToAny(..) |
-                    adjustment::AdjustReifyFnPointer |
-                    adjustment::AdjustUnsafeFnPointer |
-                    adjustment::AdjustMutToConstPointer |
-                    adjustment::AdjustDerefRef(_) => {
+                    adjustment::Adjust::NeverToAny |
+                    adjustment::Adjust::ReifyFnPointer |
+                    adjustment::Adjust::UnsafeFnPointer |
+                    adjustment::Adjust::MutToConstPointer |
+                    adjustment::Adjust::DerefRef {..} => {
                         debug!("cat_expr({:?}): {:?}",
                                adjustment,
                                expr);
@@ -477,7 +428,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                autoderefs,
                cmt);
         for deref in 1..autoderefs + 1 {
-            cmt = self.cat_deref(expr, cmt, deref, None)?;
+            cmt = self.cat_deref(expr, cmt, deref)?;
         }
         return Ok(cmt);
     }
@@ -489,7 +440,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         match expr.node {
           hir::ExprUnary(hir::UnDeref, ref e_base) => {
             let base_cmt = self.cat_expr(&e_base)?;
-            self.cat_deref(expr, base_cmt, 0, None)
+            self.cat_deref(expr, base_cmt, 0)
           }
 
           hir::ExprField(ref base, f_name) => {
@@ -508,7 +459,6 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
 
           hir::ExprIndex(ref base, _) => {
             let method_call = ty::MethodCall::expr(expr.id());
-            let context = InteriorOffsetKind::Index;
             match self.infcx.node_method_ty(method_call) {
                 Some(method_ty) => {
                     // If this is an index implemented by a method call, then it
@@ -530,10 +480,10 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                     // is an rvalue. That is what we will be
                     // dereferencing.
                     let base_cmt = self.cat_rvalue_node(expr.id(), expr.span(), ret_ty);
-                    self.cat_deref_common(expr, base_cmt, 1, elem_ty, Some(context), true)
+                    Ok(self.cat_deref_common(expr, base_cmt, 1, elem_ty, true))
                 }
                 None => {
-                    self.cat_index(expr, self.cat_expr(&base)?, context)
+                    self.cat_index(expr, self.cat_expr(&base)?, InteriorOffsetKind::Index)
                 }
             }
           }
@@ -551,7 +501,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
           hir::ExprClosure(..) | hir::ExprRet(..) |
           hir::ExprUnary(..) |
           hir::ExprMethodCall(..) | hir::ExprCast(..) |
-          hir::ExprVec(..) | hir::ExprTup(..) | hir::ExprIf(..) |
+          hir::ExprArray(..) | hir::ExprTup(..) | hir::ExprIf(..) |
           hir::ExprBinary(..) | hir::ExprWhile(..) |
           hir::ExprBlock(..) | hir::ExprLoop(..) | hir::ExprMatch(..) |
           hir::ExprLit(..) | hir::ExprBreak(..) |
@@ -572,20 +522,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                id, expr_ty, def);
 
         match def {
-          Def::Struct(..) | Def::Variant(..) | Def::Const(..) |
+          Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) |
           Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) => {
                 Ok(self.cat_rvalue_node(id, span, expr_ty))
           }
 
-          Def::Mod(_) | Def::ForeignMod(_) |
-          Def::Trait(_) | Def::Enum(..) | Def::TyAlias(..) | Def::PrimTy(_) |
-          Def::TyParam(..) |
-          Def::Label(_) | Def::SelfTy(..) |
-          Def::AssociatedTy(..) => {
-              span_bug!(span, "Unexpected definition in \
-                               memory categorization: {:?}", def);
-          }
-
           Def::Static(_, mutbl) => {
               Ok(Rc::new(cmt_ {
                   id:id,
@@ -597,7 +538,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
               }))
           }
 
-          Def::Upvar(_, var_id, _, fn_node_id) => {
+          Def::Upvar(def_id, _, fn_node_id) => {
+              let var_id = self.tcx().map.as_local_node_id(def_id).unwrap();
               let ty = self.node_ty(fn_node_id)?;
               match ty.sty {
                   ty::TyClosure(closure_id, _) => {
@@ -633,7 +575,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
               }
           }
 
-          Def::Local(_, vid) => {
+          Def::Local(def_id) => {
+            let vid = self.tcx().map.as_local_node_id(def_id).unwrap();
             Ok(Rc::new(cmt_ {
                 id: id,
                 span: span,
@@ -644,7 +587,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             }))
           }
 
-          Def::Err => bug!("Def::Err in memory categorization")
+          def => span_bug!(span, "unexpected definition in memory categorization: {:?}", def)
         }
     }
 
@@ -761,19 +704,19 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             };
 
             match fn_expr.node {
-                hir::ExprClosure(_, _, ref body, _) => body.id,
+                hir::ExprClosure(.., ref body, _) => body.id,
                 _ => bug!()
             }
         };
 
         // Region of environment pointer
-        let env_region = ty::ReFree(ty::FreeRegion {
+        let env_region = self.tcx().mk_region(ty::ReFree(ty::FreeRegion {
             // The environment of a closure is guaranteed to
             // outlive any bindings introduced in the body of the
             // closure itself.
             scope: self.tcx().region_maps.item_extent(fn_body_id),
             bound_region: ty::BrEnv
-        });
+        }));
 
         let env_ptr = BorrowedPtr(env_borrow_kind, env_region);
 
@@ -817,11 +760,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
 
     /// Returns the lifetime of a temporary created by expr with id `id`.
     /// This could be `'static` if `id` is part of a constant expression.
-    pub fn temporary_scope(&self, id: ast::NodeId) -> ty::Region {
-        match self.infcx.temporary_scope(id) {
+    pub fn temporary_scope(&self, id: ast::NodeId) -> &'tcx ty::Region {
+        self.tcx().mk_region(match self.infcx.temporary_scope(id) {
             Some(scope) => ty::ReScope(scope),
             None => ty::ReStatic
-        }
+        })
     }
 
     pub fn cat_rvalue_node(&self,
@@ -845,7 +788,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         let re = if qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
             self.temporary_scope(id)
         } else {
-            ty::ReStatic
+            self.tcx().mk_region(ty::ReStatic)
         };
         let ret = self.cat_rvalue(id, span, re, expr_ty);
         debug!("cat_rvalue_node ret {:?}", ret);
@@ -855,7 +798,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
     pub fn cat_rvalue(&self,
                       cmt_id: ast::NodeId,
                       span: Span,
-                      temp_scope: ty::Region,
+                      temp_scope: &'tcx ty::Region,
                       expr_ty: Ty<'tcx>) -> cmt<'tcx> {
         let ret = Rc::new(cmt_ {
             id:cmt_id,
@@ -908,8 +851,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
     fn cat_deref<N:ast_node>(&self,
                              node: &N,
                              base_cmt: cmt<'tcx>,
-                             deref_cnt: usize,
-                             deref_context: DerefKindContext)
+                             deref_cnt: usize)
                              -> McResult<cmt<'tcx>> {
         let method_call = ty::MethodCall {
             expr_id: node.id(),
@@ -931,12 +873,9 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         let base_cmt_ty = base_cmt.ty;
         match base_cmt_ty.builtin_deref(true, ty::NoPreference) {
             Some(mt) => {
-                let ret = self.cat_deref_common(node, base_cmt, deref_cnt,
-                                              mt.ty,
-                                              deref_context,
-                                                /* implicit: */ false);
+                let ret = self.cat_deref_common(node, base_cmt, deref_cnt, mt.ty, false);
                 debug!("cat_deref ret {:?}", ret);
-                ret
+                Ok(ret)
             }
             None => {
                 debug!("Explicit deref of non-derefable type: {:?}",
@@ -951,40 +890,29 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                                     base_cmt: cmt<'tcx>,
                                     deref_cnt: usize,
                                     deref_ty: Ty<'tcx>,
-                                    deref_context: DerefKindContext,
                                     implicit: bool)
-                                    -> McResult<cmt<'tcx>>
+                                    -> cmt<'tcx>
     {
-        let (m, cat) = match deref_kind(base_cmt.ty, deref_context)? {
-            deref_ptr(ptr) => {
-                let ptr = if implicit {
-                    match ptr {
-                        BorrowedPtr(bk, r) => Implicit(bk, r),
-                        _ => span_bug!(node.span(),
-                            "Implicit deref of non-borrowed pointer")
-                    }
-                } else {
-                    ptr
-                };
-                // for unique ptrs, we inherit mutability from the
-                // owning reference.
-                (MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr),
-                 Categorization::Deref(base_cmt, deref_cnt, ptr))
-            }
-            deref_interior(interior) => {
-                (base_cmt.mutbl.inherit(), Categorization::Interior(base_cmt, interior))
+        let ptr = match base_cmt.ty.sty {
+            ty::TyBox(..) => Unique,
+            ty::TyRawPtr(ref mt) => UnsafePtr(mt.mutbl),
+            ty::TyRef(r, mt) => {
+                let bk = ty::BorrowKind::from_mutbl(mt.mutbl);
+                if implicit { Implicit(bk, r) } else { BorrowedPtr(bk, r) }
             }
+            ref ty => bug!("unexpected type in cat_deref_common: {:?}", ty)
         };
         let ret = Rc::new(cmt_ {
             id: node.id(),
             span: node.span(),
-            cat: cat,
-            mutbl: m,
+            // For unique ptrs, we inherit mutability from the owning reference.
+            mutbl: MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr),
+            cat: Categorization::Deref(base_cmt, deref_cnt, ptr),
             ty: deref_ty,
             note: NoteNone
         });
         debug!("cat_deref_common ret {:?}", ret);
-        Ok(ret)
+        ret
     }
 
     pub fn cat_index<N:ast_node>(&self,
@@ -1138,23 +1066,29 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         // alone) because PatKind::Struct can also refer to variants.
         let cmt = match self.tcx().expect_def_or_none(pat.id) {
             Some(Def::Err) => return Err(()),
-            Some(Def::Variant(enum_did, variant_did))
+            Some(Def::Variant(variant_did)) |
+            Some(Def::VariantCtor(variant_did, ..)) => {
                 // univariant enums do not need downcasts
-                if !self.tcx().lookup_adt_def(enum_did).is_univariant() => {
+                let enum_did = self.tcx().parent_def_id(variant_did).unwrap();
+                if !self.tcx().lookup_adt_def(enum_did).is_univariant() {
                     self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
+                } else {
+                    cmt
                 }
+            }
             _ => cmt
         };
 
         match pat.node {
           PatKind::TupleStruct(_, ref subpats, ddpos) => {
             let expected_len = match self.tcx().expect_def(pat.id) {
-                Def::Variant(enum_def, def_id) => {
+                Def::VariantCtor(def_id, CtorKind::Fn) => {
+                    let enum_def = self.tcx().parent_def_id(def_id).unwrap();
                     self.tcx().lookup_adt_def(enum_def).variant_with_id(def_id).fields.len()
                 }
-                Def::Struct(..) => {
+                Def::StructCtor(_, CtorKind::Fn) => {
                     match self.pat_ty(&pat)?.sty {
-                        ty::TyStruct(adt_def, _) => {
+                        ty::TyAdt(adt_def, _) => {
                             adt_def.struct_variant().fields.len()
                         }
                         ref ty => {
@@ -1185,7 +1119,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             }
           }
 
-          PatKind::Binding(_, _, Some(ref subpat)) => {
+          PatKind::Binding(.., Some(ref subpat)) => {
               self.cat_pattern_(cmt, &subpat, op)?;
           }
 
@@ -1207,11 +1141,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             // box p1, &p1, &mut p1.  we can ignore the mutability of
             // PatKind::Ref since that information is already contained
             // in the type.
-            let subcmt = self.cat_deref(pat, cmt, 0, None)?;
+            let subcmt = self.cat_deref(pat, cmt, 0)?;
             self.cat_pattern_(subcmt, &subpat, op)?;
           }
 
-          PatKind::Vec(ref before, ref slice, ref after) => {
+          PatKind::Slice(ref before, ref slice, ref after) => {
             let context = InteriorOffsetKind::Pattern;
             let elt_cmt = self.cat_index(pat, cmt, context)?;
             for before_pat in before {
@@ -1225,7 +1159,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             }
           }
 
-          PatKind::Path(..) | PatKind::Binding(_, _, None) |
+          PatKind::Path(..) | PatKind::Binding(.., None) |
           PatKind::Lit(..) | PatKind::Range(..) | PatKind::Wild => {
             // always ok
           }
@@ -1275,9 +1209,9 @@ impl<'tcx> cmt_<'tcx> {
             Categorization::Rvalue(..) |
             Categorization::StaticItem |
             Categorization::Local(..) |
-            Categorization::Deref(_, _, UnsafePtr(..)) |
-            Categorization::Deref(_, _, BorrowedPtr(..)) |
-            Categorization::Deref(_, _, Implicit(..)) |
+            Categorization::Deref(.., UnsafePtr(..)) |
+            Categorization::Deref(.., BorrowedPtr(..)) |
+            Categorization::Deref(.., Implicit(..)) |
             Categorization::Upvar(..) => {
                 Rc::new((*self).clone())
             }
@@ -1320,7 +1254,7 @@ impl<'tcx> cmt_<'tcx> {
             Categorization::Rvalue(..) |
             Categorization::Local(..) |
             Categorization::Upvar(..) |
-            Categorization::Deref(_, _, UnsafePtr(..)) => { // yes, it's aliasable, but...
+            Categorization::Deref(.., UnsafePtr(..)) => { // yes, it's aliasable, but...
                 NonAliasable
             }
 
@@ -1349,9 +1283,9 @@ impl<'tcx> cmt_<'tcx> {
         match self.note {
             NoteClosureEnv(..) | NoteUpvarRef(..) => {
                 Some(match self.cat {
-                    Categorization::Deref(ref inner, _, _) => {
+                    Categorization::Deref(ref inner, ..) => {
                         match inner.cat {
-                            Categorization::Deref(ref inner, _, _) => inner.clone(),
+                            Categorization::Deref(ref inner, ..) => inner.clone(),
                             Categorization::Upvar(..) => inner.clone(),
                             _ => bug!()
                         }
@@ -1379,7 +1313,7 @@ impl<'tcx> cmt_<'tcx> {
                     "local variable".to_string()
                 }
             }
-            Categorization::Deref(_, _, pk) => {
+            Categorization::Deref(.., pk) => {
                 let upvar = self.upvar();
                 match upvar.as_ref().map(|i| &i.cat) {
                     Some(&Categorization::Upvar(ref var)) => {
@@ -1480,7 +1414,7 @@ pub fn ptr_sigil(ptr: PointerKind) -> &'static str {
     }
 }
 
-impl fmt::Debug for PointerKind {
+impl<'tcx> fmt::Debug for PointerKind<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             Unique => write!(f, "Box"),