(index<- )        ./librustc/middle/typeck/check/regionck.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 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  
   13  The region check is a final pass that runs over the AST after we have
   14  inferred the type constraints but before we have actually finalized
   15  the types.  Its purpose is to embed a variety of region constraints.
   16  Inserting these constraints as a separate pass is good because (1) it
   17  localizes the code that has to do with region inference and (2) often
   18  we cannot know what constraints are needed until the basic types have
   19  been inferred.
   20  
   21  ### Interaction with the borrow checker
   22  
   23  In general, the job of the borrowck module (which runs later) is to
   24  check that all soundness criteria are met, given a particular set of
   25  regions. The job of *this* module is to anticipate the needs of the
   26  borrow checker and infer regions that will satisfy its requirements.
   27  It is generally true that the inference doesn't need to be sound,
   28  meaning that if there is a bug and we inferred bad regions, the borrow
   29  checker should catch it. This is not entirely true though; for
   30  example, the borrow checker doesn't check subtyping, and it doesn't
   31  check that region pointers are always live when they are used. It
   32  might be worthwhile to fix this so that borrowck serves as a kind of
   33  verification step -- that would add confidence in the overall
   34  correctness of the compiler, at the cost of duplicating some type
   35  checks and effort.
   36  
   37  ### Inferring the duration of borrows, automatic and otherwise
   38  
   39  Whenever we introduce a borrowed pointer, for example as the result of
   40  a borrow expression `let x = &data`, the lifetime of the pointer `x`
   41  is always specified as a region inference variable. `regionck` has the
   42  job of adding constraints such that this inference variable is as
   43  narrow as possible while still accommodating all uses (that is, every
   44  dereference of the resulting pointer must be within the lifetime).
   45  
   46  #### Reborrows
   47  
   48  Generally speaking, `regionck` does NOT try to ensure that the data
   49  `data` will outlive the pointer `x`. That is the job of borrowck.  The
   50  one exception is when "re-borrowing" the contents of another borrowed
   51  pointer. For example, imagine you have a borrowed pointer `b` with
   52  lifetime L1 and you have an expression `&*b`. The result of this
   53  expression will be another borrowed pointer with lifetime L2 (which is
   54  an inference variable). The borrow checker is going to enforce the
   55  constraint that L2 < L1, because otherwise you are re-borrowing data
   56  for a lifetime larger than the original loan.  However, without the
   57  routines in this module, the region inferencer would not know of this
   58  dependency and thus it might infer the lifetime of L2 to be greater
   59  than L1 (issue #3148).
   60  
   61  There are a number of troublesome scenarios in the tests
   62  `region-dependent-*.rs`, but here is one example:
   63  
   64      struct Foo { i: int }
   65      struct Bar { foo: Foo  }
   66      fn get_i(x: &'a Bar) -> &'a int {
   67         let foo = &x.foo; // Lifetime L1
   68         &foo.i            // Lifetime L2
   69      }
   70  
   71  Note that this comes up either with `&` expressions, `ref`
   72  bindings, and `autorefs`, which are the three ways to introduce
   73  a borrow.
   74  
   75  The key point here is that when you are borrowing a value that
   76  is "guaranteed" by a borrowed pointer, you must link the
   77  lifetime of that borrowed pointer (L1, here) to the lifetime of
   78  the borrow itself (L2).  What do I mean by "guaranteed" by a
   79  borrowed pointer? I mean any data that is reached by first
   80  dereferencing a borrowed pointer and then either traversing
   81  interior offsets or owned pointers.  We say that the guarantor
   82  of such data it the region of the borrowed pointer that was
   83  traversed.  This is essentially the same as the ownership
   84  relation, except that a borrowed pointer never owns its
   85  contents.
   86  
   87  ### Inferring borrow kinds for upvars
   88  
   89  Whenever there is a closure expression, we need to determine how each
   90  upvar is used. We do this by initially assigning each upvar an
   91  immutable "borrow kind" (see `ty::BorrowKind` for details) and then
   92  "escalating" the kind as needed. The borrow kind proceeds according to
   93  the following lattice:
   94  
   95      ty::ImmBorrow -> ty::UniqueImmBorrow -> ty::MutBorrow
   96  
   97  So, for example, if we see an assignment `x = 5` to an upvar `x`, we
   98  will promote its borrow kind to mutable borrow. If we see an `&mut x`
   99  we'll do the same. Naturally, this applies not just to the upvar, but
  100  to everything owned by `x`, so the result is the same for something
  101  like `x.f = 5` and so on (presuming `x` is not a borrowed pointer to a
  102  struct). These adjustments are performed in
  103  `adjust_upvar_borrow_kind()` (you can trace backwards through the code
  104  from there).
  105  
  106  The fact that we are inferring borrow kinds as we go results in a
  107  semi-hacky interaction with mem-categorization. In particular,
  108  mem-categorization will query the current borrow kind as it
  109  categorizes, and we'll return the *current* value, but this may get
  110  adjusted later. Therefore, in this module, we generally ignore the
  111  borrow kind (and derived mutabilities) that are returned from
  112  mem-categorization, since they may be inaccurate. (Another option
  113  would be to use a unification scheme, where instead of returning a
  114  concrete borrow kind like `ty::ImmBorrow`, we return a
  115  `ty::InferBorrow(upvar_id)` or something like that, but this would
  116  then mean that all later passes would have to check for these figments
  117  and report an error, and it just seems like more mess in the end.)
  118  
  119  */
  120  
  121  
  122  use middle::freevars;
  123  use mc = middle::mem_categorization;
  124  use middle::ty::{ReScope};
  125  use middle::ty;
  126  use middle::typeck::astconv::AstConv;
  127  use middle::typeck::check::FnCtxt;
  128  use middle::typeck::check::regionmanip::relate_nested_regions;
  129  use middle::typeck::infer::resolve_and_force_all_but_regions;
  130  use middle::typeck::infer::resolve_type;
  131  use middle::typeck::infer;
  132  use middle::typeck::MethodCall;
  133  use middle::pat_util;
  134  use util::nodemap::NodeMap;
  135  use util::ppaux::{ty_to_str, region_to_str, Repr};
  136  
  137  use syntax::ast::{DefArg, DefBinding, DefLocal, DefUpvar};
  138  use syntax::ast;
  139  use syntax::ast_util;
  140  use syntax::codemap::Span;
  141  use syntax::visit;
  142  use syntax::visit::Visitor;
  143  
  144  use std::cell::RefCell;
  145  
  146  // If mem categorization results in an error, it's because the type
  147  // check failed (or will fail, when the error is uncovered and
  148  // reported during writeback). In this case, we just ignore this part
  149  // of the code and don't try to add any more region constraints.
  150  macro_rules! ignore_err(
  151      ($inp: expr) => (
  152          match $inp {
  153              Ok(v) => v,
  154              Err(()) => return
  155          }
  156      )
  157  )
  158  
  159  pub struct Rcx<'a> {
  160      fcx: &'a FnCtxt<'a>,
  161  
  162      // id of innermost fn or loop
  163      repeating_scope: ast::NodeId,
  164  }
  165  
  166  fn region_of_def(fcx: &FnCtxt, defast::Def) -> ty::Region {
  167      /*!
  168       * Returns the validity region of `def` -- that is, how long
  169       * is `def` valid?
  170       */
  171  
  172      let tcx = fcx.tcx();
  173      match def {
  174          DefLocal(node_id, _) | DefArg(node_id, _) |
  175          DefBinding(node_id, _) => {
  176              tcx.region_maps.var_region(node_id)
  177          }
  178          DefUpvar(_, subdef, closure_id, body_id) => {
  179              match ty::ty_closure_store(fcx.node_ty(closure_id)) {
  180                  ty::RegionTraitStore(..) => region_of_def(fcx, *subdef),
  181                  ty::UniqTraitStore => ReScope(body_id)
  182              }
  183          }
  184          _ => {
  185              tcx.sess.bug(format!("unexpected def in region_of_def: {:?}",
  186                                def))
  187          }
  188      }
  189  }
  190  
  191  impl<'a> Rcx<'a> {
  192      pub fn tcx(&self) -> &'a ty::ctxt {
  193          self.fcx.ccx.tcx
  194      }
  195  
  196      pub fn set_repeating_scope(&mut self, scopeast::NodeId) -> ast::NodeId {
  197          let old_scope = self.repeating_scope;
  198          self.repeating_scope = scope;
  199          old_scope
  200      }
  201  
  202      pub fn resolve_type(&self, unresolved_tyty::t) -> ty::t {
  203          /*!
  204           * Try to resolve the type for the given node, returning
  205           * t_err if an error results.  Note that we never care
  206           * about the details of the error, the same error will be
  207           * detected and reported in the writeback phase.
  208           *
  209           * Note one important point: we do not attempt to resolve
  210           * *region variables* here.  This is because regionck is
  211           * essentially adding constraints to those region variables
  212           * and so may yet influence how they are resolved.
  213           *
  214           * Consider this silly example:
  215           *
  216           *     fn borrow(x: &int) -> &int {x}
  217           *     fn foo(x: @int) -> int {  // block: B
  218           *         let b = borrow(x);    // region: <R0>
  219           *         *b
  220           *     }
  221           *
  222           * Here, the region of `b` will be `<R0>`.  `<R0>` is
  223           * constrainted to be some subregion of the block B and some
  224           * superregion of the call.  If we forced it now, we'd choose
  225           * the smaller region (the call).  But that would make the *b
  226           * illegal.  Since we don't resolve, the type of b will be
  227           * `&<R0>.int` and then `*b` will require that `<R0>` be
  228           * bigger than the let and the `*b` expression, so we will
  229           * effectively resolve `<R0>` to be the block B.
  230           */
  231          match resolve_type(self.fcx.infcx(), unresolved_ty,
  232                             resolve_and_force_all_but_regions) {
  233              Ok(t) => t,
  234              Err(_) => ty::mk_err()
  235          }
  236      }
  237  
  238      /// Try to resolve the type for the given node.
  239      fn resolve_node_type(&self, idast::NodeId) -> ty::t {
  240          let t = self.fcx.node_ty(id);
  241          self.resolve_type(t)
  242      }
  243  
  244      fn resolve_method_type(&self, method_callMethodCall) -> Option<ty::t> {
  245          let method_ty = self.fcx.inh.method_map.borrow()
  246                              .find(&method_call).map(|method| method.ty);
  247          method_ty.map(|method_ty| self.resolve_type(method_ty))
  248      }
  249  
  250      /// Try to resolve the type for the given node.
  251      pub fn resolve_expr_type_adjusted(&mut self, expr&ast::Expr) -> ty::t {
  252          let ty_unadjusted = self.resolve_node_type(expr.id);
  253          if ty::type_is_error(ty_unadjusted) || ty::type_is_bot(ty_unadjusted) {
  254              ty_unadjusted
  255          } else {
  256              let tcx = self.fcx.tcx();
  257              ty::adjust_ty(tcx, expr.span, expr.id, ty_unadjusted,
  258                            self.fcx.inh.adjustments.borrow().find(&expr.id),
  259                            |method_call| self.resolve_method_type(method_call))
  260          }
  261      }
  262  }
  263  
  264  impl<'fcx> mc::Typer for Rcx<'fcx> {
  265      fn tcx<'a>(&'a self) -> &'a ty::ctxt {
  266          self.fcx.tcx()
  267      }
  268  
  269      fn node_ty(&self, idast::NodeId) -> mc::McResult<ty::t> {
  270          let t = self.resolve_node_type(id);
  271          if ty::type_is_error(t) {Err(())} else {Ok(t)}
  272      }
  273  
  274      fn node_method_ty(&self, method_callMethodCall) -> Option<ty::t> {
  275          self.resolve_method_type(method_call)
  276      }
  277  
  278      fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>> {
  279          &self.fcx.inh.adjustments
  280      }
  281  
  282      fn is_method_call(&self, idast::NodeId) -> bool {
  283          self.fcx.inh.method_map.borrow().contains_key(&MethodCall::expr(id))
  284      }
  285  
  286      fn temporary_scope(&self, idast::NodeId) -> Option<ast::NodeId> {
  287          self.tcx().region_maps.temporary_scope(id)
  288      }
  289  
  290      fn upvar_borrow(&self, idty::UpvarId) -> ty::UpvarBorrow {
  291          self.fcx.inh.upvar_borrow_map.borrow().get_copy(&id)
  292      }
  293  }
  294  
  295  pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) {
  296      let mut rcx = Rcx { fcx: fcx, repeating_scope: e.id };
  297      let rcx = &mut rcx;
  298      if fcx.err_count_since_creation() == 0 {
  299          // regionck assumes typeck succeeded
  300          rcx.visit_expr(e, ());
  301      }
  302      fcx.infcx().resolve_regions();
  303  }
  304  
  305  pub fn regionck_fn(fcx: &FnCtxt, blk: &ast::Block) {
  306      let mut rcx = Rcx { fcx: fcx, repeating_scope: blk.id };
  307      let rcx = &mut rcx;
  308      if fcx.err_count_since_creation() == 0 {
  309          // regionck assumes typeck succeeded
  310          rcx.visit_block(blk, ());
  311      }
  312      fcx.infcx().resolve_regions();
  313  }
  314  
  315  impl<'a> Visitor<()> for Rcx<'a> {
  316      // (..) FIXME(#3238) should use visit_pat, not visit_arm/visit_local,
  317      // However, right now we run into an issue whereby some free
  318      // regions are not properly related if they appear within the
  319      // types of arguments that must be inferred. This could be
  320      // addressed by deferring the construction of the region
  321      // hierarchy, and in particular the relationships between free
  322      // regions, until regionck, as described in #3238.
  323  
  324      fn visit_item(&mut self, i&ast::Item, _()) { visit_item(self, i); }
  325  
  326      fn visit_expr(&mut self, ex&ast::Expr, _()) { visit_expr(self, ex); }
  327  
  328      //visit_pat: visit_pat, // (..) see above
  329  
  330      fn visit_arm(&mut self, a&ast::Arm, _()) { visit_arm(self, a); }
  331  
  332      fn visit_local(&mut self, l&ast::Local, _()) { visit_local(self, l); }
  333  
  334      fn visit_block(&mut self, b&ast::Block, _()) { visit_block(self, b); }
  335  }
  336  
  337  fn visit_item(_rcx: &mut Rcx, _item: &ast::Item) {
  338      // Ignore items
  339  }
  340  
  341  fn visit_block(rcx: &mut Rcx, b: &ast::Block) {
  342      visit::walk_block(rcx, b, ());
  343  }
  344  
  345  fn visit_arm(rcx: &mut Rcx, arm: &ast::Arm) {
  346      // see above
  347      for &p in arm.pats.iter() {
  348          constrain_bindings_in_pat(p, rcx);
  349      }
  350  
  351      visit::walk_arm(rcx, arm, ());
  352  }
  353  
  354  fn visit_local(rcx: &mut Rcx, l: &ast::Local) {
  355      // see above
  356      constrain_bindings_in_pat(l.pat, rcx);
  357      link_local(rcx, l);
  358      visit::walk_local(rcx, l, ());
  359  }
  360  
  361  fn constrain_bindings_in_pat(pat: &ast::Pat, rcx: &mut Rcx) {
  362      let tcx = rcx.fcx.tcx();
  363      debug!("regionck::visit_pat(pat={})", pat.repr(tcx));
  364      pat_util::pat_bindings(&tcx.def_map, pat, |_, id, span, _| {
  365          // If we have a variable that contains region'd data, that
  366          // data will be accessible from anywhere that the variable is
  367          // accessed. We must be wary of loops like this:
  368          //
  369          //     // from src/test/compile-fail/borrowck-lend-flow.rs
  370          //     let mut v = box 3, w = box 4;
  371          //     let mut x = &mut w;
  372          //     loop {
  373          //         **x += 1;   // (2)
  374          //         borrow(v);  //~ ERROR cannot borrow
  375          //         x = &mut v; // (1)
  376          //     }
  377          //
  378          // Typically, we try to determine the region of a borrow from
  379          // those points where it is dereferenced. In this case, one
  380          // might imagine that the lifetime of `x` need only be the
  381          // body of the loop. But of course this is incorrect because
  382          // the pointer that is created at point (1) is consumed at
  383          // point (2), meaning that it must be live across the loop
  384          // iteration. The easiest way to guarantee this is to require
  385          // that the lifetime of any regions that appear in a
  386          // variable's type enclose at least the variable's scope.
  387  
  388          let var_region = tcx.region_maps.var_region(id);
  389          constrain_regions_in_type_of_node(
  390              rcx, id, var_region,
  391              infer::BindingTypeIsNotValidAtDecl(span));
  392      })
  393  }
  394  
  395  fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
  396      debug!("regionck::visit_expr(e={}, repeating_scope={:?})",
  397             expr.repr(rcx.fcx.tcx()), rcx.repeating_scope);
  398  
  399      let method_call = MethodCall::expr(expr.id);
  400      let has_method_map = rcx.fcx.inh.method_map.borrow().contains_key(&method_call);
  401  
  402      // Check any autoderefs or autorefs that appear.
  403      for &adjustment in rcx.fcx.inh.adjustments.borrow().find(&expr.id).iter() {
  404          debug!("adjustment={:?}", adjustment);
  405          match *adjustment {
  406              ty::AutoDerefRef(ty::AutoDerefRef {autoderefs, autoref: opt_autoref}) => {
  407                  let expr_ty = rcx.resolve_node_type(expr.id);
  408                  constrain_autoderefs(rcx, expr, autoderefs, expr_ty);
  409                  for autoref in opt_autoref.iter() {
  410                      link_autoref(rcx, expr, autoderefs, autoref);
  411  
  412                      // Require that the resulting region encompasses
  413                      // the current node.
  414                      //
  415                      // FIXME(#6268) remove to support nested method calls
  416                      constrain_regions_in_type_of_node(
  417                          rcx, expr.id, ty::ReScope(expr.id),
  418                          infer::AutoBorrow(expr.span));
  419                  }
  420              }
  421              ty::AutoObject(ty::RegionTraitStore(trait_region, _), _, _, _) => {
  422                  // Determine if we are casting `expr` to a trait
  423                  // instance.  If so, we have to be sure that the type of
  424                  // the source obeys the trait's region bound.
  425                  //
  426                  // Note: there is a subtle point here concerning type
  427                  // parameters.  It is possible that the type of `source`
  428                  // contains type parameters, which in turn may contain
  429                  // regions that are not visible to us (only the caller
  430                  // knows about them).  The kind checker is ultimately
  431                  // responsible for guaranteeing region safety in that
  432                  // particular case.  There is an extensive comment on the
  433                  // function check_cast_for_escaping_regions() in kind.rs
  434                  // explaining how it goes about doing that.
  435  
  436                  let source_ty = rcx.fcx.expr_ty(expr);
  437                  constrain_regions_in_type(rcx, trait_region,
  438                                              infer::RelateObjectBound(expr.span), source_ty);
  439              }
  440              _ => {}
  441          }
  442      }
  443  
  444      match expr.node {
  445          ast::ExprCall(callee, ref args) => {
  446              constrain_callee(rcx, callee.id, expr, callee);
  447              constrain_call(rcx,
  448                             Some(callee.id),
  449                             expr,
  450                             None,
  451                             args.as_slice(),
  452                             false);
  453  
  454              visit::walk_expr(rcx, expr, ());
  455          }
  456  
  457          ast::ExprMethodCall(_, _, ref args) => {
  458              constrain_call(rcx, None, expr, Some(*args.get(0)),
  459                             args.slice_from(1), false);
  460  
  461              visit::walk_expr(rcx, expr, ());
  462          }
  463  
  464          ast::ExprAssign(lhs, _) => {
  465              adjust_borrow_kind_for_assignment_lhs(rcx, lhs);
  466              visit::walk_expr(rcx, expr, ());
  467          }
  468  
  469          ast::ExprAssignOp(_, lhs, rhs) => {
  470              if has_method_map {
  471                  constrain_call(rcx, None, expr, Some(lhs), [rhs], true);
  472              }
  473  
  474              adjust_borrow_kind_for_assignment_lhs(rcx, lhs);
  475  
  476              visit::walk_expr(rcx, expr, ());
  477          }
  478  
  479          ast::ExprIndex(lhs, rhs) |
  480          ast::ExprBinary(_, lhs, rhs) if has_method_map => {
  481              // As `expr_method_call`, but the call is via an
  482              // overloaded op.  Note that we (sadly) currently use an
  483              // implicit "by ref" sort of passing style here.  This
  484              // should be converted to an adjustment!
  485              constrain_call(rcx, None, expr, Some(lhs), [rhs], true);
  486  
  487              visit::walk_expr(rcx, expr, ());
  488          }
  489  
  490          ast::ExprUnary(_, lhs) if has_method_map => {
  491              // As above.
  492              constrain_call(rcx, None, expr, Some(lhs), [], true);
  493  
  494              visit::walk_expr(rcx, expr, ());
  495          }
  496  
  497          ast::ExprUnary(ast::UnDeref, base) => {
  498              // For *a, the lifetime of a must enclose the deref
  499              let method_call = MethodCall::expr(expr.id);
  500              let base_ty = match rcx.fcx.inh.method_map.borrow().find(&method_call) {
  501                  Some(method) => {
  502                      constrain_call(rcx, None, expr, Some(base), [], true);
  503                      ty::ty_fn_ret(method.ty)
  504                  }
  505                  None => rcx.resolve_node_type(base.id)
  506              };
  507              match ty::get(base_ty).sty {
  508                  ty::ty_rptr(r_ptr, _) => {
  509                      mk_subregion_due_to_dereference(rcx, expr.span,
  510                                                      ty::ReScope(expr.id), r_ptr);
  511                  }
  512                  _ => {}
  513              }
  514  
  515              visit::walk_expr(rcx, expr, ());
  516          }
  517  
  518          ast::ExprIndex(vec_expr, _) => {
  519              // For a[b], the lifetime of a must enclose the deref
  520              let vec_type = rcx.resolve_expr_type_adjusted(vec_expr);
  521              constrain_index(rcx, expr, vec_type);
  522  
  523              visit::walk_expr(rcx, expr, ());
  524          }
  525  
  526          ast::ExprCast(source, _) => {
  527              // Determine if we are casting `source` to a trait
  528              // instance.  If so, we have to be sure that the type of
  529              // the source obeys the trait's region bound.
  530              //
  531              // Note: there is a subtle point here concerning type
  532              // parameters.  It is possible that the type of `source`
  533              // contains type parameters, which in turn may contain
  534              // regions that are not visible to us (only the caller
  535              // knows about them).  The kind checker is ultimately
  536              // responsible for guaranteeing region safety in that
  537              // particular case.  There is an extensive comment on the
  538              // function check_cast_for_escaping_regions() in kind.rs
  539              // explaining how it goes about doing that.
  540              let target_ty = rcx.resolve_node_type(expr.id);
  541              match ty::get(target_ty).sty {
  542                  ty::ty_trait(box ty::TyTrait {
  543                      store: ty::RegionTraitStore(trait_region, _), ..
  544                  }) => {
  545                      let source_ty = rcx.resolve_expr_type_adjusted(source);
  546                      constrain_regions_in_type(
  547                          rcx,
  548                          trait_region,
  549                          infer::RelateObjectBound(expr.span),
  550                          source_ty);
  551                  }
  552                  _ => ()
  553              }
  554  
  555              visit::walk_expr(rcx, expr, ());
  556          }
  557  
  558          ast::ExprAddrOf(m, base) => {
  559              link_addr_of(rcx, expr, m, base);
  560  
  561              // Require that when you write a `&expr` expression, the
  562              // resulting pointer has a lifetime that encompasses the
  563              // `&expr` expression itself. Note that we constraining
  564              // the type of the node expr.id here *before applying
  565              // adjustments*.
  566              //
  567              // FIXME(#6268) nested method calls requires that this rule change
  568              let ty0 = rcx.resolve_node_type(expr.id);
  569              constrain_regions_in_type(rcx, ty::ReScope(expr.id),
  570                                        infer::AddrOf(expr.span), ty0);
  571              visit::walk_expr(rcx, expr, ());
  572          }
  573  
  574          ast::ExprMatch(discr, ref arms) => {
  575              link_match(rcx, discr, arms.as_slice());
  576  
  577              visit::walk_expr(rcx, expr, ());
  578          }
  579  
  580          ast::ExprFnBlock(_, ref body) | ast::ExprProc(_, ref body) => {
  581              check_expr_fn_block(rcx, expr, &**body);
  582          }
  583  
  584          ast::ExprLoop(body, _) => {
  585              let repeating_scope = rcx.set_repeating_scope(body.id);
  586              visit::walk_expr(rcx, expr, ());
  587              rcx.set_repeating_scope(repeating_scope);
  588          }
  589  
  590          ast::ExprWhile(cond, body) => {
  591              let repeating_scope = rcx.set_repeating_scope(cond.id);
  592              rcx.visit_expr(cond, ());
  593  
  594              rcx.set_repeating_scope(body.id);
  595              rcx.visit_block(body, ());
  596  
  597              rcx.set_repeating_scope(repeating_scope);
  598          }
  599  
  600          _ => {
  601              visit::walk_expr(rcx, expr, ());
  602          }
  603      }
  604  }
  605  
  606  fn check_expr_fn_block(rcx: &mut Rcx,
  607                         expr: &ast::Expr,
  608                         body: &ast::Block) {
  609      let tcx = rcx.fcx.tcx();
  610      let function_type = rcx.resolve_node_type(expr.id);
  611      match ty::get(function_type).sty {
  612          ty::ty_closure(box ty::ClosureTy {
  613                  store: ty::RegionTraitStore(region, _), ..}) => {
  614              freevars::with_freevars(tcx, expr.id, |freevars| {
  615                  if freevars.is_empty() {
  616                      // No free variables means that the environment
  617                      // will be NULL at runtime and hence the closure
  618                      // has static lifetime.
  619                  } else {
  620                      // Closure must not outlive the variables it closes over.
  621                      constrain_free_variables(rcx, region, expr, freevars);
  622  
  623                      // Closure cannot outlive the appropriate temporary scope.
  624                      let s = rcx.repeating_scope;
  625                      rcx.fcx.mk_subr(true, infer::InfStackClosure(expr.span),
  626                                      region, ty::ReScope(s));
  627                  }
  628              });
  629          }
  630          _ => ()
  631      }
  632  
  633      let repeating_scope = rcx.set_repeating_scope(body.id);
  634      visit::walk_expr(rcx, expr, ());
  635      rcx.set_repeating_scope(repeating_scope);
  636  
  637      match ty::get(function_type).sty {
  638          ty::ty_closure(box ty::ClosureTy {
  639                  store: ty::RegionTraitStore(..),
  640                  ..
  641              }) => {
  642              freevars::with_freevars(tcx, expr.id, |freevars| {
  643                  propagate_upupvar_borrow_kind(rcx, expr, freevars);
  644              })
  645          }
  646          _ => ()
  647      }
  648  
  649      fn constrain_free_variables(rcx&mut Rcx,
  650                                  regionty::Region,
  651                                  expr&ast::Expr,
  652                                  freevars&[freevars::freevar_entry]) {
  653          /*!
  654           * Make sure that all free variables referenced inside the closure
  655           * outlive the closure itself. Also, create an entry in the
  656           * upvar_borrows map with a region.
  657           */
  658  
  659          let tcx = rcx.fcx.ccx.tcx;
  660          let infcx = rcx.fcx.infcx();
  661          debug!("constrain_free_variables({}, {})",
  662                 region.repr(tcx), expr.repr(tcx));
  663          for freevar in freevars.iter() {
  664              debug!("freevar def is {:?}", freevar.def);
  665  
  666              // Identify the variable being closed over and its node-id.
  667              let def = freevar.def;
  668              let def_id = ast_util::def_id_of_def(def);
  669              assert!(def_id.krate == ast::LOCAL_CRATE);
  670              let upvar_id = ty::UpvarId { var_id: def_id.node,
  671                                           closure_expr_id: expr.id };
  672  
  673              // Create a region variable to represent this borrow. This borrow
  674              // must outlive the region on the closure.
  675              let origin = infer::UpvarRegion(upvar_id, expr.span);
  676              let freevar_region = infcx.next_region_var(origin);
  677              rcx.fcx.mk_subr(true, infer::FreeVariable(freevar.span, def_id.node),
  678                              region, freevar_region);
  679  
  680              // Create a UpvarBorrow entry. Note that we begin with a
  681              // const borrow_kind, but change it to either mut or
  682              // immutable as dictated by the uses.
  683              let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow,
  684                                                   region: freevar_region };
  685              rcx.fcx.inh.upvar_borrow_map.borrow_mut().insert(upvar_id,
  686                                                               upvar_borrow);
  687  
  688              // Guarantee that the closure does not outlive the variable itself.
  689              let en_region = region_of_def(rcx.fcx, def);
  690              debug!("en_region = {}", en_region.repr(tcx));
  691              rcx.fcx.mk_subr(true, infer::FreeVariable(freevar.span, def_id.node),
  692                              region, en_region);
  693          }
  694      }
  695  
  696      fn propagate_upupvar_borrow_kind(rcx&mut Rcx,
  697                                       expr&ast::Expr,
  698                                       freevars&[freevars::freevar_entry]) {
  699          let tcx = rcx.fcx.ccx.tcx;
  700          debug!("propagate_upupvar_borrow_kind({})", expr.repr(tcx));
  701          for freevar in freevars.iter() {
  702              // Because of the semi-hokey way that we are doing
  703              // borrow_kind inference, we need to check for
  704              // indirect dependencies, like so:
  705              //
  706              //     let mut x = 0;
  707              //     outer_call(|| {
  708              //         inner_call(|| {
  709              //             x = 1;
  710              //         });
  711              //     });
  712              //
  713              // Here, the `inner_call` is basically "reborrowing" the
  714              // outer pointer. With no other changes, `inner_call`
  715              // would infer that it requires a mutable borrow, but
  716              // `outer_call` would infer that a const borrow is
  717              // sufficient. This is because we haven't linked the
  718              // borrow_kind of the borrow that occurs in the inner
  719              // closure to the borrow_kind of the borrow in the outer
  720              // closure. Note that regions *are* naturally linked
  721              // because we have a proper inference scheme there.
  722              //
  723              // Anyway, for borrow_kind, we basically go back over now
  724              // after checking the inner closure (and hence
  725              // determining the final borrow_kind) and propagate that as
  726              // a constraint on the outer closure.
  727              match freevar.def {
  728                  ast::DefUpvar(var_id, _, outer_closure_id, _) => {
  729                      // thing being captured is itself an upvar:
  730                      let outer_upvar_id = ty::UpvarId {
  731                          var_id: var_id,
  732                          closure_expr_id: outer_closure_id };
  733                      let inner_upvar_id = ty::UpvarId {
  734                          var_id: var_id,
  735                          closure_expr_id: expr.id };
  736                      link_upvar_borrow_kind_for_nested_closures(rcx,
  737                                                                 inner_upvar_id,
  738                                                                 outer_upvar_id);
  739                  }
  740                  _ => {}
  741              }
  742          }
  743      }
  744  }
  745  
  746  fn constrain_callee(rcx: &mut Rcx,
  747                      callee_idast::NodeId,
  748                      call_expr: &ast::Expr,
  749                      callee_expr: &ast::Expr) {
  750      let call_region = ty::ReScope(call_expr.id);
  751  
  752      let callee_ty = rcx.resolve_node_type(callee_id);
  753      match ty::get(callee_ty).sty {
  754          ty::ty_bare_fn(..) => { }
  755          ty::ty_closure(ref closure_ty) => {
  756              let region = match closure_ty.store {
  757                  ty::RegionTraitStore(r, _) => {
  758                      // While we're here, link the closure's region with a unique
  759                      // immutable borrow (gathered later in borrowck)
  760                      let mc = mc::MemCategorizationContext::new(rcx);
  761                      let expr_cmt = ignore_err!(mc.cat_expr(callee_expr));
  762                      link_region(rcx, callee_expr.span, call_region,
  763                                  ty::UniqueImmBorrow, expr_cmt);
  764                      r
  765                  }
  766                  ty::UniqTraitStore => ty::ReStatic
  767              };
  768              rcx.fcx.mk_subr(true, infer::InvokeClosure(callee_expr.span),
  769                              call_region, region);
  770          }
  771          _ => {
  772              // this should not happen, but it does if the program is
  773              // erroneous
  774              //
  775              // tcx.sess.span_bug(
  776              //     callee_expr.span,
  777              //     format!("Calling non-function: {}", callee_ty.repr(tcx)));
  778          }
  779      }
  780  }
  781  
  782  fn constrain_call(rcx: &mut Rcx,
  783                    // might be expr_call, expr_method_call, or an overloaded
  784                    // operator
  785                    fn_expr_idOption<ast::NodeId>,
  786                    call_expr: &ast::Expr,
  787                    receiverOption<@ast::Expr>,
  788                    arg_exprs: &[@ast::Expr],
  789                    implicitly_ref_args: bool) {
  790      //! Invoked on every call site (i.e., normal calls, method calls,
  791      //! and overloaded operators). Constrains the regions which appear
  792      //! in the type of the function. Also constrains the regions that
  793      //! appear in the arguments appropriately.
  794  
  795      let tcx = rcx.fcx.tcx();
  796      debug!("constrain_call(call_expr={}, \
  797              receiver={}, \
  798              arg_exprs={}, \
  799              implicitly_ref_args={:?})",
  800              call_expr.repr(tcx),
  801              receiver.repr(tcx),
  802              arg_exprs.repr(tcx),
  803              implicitly_ref_args);
  804      let callee_ty = match fn_expr_id {
  805          Some(id) => rcx.resolve_node_type(id),
  806          None => rcx.resolve_method_type(MethodCall::expr(call_expr.id))
  807                     .expect("call should have been to a method")
  808      };
  809      if ty::type_is_error(callee_ty) {
  810          // Bail, as function type is unknown
  811          return;
  812      }
  813      let fn_sig = ty::ty_fn_sig(callee_ty);
  814  
  815      // `callee_region` is the scope representing the time in which the
  816      // call occurs.
  817      //
  818      // FIXME(#6268) to support nested method calls, should be callee_id
  819      let callee_scope = call_expr.id;
  820      let callee_region = ty::ReScope(callee_scope);
  821  
  822      for &arg_expr in arg_exprs.iter() {
  823          debug!("Argument");
  824  
  825          // ensure that any regions appearing in the argument type are
  826          // valid for at least the lifetime of the function:
  827          constrain_regions_in_type_of_node(
  828              rcx, arg_expr.id, callee_region,
  829              infer::CallArg(arg_expr.span));
  830  
  831          // unfortunately, there are two means of taking implicit
  832          // references, and we need to propagate constraints as a
  833          // result. modes are going away and the "DerefArgs" code
  834          // should be ported to use adjustments
  835          if implicitly_ref_args {
  836              link_by_ref(rcx, arg_expr, callee_scope);
  837          }
  838      }
  839  
  840      // as loop above, but for receiver
  841      for &r in receiver.iter() {
  842          debug!("Receiver");
  843          constrain_regions_in_type_of_node(
  844              rcx, r.id, callee_region, infer::CallRcvr(r.span));
  845          if implicitly_ref_args {
  846              link_by_ref(rcx, r, callee_scope);
  847          }
  848      }
  849  
  850      // constrain regions that may appear in the return type to be
  851      // valid for the function call:
  852      constrain_regions_in_type(
  853          rcx, callee_region, infer::CallReturn(call_expr.span),
  854          fn_sig.output);
  855  }
  856  
  857  fn constrain_autoderefs(rcx: &mut Rcx,
  858                          deref_expr: &ast::Expr,
  859                          derefs: uint,
  860                          mut derefd_tyty::t) {
  861      /*!
  862       * Invoked on any auto-dereference that occurs.  Checks that if
  863       * this is a region pointer being dereferenced, the lifetime of
  864       * the pointer includes the deref expr.
  865       */
  866      let r_deref_expr = ty::ReScope(deref_expr.id);
  867      for i in range(0u, derefs) {
  868          debug!("constrain_autoderefs(deref_expr=?, derefd_ty={}, derefs={:?}/{:?}",
  869                 rcx.fcx.infcx().ty_to_str(derefd_ty),
  870                 i, derefs);
  871  
  872          let method_call = MethodCall::autoderef(deref_expr.id, i as u32);
  873          derefd_ty = match rcx.fcx.inh.method_map.borrow().find(&method_call) {
  874              Some(method) => {
  875                  // Treat overloaded autoderefs as if an AutoRef adjustment
  876                  // was applied on the base type, as that is always the case.
  877                  let fn_sig = ty::ty_fn_sig(method.ty);
  878                  let self_ty = *fn_sig.inputs.get(0);
  879                  let (m, r) = match ty::get(self_ty).sty {
  880                      ty::ty_rptr(r, ref m) => (m.mutbl, r),
  881                      _ => rcx.tcx().sess.span_bug(deref_expr.span,
  882                              format!("bad overloaded deref type {}",
  883                                  method.ty.repr(rcx.tcx())))
  884                  };
  885                  {
  886                      let mc = mc::MemCategorizationContext::new(rcx);
  887                      let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i));
  888                      link_region(rcx, deref_expr.span, r,
  889                                  ty::BorrowKind::from_mutbl(m), self_cmt);
  890                  }
  891  
  892                  // Specialized version of constrain_call.
  893                  constrain_regions_in_type(rcx, r_deref_expr,
  894                                            infer::CallRcvr(deref_expr.span),
  895                                            self_ty);
  896                  constrain_regions_in_type(rcx, r_deref_expr,
  897                                            infer::CallReturn(deref_expr.span),
  898                                            fn_sig.output);
  899                  fn_sig.output
  900              }
  901              None => derefd_ty
  902          };
  903  
  904          match ty::get(derefd_ty).sty {
  905              ty::ty_rptr(r_ptr, _) => {
  906                  mk_subregion_due_to_dereference(rcx, deref_expr.span,
  907                                                  r_deref_expr, r_ptr);
  908              }
  909              _ => {}
  910          }
  911  
  912          match ty::deref(derefd_ty, true) {
  913              Some(mt) => derefd_ty = mt.ty,
  914              /* if this type can't be dereferenced, then there's already an error
  915                 in the session saying so. Just bail out for now */
  916              None => break
  917          }
  918      }
  919  }
  920  
  921  pub fn mk_subregion_due_to_dereference(rcx: &mut Rcx,
  922                                         deref_spanSpan,
  923                                         minimum_lifetimety::Region,
  924                                         maximum_lifetimety::Region) {
  925      rcx.fcx.mk_subr(true, infer::DerefPointer(deref_span),
  926                      minimum_lifetime, maximum_lifetime)
  927  }
  928  
  929  
  930  fn constrain_index(rcx: &mut Rcx,
  931                     index_expr: &ast::Expr,
  932                     indexed_tyty::t)
  933  {
  934      /*!
  935       * Invoked on any index expression that occurs.  Checks that if
  936       * this is a slice being indexed, the lifetime of the pointer
  937       * includes the deref expr.
  938       */
  939  
  940      debug!("constrain_index(index_expr=?, indexed_ty={}",
  941             rcx.fcx.infcx().ty_to_str(indexed_ty));
  942  
  943      let r_index_expr = ty::ReScope(index_expr.id);
  944      match ty::get(indexed_ty).sty {
  945          ty::ty_rptr(r_ptr, mt) => match ty::get(mt.ty).sty {
  946              ty::ty_vec(_, None) | ty::ty_str => {
  947                  rcx.fcx.mk_subr(true, infer::IndexSlice(index_expr.span),
  948                                  r_index_expr, r_ptr);
  949              }
  950              _ => {}
  951          },
  952  
  953          _ => {}
  954      }
  955  }
  956  
  957  fn constrain_regions_in_type_of_node(
  958      rcx: &mut Rcx,
  959      idast::NodeId,
  960      minimum_lifetimety::Region,
  961      origininfer::SubregionOrigin) {
  962      //! Guarantees that any lifetimes which appear in the type of
  963      //! the node `id` (after applying adjustments) are valid for at
  964      //! least `minimum_lifetime`
  965  
  966      let tcx = rcx.fcx.tcx();
  967  
  968      // Try to resolve the type.  If we encounter an error, then typeck
  969      // is going to fail anyway, so just stop here and let typeck
  970      // report errors later on in the writeback phase.
  971      let ty0 = rcx.resolve_node_type(id);
  972      let ty = ty::adjust_ty(tcx, origin.span(), id, ty0,
  973                             rcx.fcx.inh.adjustments.borrow().find(&id),
  974                             |method_call| rcx.resolve_method_type(method_call));
  975      debug!("constrain_regions_in_type_of_node(\
  976              ty={}, ty0={}, id={}, minimum_lifetime={:?})",
  977             ty_to_str(tcx, ty), ty_to_str(tcx, ty0),
  978             id, minimum_lifetime);
  979      constrain_regions_in_type(rcx, minimum_lifetime, origin, ty);
  980  }
  981  
  982  fn constrain_regions_in_type(
  983      rcx: &mut Rcx,
  984      minimum_lifetimety::Region,
  985      origininfer::SubregionOrigin,
  986      tyty::t) {
  987      /*!
  988       * Requires that any regions which appear in `ty` must be
  989       * superregions of `minimum_lifetime`.  Also enforces the constraint
  990       * that given a pointer type `&'r T`, T must not contain regions
  991       * that outlive 'r, as well as analogous constraints for other
  992       * lifetime'd types.
  993       *
  994       * This check prevents regions from being used outside of the block in
  995       * which they are valid.  Recall that regions represent blocks of
  996       * code or expressions: this requirement basically says "any place
  997       * that uses or may use a region R must be within the block of
  998       * code that R corresponds to."
  999       */
 1000  
 1001      let tcx = rcx.fcx.ccx.tcx;
 1002  
 1003      debug!("constrain_regions_in_type(minimum_lifetime={}, ty={})",
 1004             region_to_str(tcx, "", false, minimum_lifetime),
 1005             ty_to_str(tcx, ty));
 1006  
 1007      relate_nested_regions(tcx, Some(minimum_lifetime), ty, |r_sub, r_sup| {
 1008          debug!("relate_nested_regions(r_sub={}, r_sup={})",
 1009                  r_sub.repr(tcx),
 1010                  r_sup.repr(tcx));
 1011  
 1012          if r_sup.is_bound() || r_sub.is_bound() {
 1013              // a bound region is one which appears inside an fn type.
 1014              // (e.g., the `&` in `fn(&T)`).  Such regions need not be
 1015              // constrained by `minimum_lifetime` as they are placeholders
 1016              // for regions that are as-yet-unknown.
 1017          } else if r_sub == minimum_lifetime {
 1018              rcx.fcx.mk_subr(
 1019                  true, origin.clone(),
 1020                  r_sub, r_sup);
 1021          } else {
 1022              rcx.fcx.mk_subr(
 1023                  true, infer::ReferenceOutlivesReferent(ty, origin.span()),
 1024                  r_sub, r_sup);
 1025          }
 1026      });
 1027  }
 1028  
 1029  fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr,
 1030                 mutabilityast::Mutability, base: &ast::Expr) {
 1031      /*!
 1032       * Computes the guarantor for an expression `&base` and then
 1033       * ensures that the lifetime of the resulting pointer is linked
 1034       * to the lifetime of its guarantor (if any).
 1035       */
 1036  
 1037      debug!("link_addr_of(base=?)");
 1038  
 1039      let cmt = {
 1040          let mc = mc::MemCategorizationContext::new(rcx);
 1041          ignore_err!(mc.cat_expr(base))
 1042      };
 1043      link_region_from_node_type(rcx, expr.span, expr.id, mutability, cmt);
 1044  }
 1045  
 1046  fn link_local(rcx: &Rcx, local: &ast::Local) {
 1047      /*!
 1048       * Computes the guarantors for any ref bindings in a `let` and
 1049       * then ensures that the lifetime of the resulting pointer is
 1050       * linked to the lifetime of the initialization expression.
 1051       */
 1052  
 1053      debug!("regionck::for_local()");
 1054      let init_expr = match local.init {
 1055          None => { return; }
 1056          Some(expr) => expr,
 1057      };
 1058      let mc = mc::MemCategorizationContext::new(rcx);
 1059      let discr_cmt = ignore_err!(mc.cat_expr(init_expr));
 1060      link_pattern(rcx, mc, discr_cmt, local.pat);
 1061  }
 1062  
 1063  fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
 1064      /*!
 1065       * Computes the guarantors for any ref bindings in a match and
 1066       * then ensures that the lifetime of the resulting pointer is
 1067       * linked to the lifetime of its guarantor (if any).
 1068       */
 1069  
 1070      debug!("regionck::for_match()");
 1071      let mc = mc::MemCategorizationContext::new(rcx);
 1072      let discr_cmt = ignore_err!(mc.cat_expr(discr));
 1073      debug!("discr_cmt={}", discr_cmt.repr(rcx.tcx()));
 1074      for arm in arms.iter() {
 1075          for &root_pat in arm.pats.iter() {
 1076              link_pattern(rcx, mc, discr_cmt.clone(), root_pat);
 1077          }
 1078      }
 1079  }
 1080  
 1081  fn link_pattern(rcx: &Rcx,
 1082                  mcmc::MemCategorizationContext<Rcx>,
 1083                  discr_cmtmc::cmt,
 1084                  root_pat: &ast::Pat) {
 1085      /*!
 1086       * Link lifetimes of any ref bindings in `root_pat` to
 1087       * the pointers found in the discriminant, if needed.
 1088       */
 1089  
 1090      let _ = mc.cat_pattern(discr_cmt, root_pat, |mc, sub_cmt, sub_pat| {
 1091              match sub_pat.node {
 1092                  // `ref x` pattern
 1093                  ast::PatIdent(ast::BindByRef(mutbl), _, _) => {
 1094                      link_region_from_node_type(
 1095                          rcx, sub_pat.span, sub_pat.id,
 1096                          mutbl, sub_cmt);
 1097                  }
 1098  
 1099                  // `[_, ..slice, _]` pattern
 1100                  ast::PatVec(_, Some(slice_pat), _) => {
 1101                      match mc.cat_slice_pattern(sub_cmt, slice_pat) {
 1102                          Ok((slice_cmt, slice_mutbl, slice_r)) => {
 1103                              link_region(rcx, sub_pat.span, slice_r,
 1104                                          ty::BorrowKind::from_mutbl(slice_mutbl),
 1105                                          slice_cmt);
 1106                          }
 1107                          Err(()) => {}
 1108                      }
 1109                  }
 1110                  _ => {}
 1111              }
 1112          });
 1113  }
 1114  
 1115  fn link_autoref(rcx: &Rcx,
 1116                  expr: &ast::Expr,
 1117                  autoderefs: uint,
 1118                  autoref: &ty::AutoRef) {
 1119      /*!
 1120       * Link lifetime of borrowed pointer resulting from autoref
 1121       * to lifetimes in the value being autoref'd.
 1122       */
 1123  
 1124      debug!("link_autoref(autoref={:?})", autoref);
 1125      let mc = mc::MemCategorizationContext::new(rcx);
 1126      let expr_cmt = ignore_err!(mc.cat_expr_autoderefd(expr, autoderefs));
 1127      debug!("expr_cmt={}", expr_cmt.repr(rcx.tcx()));
 1128  
 1129      match *autoref {
 1130          ty::AutoPtr(r, m) => {
 1131              link_region(rcx, expr.span, r,
 1132                          ty::BorrowKind::from_mutbl(m), expr_cmt);
 1133          }
 1134  
 1135          ty::AutoBorrowVec(r, m) | ty::AutoBorrowVecRef(r, m) => {
 1136              let cmt_index = mc.cat_index(expr, expr_cmt, autoderefs+1);
 1137              link_region(rcx, expr.span, r,
 1138                          ty::BorrowKind::from_mutbl(m), cmt_index);
 1139          }
 1140  
 1141          ty::AutoBorrowObj(r, m) => {
 1142              let cmt_deref = mc.cat_deref_obj(expr, expr_cmt);
 1143              link_region(rcx, expr.span, r,
 1144                          ty::BorrowKind::from_mutbl(m), cmt_deref);
 1145          }
 1146  
 1147          ty::AutoUnsafe(_) => {}
 1148      }
 1149  }
 1150  
 1151  fn link_by_ref(rcx: &Rcx,
 1152                 expr: &ast::Expr,
 1153                 callee_scopeast::NodeId) {
 1154      /*!
 1155       * Computes the guarantor for cases where the `expr` is
 1156       * being passed by implicit reference and must outlive
 1157       * `callee_scope`.
 1158       */
 1159  
 1160      let tcx = rcx.tcx();
 1161      debug!("link_by_ref(expr={}, callee_scope={})",
 1162             expr.repr(tcx), callee_scope);
 1163      let mc = mc::MemCategorizationContext::new(rcx);
 1164      let expr_cmt = ignore_err!(mc.cat_expr(expr));
 1165      let region_min = ty::ReScope(callee_scope);
 1166      link_region(rcx, expr.span, region_min, ty::ImmBorrow, expr_cmt);
 1167  }
 1168  
 1169  fn link_region_from_node_type(rcx: &Rcx,
 1170                                spanSpan,
 1171                                idast::NodeId,
 1172                                mutblast::Mutability,
 1173                                cmt_borrowedmc::cmt) {
 1174      /*!
 1175       * Like `link_region()`, except that the region is
 1176       * extracted from the type of `id`, which must be some
 1177       * reference (`&T`, `&str`, etc).
 1178       */
 1179  
 1180      let rptr_ty = rcx.resolve_node_type(id);
 1181      if !ty::type_is_bot(rptr_ty) && !ty::type_is_error(rptr_ty) {
 1182          let tcx = rcx.fcx.ccx.tcx;
 1183          debug!("rptr_ty={}", ty_to_str(tcx, rptr_ty));
 1184          let r = ty::ty_region(tcx, span, rptr_ty);
 1185          link_region(rcx, span, r, ty::BorrowKind::from_mutbl(mutbl),
 1186                      cmt_borrowed);
 1187      }
 1188  }
 1189  
 1190  fn link_region(rcx: &Rcx,
 1191                 spanSpan,
 1192                 region_minty::Region,
 1193                 kindty::BorrowKind,
 1194                 cmt_borrowedmc::cmt) {
 1195      /*!
 1196       * Informs the inference engine that a borrow of `cmt`
 1197       * must have the borrow kind `kind` and lifetime `region_min`.
 1198       * If `cmt` is a deref of a region pointer with
 1199       * lifetime `r_borrowed`, this will add the constraint that
 1200       * `region_min <= r_borrowed`.
 1201       */
 1202  
 1203      // Iterate through all the things that must be live at least
 1204      // for the lifetime `region_min` for the borrow to be valid:
 1205      let mut cmt_borrowed = cmt_borrowed;
 1206      loop {
 1207          debug!("link_region(region_min={}, kind={}, cmt_borrowed={})",
 1208                 region_min.repr(rcx.tcx()),
 1209                 kind.repr(rcx.tcx()),
 1210                 cmt_borrowed.repr(rcx.tcx()));
 1211          match cmt_borrowed.cat.clone() {
 1212              mc::cat_deref(base, _, mc::BorrowedPtr(_, r_borrowed)) => {
 1213                  // References to an upvar `x` are translated to
 1214                  // `*x`, since that is what happens in the
 1215                  // underlying machine.  We detect such references
 1216                  // and treat them slightly differently, both to
 1217                  // offer better error messages and because we need
 1218                  // to infer the kind of borrow (mut, const, etc)
 1219                  // to use for each upvar.
 1220                  let cause = match base.cat {
 1221                      mc::cat_upvar(ref upvar_id, _) => {
 1222                          match rcx.fcx.inh.upvar_borrow_map.borrow_mut()
 1223                                   .find_mut(upvar_id) {
 1224                              Some(upvar_borrow) => {
 1225                                  debug!("link_region: {} <= {}",
 1226                                         region_min.repr(rcx.tcx()),
 1227                                         upvar_borrow.region.repr(rcx.tcx()));
 1228                                  adjust_upvar_borrow_kind_for_loan(
 1229                                      *upvar_id,
 1230                                      upvar_borrow,
 1231                                      kind);
 1232                                  infer::ReborrowUpvar(span, *upvar_id)
 1233                              }
 1234                              None => {
 1235                                  rcx.tcx().sess.span_bug(
 1236                                      span,
 1237                                      format!("Illegal upvar id: {}",
 1238                                              upvar_id.repr(rcx.tcx())));
 1239                              }
 1240                          }
 1241                      }
 1242  
 1243                      _ => {
 1244                          infer::Reborrow(span)
 1245                      }
 1246                  };
 1247  
 1248                  debug!("link_region: {} <= {}",
 1249                         region_min.repr(rcx.tcx()),
 1250                         r_borrowed.repr(rcx.tcx()));
 1251                  rcx.fcx.mk_subr(true, cause, region_min, r_borrowed);
 1252  
 1253                  if kind != ty::ImmBorrow {
 1254                      // If this is a mutable borrow, then the thing
 1255                      // being borrowed will have to be unique.
 1256                      // In user code, this means it must be an `&mut`
 1257                      // borrow, but for an upvar, we might opt
 1258                      // for an immutable-unique borrow.
 1259                      adjust_upvar_borrow_kind_for_unique(rcx, base);
 1260                  }
 1261  
 1262                  // Borrowing an `&mut` pointee for `region_min` is
 1263                  // only valid if the pointer resides in a unique
 1264                  // location which is itself valid for
 1265                  // `region_min`.  We don't care about the unique
 1266                  // part, but we may need to influence the
 1267                  // inference to ensure that the location remains
 1268                  // valid.
 1269                  //
 1270                  // FIXME(#8624) fixing borrowck will require this
 1271                  // if m == ast::m_mutbl {
 1272                  //    cmt_borrowed = cmt_base;
 1273                  // } else {
 1274                  //    return;
 1275                  // }
 1276                  return;
 1277              }
 1278              mc::cat_discr(cmt_base, _) |
 1279              mc::cat_downcast(cmt_base) |
 1280              mc::cat_deref(cmt_base, _, mc::GcPtr(..)) |
 1281              mc::cat_deref(cmt_base, _, mc::OwnedPtr) |
 1282              mc::cat_interior(cmt_base, _) => {
 1283                  // Interior or owned data requires its base to be valid
 1284                  cmt_borrowed = cmt_base;
 1285              }
 1286              mc::cat_deref(_, _, mc::UnsafePtr(..)) |
 1287              mc::cat_static_item |
 1288              mc::cat_copied_upvar(..) |
 1289              mc::cat_local(..) |
 1290              mc::cat_arg(..) |
 1291              mc::cat_upvar(..) |
 1292              mc::cat_rvalue(..) => {
 1293                  // These are all "base cases" with independent lifetimes
 1294                  // that are not subject to inference
 1295                  return;
 1296              }
 1297          }
 1298      }
 1299  }
 1300  
 1301  fn adjust_borrow_kind_for_assignment_lhs(rcx: &Rcx,
 1302                                           lhs: &ast::Expr) {
 1303      /*!
 1304       * Adjusts the inferred borrow_kind as needed to account
 1305       * for upvars that are assigned to in an assignment
 1306       * expression.
 1307       */
 1308  
 1309      let mc = mc::MemCategorizationContext::new(rcx);
 1310      let cmt = ignore_err!(mc.cat_expr(lhs));
 1311      adjust_upvar_borrow_kind_for_mut(rcx, cmt);
 1312  }
 1313  
 1314  fn adjust_upvar_borrow_kind_for_mut(rcx: &Rcx,
 1315                                      cmtmc::cmt) {
 1316      let mut cmt = cmt;
 1317      loop {
 1318          debug!("adjust_upvar_borrow_kind_for_mut(cmt={})",
 1319                 cmt.repr(rcx.tcx()));
 1320  
 1321          match cmt.cat.clone() {
 1322              mc::cat_deref(base, _, mc::OwnedPtr) |
 1323              mc::cat_interior(base, _) |
 1324              mc::cat_downcast(base) |
 1325              mc::cat_discr(base, _) => {
 1326                  // Interior or owned data is mutable if base is
 1327                  // mutable, so iterate to the base.
 1328                  cmt = base;
 1329                  continue;
 1330              }
 1331  
 1332              mc::cat_deref(base, _, mc::BorrowedPtr(..)) => {
 1333                  match base.cat {
 1334                      mc::cat_upvar(ref upvar_id, _) => {
 1335                          // if this is an implicit deref of an
 1336                          // upvar, then we need to modify the
 1337                          // borrow_kind of the upvar to make sure it
 1338                          // is inferred to mutable if necessary
 1339                          let mut upvar_borrow_map =
 1340                              rcx.fcx.inh.upvar_borrow_map.borrow_mut();
 1341                          let ub = upvar_borrow_map.get_mut(upvar_id);
 1342                          return adjust_upvar_borrow_kind(*upvar_id, ub, ty::MutBorrow);
 1343                      }
 1344  
 1345                      _ => {}
 1346                  }
 1347  
 1348                  // assignment to deref of an `&mut`
 1349                  // borrowed pointer implies that the
 1350                  // pointer itself must be unique, but not
 1351                  // necessarily *mutable*
 1352                  return adjust_upvar_borrow_kind_for_unique(rcx, base);
 1353              }
 1354  
 1355              mc::cat_deref(_, _, mc::UnsafePtr(..)) |
 1356              mc::cat_deref(_, _, mc::GcPtr) |
 1357              mc::cat_static_item |
 1358              mc::cat_rvalue(_) |
 1359              mc::cat_copied_upvar(_) |
 1360              mc::cat_local(_) |
 1361              mc::cat_arg(_) |
 1362              mc::cat_upvar(..) => {
 1363                  return;
 1364              }
 1365          }
 1366      }
 1367  }
 1368  
 1369  fn adjust_upvar_borrow_kind_for_unique(rcx: &Rcx, cmtmc::cmt) {
 1370      let mut cmt = cmt;
 1371      loop {
 1372          debug!("adjust_upvar_borrow_kind_for_unique(cmt={})",
 1373                 cmt.repr(rcx.tcx()));
 1374  
 1375          match cmt.cat.clone() {
 1376              mc::cat_deref(base, _, mc::OwnedPtr) |
 1377              mc::cat_interior(base, _) |
 1378              mc::cat_downcast(base) |
 1379              mc::cat_discr(base, _) => {
 1380                  // Interior or owned data is unique if base is
 1381                  // unique.
 1382                  cmt = base;
 1383                  continue;
 1384              }
 1385  
 1386              mc::cat_deref(base, _, mc::BorrowedPtr(..)) => {
 1387                  match base.cat {
 1388                      mc::cat_upvar(ref upvar_id, _) => {
 1389                          // if this is an implicit deref of an
 1390                          // upvar, then we need to modify the
 1391                          // borrow_kind of the upvar to make sure it
 1392                          // is inferred to unique if necessary
 1393                          let mut ub = rcx.fcx.inh.upvar_borrow_map.borrow_mut();
 1394                          let ub = ub.get_mut(upvar_id);
 1395                          return adjust_upvar_borrow_kind(*upvar_id, ub, ty::UniqueImmBorrow);
 1396                      }
 1397  
 1398                      _ => {}
 1399                  }
 1400  
 1401                  // for a borrowed pointer to be unique, its
 1402                  // base must be unique
 1403                  return adjust_upvar_borrow_kind_for_unique(rcx, base);
 1404              }
 1405  
 1406              mc::cat_deref(_, _, mc::UnsafePtr(..)) |
 1407              mc::cat_deref(_, _, mc::GcPtr) |
 1408              mc::cat_static_item |
 1409              mc::cat_rvalue(_) |
 1410              mc::cat_copied_upvar(_) |
 1411              mc::cat_local(_) |
 1412              mc::cat_arg(_) |
 1413              mc::cat_upvar(..) => {
 1414                  return;
 1415              }
 1416          }
 1417      }
 1418  }
 1419  
 1420  fn link_upvar_borrow_kind_for_nested_closures(rcx: &mut Rcx,
 1421                                                inner_upvar_idty::UpvarId,
 1422                                                outer_upvar_idty::UpvarId) {
 1423      /*!
 1424       * Indicates that the borrow_kind of `outer_upvar_id` must
 1425       * permit a reborrowing with the borrow_kind of `inner_upvar_id`.
 1426       * This occurs in nested closures, see comment above at the call to
 1427       * this function.
 1428       */
 1429  
 1430      debug!("link_upvar_borrow_kind: inner_upvar_id={:?} outer_upvar_id={:?}",
 1431             inner_upvar_id, outer_upvar_id);
 1432  
 1433      let mut upvar_borrow_map = rcx.fcx.inh.upvar_borrow_map.borrow_mut();
 1434      let inner_borrow = upvar_borrow_map.get_copy(&inner_upvar_id);
 1435      match upvar_borrow_map.find_mut(&outer_upvar_id) {
 1436          Some(outer_borrow) => {
 1437              adjust_upvar_borrow_kind(outer_upvar_id, outer_borrow, inner_borrow.kind);
 1438          }
 1439          None => { /* outer closure is not a stack closure */ }
 1440      }
 1441  }
 1442  
 1443  fn adjust_upvar_borrow_kind_for_loan(upvar_idty::UpvarId,
 1444                                       upvar_borrow: &mut ty::UpvarBorrow,
 1445                                       kindty::BorrowKind) {
 1446      debug!("adjust_upvar_borrow_kind_for_loan: upvar_id={:?} kind={:?} -> {:?}",
 1447             upvar_id, upvar_borrow.kind, kind);
 1448  
 1449      adjust_upvar_borrow_kind(upvar_id, upvar_borrow, kind)
 1450  }
 1451  
 1452  fn adjust_upvar_borrow_kind(upvar_idty::UpvarId,
 1453                              upvar_borrow: &mut ty::UpvarBorrow,
 1454                              kindty::BorrowKind) {
 1455      /*!
 1456       * We infer the borrow_kind with which to borrow upvars in a stack
 1457       * closure. The borrow_kind basically follows a lattice of
 1458       * `imm < unique-imm < mut`, moving from left to right as needed (but never
 1459       * right to left). Here the argument `mutbl` is the borrow_kind that
 1460       * is required by some particular use.
 1461       */
 1462  
 1463      debug!("adjust_upvar_borrow_kind: id={:?} kind=({:?} -> {:?})",
 1464             upvar_id, upvar_borrow.kind, kind);
 1465  
 1466      match (upvar_borrow.kind, kind) {
 1467          // Take RHS:
 1468          (ty::ImmBorrow, ty::UniqueImmBorrow) |
 1469          (ty::ImmBorrow, ty::MutBorrow) |
 1470          (ty::UniqueImmBorrow, ty::MutBorrow) => {
 1471              upvar_borrow.kind = kind;
 1472          }
 1473          // Take LHS:
 1474          (ty::ImmBorrow, ty::ImmBorrow) |
 1475          (ty::UniqueImmBorrow, ty::ImmBorrow) |
 1476          (ty::UniqueImmBorrow, ty::UniqueImmBorrow) |
 1477          (ty::MutBorrow, _) => {
 1478          }
 1479      }
 1480  }


librustc/middle/typeck/check/regionck.rs:781:1-781:1 -fn- definition:
fn constrain_call(rcx: &mut Rcx,
                  // might be expr_call, expr_method_call, or an overloaded
                  // operator
references:- 6
457:         ast::ExprMethodCall(_, _, ref args) => {
458:             constrain_call(rcx, None, expr, Some(*args.get(0)),
459:                            args.slice_from(1), false);
--
501:                 Some(method) => {
502:                     constrain_call(rcx, None, expr, Some(base), [], true);
503:                     ty::ty_fn_ret(method.ty)


librustc/middle/typeck/check/regionck.rs:158:1-158:1 -struct- definition:
pub struct Rcx<'a> {
    fcx: &'a FnCtxt<'a>,
    // id of innermost fn or loop
references:- 34


librustc/middle/typeck/check/regionck.rs:1189:1-1189:1 -fn- definition:
fn link_region(rcx: &Rcx,
               span: Span,
               region_min: ty::Region,
references:- 8
1136:             let cmt_index = mc.cat_index(expr, expr_cmt, autoderefs+1);
1137:             link_region(rcx, expr.span, r,
1138:                         ty::BorrowKind::from_mutbl(m), cmt_index);
--
1184:         let r = ty::ty_region(tcx, span, rptr_ty);
1185:         link_region(rcx, span, r, ty::BorrowKind::from_mutbl(mutbl),
1186:                     cmt_borrowed);


librustc/middle/typeck/check/regionck.rs:1451:1-1451:1 -fn- definition:
fn adjust_upvar_borrow_kind(upvar_id: ty::UpvarId,
                            upvar_borrow: &mut ty::UpvarBorrow,
                            kind: ty::BorrowKind) {
references:- 4
1436:         Some(outer_borrow) => {
1437:             adjust_upvar_borrow_kind(outer_upvar_id, outer_borrow, inner_borrow.kind);
1438:         }
--
1449:     adjust_upvar_borrow_kind(upvar_id, upvar_borrow, kind)
1450: }


librustc/middle/typeck/check/regionck.rs:1368:1-1368:1 -fn- definition:
fn adjust_upvar_borrow_kind_for_unique(rcx: &Rcx, cmt: mc::cmt) {
    let mut cmt = cmt;
    loop {
references:- 3
1402:                 // base must be unique
1403:                 return adjust_upvar_borrow_kind_for_unique(rcx, base);
1404:             }


librustc/middle/typeck/check/regionck.rs:1150:1-1150:1 -fn- definition:
fn link_by_ref(rcx: &Rcx,
               expr: &ast::Expr,
               callee_scope: ast::NodeId) {
references:- 2
835:         if implicitly_ref_args {
836:             link_by_ref(rcx, arg_expr, callee_scope);
837:         }
--
845:         if implicitly_ref_args {
846:             link_by_ref(rcx, r, callee_scope);
847:         }


librustc/middle/typeck/check/regionck.rs:165:1-165:1 -fn- definition:
fn region_of_def(fcx: &FnCtxt, def: ast::Def) -> ty::Region {
    /*!
     * Returns the validity region of `def` -- that is, how long
references:- 2
688:             // Guarantee that the closure does not outlive the variable itself.
689:             let en_region = region_of_def(rcx.fcx, def);
690:             debug!("en_region = {}", en_region.repr(tcx));


librustc/middle/typeck/check/regionck.rs:1080:1-1080:1 -fn- definition:
fn link_pattern(rcx: &Rcx,
                mc: mc::MemCategorizationContext<Rcx>,
                discr_cmt: mc::cmt,
references:- 2
1059:     let discr_cmt = ignore_err!(mc.cat_expr(init_expr));
1060:     link_pattern(rcx, mc, discr_cmt, local.pat);
1061: }
--
1075:         for &root_pat in arm.pats.iter() {
1076:             link_pattern(rcx, mc, discr_cmt.clone(), root_pat);
1077:         }


librustc/middle/typeck/check/regionck.rs:920:1-920:1 -fn- definition:
pub fn mk_subregion_due_to_dereference(rcx: &mut Rcx,
                                       deref_span: Span,
                                       minimum_lifetime: ty::Region,
references:- 2
905:             ty::ty_rptr(r_ptr, _) => {
906:                 mk_subregion_due_to_dereference(rcx, deref_expr.span,
907:                                                 r_deref_expr, r_ptr);


librustc/middle/typeck/check/regionck.rs:1168:1-1168:1 -fn- definition:
fn link_region_from_node_type(rcx: &Rcx,
                              span: Span,
                              id: ast::NodeId,
references:- 2
1093:                 ast::PatIdent(ast::BindByRef(mutbl), _, _) => {
1094:                     link_region_from_node_type(
1095:                         rcx, sub_pat.span, sub_pat.id,


librustc/middle/typeck/check/regionck.rs:981:1-981:1 -fn- definition:
fn constrain_regions_in_type(
    rcx: &mut Rcx,
    minimum_lifetime: ty::Region,
references:- 7
545:                     let source_ty = rcx.resolve_expr_type_adjusted(source);
546:                     constrain_regions_in_type(
547:                         rcx,
--
851:     // valid for the function call:
852:     constrain_regions_in_type(
853:         rcx, callee_region, infer::CallReturn(call_expr.span),
--
892:                 // Specialized version of constrain_call.
893:                 constrain_regions_in_type(rcx, r_deref_expr,
894:                                           infer::CallRcvr(deref_expr.span),
--
978:            id, minimum_lifetime);
979:     constrain_regions_in_type(rcx, minimum_lifetime, origin, ty);
980: }


librustc/middle/typeck/check/regionck.rs:360:1-360:1 -fn- definition:
fn constrain_bindings_in_pat(pat: &ast::Pat, rcx: &mut Rcx) {
    let tcx = rcx.fcx.tcx();
    debug!("regionck::visit_pat(pat={})", pat.repr(tcx));
references:- 2
347:     for &p in arm.pats.iter() {
348:         constrain_bindings_in_pat(p, rcx);
349:     }
--
355:     // see above
356:     constrain_bindings_in_pat(l.pat, rcx);
357:     link_local(rcx, l);


librustc/middle/typeck/check/regionck.rs:956:1-956:1 -fn- definition:
fn constrain_regions_in_type_of_node(
    rcx: &mut Rcx,
    id: ast::NodeId,
references:- 4
388:         let var_region = tcx.region_maps.var_region(id);
389:         constrain_regions_in_type_of_node(
390:             rcx, id, var_region,
--
826:         // valid for at least the lifetime of the function:
827:         constrain_regions_in_type_of_node(
828:             rcx, arg_expr.id, callee_region,
--
842:         debug!("Receiver");
843:         constrain_regions_in_type_of_node(
844:             rcx, r.id, callee_region, infer::CallRcvr(r.span));


librustc/middle/typeck/check/regionck.rs:1300:1-1300:1 -fn- definition:
fn adjust_borrow_kind_for_assignment_lhs(rcx: &Rcx,
                                         lhs: &ast::Expr) {
    /*!
references:- 2
474:             adjust_borrow_kind_for_assignment_lhs(rcx, lhs);