(index<- )        ./librustc/middle/mem_categorization.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
    1  // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
    2  // file at the top-level directory of this distribution and at
    3  // http://rust-lang.org/COPYRIGHT.
    4  //
    5  // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
    6  // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    7  // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
    8  // option. This file may not be copied, modified, or distributed
    9  // except according to those terms.
   10  
   11  /*!
   12   * # Categorization
   13   *
   14   * The job of the categorization module is to analyze an expression to
   15   * determine what kind of memory is used in evaluating it (for example,
   16   * where dereferences occur and what kind of pointer is dereferenced;
   17   * whether the memory is mutable; etc)
   18   *
   19   * Categorization effectively transforms all of our expressions into
   20   * expressions of the following forms (the actual enum has many more
   21   * possibilities, naturally, but they are all variants of these base
   22   * forms):
   23   *
   24   *     E = rvalue    // some computed rvalue
   25   *       | x         // address of a local variable or argument
   26   *       | *E        // deref of a ptr
   27   *       | E.comp    // access to an interior component
   28   *
   29   * Imagine a routine ToAddr(Expr) that evaluates an expression and returns an
   30   * address where the result is to be found.  If Expr is an lvalue, then this
   31   * is the address of the lvalue.  If Expr is an rvalue, this is the address of
   32   * some temporary spot in memory where the result is stored.
   33   *
   34   * Now, cat_expr() classies the expression Expr and the address A=ToAddr(Expr)
   35   * as follows:
   36   *
   37   * - cat: what kind of expression was this?  This is a subset of the
   38   *   full expression forms which only includes those that we care about
   39   *   for the purpose of the analysis.
   40   * - mutbl: mutability of the address A
   41   * - ty: the type of data found at the address A
   42   *
   43   * The resulting categorization tree differs somewhat from the expressions
   44   * themselves.  For example, auto-derefs are explicit.  Also, an index a[b] is
   45   * decomposed into two operations: a derefence to reach the array data and
   46   * then an index to jump forward to the relevant item.
   47   *
   48   * ## By-reference upvars
   49   *
   50   * One part of the translation which may be non-obvious is that we translate
   51   * closure upvars into the dereference of a borrowed pointer; this more closely
   52   * resembles the runtime translation. So, for example, if we had:
   53   *
   54   *     let mut x = 3;
   55   *     let y = 5;
   56   *     let inc = || x += y;
   57   *
   58   * Then when we categorize `x` (*within* the closure) we would yield a
   59   * result of `*x'`, effectively, where `x'` is a `cat_upvar` reference
   60   * tied to `x`. The type of `x'` will be a borrowed pointer.
   61   */
   62  
   63  #![allow(non_camel_case_types)]
   64  
   65  use middle::ty;
   66  use middle::typeck;
   67  use util::nodemap::NodeMap;
   68  use util::ppaux::{ty_to_str, Repr};
   69  
   70  use syntax::ast::{MutImmutable, MutMutable};
   71  use syntax::ast;
   72  use syntax::codemap::Span;
   73  use syntax::print::pprust;
   74  use syntax::parse::token;
   75  
   76  use std::cell::RefCell;
   77  use std::rc::Rc;
   78  
   79  #[deriving(Clone, Eq)]
   80  pub enum categorization {
   81      cat_rvalue(ty::Region),            // temporary val, argument is its scope
   82      cat_static_item,
   83      cat_copied_upvar(CopiedUpvar),     // upvar copied into proc env
   84      cat_upvar(ty::UpvarId, ty::UpvarBorrow), // by ref upvar from stack closure
   85      cat_local(ast::NodeId),            // local variable
   86      cat_arg(ast::NodeId),              // formal argument
   87      cat_deref(cmt, uint, PointerKind), // deref of a ptr
   88      cat_interior(cmt, InteriorKind),   // something interior: field, tuple, etc
   89      cat_downcast(cmt),                 // selects a particular enum variant (*1)
   90      cat_discr(cmt, ast::NodeId),       // match discriminant (see preserve())
   91  
   92      // (*1) downcast is only required if the enum has more than one variant
   93  }
   94  
   95  #[deriving(Clone, Eq)]
   96  pub struct CopiedUpvar {
   97      pub upvar_id: ast::NodeId,
   98      pub onceness: ast::Onceness,
   99  }
  100  
  101  // different kinds of pointers:
  102  #[deriving(Clone, Eq, TotalEq, Hash)]
  103  pub enum PointerKind {
  104      OwnedPtr,
  105      GcPtr,
  106      BorrowedPtr(ty::BorrowKind, ty::Region),
  107      UnsafePtr(ast::Mutability),
  108  }
  109  
  110  // We use the term "interior" to mean "something reachable from the
  111  // base without a pointer dereference", e.g. a field
  112  #[deriving(Clone, Eq, TotalEq, Hash)]
  113  pub enum InteriorKind {
  114      InteriorField(FieldName),
  115      InteriorElement(ElementKind),
  116  }
  117  
  118  #[deriving(Clone, Eq, TotalEq, Hash)]
  119  pub enum FieldName {
  120      NamedField(ast::Name),
  121      PositionalField(uint)
  122  }
  123  
  124  #[deriving(Clone, Eq, TotalEq, Hash)]
  125  pub enum ElementKind {
  126      VecElement,
  127      StrElement,
  128      OtherElement,
  129  }
  130  
  131  #[deriving(Clone, Eq, TotalEq, Hash, Show)]
  132  pub enum MutabilityCategory {
  133      McImmutable, // Immutable.
  134      McDeclared,  // Directly declared as mutable.
  135      McInherited, // Inherited from the fact that owner is mutable.
  136  }
  137  
  138  // `cmt`: "Category, Mutability, and Type".
  139  //
  140  // a complete categorization of a value indicating where it originated
  141  // and how it is located, as well as the mutability of the memory in
  142  // which the value is stored.
  143  //
  144  // *WARNING* The field `cmt.type` is NOT necessarily the same as the
  145  // result of `node_id_to_type(cmt.id)`. This is because the `id` is
  146  // always the `id` of the node producing the type; in an expression
  147  // like `*x`, the type of this deref node is the deref'd type (`T`),
  148  // but in a pattern like `@x`, the `@x` pattern is again a
  149  // dereference, but its type is the type *before* the dereference
  150  // (`@T`). So use `cmt.type` to find the type of the value in a consistent
  151  // fashion. For more details, see the method `cat_pattern`
  152  #[deriving(Clone, Eq)]
  153  pub struct cmt_ {
  154      pub id: ast::NodeId,          // id of expr/pat producing this value
  155      pub span: Span,                // span of same expr/pat
  156      pub cat: categorization,       // categorization of expr
  157      pub mutbl: MutabilityCategory, // mutability of expr as lvalue
  158      pub ty: ty::t                  // type of the expr (*see WARNING above*)
  159  }
  160  
  161  pub type cmt = Rc<cmt_>;
  162  
  163  // We pun on *T to mean both actual deref of a ptr as well
  164  // as accessing of components:
  165  pub enum deref_kind {
  166      deref_ptr(PointerKind),
  167      deref_interior(InteriorKind),
  168  }
  169  
  170  // Categorizes a derefable type.  Note that we include vectors and strings as
  171  // derefable (we model an index as the combination of a deref and then a
  172  // pointer adjustment).
  173  pub fn opt_deref_kind(tty::t) -> Option<deref_kind> {
  174      match ty::get(t).sty {
  175          ty::ty_uniq(_) |
  176          ty::ty_trait(box ty::TyTrait { store: ty::UniqTraitStore, .. }) |
  177          ty::ty_closure(box ty::ClosureTy {store: ty::UniqTraitStore, ..}) => {
  178              Some(deref_ptr(OwnedPtr))
  179          }
  180  
  181          ty::ty_rptr(r, mt) => {
  182              let kind = ty::BorrowKind::from_mutbl(mt.mutbl);
  183              Some(deref_ptr(BorrowedPtr(kind, r)))
  184          }
  185          ty::ty_trait(box ty::TyTrait {
  186                  store: ty::RegionTraitStore(r, mutbl),
  187                  ..
  188              }) => {
  189              let kind = ty::BorrowKind::from_mutbl(mutbl);
  190              Some(deref_ptr(BorrowedPtr(kind, r)))
  191          }
  192  
  193          ty::ty_closure(box ty::ClosureTy {
  194                  store: ty::RegionTraitStore(r, _),
  195                  ..
  196              }) => {
  197              Some(deref_ptr(BorrowedPtr(ty::ImmBorrow, r)))
  198          }
  199  
  200          ty::ty_box(..) => {
  201              Some(deref_ptr(GcPtr))
  202          }
  203  
  204          ty::ty_ptr(ref mt) => {
  205              Some(deref_ptr(UnsafePtr(mt.mutbl)))
  206          }
  207  
  208          ty::ty_enum(..) |
  209          ty::ty_struct(..) => { // newtype
  210              Some(deref_interior(InteriorField(PositionalField(0))))
  211          }
  212  
  213          ty::ty_vec(_, Some(_)) => {
  214              Some(deref_interior(InteriorElement(element_kind(t))))
  215          }
  216  
  217          _ => None
  218      }
  219  }
  220  
  221  pub fn deref_kind(tcx: &ty::ctxt, tty::t) -> deref_kind {
  222      match opt_deref_kind(t) {
  223        Some(k) => k,
  224        None => {
  225          tcx.sess.bug(
  226              format!("deref_cat() invoked on non-derefable type {}",
  227                   ty_to_str(tcx, t)));
  228        }
  229      }
  230  }
  231  
  232  trait ast_node {
  233      fn id(&self) -> ast::NodeId;
  234      fn span(&self) -> Span;
  235  }
  236  
  237  impl ast_node for ast::Expr {
  238      fn id(&self) -> ast::NodeId { self.id }
  239      fn span(&self) -> Span { self.span }
  240  }
  241  
  242  impl ast_node for ast::Pat {
  243      fn id(&self) -> ast::NodeId { self.id }
  244      fn span(&self) -> Span { self.span }
  245  }
  246  
  247  pub struct MemCategorizationContext<'t,TYPER> {
  248      typer: &'t TYPER
  249  }
  250  
  251  pub type McResult<T> = Result<T, ()>;
  252  
  253  /**
  254   * The `Typer` trait provides the interface for the mem-categorization
  255   * module to the results of the type check. It can be used to query
  256   * the type assigned to an expression node, to inquire after adjustments,
  257   * and so on.
  258   *
  259   * This interface is needed because mem-categorization is used from
  260   * two places: `regionck` and `borrowck`. `regionck` executes before
  261   * type inference is complete, and hence derives types and so on from
  262   * intermediate tables.  This also implies that type errors can occur,
  263   * and hence `node_ty()` and friends return a `Result` type -- any
  264   * error will propagate back up through the mem-categorization
  265   * routines.
  266   *
  267   * In the borrow checker, in contrast, type checking is complete and we
  268   * know that no errors have occurred, so we simply consult the tcx and we
  269   * can be sure that only `Ok` results will occur.
  270   */
  271  pub trait Typer {
  272      fn tcx<'a>(&'a self) -> &'a ty::ctxt;
  273      fn node_ty(&self, id: ast::NodeId) -> McResult<ty::t>;
  274      fn node_method_ty(&self, method_call: typeck::MethodCall) -> Option<ty::t>;
  275      fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>>;
  276      fn is_method_call(&self, id: ast::NodeId) -> bool;
  277      fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId>;
  278      fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow;
  279  }
  280  
  281  impl MutabilityCategory {
  282      pub fn from_mutbl(mast::Mutability) -> MutabilityCategory {
  283          match m {
  284              MutImmutable => McImmutable,
  285              MutMutable => McDeclared
  286          }
  287      }
  288  
  289      pub fn from_borrow_kind(borrow_kindty::BorrowKind) -> MutabilityCategory {
  290          match borrow_kind {
  291              ty::ImmBorrow => McImmutable,
  292              ty::UniqueImmBorrow => McImmutable,
  293              ty::MutBorrow => McDeclared,
  294          }
  295      }
  296  
  297      pub fn from_pointer_kind(base_mutblMutabilityCategory,
  298                               ptrPointerKind) -> MutabilityCategory {
  299          match ptr {
  300              OwnedPtr => {
  301                  base_mutbl.inherit()
  302              }
  303              BorrowedPtr(borrow_kind, _) => {
  304                  MutabilityCategory::from_borrow_kind(borrow_kind)
  305              }
  306              GcPtr => {
  307                  McImmutable
  308              }
  309              UnsafePtr(m) => {
  310                  MutabilityCategory::from_mutbl(m)
  311              }
  312          }
  313      }
  314  
  315      pub fn inherit(&self) -> MutabilityCategory {
  316          match *self {
  317              McImmutable => McImmutable,
  318              McDeclared => McInherited,
  319              McInherited => McInherited,
  320          }
  321      }
  322  
  323      pub fn is_mutable(&self) -> bool {
  324          match *self {
  325              McImmutable => false,
  326              McInherited => true,
  327              McDeclared => true,
  328          }
  329      }
  330  
  331      pub fn is_immutable(&self) -> bool {
  332          match *self {
  333              McImmutable => true,
  334              McDeclared | McInherited => false
  335          }
  336      }
  337  
  338      pub fn to_user_str(&self) -> &'static str {
  339          match *self {
  340              McDeclared | McInherited => "mutable",
  341              McImmutable => "immutable",
  342          }
  343      }
  344  }
  345  
  346  macro_rules! if_ok(
  347      ($inp: expr) => (
  348          match $inp {
  349              Ok(v) => { v }
  350              Err(e) => { return Err(e); }
  351          }
  352      )
  353  )
  354  
  355  impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
  356      pub fn new(typer&'t TYPER) -> MemCategorizationContext<'t,TYPER> {
  357          MemCategorizationContext { typer: typer }
  358      }
  359  
  360      fn tcx(&self) -> &'t ty::ctxt {
  361          self.typer.tcx()
  362      }
  363  
  364      fn expr_ty(&self, expr&ast::Expr) -> McResult<ty::t> {
  365          self.typer.node_ty(expr.id)
  366      }
  367  
  368      fn expr_ty_adjusted(&self, expr&ast::Expr) -> McResult<ty::t> {
  369          let unadjusted_ty = if_ok!(self.expr_ty(expr));
  370          Ok(ty::adjust_ty(self.tcx(), expr.span, expr.id, unadjusted_ty,
  371                           self.typer.adjustments().borrow().find(&expr.id),
  372                           |method_call| self.typer.node_method_ty(method_call)))
  373      }
  374  
  375      fn node_ty(&self, idast::NodeId) -> McResult<ty::t> {
  376          self.typer.node_ty(id)
  377      }
  378  
  379      fn pat_ty(&self, pat&ast::Pat) -> McResult<ty::t> {
  380          self.typer.node_ty(pat.id)
  381      }
  382  
  383      pub fn cat_expr(&self, expr&ast::Expr) -> McResult<cmt> {
  384          match self.typer.adjustments().borrow().find(&expr.id) {
  385              None => {
  386                  // No adjustments.
  387                  self.cat_expr_unadjusted(expr)
  388              }
  389  
  390              Some(adjustment) => {
  391                  match *adjustment {
  392                      ty::AutoObject(..) => {
  393                          // Implicity casts a concrete object to trait object
  394                          // so just patch up the type
  395                          let expr_ty = if_ok!(self.expr_ty_adjusted(expr));
  396                          let mut expr_cmt = (*if_ok!(self.cat_expr_unadjusted(expr))).clone();
  397                          expr_cmt.ty = expr_ty;
  398                          Ok(Rc::new(expr_cmt))
  399                      }
  400  
  401                      ty::AutoAddEnv(..) => {
  402                          // Convert a bare fn to a closure by adding NULL env.
  403                          // Result is an rvalue.
  404                          let expr_ty = if_ok!(self.expr_ty_adjusted(expr));
  405                          Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
  406                      }
  407  
  408                      ty::AutoDerefRef(
  409                          ty::AutoDerefRef {
  410                              autoref: Some(_), ..}) => {
  411                          // Equivalent to &*expr or something similar.
  412                          // Result is an rvalue.
  413                          let expr_ty = if_ok!(self.expr_ty_adjusted(expr));
  414                          Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
  415                      }
  416  
  417                      ty::AutoDerefRef(
  418                          ty::AutoDerefRef {
  419                              autoref: None, autoderefs: autoderefs}) => {
  420                          // Equivalent to *expr or something similar.
  421                          self.cat_expr_autoderefd(expr, autoderefs)
  422                      }
  423                  }
  424              }
  425          }
  426      }
  427  
  428      pub fn cat_expr_autoderefd(&self,
  429                                 expr&ast::Expr,
  430                                 autoderefsuint)
  431                                 -> McResult<cmt> {
  432          let mut cmt = if_ok!(self.cat_expr_unadjusted(expr));
  433          for deref in range(1u, autoderefs + 1) {
  434              cmt = self.cat_deref(expr, cmt, deref);
  435          }
  436          return Ok(cmt);
  437      }
  438  
  439      pub fn cat_expr_unadjusted(&self, expr&ast::Expr) -> McResult<cmt> {
  440          debug!("cat_expr: id={} expr={}", expr.id, expr.repr(self.tcx()));
  441  
  442          let expr_ty = if_ok!(self.expr_ty(expr));
  443          match expr.node {
  444            ast::ExprUnary(ast::UnDeref, e_base) => {
  445              let base_cmt = if_ok!(self.cat_expr(e_base));
  446              Ok(self.cat_deref(expr, base_cmt, 0))
  447            }
  448  
  449            ast::ExprField(base, f_name, _) => {
  450              let base_cmt = if_ok!(self.cat_expr(base));
  451              Ok(self.cat_field(expr, base_cmt, f_name, expr_ty))
  452            }
  453  
  454            ast::ExprIndex(base, _) => {
  455              if self.typer.is_method_call(expr.id) {
  456                  return Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty));
  457              }
  458  
  459              let base_cmt = if_ok!(self.cat_expr(base));
  460              Ok(self.cat_index(expr, base_cmt, 0))
  461            }
  462  
  463            ast::ExprPath(_) => {
  464              let def = self.tcx().def_map.borrow().get_copy(&expr.id);
  465              self.cat_def(expr.id, expr.span, expr_ty, def)
  466            }
  467  
  468            ast::ExprParen(e) => {
  469              self.cat_expr(e)
  470            }
  471  
  472            ast::ExprAddrOf(..) | ast::ExprCall(..) |
  473            ast::ExprAssign(..) | ast::ExprAssignOp(..) |
  474            ast::ExprFnBlock(..) | ast::ExprProc(..) | ast::ExprRet(..) |
  475            ast::ExprUnary(..) |
  476            ast::ExprMethodCall(..) | ast::ExprCast(..) | ast::ExprVstore(..) |
  477            ast::ExprVec(..) | ast::ExprTup(..) | ast::ExprIf(..) |
  478            ast::ExprBinary(..) | ast::ExprWhile(..) |
  479            ast::ExprBlock(..) | ast::ExprLoop(..) | ast::ExprMatch(..) |
  480            ast::ExprLit(..) | ast::ExprBreak(..) | ast::ExprMac(..) |
  481            ast::ExprAgain(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) |
  482            ast::ExprInlineAsm(..) | ast::ExprBox(..) => {
  483              Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
  484            }
  485  
  486            ast::ExprForLoop(..) => fail!("non-desugared expr_for_loop")
  487          }
  488      }
  489  
  490      pub fn cat_def(&self,
  491                     idast::NodeId,
  492                     spanSpan,
  493                     expr_tyty::t,
  494                     defast::Def)
  495                     -> McResult<cmt> {
  496          debug!("cat_def: id={} expr={} def={:?}",
  497                 id, expr_ty.repr(self.tcx()), def);
  498  
  499          match def {
  500            ast::DefStruct(..) | ast::DefVariant(..) => {
  501                  Ok(self.cat_rvalue_node(id, span, expr_ty))
  502            }
  503            ast::DefFn(..) | ast::DefStaticMethod(..) | ast::DefMod(_) |
  504            ast::DefForeignMod(_) | ast::DefStatic(_, false) |
  505            ast::DefUse(_) | ast::DefTrait(_) | ast::DefTy(_) | ast::DefPrimTy(_) |
  506            ast::DefTyParam(..) | ast::DefTyParamBinder(..) | ast::DefRegion(_) |
  507            ast::DefLabel(_) | ast::DefSelfTy(..) | ast::DefMethod(..) => {
  508                Ok(Rc::new(cmt_ {
  509                    id:id,
  510                    span:span,
  511                    cat:cat_static_item,
  512                    mutbl: McImmutable,
  513                    ty:expr_ty
  514                }))
  515            }
  516  
  517            ast::DefStatic(_, true) => {
  518                Ok(Rc::new(cmt_ {
  519                    id:id,
  520                    span:span,
  521                    cat:cat_static_item,
  522                    mutbl: McDeclared,
  523                    ty:expr_ty
  524                }))
  525            }
  526  
  527            ast::DefArg(vid, binding_mode) => {
  528              // Idea: make this could be rewritten to model by-ref
  529              // stuff as `&const` and `&mut`?
  530  
  531              // m: mutability of the argument
  532              let m = match binding_mode {
  533                  ast::BindByValue(ast::MutMutable) => McDeclared,
  534                  _ => McImmutable
  535              };
  536              Ok(Rc::new(cmt_ {
  537                  id: id,
  538                  span: span,
  539                  cat: cat_arg(vid),
  540                  mutbl: m,
  541                  ty:expr_ty
  542              }))
  543            }
  544  
  545            ast::DefUpvar(var_id, _, fn_node_id, _) => {
  546                let ty = if_ok!(self.node_ty(fn_node_id));
  547                match ty::get(ty).sty {
  548                    ty::ty_closure(ref closure_ty) => {
  549                        // Decide whether to use implicit reference or by copy/move
  550                        // capture for the upvar. This, combined with the onceness,
  551                        // determines whether the closure can move out of it.
  552                        let var_is_refd = match (closure_ty.store, closure_ty.onceness) {
  553                            // Many-shot stack closures can never move out.
  554                            (ty::RegionTraitStore(..), ast::Many) => true,
  555                            // 1-shot stack closures can move out.
  556                            (ty::RegionTraitStore(..), ast::Once) => false,
  557                            // Heap closures always capture by copy/move, and can
  558                            // move out if they are once.
  559                            (ty::UniqTraitStore, _) => false,
  560  
  561                        };
  562                        if var_is_refd {
  563                            self.cat_upvar(id, span, var_id, fn_node_id)
  564                        } else {
  565                            // FIXME #2152 allow mutation of moved upvars
  566                            Ok(Rc::new(cmt_ {
  567                                id:id,
  568                                span:span,
  569                                cat:cat_copied_upvar(CopiedUpvar {
  570                                    upvar_id: var_id,
  571                                    onceness: closure_ty.onceness}),
  572                                mutbl:McImmutable,
  573                                ty:expr_ty
  574                            }))
  575                        }
  576                    }
  577                    _ => {
  578                        self.tcx().sess.span_bug(
  579                            span,
  580                            format!("Upvar of non-closure {} - {}",
  581                                    fn_node_id, ty.repr(self.tcx())));
  582                    }
  583                }
  584            }
  585  
  586            ast::DefLocal(vid, binding_mode) |
  587            ast::DefBinding(vid, binding_mode) => {
  588              // by-value/by-ref bindings are local variables
  589              let m = match binding_mode {
  590                  ast::BindByValue(ast::MutMutable) => McDeclared,
  591                  _ => McImmutable
  592              };
  593  
  594              Ok(Rc::new(cmt_ {
  595                  id: id,
  596                  span: span,
  597                  cat: cat_local(vid),
  598                  mutbl: m,
  599                  ty: expr_ty
  600              }))
  601            }
  602          }
  603      }
  604  
  605      fn cat_upvar(&self,
  606                   idast::NodeId,
  607                   spanSpan,
  608                   var_idast::NodeId,
  609                   fn_node_idast::NodeId)
  610                   -> McResult<cmt> {
  611          /*!
  612           * Upvars through a closure are in fact indirect
  613           * references. That is, when a closure refers to a
  614           * variable from a parent stack frame like `x = 10`,
  615           * that is equivalent to `*x_ = 10` where `x_` is a
  616           * borrowed pointer (`&mut x`) created when the closure
  617           * was created and store in the environment. This
  618           * equivalence is expose in the mem-categorization.
  619           */
  620  
  621          let upvar_id = ty::UpvarId { var_id: var_id,
  622                                       closure_expr_id: fn_node_id };
  623  
  624          let upvar_borrow = self.typer.upvar_borrow(upvar_id);
  625  
  626          let var_ty = if_ok!(self.node_ty(var_id));
  627  
  628          // We can't actually represent the types of all upvars
  629          // as user-describable types, since upvars support const
  630          // and unique-imm borrows! Therefore, we cheat, and just
  631          // give err type. Nobody should be inspecting this type anyhow.
  632          let upvar_ty = ty::mk_err();
  633  
  634          let base_cmt = Rc::new(cmt_ {
  635              id:id,
  636              span:span,
  637              cat:cat_upvar(upvar_id, upvar_borrow),
  638              mutbl:McImmutable,
  639              ty:upvar_ty,
  640          });
  641  
  642          let ptr = BorrowedPtr(upvar_borrow.kind, upvar_borrow.region);
  643  
  644          let deref_cmt = Rc::new(cmt_ {
  645              id:id,
  646              span:span,
  647              cat:cat_deref(base_cmt, 0, ptr),
  648              mutbl:MutabilityCategory::from_borrow_kind(upvar_borrow.kind),
  649              ty:var_ty,
  650          });
  651  
  652          Ok(deref_cmt)
  653      }
  654  
  655      pub fn cat_rvalue_node(&self,
  656                             idast::NodeId,
  657                             spanSpan,
  658                             expr_tyty::t)
  659                             -> cmt {
  660          match self.typer.temporary_scope(id) {
  661              Some(scope) => {
  662                  self.cat_rvalue(id, span, ty::ReScope(scope), expr_ty)
  663              }
  664              None => {
  665                  self.cat_rvalue(id, span, ty::ReStatic, expr_ty)
  666              }
  667          }
  668      }
  669  
  670      pub fn cat_rvalue(&self,
  671                        cmt_idast::NodeId,
  672                        spanSpan,
  673                        temp_scopety::Region,
  674                        expr_tyty::t) -> cmt {
  675          Rc::new(cmt_ {
  676              id:cmt_id,
  677              span:span,
  678              cat:cat_rvalue(temp_scope),
  679              mutbl:McDeclared,
  680              ty:expr_ty
  681          })
  682      }
  683  
  684      pub fn cat_field<N:ast_node>(&self,
  685                                   node&N,
  686                                   base_cmtcmt,
  687                                   f_nameast::Ident,
  688                                   f_tyty::t)
  689                                   -> cmt {
  690          Rc::new(cmt_ {
  691              id: node.id(),
  692              span: node.span(),
  693              mutbl: base_cmt.mutbl.inherit(),
  694              cat: cat_interior(base_cmt, InteriorField(NamedField(f_name.name))),
  695              ty: f_ty
  696          })
  697      }
  698  
  699      pub fn cat_deref_obj<N:ast_node>(&self, node&N, base_cmtcmt) -> cmt {
  700          self.cat_deref_common(node, base_cmt, 0, ty::mk_nil())
  701      }
  702  
  703      fn cat_deref<N:ast_node>(&self,
  704                               node&N,
  705                               base_cmtcmt,
  706                               deref_cntuint)
  707                               -> cmt {
  708          let method_call = typeck::MethodCall {
  709              expr_id: node.id(),
  710              autoderef: deref_cnt as u32
  711          };
  712          let method_ty = self.typer.node_method_ty(method_call);
  713  
  714          debug!("cat_deref: method_call={:?} method_ty={}",
  715              method_call, method_ty.map(|ty| ty.repr(self.tcx())));
  716  
  717          let base_cmt = match method_ty {
  718              Some(method_ty) => {
  719                  let ref_ty = ty::ty_fn_ret(method_ty);
  720                  self.cat_rvalue_node(node.id(), node.span(), ref_ty)
  721              }
  722              None => base_cmt
  723          };
  724          match ty::deref(base_cmt.ty, true) {
  725              Some(mt) => self.cat_deref_common(node, base_cmt, deref_cnt, mt.ty),
  726              None => {
  727                  self.tcx().sess.span_bug(
  728                      node.span(),
  729                      format!("Explicit deref of non-derefable type{}",
  730                              base_cmt.ty.repr(self.tcx())));
  731              }
  732          }
  733      }
  734  
  735      fn cat_deref_common<N:ast_node>(&self,
  736                                      node&N,
  737                                      base_cmtcmt,
  738                                      deref_cntuint,
  739                                      deref_tyty::t)
  740                                      -> cmt {
  741          let (m, cat) = match deref_kind(self.tcx(), base_cmt.ty) {
  742              deref_ptr(ptr) => {
  743                  // for unique ptrs, we inherit mutability from the
  744                  // owning reference.
  745                  (MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr),
  746                   cat_deref(base_cmt, deref_cnt, ptr))
  747              }
  748              deref_interior(interior) => {
  749                  (base_cmt.mutbl.inherit(), cat_interior(base_cmt, interior))
  750              }
  751          };
  752          Rc::new(cmt_ {
  753              id: node.id(),
  754              span: node.span(),
  755              cat: cat,
  756              mutbl: m,
  757              ty: deref_ty
  758          })
  759      }
  760  
  761      pub fn cat_index<N:ast_node>(&self,
  762                                   elt&N,
  763                                   base_cmtcmt,
  764                                   derefsuint)
  765                                   -> cmt {
  766          //! Creates a cmt for an indexing operation (`[]`); this
  767          //! indexing operation may occurs as part of an
  768          //! AutoBorrowVec, which when converting a `~[]` to an `&[]`
  769          //! effectively takes the address of the 0th element.
  770          //!
  771          //! One subtle aspect of indexing that may not be
  772          //! immediately obvious: for anything other than a fixed-length
  773          //! vector, an operation like `x[y]` actually consists of two
  774          //! disjoint (from the point of view of borrowck) operations.
  775          //! The first is a deref of `x` to create a pointer `p` that points
  776          //! at the first element in the array. The second operation is
  777          //! an index which adds `y*sizeof(T)` to `p` to obtain the
  778          //! pointer to `x[y]`. `cat_index` will produce a resulting
  779          //! cmt containing both this deref and the indexing,
  780          //! presuming that `base_cmt` is not of fixed-length type.
  781          //!
  782          //! In the event that a deref is needed, the "deref count"
  783          //! is taken from the parameter `derefs`. See the comment
  784          //! on the def'n of `root_map_key` in borrowck/mod.rs
  785          //! for more details about deref counts; the summary is
  786          //! that `derefs` should be 0 for an explicit indexing
  787          //! operation and N+1 for an indexing that is part of
  788          //! an auto-adjustment, where N is the number of autoderefs
  789          //! in that adjustment.
  790          //!
  791          //! # Parameters
  792          //! - `elt`: the AST node being indexed
  793          //! - `base_cmt`: the cmt of `elt`
  794          //! - `derefs`: the deref number to be used for
  795          //!   the implicit index deref, if any (see above)
  796  
  797          let element_ty = match ty::index(base_cmt.ty) {
  798            Some(ref mt) => mt.ty,
  799            None => {
  800              self.tcx().sess.span_bug(
  801                  elt.span(),
  802                  format!("Explicit index of non-index type `{}`",
  803                       base_cmt.ty.repr(self.tcx())));
  804            }
  805          };
  806  
  807          return match deref_kind(self.tcx(), base_cmt.ty) {
  808            deref_ptr(ptr) => {
  809              // for unique ptrs, we inherit mutability from the
  810              // owning reference.
  811              let m = MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr);
  812  
  813              // the deref is explicit in the resulting cmt
  814              let deref_cmt = Rc::new(cmt_ {
  815                  id:elt.id(),
  816                  span:elt.span(),
  817                  cat:cat_deref(base_cmt.clone(), derefs, ptr),
  818                  mutbl:m,
  819                  ty:element_ty
  820              });
  821  
  822              interior(elt, deref_cmt, base_cmt.ty, m.inherit(), element_ty)
  823            }
  824  
  825            deref_interior(_) => {
  826              // fixed-length vectors have no deref
  827              let m = base_cmt.mutbl.inherit();
  828              interior(elt, base_cmt.clone(), base_cmt.ty, m, element_ty)
  829            }
  830          };
  831  
  832          fn interior<N: ast_node>(elt&N,
  833                                   of_cmtcmt,
  834                                   vec_tyty::t,
  835                                   mutblMutabilityCategory,
  836                                   element_tyty::t) -> cmt
  837          {
  838              Rc::new(cmt_ {
  839                  id:elt.id(),
  840                  span:elt.span(),
  841                  cat:cat_interior(of_cmt, InteriorElement(element_kind(vec_ty))),
  842                  mutbl:mutbl,
  843                  ty:element_ty
  844              })
  845          }
  846      }
  847  
  848      pub fn cat_slice_pattern(&self,
  849                               vec_cmtcmt,
  850                               slice_pat&ast::Pat)
  851                               -> McResult<(cmt, ast::Mutability, ty::Region)> {
  852          /*!
  853           * Given a pattern P like: `[_, ..Q, _]`, where `vec_cmt` is
  854           * the cmt for `P`, `slice_pat` is the pattern `Q`, returns:
  855           * - a cmt for `Q`
  856           * - the mutability and region of the slice `Q`
  857           *
  858           * These last two bits of info happen to be things that
  859           * borrowck needs.
  860           */
  861  
  862          let slice_ty = if_ok!(self.node_ty(slice_pat.id));
  863          let (slice_mutbl, slice_r) = vec_slice_info(self.tcx(),
  864                                                      slice_pat,
  865                                                      slice_ty);
  866          let cmt_slice = self.cat_index(slice_pat, vec_cmt, 0);
  867          return Ok((cmt_slice, slice_mutbl, slice_r));
  868  
  869          fn vec_slice_info(tcx&ty::ctxt,
  870                            pat&ast::Pat,
  871                            slice_tyty::t)
  872                            -> (ast::Mutability, ty::Region) {
  873              /*!
  874               * In a pattern like [a, b, ..c], normally `c` has slice type,
  875               * but if you have [a, b, ..ref c], then the type of `ref c`
  876               * will be `&&[]`, so to extract the slice details we have
  877               * to recurse through rptrs.
  878               */
  879  
  880              match ty::get(slice_ty).sty {
  881                  ty::ty_rptr(r, ref mt) => match ty::get(mt.ty).sty {
  882                      ty::ty_vec(slice_mt, None) => (slice_mt.mutbl, r),
  883                      _ => vec_slice_info(tcx, pat, mt.ty),
  884                  },
  885  
  886                  _ => {
  887                      tcx.sess.span_bug(
  888                          pat.span,
  889                          format!("Type of slice pattern is not a slice"));
  890                  }
  891              }
  892          }
  893      }
  894  
  895      pub fn cat_imm_interior<N:ast_node>(&self,
  896                                          node&N,
  897                                          base_cmtcmt,
  898                                          interior_tyty::t,
  899                                          interiorInteriorKind)
  900                                          -> cmt {
  901          Rc::new(cmt_ {
  902              id: node.id(),
  903              span: node.span(),
  904              mutbl: base_cmt.mutbl.inherit(),
  905              cat: cat_interior(base_cmt, interior),
  906              ty: interior_ty
  907          })
  908      }
  909  
  910      pub fn cat_downcast<N:ast_node>(&self,
  911                                      node&N,
  912                                      base_cmtcmt,
  913                                      downcast_tyty::t)
  914                                      -> cmt {
  915          Rc::new(cmt_ {
  916              id: node.id(),
  917              span: node.span(),
  918              mutbl: base_cmt.mutbl.inherit(),
  919              cat: cat_downcast(base_cmt),
  920              ty: downcast_ty
  921          })
  922      }
  923  
  924      pub fn cat_pattern(&self,
  925                         cmtcmt,
  926                         pat&ast::Pat,
  927                         op|&MemCategorizationContext<TYPER>,
  928                              cmt,
  929                              &ast::Pat|)
  930                         -> McResult<()> {
  931          // Here, `cmt` is the categorization for the value being
  932          // matched and pat is the pattern it is being matched against.
  933          //
  934          // In general, the way that this works is that we walk down
  935          // the pattern, constructing a cmt that represents the path
  936          // that will be taken to reach the value being matched.
  937          //
  938          // When we encounter named bindings, we take the cmt that has
  939          // been built up and pass it off to guarantee_valid() so that
  940          // we can be sure that the binding will remain valid for the
  941          // duration of the arm.
  942          //
  943          // (*2) There is subtlety concerning the correspondence between
  944          // pattern ids and types as compared to *expression* ids and
  945          // types. This is explained briefly. on the definition of the
  946          // type `cmt`, so go off and read what it says there, then
  947          // come back and I'll dive into a bit more detail here. :) OK,
  948          // back?
  949          //
  950          // In general, the id of the cmt should be the node that
  951          // "produces" the value---patterns aren't executable code
  952          // exactly, but I consider them to "execute" when they match a
  953          // value, and I consider them to produce the value that was
  954          // matched. So if you have something like:
  955          //
  956          //     let x = @@3;
  957          //     match x {
  958          //       @@y { ... }
  959          //     }
  960          //
  961          // In this case, the cmt and the relevant ids would be:
  962          //
  963          //     CMT             Id                  Type of Id Type of cmt
  964          //
  965          //     local(x)->@->@
  966          //     ^~~~~~~^        `x` from discr      @@int      @@int
  967          //     ^~~~~~~~~~^     `@@y` pattern node  @@int      @int
  968          //     ^~~~~~~~~~~~~^  `@y` pattern node   @int       int
  969          //
  970          // You can see that the types of the id and the cmt are in
  971          // sync in the first line, because that id is actually the id
  972          // of an expression. But once we get to pattern ids, the types
  973          // step out of sync again. So you'll see below that we always
  974          // get the type of the *subpattern* and use that.
  975  
  976          debug!("cat_pattern: id={} pat={} cmt={}",
  977                 pat.id, pprust::pat_to_str(pat),
  978                 cmt.repr(self.tcx()));
  979  
  980          op(self, cmt.clone(), pat);
  981  
  982          match pat.node {
  983            ast::PatWild | ast::PatWildMulti => {
  984              // _
  985            }
  986  
  987            ast::PatEnum(_, None) => {
  988              // variant(..)
  989            }
  990            ast::PatEnum(_, Some(ref subpats)) => {
  991              match self.tcx().def_map.borrow().find(&pat.id) {
  992                  Some(&ast::DefVariant(enum_did, _, _)) => {
  993                      // variant(x, y, z)
  994  
  995                      let downcast_cmt = {
  996                          if ty::enum_is_univariant(self.tcx(), enum_did) {
  997                              cmt // univariant, no downcast needed
  998                          } else {
  999                              self.cat_downcast(pat, cmt.clone(), cmt.ty)
 1000                          }
 1001                      };
 1002  
 1003                      for (i, &subpat) in subpats.iter().enumerate() {
 1004                          let subpat_ty = if_ok!(self.pat_ty(subpat)); // see (*2)
 1005  
 1006                          let subcmt =
 1007                              self.cat_imm_interior(
 1008                                  pat, downcast_cmt.clone(), subpat_ty,
 1009                                  InteriorField(PositionalField(i)));
 1010  
 1011                          if_ok!(self.cat_pattern(subcmt, subpat, |x,y,z| op(x,y,z)));
 1012                      }
 1013                  }
 1014                  Some(&ast::DefFn(..)) |
 1015                  Some(&ast::DefStruct(..)) => {
 1016                      for (i, &subpat) in subpats.iter().enumerate() {
 1017                          let subpat_ty = if_ok!(self.pat_ty(subpat)); // see (*2)
 1018                          let cmt_field =
 1019                              self.cat_imm_interior(
 1020                                  pat, cmt.clone(), subpat_ty,
 1021                                  InteriorField(PositionalField(i)));
 1022                          if_ok!(self.cat_pattern(cmt_field, subpat, |x,y,z| op(x,y,z)));
 1023                      }
 1024                  }
 1025                  Some(&ast::DefStatic(..)) => {
 1026                      for &subpat in subpats.iter() {
 1027                          if_ok!(self.cat_pattern(cmt.clone(), subpat, |x,y,z| op(x,y,z)));
 1028                      }
 1029                  }
 1030                  _ => {
 1031                      self.tcx().sess.span_bug(
 1032                          pat.span,
 1033                          "enum pattern didn't resolve to enum or struct");
 1034                  }
 1035              }
 1036            }
 1037  
 1038            ast::PatIdent(_, _, Some(subpat)) => {
 1039                if_ok!(self.cat_pattern(cmt, subpat, op));
 1040            }
 1041  
 1042            ast::PatIdent(_, _, None) => {
 1043                // nullary variant or identifier: ignore
 1044            }
 1045  
 1046            ast::PatStruct(_, ref field_pats, _) => {
 1047              // {f1: p1, ..., fN: pN}
 1048              for fp in field_pats.iter() {
 1049                  let field_ty = if_ok!(self.pat_ty(fp.pat)); // see (*2)
 1050                  let cmt_field = self.cat_field(pat, cmt.clone(), fp.ident, field_ty);
 1051                  if_ok!(self.cat_pattern(cmt_field, fp.pat, |x,y,z| op(x,y,z)));
 1052              }
 1053            }
 1054  
 1055            ast::PatTup(ref subpats) => {
 1056              // (p1, ..., pN)
 1057              for (i, &subpat) in subpats.iter().enumerate() {
 1058                  let subpat_ty = if_ok!(self.pat_ty(subpat)); // see (*2)
 1059                  let subcmt =
 1060                      self.cat_imm_interior(
 1061                          pat, cmt.clone(), subpat_ty,
 1062                          InteriorField(PositionalField(i)));
 1063                  if_ok!(self.cat_pattern(subcmt, subpat, |x,y,z| op(x,y,z)));
 1064              }
 1065            }
 1066  
 1067            ast::PatUniq(subpat) | ast::PatRegion(subpat) => {
 1068              // @p1, ~p1
 1069              let subcmt = self.cat_deref(pat, cmt, 0);
 1070              if_ok!(self.cat_pattern(subcmt, subpat, op));
 1071            }
 1072  
 1073            ast::PatVec(ref before, slice, ref after) => {
 1074                let elt_cmt = self.cat_index(pat, cmt, 0);
 1075                for &before_pat in before.iter() {
 1076                    if_ok!(self.cat_pattern(elt_cmt.clone(), before_pat, |x,y,z| op(x,y,z)));
 1077                }
 1078                for &slice_pat in slice.iter() {
 1079                    let slice_ty = if_ok!(self.pat_ty(slice_pat));
 1080                    let slice_cmt = self.cat_rvalue_node(pat.id(), pat.span(), slice_ty);
 1081                    if_ok!(self.cat_pattern(slice_cmt, slice_pat, |x,y,z| op(x,y,z)));
 1082                }
 1083                for &after_pat in after.iter() {
 1084                    if_ok!(self.cat_pattern(elt_cmt.clone(), after_pat, |x,y,z| op(x,y,z)));
 1085                }
 1086            }
 1087  
 1088            ast::PatLit(_) | ast::PatRange(_, _) => {
 1089                /*always ok*/
 1090            }
 1091          }
 1092  
 1093          Ok(())
 1094      }
 1095  
 1096      pub fn cmt_to_str(&self, cmt&cmt_) -> ~str {
 1097          match cmt.cat {
 1098            cat_static_item => {
 1099                "static item".to_owned()
 1100            }
 1101            cat_copied_upvar(_) => {
 1102                "captured outer variable in a proc".to_owned()
 1103            }
 1104            cat_rvalue(..) => {
 1105                "non-lvalue".to_owned()
 1106            }
 1107            cat_local(_) => {
 1108                "local variable".to_owned()
 1109            }
 1110            cat_arg(..) => {
 1111                "argument".to_owned()
 1112            }
 1113            cat_deref(ref base, _, pk) => {
 1114                match base.cat {
 1115                    cat_upvar(..) => {
 1116                        format!("captured outer variable")
 1117                    }
 1118                    _ => {
 1119                        format!("dereference of `{}`-pointer", ptr_sigil(pk))
 1120                    }
 1121                }
 1122            }
 1123            cat_interior(_, InteriorField(NamedField(_))) => {
 1124                "field".to_owned()
 1125            }
 1126            cat_interior(_, InteriorField(PositionalField(_))) => {
 1127                "anonymous field".to_owned()
 1128            }
 1129            cat_interior(_, InteriorElement(VecElement)) => {
 1130                "vec content".to_owned()
 1131            }
 1132            cat_interior(_, InteriorElement(StrElement)) => {
 1133                "str content".to_owned()
 1134            }
 1135            cat_interior(_, InteriorElement(OtherElement)) => {
 1136                "indexed content".to_owned()
 1137            }
 1138            cat_upvar(..) => {
 1139                "captured outer variable".to_owned()
 1140            }
 1141            cat_discr(ref cmt, _) => {
 1142              self.cmt_to_str(&**cmt)
 1143            }
 1144            cat_downcast(ref cmt) => {
 1145              self.cmt_to_str(&**cmt)
 1146            }
 1147          }
 1148      }
 1149  }
 1150  
 1151  pub enum InteriorSafety {
 1152      InteriorUnsafe,
 1153      InteriorSafe
 1154  }
 1155  
 1156  pub enum AliasableReason {
 1157      AliasableManaged,
 1158      AliasableBorrowed,
 1159      AliasableOther,
 1160      AliasableStatic(InteriorSafety),
 1161      AliasableStaticMut(InteriorSafety),
 1162  }
 1163  
 1164  impl cmt_ {
 1165      pub fn guarantor(&self) -> cmt {
 1166          //! Returns `self` after stripping away any owned pointer derefs or
 1167          //! interior content. The return value is basically the `cmt` which
 1168          //! determines how long the value in `self` remains live.
 1169  
 1170          match self.cat {
 1171              cat_rvalue(..) |
 1172              cat_static_item |
 1173              cat_copied_upvar(..) |
 1174              cat_local(..) |
 1175              cat_arg(..) |
 1176              cat_deref(_, _, UnsafePtr(..)) |
 1177              cat_deref(_, _, GcPtr(..)) |
 1178              cat_deref(_, _, BorrowedPtr(..)) |
 1179              cat_upvar(..) => {
 1180                  Rc::new((*self).clone())
 1181              }
 1182              cat_downcast(ref b) |
 1183              cat_discr(ref b, _) |
 1184              cat_interior(ref b, _) |
 1185              cat_deref(ref b, _, OwnedPtr) => {
 1186                  b.guarantor()
 1187              }
 1188          }
 1189      }
 1190  
 1191      pub fn freely_aliasable(&self, ctxt&ty::ctxt) -> Option<AliasableReason> {
 1192          /*!
 1193           * Returns `Some(_)` if this lvalue represents a freely aliasable
 1194           * pointer type.
 1195           */
 1196  
 1197          // Maybe non-obvious: copied upvars can only be considered
 1198          // non-aliasable in once closures, since any other kind can be
 1199          // aliased and eventually recused.
 1200  
 1201          match self.cat {
 1202              cat_deref(ref b, _, BorrowedPtr(ty::MutBorrow, _)) |
 1203              cat_deref(ref b, _, BorrowedPtr(ty::UniqueImmBorrow, _)) |
 1204              cat_downcast(ref b) |
 1205              cat_deref(ref b, _, OwnedPtr) |
 1206              cat_interior(ref b, _) |
 1207              cat_discr(ref b, _) => {
 1208                  // Aliasability depends on base cmt
 1209                  b.freely_aliasable(ctxt)
 1210              }
 1211  
 1212              cat_copied_upvar(CopiedUpvar {onceness: ast::Once, ..}) |
 1213              cat_rvalue(..) |
 1214              cat_local(..) |
 1215              cat_upvar(..) |
 1216              cat_arg(_) |
 1217              cat_deref(_, _, UnsafePtr(..)) => { // yes, it's aliasable, but...
 1218                  None
 1219              }
 1220  
 1221              cat_copied_upvar(CopiedUpvar {onceness: ast::Many, ..}) => {
 1222                  Some(AliasableOther)
 1223              }
 1224  
 1225              cat_static_item(..) => {
 1226                  let int_safe = if ty::type_interior_is_unsafe(ctxt, self.ty) {
 1227                      InteriorUnsafe
 1228                  } else {
 1229                      InteriorSafe
 1230                  };
 1231  
 1232                  if self.mutbl.is_mutable() {
 1233                      Some(AliasableStaticMut(int_safe))
 1234                  } else {
 1235                      Some(AliasableStatic(int_safe))
 1236                  }
 1237              }
 1238  
 1239              cat_deref(_, _, GcPtr) => {
 1240                  Some(AliasableManaged)
 1241              }
 1242  
 1243              cat_deref(_, _, BorrowedPtr(ty::ImmBorrow, _)) => {
 1244                  Some(AliasableBorrowed)
 1245              }
 1246          }
 1247      }
 1248  }
 1249  
 1250  impl Repr for cmt_ {
 1251      fn repr(&self, tcx&ty::ctxt) -> ~str {
 1252          format!("\\{{} id:{} m:{:?} ty:{}\\}",
 1253               self.cat.repr(tcx),
 1254               self.id,
 1255               self.mutbl,
 1256               self.ty.repr(tcx))
 1257      }
 1258  }
 1259  
 1260  impl Repr for categorization {
 1261      fn repr(&self, tcx&ty::ctxt) -> ~str {
 1262          match *self {
 1263              cat_static_item |
 1264              cat_rvalue(..) |
 1265              cat_copied_upvar(..) |
 1266              cat_local(..) |
 1267              cat_upvar(..) |
 1268              cat_arg(..) => {
 1269                  format!("{:?}", *self)
 1270              }
 1271              cat_deref(ref cmt, derefs, ptr) => {
 1272                  format!("{}-{}{}->",
 1273                          cmt.cat.repr(tcx),
 1274                          ptr_sigil(ptr),
 1275                          derefs)
 1276              }
 1277              cat_interior(ref cmt, interior) => {
 1278                  format!("{}.{}",
 1279                       cmt.cat.repr(tcx),
 1280                       interior.repr(tcx))
 1281              }
 1282              cat_downcast(ref cmt) => {
 1283                  format!("{}->(enum)", cmt.cat.repr(tcx))
 1284              }
 1285              cat_discr(ref cmt, _) => {
 1286                  cmt.cat.repr(tcx)
 1287              }
 1288          }
 1289      }
 1290  }
 1291  
 1292  pub fn ptr_sigil(ptrPointerKind) -> &'static str {
 1293      match ptr {
 1294          OwnedPtr => "~",
 1295          GcPtr => "@",
 1296          BorrowedPtr(ty::ImmBorrow, _) => "&",
 1297          BorrowedPtr(ty::MutBorrow, _) => "&mut",
 1298          BorrowedPtr(ty::UniqueImmBorrow, _) => "&unique",
 1299          UnsafePtr(_) => "*"
 1300      }
 1301  }
 1302  
 1303  impl Repr for InteriorKind {
 1304      fn repr(&self, _tcx&ty::ctxt) -> ~str {
 1305          match *self {
 1306              InteriorField(NamedField(fld)) => {
 1307                  token::get_name(fld).get().to_str()
 1308              }
 1309              InteriorField(PositionalField(i)) => format!("\\#{:?}", i),
 1310              InteriorElement(_) => "[]".to_owned(),
 1311          }
 1312      }
 1313  }
 1314  
 1315  fn element_kind(tty::t) -> ElementKind {
 1316      match ty::get(t).sty {
 1317          ty::ty_rptr(_, ty::mt{ty:ty, ..}) |
 1318          ty::ty_uniq(ty) => match ty::get(ty).sty {
 1319              ty::ty_vec(_, None) => VecElement,
 1320              ty::ty_str => StrElement,
 1321              _ => OtherElement
 1322          },
 1323          ty::ty_vec(..) => VecElement,
 1324          _ => OtherElement
 1325      }
 1326  }


librustc/middle/mem_categorization.rs:1291:1-1291:1 -fn- definition:
pub fn ptr_sigil(ptr: PointerKind) -> &'static str {
    match ptr {
        OwnedPtr => "~",
references:- 2
1273:                         cmt.cat.repr(tcx),
1274:                         ptr_sigil(ptr),
1275:                         derefs)


librustc/middle/mem_categorization.rs:79:23-79:23 -enum- definition:
pub enum categorization {
    cat_rvalue(ty::Region),            // temporary val, argument is its scope
    cat_static_item,
references:- 7
80: pub enum categorization {
--
1260: impl Repr for categorization {
1261:     fn repr(&self, tcx: &ty::ctxt) -> ~str {


librustc/middle/mem_categorization.rs:1155:1-1155:1 -enum- definition:
pub enum AliasableReason {
    AliasableManaged,
    AliasableBorrowed,
references:- 2
1191:     pub fn freely_aliasable(&self, ctxt: &ty::ctxt) -> Option<AliasableReason> {
1192:         /*!
librustc/middle/borrowck/mod.rs:
626:                                          kind: AliasableViolationKind,
627:                                          cause: mc::AliasableReason) {
628:         let prefix = match kind {


librustc/middle/mem_categorization.rs:1314:1-1314:1 -fn- definition:
fn element_kind(t: ty::t) -> ElementKind {
    match ty::get(t).sty {
        ty::ty_rptr(_, ty::mt{ty:ty, ..}) |
references:- 2
213:         ty::ty_vec(_, Some(_)) => {
214:             Some(deref_interior(InteriorElement(element_kind(t))))
215:         }
--
840:                 span:elt.span(),
841:                 cat:cat_interior(of_cmt, InteriorElement(element_kind(vec_ty))),
842:                 mutbl:mutbl,


librustc/middle/mem_categorization.rs:118:38-118:38 -enum- definition:
pub enum FieldName {
    NamedField(ast::Name),
    PositionalField(uint)
references:- 8
113: pub enum InteriorKind {
114:     InteriorField(FieldName),
115:     InteriorElement(ElementKind),
--
119: pub enum FieldName {


librustc/middle/mem_categorization.rs:124:38-124:38 -enum- definition:
pub enum ElementKind {
    VecElement,
    StrElement,
references:- 9
125: pub enum ElementKind {
--
1315: fn element_kind(t: ty::t) -> ElementKind {
1316:     match ty::get(t).sty {


librustc/middle/mem_categorization.rs:1150:1-1150:1 -enum- definition:
pub enum InteriorSafety {
    InteriorUnsafe,
    InteriorSafe
references:- 2
1159:     AliasableOther,
1160:     AliasableStatic(InteriorSafety),
1161:     AliasableStaticMut(InteriorSafety),
1162: }


librustc/middle/mem_categorization.rs:250:1-250:1 -NK_AS_STR_TODO- definition:
pub type McResult<T> = Result<T, ()>;
/**
 * The `Typer` trait provides the interface for the mem-categorization
references:- 15
929:                             &ast::Pat|)
930:                        -> McResult<()> {
931:         // Here, `cmt` is the categorization for the value being
librustc/middle/expr_use_visitor.rs:
846:                         upvar_def: ast::Def)
847:                         -> mc::McResult<mc::cmt> {
848:         // Create the cmt for the variable being borrowed, from the
librustc/middle/ty.rs:
4749:     fn node_ty(&self, id: ast::NodeId) -> mc::McResult<ty::t> {
4750:         Ok(ty::node_id_to_type(self, id))
librustc/middle/typeck/check/regionck.rs:
269:     fn node_ty(&self, id: ast::NodeId) -> mc::McResult<ty::t> {
270:         let t = self.resolve_node_type(id);
librustc/middle/mem_categorization.rs:
439:     pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> McResult<cmt> {
440:         debug!("cat_expr: id={} expr={}", expr.id, expr.repr(self.tcx()));


librustc/middle/mem_categorization.rs:231:1-231:1 -trait- definition:
trait ast_node {
    fn id(&self) -> ast::NodeId;
    fn span(&self) -> Span;
references:- 10
910:     pub fn cat_downcast<N:ast_node>(&self,
911:                                     node: &N,


librustc/middle/mem_categorization.rs:270:4-270:4 -trait- definition:
 */
pub trait Typer {
    fn tcx<'a>(&'a self) -> &'a ty::ctxt;
references:- 4
355: impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
356:     pub fn new(typer: &'t TYPER) -> MemCategorizationContext<'t,TYPER> {
librustc/middle/ty.rs:
4744: impl mc::Typer for ty::ctxt {
4745:     fn tcx<'a>(&'a self) -> &'a ty::ctxt {
librustc/middle/typeck/check/regionck.rs:
264: impl<'fcx> mc::Typer for Rcx<'fcx> {
265:     fn tcx<'a>(&'a self) -> &'a ty::ctxt {
librustc/middle/expr_use_visitor.rs:
123: impl<'d,'t,TYPER:mc::Typer> ExprUseVisitor<'d,'t,TYPER> {
124:     pub fn new(delegate: &'d mut Delegate,


librustc/middle/mem_categorization.rs:246:1-246:1 -struct- definition:
pub struct MemCategorizationContext<'t,TYPER> {
    typer: &'t TYPER
}
references:- 7
356:     pub fn new(typer: &'t TYPER) -> MemCategorizationContext<'t,TYPER> {
357:         MemCategorizationContext { typer: typer }
358:     }
librustc/middle/expr_use_visitor.rs:
102:     typer: &'t TYPER,
103:     mc: mc::MemCategorizationContext<'t,TYPER>,
104:     delegate: &'d mut Delegate,
librustc/middle/typeck/check/regionck.rs:
1081: fn link_pattern(rcx: &Rcx,
1082:                 mc: mc::MemCategorizationContext<Rcx>,
1083:                 discr_cmt: mc::cmt,
librustc/middle/borrowck/mod.rs:
357:     pub fn mc(&self) -> mc::MemCategorizationContext<'a,ty::ctxt> {
358:         mc::MemCategorizationContext::new(self.tcx)
librustc/middle/mem_categorization.rs:
926:                        pat: &ast::Pat,
927:                        op: |&MemCategorizationContext<TYPER>,
928:                             cmt,


librustc/middle/mem_categorization.rs:112:38-112:38 -enum- definition:
pub enum InteriorKind {
    InteriorField(FieldName),
    InteriorElement(ElementKind),
references:- 12
111: // base without a pointer dereference", e.g. a field
113: pub enum InteriorKind {
--
1303: impl Repr for InteriorKind {
1304:     fn repr(&self, _tcx: &ty::ctxt) -> ~str {
librustc/middle/borrowck/mod.rs:
206:     LpDeref(mc::PointerKind),    // `*LV` in doc.rs
207:     LpInterior(mc::InteriorKind) // `LV.f` in doc.rs
208: }
librustc/middle/mem_categorization.rs:
898:                                         interior_ty: ty::t,
899:                                         interior: InteriorKind)
900:                                         -> cmt {


librustc/middle/mem_categorization.rs:131:44-131:44 -enum- definition:
pub enum MutabilityCategory {
    McImmutable, // Immutable.
    McDeclared,  // Directly declared as mutable.
references:- 18
132: pub enum MutabilityCategory {
--
281: impl MutabilityCategory {
282:     pub fn from_mutbl(m: ast::Mutability) -> MutabilityCategory {
--
289:     pub fn from_borrow_kind(borrow_kind: ty::BorrowKind) -> MutabilityCategory {
290:         match borrow_kind {
--
315:     pub fn inherit(&self) -> MutabilityCategory {
316:         match *self {
--
834:                                  vec_ty: ty::t,
835:                                  mutbl: MutabilityCategory,
836:                                  element_ty: ty::t) -> cmt
librustc/middle/borrowck/mod.rs:
200:     LpVar(ast::NodeId),               // `x` in doc.rs
201:     LpExtend(Rc<LoanPath>, mc::MutabilityCategory, LoanPathElem)
202: }
librustc/middle/borrowck/gather_loans/restrictions.rs:
173:               result: RestrictionResult,
174:               mc: mc::MutabilityCategory,
175:               elem: LoanPathElem,
librustc/middle/mem_categorization.rs:
132: pub enum MutabilityCategory {


librustc/middle/mem_categorization.rs:152:23-152:23 -struct- definition:
pub struct cmt_ {
    pub id: ast::NodeId,          // id of expr/pat producing this value
    pub span: Span,                // span of same expr/pat
references:- 31
librustc/middle/borrowck/mod.rs:
librustc/middle/mem_categorization.rs:
librustc/middle/borrowck/mod.rs:
librustc/middle/mem_categorization.rs:


librustc/middle/mem_categorization.rs:102:38-102:38 -enum- definition:
pub enum PointerKind {
    OwnedPtr,
    GcPtr,
references:- 12
297:     pub fn from_pointer_kind(base_mutbl: MutabilityCategory,
298:                              ptr: PointerKind) -> MutabilityCategory {
299:         match ptr {
--
1292: pub fn ptr_sigil(ptr: PointerKind) -> &'static str {
1293:     match ptr {
librustc/middle/borrowck/mod.rs:
205: pub enum LoanPathElem {
206:     LpDeref(mc::PointerKind),    // `*LV` in doc.rs
207:     LpInterior(mc::InteriorKind) // `LV.f` in doc.rs
librustc/middle/mem_categorization.rs:
101: // different kinds of pointers:
103: pub enum PointerKind {


librustc/middle/mem_categorization.rs:164:31-164:31 -enum- definition:
// as accessing of components:
pub enum deref_kind {
    deref_ptr(PointerKind),
references:- 2
172: // pointer adjustment).
173: pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
174:     match ty::get(t).sty {
--
221: pub fn deref_kind(tcx: &ty::ctxt, t: ty::t) -> deref_kind {
222:     match opt_deref_kind(t) {


librustc/middle/mem_categorization.rs:832:8-832:8 -fn- definition:
        fn interior<N: ast_node>(elt: &N,
                                 of_cmt: cmt,
                                 vec_ty: ty::t,
references:- 2
827:             let m = base_cmt.mutbl.inherit();
828:             interior(elt, base_cmt.clone(), base_cmt.ty, m, element_ty)
829:           }


librustc/middle/mem_categorization.rs:869:8-869:8 -fn- definition:
        fn vec_slice_info(tcx: &ty::ctxt,
                          pat: &ast::Pat,
                          slice_ty: ty::t)
references:- 2
862:         let slice_ty = if_ok!(self.node_ty(slice_pat.id));
863:         let (slice_mutbl, slice_r) = vec_slice_info(self.tcx(),
864:                                                     slice_pat,
--
882:                     ty::ty_vec(slice_mt, None) => (slice_mt.mutbl, r),
883:                     _ => vec_slice_info(tcx, pat, mt.ty),
884:                 },


librustc/middle/mem_categorization.rs:220:1-220:1 -fn- definition:
pub fn deref_kind(tcx: &ty::ctxt, t: ty::t) -> deref_kind {
    match opt_deref_kind(t) {
      Some(k) => k,
references:- 2
807:         return match deref_kind(self.tcx(), base_cmt.ty) {
808:           deref_ptr(ptr) => {


librustc/middle/mem_categorization.rs:95:23-95:23 -struct- definition:
pub struct CopiedUpvar {
    pub upvar_id: ast::NodeId,
    pub onceness: ast::Onceness,
references:- 20
96: pub struct CopiedUpvar {
--
568:                               span:span,
569:                               cat:cat_copied_upvar(CopiedUpvar {
570:                                   upvar_id: var_id,
--
1221:             cat_copied_upvar(CopiedUpvar {onceness: ast::Many, ..}) => {
1222:                 Some(AliasableOther)
librustc/middle/borrowck/mod.rs:
228:         mc::cat_static_item |
229:         mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
230:             None
librustc/middle/borrowck/gather_loans/gather_moves.rs:
138:         // (see mem_categorization.rs).
139:         mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Once, .. }) => {
140:             None
librustc/middle/borrowck/gather_loans/move_error.rs:
129:         mc::cat_upvar(..) | mc::cat_static_item |
130:         mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
131:             bccx.span_err(
librustc/middle/borrowck/mod.rs:
234:         mc::cat_arg(id) |
235:         mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id: id, .. }) |
236:         mc::cat_upvar(ty::UpvarId {var_id: id, ..}, _) => {


librustc/middle/mem_categorization.rs:160:1-160:1 -NK_AS_STR_TODO- definition:
pub type cmt = Rc<cmt_>;
// We pun on *T to mean both actual deref of a ptr as well
// as accessing of components:
references:- 85
librustc/middle/expr_use_visitor.rs:
librustc/middle/typeck/check/regionck.rs:
librustc/middle/borrowck/mod.rs:
librustc/middle/borrowck/check_loans.rs:
librustc/middle/borrowck/gather_loans/mod.rs:
librustc/middle/borrowck/gather_loans/lifetime.rs:
librustc/middle/borrowck/gather_loans/restrictions.rs:
librustc/middle/borrowck/gather_loans/gather_moves.rs:
librustc/middle/borrowck/gather_loans/move_error.rs:
librustc/middle/mem_categorization.rs: