(index<- )        ./librustc/middle/typeck/infer/lub.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  use middle::ty::{BuiltinBounds};
  13  use middle::ty::RegionVid;
  14  use middle::ty;
  15  use middle::typeck::infer::then;
  16  use middle::typeck::infer::combine::*;
  17  use middle::typeck::infer::glb::Glb;
  18  use middle::typeck::infer::lattice::*;
  19  use middle::typeck::infer::sub::Sub;
  20  use middle::typeck::infer::to_str::InferStr;
  21  use middle::typeck::infer::{cres, InferCtxt};
  22  use middle::typeck::infer::fold_regions_in_sig;
  23  use middle::typeck::infer::{TypeTrace, Subtype};
  24  use collections::HashMap;
  25  use syntax::ast::{Many, Once, NodeId};
  26  use syntax::ast::{NormalFn, UnsafeFn};
  27  use syntax::ast::{Onceness, FnStyle};
  28  use util::ppaux::mt_to_str;
  29  
  30  pub struct Lub<'f>(pub CombineFields<'f>);  // least-upper-bound: common supertype
  31  
  32  impl<'f> Lub<'f> {
  33      pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> { let Lub(ref v) = *self; v }
  34  }
  35  
  36  impl<'f> Combine for Lub<'f> {
  37      fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx }
  38      fn tag(&self) -> ~str { "lub".to_owned() }
  39      fn a_is_expected(&self) -> bool { self.get_ref().a_is_expected }
  40      fn trace(&self) -> TypeTrace { self.get_ref().trace.clone() }
  41  
  42      fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.get_ref().clone()) }
  43      fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.get_ref().clone()) }
  44      fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.get_ref().clone()) }
  45  
  46      fn mts(&self, a&ty::mt, b&ty::mt) -> cres<ty::mt> {
  47          let tcx = self.get_ref().infcx.tcx;
  48  
  49          debug!("{}.mts({}, {})",
  50                 self.tag(),
  51                 mt_to_str(tcx, a),
  52                 mt_to_str(tcx, b));
  53  
  54          if a.mutbl != b.mutbl {
  55              return Err(ty::terr_mutability)
  56          }
  57  
  58          let m = a.mutbl;
  59          match m {
  60            MutImmutable => {
  61              self.tys(a.ty, b.ty).and_then(|t| Ok(ty::mt {ty: t, mutbl: m}) )
  62            }
  63  
  64            MutMutable => {
  65              self.get_ref().infcx.try(|| {
  66                  eq_tys(self, a.ty, b.ty).then(|| {
  67                      Ok(ty::mt {ty: a.ty, mutbl: m})
  68                  })
  69              }).or_else(|e| Err(e))
  70            }
  71          }
  72      }
  73  
  74      fn contratys(&self, aty::t, bty::t) -> cres<ty::t> {
  75          self.glb().tys(a, b)
  76      }
  77  
  78      fn fn_styles(&self, aFnStyle, bFnStyle) -> cres<FnStyle> {
  79          match (a, b) {
  80            (UnsafeFn, _) | (_, UnsafeFn) => Ok(UnsafeFn),
  81            (NormalFn, NormalFn) => Ok(NormalFn),
  82          }
  83      }
  84  
  85      fn oncenesses(&self, aOnceness, bOnceness) -> cres<Onceness> {
  86          match (a, b) {
  87              (Once, _) | (_, Once) => Ok(Once),
  88              (Many, Many) => Ok(Many)
  89          }
  90      }
  91  
  92      fn bounds(&self, aBuiltinBounds, bBuiltinBounds) -> cres<BuiltinBounds> {
  93          // More bounds is a subtype of fewer bounds, so
  94          // the LUB (mutual supertype) is the intersection.
  95          Ok(a.intersection(b))
  96      }
  97  
  98      fn contraregions(&self, aty::Region, bty::Region)
  99                      -> cres<ty::Region> {
 100          self.glb().regions(a, b)
 101      }
 102  
 103      fn regions(&self, aty::Region, bty::Region) -> cres<ty::Region> {
 104          debug!("{}.regions({:?}, {:?})",
 105                 self.tag(),
 106                 a.inf_str(self.get_ref().infcx),
 107                 b.inf_str(self.get_ref().infcx));
 108  
 109          Ok(self.get_ref().infcx.region_vars.lub_regions(Subtype(self.trace()), a, b))
 110      }
 111  
 112      fn fn_sigs(&self, a&ty::FnSig, b&ty::FnSig) -> cres<ty::FnSig> {
 113          // Note: this is a subtle algorithm.  For a full explanation,
 114          // please see the large comment in `region_inference.rs`.
 115  
 116          // Take a snapshot.  We'll never roll this back, but in later
 117          // phases we do want to be able to examine "all bindings that
 118          // were created as part of this type comparison", and making a
 119          // snapshot is a convenient way to do that.
 120          let snapshot = self.get_ref().infcx.region_vars.start_snapshot();
 121  
 122          // Instantiate each bound region with a fresh region variable.
 123          let (a_with_fresh, a_map) =
 124              self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
 125                  self.trace(), a);
 126          let (b_with_fresh, _) =
 127              self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
 128                  self.trace(), b);
 129  
 130          // Collect constraints.
 131          let sig0 = if_ok!(super_fn_sigs(self, &a_with_fresh, &b_with_fresh));
 132          debug!("sig0 = {}", sig0.inf_str(self.get_ref().infcx));
 133  
 134          // Generalize the regions appearing in sig0 if possible
 135          let new_vars =
 136              self.get_ref().infcx.region_vars.vars_created_since_snapshot(snapshot);
 137          let sig1 =
 138              fold_regions_in_sig(
 139                  self.get_ref().infcx.tcx,
 140                  &sig0,
 141                  |r| generalize_region(self, snapshot, new_vars.as_slice(),
 142                                        sig0.binder_id, &a_map, r));
 143          return Ok(sig1);
 144  
 145          fn generalize_region(this&Lub,
 146                               snapshotuint,
 147                               new_vars&[RegionVid],
 148                               new_scopeNodeId,
 149                               a_map&HashMap<ty::BoundRegion, ty::Region>,
 150                               r0ty::Region)
 151                               -> ty::Region {
 152              // Regions that pre-dated the LUB computation stay as they are.
 153              if !is_var_in_set(new_vars, r0) {
 154                  assert!(!r0.is_bound());
 155                  debug!("generalize_region(r0={:?}): not new variable", r0);
 156                  return r0;
 157              }
 158  
 159              let tainted = this.get_ref().infcx.region_vars.tainted(snapshot, r0);
 160  
 161              // Variables created during LUB computation which are
 162              // *related* to regions that pre-date the LUB computation
 163              // stay as they are.
 164              if !tainted.iter().all(|r| is_var_in_set(new_vars, *r)) {
 165                  debug!("generalize_region(r0={:?}): \
 166                          non-new-variables found in {:?}",
 167                         r0, tainted);
 168                  assert!(!r0.is_bound());
 169                  return r0;
 170              }
 171  
 172              // Otherwise, the variable must be associated with at
 173              // least one of the variables representing bound regions
 174              // in both A and B.  Replace the variable with the "first"
 175              // bound region from A that we find it to be associated
 176              // with.
 177              for (a_br, a_r) in a_map.iter() {
 178                  if tainted.iter().any(|x| x == a_r) {
 179                      debug!("generalize_region(r0={:?}): \
 180                              replacing with {:?}, tainted={:?}",
 181                             r0, *a_br, tainted);
 182                      return ty::ReLateBound(new_scope, *a_br);
 183                  }
 184              }
 185  
 186              this.get_ref().infcx.tcx.sess.span_bug(
 187                  this.get_ref().trace.origin.span(),
 188                  format!("Region {:?} is not associated with \
 189                          any bound region from A!", r0))
 190          }
 191      }
 192  
 193      fn tys(&self, aty::t, bty::t) -> cres<ty::t> {
 194          super_lattice_tys(self, a, b)
 195      }
 196  }


librustc/middle/typeck/infer/lub.rs:29:1-29:1 -struct- definition:
pub struct Lub<'f>(pub CombineFields<'f>);  // least-upper-bound: common supertype
impl<'f> Lub<'f> {
    pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> { let Lub(ref v) = *self; v }
references:- 10
32: impl<'f> Lub<'f> {
33:     pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> { let Lub(ref v) = *self; v }
--
42:     fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.get_ref().clone()) }
43:     fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.get_ref().clone()) }
44:     fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.get_ref().clone()) }
--
145:         fn generalize_region(this: &Lub,
146:                              snapshot: uint,
librustc/middle/typeck/infer/sub.rs:
42:     fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.get_ref().clone()) }
43:     fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.get_ref().clone()) }
44:     fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.get_ref().clone()) }
librustc/middle/typeck/infer/mod.rs:
511:     pub fn lub<'a>(&'a self, a_is_expected: bool, trace: TypeTrace) -> Lub<'a> {
512:         Lub(self.combine_fields(a_is_expected, trace))
librustc/middle/typeck/infer/combine.rs:
78:     fn sub<'a>(&'a self) -> Sub<'a>;
79:     fn lub<'a>(&'a self) -> Lub<'a>;
80:     fn glb<'a>(&'a self) -> Glb<'a>;
librustc/middle/typeck/infer/glb.rs:
43:     fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.get_ref().clone()) }
44:     fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.get_ref().clone()) }
45:     fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.get_ref().clone()) }
librustc/middle/typeck/infer/lattice.rs:
347: impl<'f> TyLatticeDir for Lub<'f> {
348:     fn ty_bot(&self, t: ty::t) -> cres<ty::t> {
librustc/middle/typeck/infer/lub.rs:
36: impl<'f> Combine for Lub<'f> {
37:     fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx }