(index<- )        ./librustc/middle/typeck/check/regionmanip.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri Apr 25 22:40:04 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  // #![warn(deprecated_mode)]
  12  
  13  use middle::ty;
  14  use middle::ty_fold;
  15  use middle::ty_fold::TypeFolder;
  16  
  17  use collections::HashMap;
  18  use util::ppaux::Repr;
  19  use util::ppaux;
  20  
  21  // Helper functions related to manipulating region types.
  22  
  23  pub fn replace_late_bound_regions_in_fn_sig(
  24          tcx: &ty::ctxt,
  25          fn_sig: &ty::FnSig,
  26          mapf: |ty::BoundRegion-> ty::Region)
  27          -> (HashMap<ty::BoundRegion,ty::Region>, ty::FnSig) {
  28      debug!("replace_late_bound_regions_in_fn_sig({})", fn_sig.repr(tcx));
  29  
  30      let mut map = HashMap::new();
  31      let fn_sig = {
  32          let mut f = ty_fold::RegionFolder::regions(tcx, |r| {
  33              debug!("region r={}", r.to_str());
  34              match r {
  35                  ty::ReLateBound(s, br) if s == fn_sig.binder_id => {
  36                      *map.find_or_insert_with(br, |_| mapf(br))
  37                  }
  38                  _ => r
  39              }
  40          });
  41          ty_fold::super_fold_sig(&mut f, fn_sig)
  42      };
  43      debug!("resulting map: {}", map);
  44      (map, fn_sig)
  45  }
  46  
  47  pub fn relate_nested_regions(tcx: &ty::ctxt,
  48                               opt_regionOption<ty::Region>,
  49                               tyty::t,
  50                               relate_op: |ty::Region, ty::Region|) {
  51      /*!
  52       * This rather specialized function walks each region `r` that appear
  53       * in `ty` and invokes `relate_op(r_encl, r)` for each one.  `r_encl`
  54       * here is the region of any enclosing `&'r T` pointer.  If there is
  55       * no enclosing pointer, and `opt_region` is Some, then `opt_region.get()`
  56       * is used instead.  Otherwise, no callback occurs at all).
  57       *
  58       * Here are some examples to give you an intution:
  59       *
  60       * - `relate_nested_regions(Some('r1), &'r2 uint)` invokes
  61       *   - `relate_op('r1, 'r2)`
  62       * - `relate_nested_regions(Some('r1), &'r2 &'r3 uint)` invokes
  63       *   - `relate_op('r1, 'r2)`
  64       *   - `relate_op('r2, 'r3)`
  65       * - `relate_nested_regions(None, &'r2 &'r3 uint)` invokes
  66       *   - `relate_op('r2, 'r3)`
  67       * - `relate_nested_regions(None, &'r2 &'r3 &'r4 uint)` invokes
  68       *   - `relate_op('r2, 'r3)`
  69       *   - `relate_op('r2, 'r4)`
  70       *   - `relate_op('r3, 'r4)`
  71       *
  72       * This function is used in various pieces of code because we enforce the
  73       * constraint that a region pointer cannot outlive the things it points at.
  74       * Hence, in the second example above, `'r2` must be a subregion of `'r3`.
  75       */
  76  
  77      let mut rr = RegionRelator { tcx: tcx,
  78                                   stack: Vec::new(),
  79                                   relate_op: relate_op };
  80      match opt_region {
  81          Some(o_r) => { rr.stack.push(o_r); }
  82          None => {}
  83      }
  84      rr.fold_ty(ty);
  85  
  86      struct RegionRelator<'a> {
  87          tcx: &'a ty::ctxt,
  88          stack: Vec<ty::Region>,
  89          relate_op: |ty::Region, ty::Region|: 'a,
  90      }
  91  
  92      // FIXME(#10151) -- Define more precisely when a region is
  93      // considered "nested". Consider taking variance into account as
  94      // well.
  95  
  96      impl<'a> TypeFolder for RegionRelator<'a> {
  97          fn tcx<'a>(&'a self) -> &'a ty::ctxt {
  98              self.tcx
  99          }
 100  
 101          fn fold_ty(&mut self, tyty::t) -> ty::t {
 102              match ty::get(ty).sty {
 103                  ty::ty_rptr(r, ty::mt {ty, ..}) => {
 104                      self.relate(r);
 105                      self.stack.push(r);
 106                      ty_fold::super_fold_ty(self, ty);
 107                      self.stack.pop().unwrap();
 108                  }
 109  
 110                  _ => {
 111                      ty_fold::super_fold_ty(self, ty);
 112                  }
 113              }
 114  
 115              ty
 116          }
 117  
 118          fn fold_region(&mut self, rty::Region) -> ty::Region {
 119              self.relate(r);
 120              r
 121          }
 122      }
 123  
 124      impl<'a> RegionRelator<'a> {
 125          fn relate(&mut self, r_subty::Region) {
 126              for &r in self.stack.iter() {
 127                  if !r.is_bound() && !r_sub.is_bound() {
 128                      (self.relate_op)(r, r_sub);
 129                  }
 130              }
 131          }
 132      }
 133  }
 134  
 135  pub fn relate_free_regions(tcx: &ty::ctxt, fn_sig: &ty::FnSig) {
 136      /*!
 137       * This function populates the region map's `free_region_map`.
 138       * It walks over the transformed self type and argument types
 139       * for each function just before we check the body of that
 140       * function, looking for types where you have a borrowed
 141       * pointer to other borrowed data (e.g., `&'a &'b [uint]`.
 142       * We do not allow references to outlive the things they
 143       * point at, so we can assume that `'a <= 'b`.
 144       *
 145       * Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs`
 146       */
 147  
 148      debug!("relate_free_regions >>");
 149  
 150      let mut all_tys = Vec::new();
 151      for arg in fn_sig.inputs.iter() {
 152          all_tys.push(*arg);
 153      }
 154  
 155      for &t in all_tys.iter() {
 156          debug!("relate_free_regions(t={})", ppaux::ty_to_str(tcx, t));
 157          relate_nested_regions(tcx, None, t, |a, b| {
 158              match (&a, &b) {
 159                  (&ty::ReFree(free_a), &ty::ReFree(free_b)) => {
 160                      tcx.region_maps.relate_free_regions(free_a, free_b);
 161                  }
 162                  _ => {}
 163              }
 164          })
 165      }
 166  
 167      debug!("<< relate_free_regions");
 168  }


librustc/middle/typeck/check/regionmanip.rs:86:4-86:4 -struct- definition:
    struct RegionRelator<'a> {
        tcx: &'a ty::ctxt,
        stack: Vec<ty::Region>,
references:- 3
77:     let mut rr = RegionRelator { tcx: tcx,
78:                                  stack: Vec::new(),
--
124:     impl<'a> RegionRelator<'a> {
125:         fn relate(&mut self, r_sub: ty::Region) {


librustc/middle/typeck/check/regionmanip.rs:46:1-46:1 -fn- definition:
pub fn relate_nested_regions(tcx: &ty::ctxt,
                             opt_region: Option<ty::Region>,
                             ty: ty::t,
references:- 2
156:         debug!("relate_free_regions(t={})", ppaux::ty_to_str(tcx, t));
157:         relate_nested_regions(tcx, None, t, |a, b| {
158:             match (&a, &b) {
librustc/middle/typeck/check/regionck.rs:
1007:     relate_nested_regions(tcx, Some(minimum_lifetime), ty, |r_sub, r_sup| {
1008:         debug!("relate_nested_regions(r_sub={}, r_sup={})",


librustc/middle/typeck/check/regionmanip.rs:22:1-22:1 -fn- definition:
pub fn replace_late_bound_regions_in_fn_sig(
        tcx: &ty::ctxt,
        fn_sig: &ty::FnSig,
references:- 6
librustc/middle/typeck/check/method.rs:
1219:         // signature with region variables
1220:         let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(
1221:             tcx, &fn_sig,
librustc/middle/typeck/infer/mod.rs:
794:         let (map, fn_sig) =
795:             replace_late_bound_regions_in_fn_sig(self.tcx, fsig, |br| {
796:                 let rvar = self.next_region_var(
librustc/middle/typeck/check/mod.rs:
1930:         // signature with region variables
1931:         let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
1932:             fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
--
2278:                     let (_, sig) =
2279:                         replace_late_bound_regions_in_fn_sig(
2280:                             tcx, &cenv.sig,
librustc/middle/typeck/infer/sub.rs:
176:         let (skol_map, b_sig) = {
177:             replace_late_bound_regions_in_fn_sig(self.get_ref().infcx.tcx, b, |br| {
178:                 let skol = self.get_ref().infcx.region_vars.new_skolemized(br);