(index<- )        ./librustc/middle/typeck/infer/lattice.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  /*!
  12   *
  13   * # Lattice Variables
  14   *
  15   * This file contains generic code for operating on inference variables
  16   * that are characterized by an upper- and lower-bound.  The logic and
  17   * reasoning is explained in detail in the large comment in `infer.rs`.
  18   *
  19   * The code in here is defined quite generically so that it can be
  20   * applied both to type variables, which represent types being inferred,
  21   * and fn variables, which represent function types being inferred.
  22   * It may eventually be applied to ther types as well, who knows.
  23   * In some cases, the functions are also generic with respect to the
  24   * operation on the lattice (GLB vs LUB).
  25   *
  26   * Although all the functions are generic, we generally write the
  27   * comments in a way that is specific to type variables and the LUB
  28   * operation.  It's just easier that way.
  29   *
  30   * In general all of the functions are defined parametrically
  31   * over a `LatticeValue`, which is a value defined with respect to
  32   * a lattice.
  33   */
  34  
  35  
  36  use middle::ty::{RegionVid, TyVar, Vid};
  37  use middle::ty;
  38  use middle::typeck::infer::{then, ToUres};
  39  use middle::typeck::infer::*;
  40  use middle::typeck::infer::combine::*;
  41  use middle::typeck::infer::glb::Glb;
  42  use middle::typeck::infer::lub::Lub;
  43  use middle::typeck::infer::unify::*;
  44  use middle::typeck::infer::sub::Sub;
  45  use middle::typeck::infer::to_str::InferStr;
  46  use util::common::indenter;
  47  
  48  use collections::HashMap;
  49  
  50  trait LatticeValue {
  51      fn sub(cf: CombineFields, a: &Self, b: &Self) -> ures;
  52      fn lub(cf: CombineFields, a: &Self, b: &Self) -> cres<Self>;
  53      fn glb(cf: CombineFields, a: &Self, b: &Self) -> cres<Self>;
  54  }
  55  
  56  pub type LatticeOp<'a, T> =
  57      |cf: CombineFields, a: &T, b: &T|: 'a -> cres<T>;
  58  
  59  impl LatticeValue for ty::t {
  60      fn sub(cfCombineFields, a&ty::t, b&ty::t) -> ures {
  61          Sub(cf).tys(*a, *b).to_ures()
  62      }
  63  
  64      fn lub(cfCombineFields, a&ty::t, b&ty::t) -> cres<ty::t> {
  65          Lub(cf).tys(*a, *b)
  66      }
  67  
  68      fn glb(cfCombineFields, a&ty::t, b&ty::t) -> cres<ty::t> {
  69          Glb(cf).tys(*a, *b)
  70      }
  71  }
  72  
  73  pub trait CombineFieldsLatticeMethods {
  74      fn var_sub_var<T:Clone + InferStr + LatticeValue,
  75                     V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(&self,
  76                                                                       a_id: V,
  77                                                                       b_id: V)
  78                                                                       -> ures;
  79      /// make variable a subtype of T
  80      fn var_sub_t<T:Clone + InferStr + LatticeValue,
  81                   V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
  82                   &self,
  83                   a_id: V,
  84                   b: T)
  85                   -> ures;
  86      fn t_sub_var<T:Clone + InferStr + LatticeValue,
  87                   V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
  88                   &self,
  89                   a: T,
  90                   b_id: V)
  91                   -> ures;
  92      fn merge_bnd<T:Clone + InferStr + LatticeValue>(
  93                   &self,
  94                   a: &Bound<T>,
  95                   b: &Bound<T>,
  96                   lattice_op: LatticeOp<T>)
  97                   -> cres<Bound<T>>;
  98      fn set_var_to_merged_bounds<T:Clone + InferStr + LatticeValue,
  99                                  V:Clone+Eq+ToStr+Vid+UnifyVid<Bounds<T>>>(
 100                                  &self,
 101                                  v_id: V,
 102                                  a: &Bounds<T>,
 103                                  b: &Bounds<T>,
 104                                  rank: uint)
 105                                  -> ures;
 106      fn bnds<T:Clone + InferStr + LatticeValue>(
 107              &self,
 108              a: &Bound<T>,
 109              b: &Bound<T>)
 110              -> ures;
 111  }
 112  
 113  impl<'f> CombineFieldsLatticeMethods for CombineFields<'f> {
 114      fn var_sub_var<T:Clone + InferStr + LatticeValue,
 115                     V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
 116                     &self,
 117                     a_idV,
 118                     b_idV)
 119                     -> ures {
 120          /*!
 121           *
 122           * Make one variable a subtype of another variable.  This is a
 123           * subtle and tricky process, as described in detail at the
 124           * top of infer.rs*/
 125  
 126          // Need to make sub_id a subtype of sup_id.
 127          let node_a = self.infcx.get(a_id);
 128          let node_b = self.infcx.get(b_id);
 129          let a_id = node_a.root.clone();
 130          let b_id = node_b.root.clone();
 131          let a_bounds = node_a.possible_types.clone();
 132          let b_bounds = node_b.possible_types.clone();
 133  
 134          debug!("vars({}={} <: {}={})",
 135                 a_id.to_str(), a_bounds.inf_str(self.infcx),
 136                 b_id.to_str(), b_bounds.inf_str(self.infcx));
 137  
 138          if a_id == b_id { return uok(); }
 139  
 140          // If both A's UB and B's LB have already been bound to types,
 141          // see if we can make those types subtypes.
 142          match (&a_bounds.ub, &b_bounds.lb) {
 143              (&Some(ref a_ub), &Some(ref b_lb)) => {
 144                  let r = self.infcx.try(
 145                      || LatticeValue::sub(self.clone(), a_ub, b_lb));
 146                  match r {
 147                      Ok(()) => {
 148                          return Ok(());
 149                      }
 150                      Err(_) => { /*fallthrough */ }
 151                  }
 152              }
 153              _ => { /*fallthrough*/ }
 154          }
 155  
 156          // Otherwise, we need to merge A and B so as to guarantee that
 157          // A remains a subtype of B.  Actually, there are other options,
 158          // but that's the route we choose to take.
 159  
 160          let (new_root, new_rank) = self.infcx.unify(&node_a, &node_b);
 161          self.set_var_to_merged_bounds(new_root,
 162                                        &a_bounds, &b_bounds,
 163                                        new_rank)
 164      }
 165  
 166      /// make variable a subtype of T
 167      fn var_sub_t<T:Clone + InferStr + LatticeValue,
 168                   V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
 169                   &self,
 170                   a_idV,
 171                   bT)
 172                   -> ures {
 173          /*!
 174           *
 175           * Make a variable (`a_id`) a subtype of the concrete type `b` */
 176  
 177          let node_a = self.infcx.get(a_id);
 178          let a_id = node_a.root.clone();
 179          let a_bounds = &node_a.possible_types;
 180          let b_bounds = &Bounds { lb: None, ub: Some(b.clone()) };
 181  
 182          debug!("var_sub_t({}={} <: {})",
 183                 a_id.to_str(),
 184                 a_bounds.inf_str(self.infcx),
 185                 b.inf_str(self.infcx));
 186  
 187          self.set_var_to_merged_bounds(
 188              a_id, a_bounds, b_bounds, node_a.rank)
 189      }
 190  
 191      fn t_sub_var<T:Clone + InferStr + LatticeValue,
 192                   V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
 193                   &self,
 194                   aT,
 195                   b_idV)
 196                   -> ures {
 197          /*!
 198           *
 199           * Make a concrete type (`a`) a subtype of the variable `b_id` */
 200  
 201          let a_bounds = &Bounds { lb: Some(a.clone()), ub: None };
 202          let node_b = self.infcx.get(b_id);
 203          let b_id = node_b.root.clone();
 204          let b_bounds = &node_b.possible_types;
 205  
 206          debug!("t_sub_var({} <: {}={})",
 207                 a.inf_str(self.infcx),
 208                 b_id.to_str(),
 209                 b_bounds.inf_str(self.infcx));
 210  
 211          self.set_var_to_merged_bounds(
 212              b_id, a_bounds, b_bounds, node_b.rank)
 213      }
 214  
 215      fn merge_bnd<T:Clone + InferStr + LatticeValue>(
 216                   &self,
 217                   a&Bound<T>,
 218                   b&Bound<T>,
 219                   lattice_opLatticeOp<T>)
 220                   -> cres<Bound<T>> {
 221          /*!
 222           *
 223           * Combines two bounds into a more general bound. */
 224  
 225          debug!("merge_bnd({},{})",
 226                 a.inf_str(self.infcx),
 227                 b.inf_str(self.infcx));
 228          let _r = indenter();
 229  
 230          match (a, b) {
 231              (&None,          &None) => Ok(None),
 232              (&Some(_),       &None) => Ok((*a).clone()),
 233              (&None,          &Some(_)) => Ok((*b).clone()),
 234              (&Some(ref v_a), &Some(ref v_b)) => {
 235                  lattice_op(self.clone(), v_a, v_b).and_then(|v| Ok(Some(v)))
 236              }
 237          }
 238      }
 239  
 240      fn set_var_to_merged_bounds<T:Clone + InferStr + LatticeValue,
 241                                  V:Clone+Eq+ToStr+Vid+UnifyVid<Bounds<T>>>(
 242                                  &self,
 243                                  v_idV,
 244                                  a&Bounds<T>,
 245                                  b&Bounds<T>,
 246                                  rankuint)
 247                                  -> ures {
 248          /*!
 249           *
 250           * Updates the bounds for the variable `v_id` to be the intersection
 251           * of `a` and `b`.  That is, the new bounds for `v_id` will be
 252           * a bounds c such that:
 253           *    c.ub <: a.ub
 254           *    c.ub <: b.ub
 255           *    a.lb <: c.lb
 256           *    b.lb <: c.lb
 257           * If this cannot be achieved, the result is failure. */
 258  
 259          // Think of the two diamonds, we want to find the
 260          // intersection.  There are basically four possibilities (you
 261          // can swap A/B in these pictures):
 262          //
 263          //       A         A
 264          //      / \       / \
 265          //     / B \     / B \
 266          //    / / \ \   / / \ \
 267          //   * *   * * * /   * *
 268          //    \ \ / /   \   / /
 269          //     \ B /   / \ / /
 270          //      \ /   *   \ /
 271          //       A     \ / A
 272          //              B
 273  
 274          debug!("merge({},{},{})",
 275                 v_id.to_str(),
 276                 a.inf_str(self.infcx),
 277                 b.inf_str(self.infcx));
 278          let _indent = indenter();
 279  
 280          // First, relate the lower/upper bounds of A and B.
 281          // Note that these relations *must* hold for us
 282          // to be able to merge A and B at all, and relating
 283          // them explicitly gives the type inferencer more
 284          // information and helps to produce tighter bounds
 285          // when necessary.
 286          let () = if_ok!(self.bnds(&a.lb, &b.ub));
 287          let () = if_ok!(self.bnds(&b.lb, &a.ub));
 288          let ub = if_ok!(self.merge_bnd(&a.ub, &b.ub, LatticeValue::glb));
 289          let lb = if_ok!(self.merge_bnd(&a.lb, &b.lb, LatticeValue::lub));
 290          let bounds = Bounds { lb: lb, ub: ub };
 291          debug!("merge({}): bounds={}",
 292                 v_id.to_str(),
 293                 bounds.inf_str(self.infcx));
 294  
 295          // the new bounds must themselves
 296          // be relatable:
 297          let () = if_ok!(self.bnds(&bounds.lb, &bounds.ub));
 298          self.infcx.set(v_id, Root(bounds, rank));
 299          uok()
 300      }
 301  
 302      fn bnds<T:Clone + InferStr + LatticeValue>(&self,
 303                                                 a&Bound<T>,
 304                                                 b&Bound<T>)
 305                                                 -> ures {
 306          debug!("bnds({} <: {})", a.inf_str(self.infcx),
 307                 b.inf_str(self.infcx));
 308          let _r = indenter();
 309  
 310          match (a, b) {
 311              (&None, &None) |
 312              (&Some(_), &None) |
 313              (&None, &Some(_)) => {
 314                  uok()
 315              }
 316              (&Some(ref t_a), &Some(ref t_b)) => {
 317                  LatticeValue::sub(self.clone(), t_a, t_b)
 318              }
 319          }
 320      }
 321  }
 322  
 323  // ______________________________________________________________________
 324  // Lattice operations on variables
 325  //
 326  // This is common code used by both LUB and GLB to compute the LUB/GLB
 327  // for pairs of variables or for variables and values.
 328  
 329  pub trait LatticeDir {
 330      fn combine_fields<'a>(&'a self) -> CombineFields<'a>;
 331      fn bnd<T:Clone>(&self, b: &Bounds<T>) -> Option<T>;
 332      fn with_bnd<T:Clone>(&self, b: &Bounds<T>, t: T) -> Bounds<T>;
 333  }
 334  
 335  pub trait TyLatticeDir {
 336      fn ty_bot(&self, t: ty::t) -> cres<ty::t>;
 337  }
 338  
 339  impl<'f> LatticeDir for Lub<'f> {
 340      fn combine_fields<'a>(&'a self) -> CombineFields<'a> { self.get_ref().clone() }
 341      fn bnd<T:Clone>(&self, b&Bounds<T>) -> Option<T> { b.ub.clone() }
 342      fn with_bnd<T:Clone>(&self, b&Bounds<T>, tT) -> Bounds<T> {
 343          Bounds { ub: Some(t), ..(*b).clone() }
 344      }
 345  }
 346  
 347  impl<'f> TyLatticeDir for Lub<'f> {
 348      fn ty_bot(&self, tty::t) -> cres<ty::t> {
 349          Ok(t)
 350      }
 351  }
 352  
 353  impl<'f> LatticeDir for Glb<'f> {
 354      fn combine_fields<'a>(&'a self) -> CombineFields<'a> { self.get_ref().clone() }
 355      fn bnd<T:Clone>(&self, b&Bounds<T>) -> Option<T> { b.lb.clone() }
 356      fn with_bnd<T:Clone>(&self, b&Bounds<T>, tT) -> Bounds<T> {
 357          Bounds { lb: Some(t), ..(*b).clone() }
 358      }
 359  }
 360  
 361  impl<'f> TyLatticeDir for Glb<'f> {
 362      fn ty_bot(&self, _tty::t) -> cres<ty::t> {
 363          Ok(ty::mk_bot())
 364      }
 365  }
 366  
 367  pub fn super_lattice_tys<L:LatticeDir+TyLatticeDir+Combine>(this: &L,
 368                                                              aty::t,
 369                                                              bty::t)
 370                                                              -> cres<ty::t> {
 371      debug!("{}.lattice_tys({}, {})", this.tag(),
 372             a.inf_str(this.infcx()),
 373             b.inf_str(this.infcx()));
 374  
 375      if a == b {
 376          return Ok(a);
 377      }
 378  
 379      let tcx = this.infcx().tcx;
 380  
 381      match (&ty::get(a).sty, &ty::get(b).sty) {
 382          (&ty::ty_bot, _) => { return this.ty_bot(b); }
 383          (_, &ty::ty_bot) => { return this.ty_bot(a); }
 384  
 385          (&ty::ty_infer(TyVar(a_id)), &ty::ty_infer(TyVar(b_id))) => {
 386              let r = if_ok!(lattice_vars(this, a_id, b_id,
 387                                          |x, y| this.tys(*x, *y)));
 388              return match r {
 389                  VarResult(v) => Ok(ty::mk_var(tcx, v)),
 390                  ValueResult(t) => Ok(t)
 391              };
 392          }
 393  
 394          (&ty::ty_infer(TyVar(a_id)), _) => {
 395              return lattice_var_and_t(this, a_id, &b,
 396                                       |x, y| this.tys(*x, *y));
 397          }
 398  
 399          (_, &ty::ty_infer(TyVar(b_id))) => {
 400              return lattice_var_and_t(this, b_id, &a,
 401                                       |x, y| this.tys(*x, *y));
 402          }
 403  
 404          _ => {
 405              return super_tys(this, a, b);
 406          }
 407      }
 408  }
 409  
 410  pub type LatticeDirOp<'a, T> = |a: &T, b: &T|: 'a -> cres<T>;
 411  
 412  #[deriving(Clone)]
 413  pub enum LatticeVarResult<V,T> {
 414      VarResult(V),
 415      ValueResult(T)
 416  }
 417  
 418  /**
 419   * Computes the LUB or GLB of two bounded variables.  These could be any
 420   * sort of variables, but in the comments on this function I'll assume
 421   * we are doing an LUB on two type variables.
 422   *
 423   * This computation can be done in one of two ways:
 424   *
 425   * - If both variables have an upper bound, we may just compute the
 426   *   LUB of those bounds and return that, in which case we are
 427   *   returning a type.  This is indicated with a `ValueResult` return.
 428   *
 429   * - If the variables do not both have an upper bound, we will unify
 430   *   the variables and return the unified variable, in which case the
 431   *   result is a variable.  This is indicated with a `VarResult`
 432   *   return. */
 433  pub fn lattice_vars<L:LatticeDir + Combine,
 434                      T:Clone + InferStr + LatticeValue,
 435                      V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
 436      this: &L,                           // defines whether we want LUB or GLB
 437      a_vidV,                          // first variable
 438      b_vidV,                          // second variable
 439      lattice_dir_opLatticeDirOp<T>)    // LUB or GLB operation on types
 440      -> cres<LatticeVarResult<V,T>> {
 441      let nde_a = this.infcx().get(a_vid);
 442      let nde_b = this.infcx().get(b_vid);
 443      let a_vid = nde_a.root.clone();
 444      let b_vid = nde_b.root.clone();
 445      let a_bounds = &nde_a.possible_types;
 446      let b_bounds = &nde_b.possible_types;
 447  
 448      debug!("{}.lattice_vars({}={} <: {}={})",
 449             this.tag(),
 450             a_vid.to_str(), a_bounds.inf_str(this.infcx()),
 451             b_vid.to_str(), b_bounds.inf_str(this.infcx()));
 452  
 453      // Same variable: the easy case.
 454      if a_vid == b_vid {
 455          return Ok(VarResult(a_vid));
 456      }
 457  
 458      // If both A and B have an UB type, then we can just compute the
 459      // LUB of those types:
 460      let (a_bnd, b_bnd) = (this.bnd(a_bounds), this.bnd(b_bounds));
 461      match (a_bnd, b_bnd) {
 462          (Some(ref a_ty), Some(ref b_ty)) => {
 463              match this.infcx().try(|| lattice_dir_op(a_ty, b_ty) ) {
 464                  Ok(t) => return Ok(ValueResult(t)),
 465                  Err(_) => { /*fallthrough */ }
 466              }
 467          }
 468          _ => {/*fallthrough*/}
 469      }
 470  
 471      // Otherwise, we need to merge A and B into one variable.  We can
 472      // then use either variable as an upper bound:
 473      let cf = this.combine_fields();
 474      cf.var_sub_var(a_vid.clone(), b_vid.clone()).then(|| {
 475          Ok(VarResult(a_vid.clone()))
 476      })
 477  }
 478  
 479  pub fn lattice_var_and_t<L:LatticeDir + Combine,
 480                           T:Clone + InferStr + LatticeValue,
 481                           V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
 482      this: &L,
 483      a_idV,
 484      b: &T,
 485      lattice_dir_opLatticeDirOp<T>)
 486      -> cres<T> {
 487      let nde_a = this.infcx().get(a_id);
 488      let a_id = nde_a.root.clone();
 489      let a_bounds = &nde_a.possible_types;
 490  
 491      // The comments in this function are written for LUB, but they
 492      // apply equally well to GLB if you inverse upper/lower/sub/super/etc.
 493  
 494      debug!("{}.lattice_var_and_t({}={} <: {})",
 495             this.tag(),
 496             a_id.to_str(),
 497             a_bounds.inf_str(this.infcx()),
 498             b.inf_str(this.infcx()));
 499  
 500      match this.bnd(a_bounds) {
 501          Some(ref a_bnd) => {
 502              // If a has an upper bound, return the LUB(a.ub, b)
 503              debug!("bnd=Some({})", a_bnd.inf_str(this.infcx()));
 504              lattice_dir_op(a_bnd, b)
 505          }
 506          None => {
 507              // If a does not have an upper bound, make b the upper bound of a
 508              // and then return b.
 509              debug!("bnd=None");
 510              let a_bounds = this.with_bnd(a_bounds, (*b).clone());
 511              this.combine_fields().bnds(&a_bounds.lb, &a_bounds.ub).then(|| {
 512                  this.infcx().set(a_id.clone(),
 513                                   Root(a_bounds.clone(), nde_a.rank));
 514                  Ok((*b).clone())
 515              })
 516          }
 517      }
 518  }
 519  
 520  // ___________________________________________________________________________
 521  // Random utility functions used by LUB/GLB when computing LUB/GLB of
 522  // fn types
 523  
 524  pub fn var_ids<T:Combine>(this: &T,
 525                            map: &HashMap<ty::BoundRegion, ty::Region>)
 526                            -> Vec<RegionVid> {
 527      map.iter().map(|(_, r)| match *r {
 528              ty::ReInfer(ty::ReVar(r)) => { r }
 529              r => {
 530                  this.infcx().tcx.sess.span_bug(
 531                      this.trace().origin.span(),
 532                      format!("found non-region-vid: {:?}", r));
 533              }
 534          }).collect()
 535  }
 536  
 537  pub fn is_var_in_set(new_vars: &[RegionVid], rty::Region) -> bool {
 538      match r {
 539          ty::ReInfer(ty::ReVar(ref v)) => new_vars.iter().any(|x| x == v),
 540          _ => false
 541      }
 542  }


librustc/middle/typeck/infer/lattice.rs:49:1-49:1 -trait- definition:
trait LatticeValue {
    fn sub(cf: CombineFields, a: &Self, b: &Self) -> ures;
    fn lub(cf: CombineFields, a: &Self, b: &Self) -> cres<Self>;
references:- 23
79:     /// make variable a subtype of T
80:     fn var_sub_t<T:Clone + InferStr + LatticeValue,
81:                  V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
--
105:                                 -> ures;
106:     fn bnds<T:Clone + InferStr + LatticeValue>(
107:             &self,
--
240:     fn set_var_to_merged_bounds<T:Clone + InferStr + LatticeValue,
241:                                 V:Clone+Eq+ToStr+Vid+UnifyVid<Bounds<T>>>(
--
433: pub fn lattice_vars<L:LatticeDir + Combine,
434:                     T:Clone + InferStr + LatticeValue,
435:                     V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
--
479: pub fn lattice_var_and_t<L:LatticeDir + Combine,
480:                          T:Clone + InferStr + LatticeValue,
481:                          V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(


librustc/middle/typeck/infer/lattice.rs:366:1-366:1 -fn- definition:
pub fn super_lattice_tys<L:LatticeDir+TyLatticeDir+Combine>(this: &L,
                                                            a: ty::t,
                                                            b: ty::t)
references:- 2
librustc/middle/typeck/infer/glb.rs:
118:     fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
119:         super_lattice_tys(self, a, b)
120:     }
librustc/middle/typeck/infer/lub.rs:
193:     fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
194:         super_lattice_tys(self, a, b)
195:     }


librustc/middle/typeck/infer/lattice.rs:478:1-478:1 -fn- definition:
pub fn lattice_var_and_t<L:LatticeDir + Combine,
                         T:Clone + InferStr + LatticeValue,
                         V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
references:- 2
394:         (&ty::ty_infer(TyVar(a_id)), _) => {
395:             return lattice_var_and_t(this, a_id, &b,
396:                                      |x, y| this.tys(*x, *y));
--
399:         (_, &ty::ty_infer(TyVar(b_id))) => {
400:             return lattice_var_and_t(this, b_id, &a,
401:                                      |x, y| this.tys(*x, *y));


librustc/middle/typeck/infer/lattice.rs:55:1-55:1 -NK_AS_STR_TODO- definition:
pub type LatticeOp<'a, T> =
    |cf: CombineFields, a: &T, b: &T|: 'a -> cres<T>;
impl LatticeValue for ty::t {
references:- 2
218:                  b: &Bound<T>,
219:                  lattice_op: LatticeOp<T>)
220:                  -> cres<Bound<T>> {


librustc/middle/typeck/infer/lattice.rs:523:1-523:1 -fn- definition:
pub fn var_ids<T:Combine>(this: &T,
                          map: &HashMap<ty::BoundRegion, ty::Region>)
                          -> Vec<RegionVid> {
references:- 2
librustc/middle/typeck/infer/glb.rs:
143:                 self.trace(), b);
144:         let b_vars = var_ids(self, &b_map);


librustc/middle/typeck/infer/lattice.rs:328:1-328:1 -trait- definition:
pub trait LatticeDir {
    fn combine_fields<'a>(&'a self) -> CombineFields<'a>;
    fn bnd<T:Clone>(&self, b: &Bounds<T>) -> Option<T>;
references:- 5
339: impl<'f> LatticeDir for Lub<'f> {
340:     fn combine_fields<'a>(&'a self) -> CombineFields<'a> { self.get_ref().clone() }
--
432:  *   return. */
433: pub fn lattice_vars<L:LatticeDir + Combine,
434:                     T:Clone + InferStr + LatticeValue,
--
479: pub fn lattice_var_and_t<L:LatticeDir + Combine,
480:                          T:Clone + InferStr + LatticeValue,


librustc/middle/typeck/infer/lattice.rs:536:1-536:1 -fn- definition:
pub fn is_var_in_set(new_vars: &[RegionVid], r: ty::Region) -> bool {
    match r {
        ty::ReInfer(ty::ReVar(ref v)) => new_vars.iter().any(|x| x == v),
references:- 6
librustc/middle/typeck/infer/lub.rs:
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());
--
163:             // stay as they are.
164:             if !tainted.iter().all(|r| is_var_in_set(new_vars, *r)) {
165:                 debug!("generalize_region(r0={:?}): \
librustc/middle/typeck/infer/glb.rs:
194:                     }
195:                 } else if is_var_in_set(b_vars, *r) {
196:                     if b_r.is_some() {
--
200:                     }
201:                 } else if !is_var_in_set(new_vars, *r) {
202:                     only_new_vars = false;


librustc/middle/typeck/infer/lattice.rs:334:1-334:1 -trait- definition:
pub trait TyLatticeDir {
    fn ty_bot(&self, t: ty::t) -> cres<ty::t>;
}
references:- 3
347: impl<'f> TyLatticeDir for Lub<'f> {
348:     fn ty_bot(&self, t: ty::t) -> cres<ty::t> {
--
367: pub fn super_lattice_tys<L:LatticeDir+TyLatticeDir+Combine>(this: &L,
368:                                                             a: ty::t,


librustc/middle/typeck/infer/lattice.rs:412:19-412:19 -enum- definition:
pub enum LatticeVarResult<V,T> {
    VarResult(V),
    ValueResult(T)
references:- 3
413: pub enum LatticeVarResult<V,T> {
--
439:     lattice_dir_op: LatticeDirOp<T>)    // LUB or GLB operation on types
440:     -> cres<LatticeVarResult<V,T>> {
441:     let nde_a = this.infcx().get(a_vid);


librustc/middle/typeck/infer/lattice.rs:409:1-409:1 -NK_AS_STR_TODO- definition:
pub type LatticeDirOp<'a, T> = |a: &T, b: &T|: 'a -> cres<T>;
pub enum LatticeVarResult<V,T> {
    VarResult(V),
references:- 2
438:     b_vid: V,                          // second variable
439:     lattice_dir_op: LatticeDirOp<T>)    // LUB or GLB operation on types
440:     -> cres<LatticeVarResult<V,T>> {
--
484:     b: &T,
485:     lattice_dir_op: LatticeDirOp<T>)
486:     -> cres<T> {