(index<- )        ./librustc/middle/typeck/infer/combine.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  // Type combining
  13  //
  14  // There are three type combiners: sub, lub, and glb.  Each implements
  15  // the trait `Combine` and contains methods for combining two
  16  // instances of various things and yielding a new instance.  These
  17  // combiner methods always yield a `result<T>`---failure is propagated
  18  // upward using `and_then()` methods.  There is a lot of common code for
  19  // these operations, implemented as default methods on the `Combine`
  20  // trait.
  21  //
  22  // In reality, the sub operation is rather different from lub/glb, but
  23  // they are combined into one trait to avoid duplication (they used to
  24  // be separate but there were many bugs because there were two copies
  25  // of most routines).
  26  //
  27  // The differences are:
  28  //
  29  // - when making two things have a sub relationship, the order of the
  30  //   arguments is significant (a <: b) and the return value of the
  31  //   combine functions is largely irrelevant.  The important thing is
  32  //   whether the action succeeds or fails.  If it succeeds, then side
  33  //   effects have been committed into the type variables.
  34  //
  35  // - for GLB/LUB, the order of arguments is not significant (GLB(a,b) ==
  36  //   GLB(b,a)) and the return value is important (it is the GLB).  Of
  37  //   course GLB/LUB may also have side effects.
  38  //
  39  // Contravariance
  40  //
  41  // When you are relating two things which have a contravariant
  42  // relationship, you should use `contratys()` or `contraregions()`,
  43  // rather than inversing the order of arguments!  This is necessary
  44  // because the order of arguments is not relevant for LUB and GLB.  It
  45  // is also useful to track which value is the "expected" value in
  46  // terms of error reporting, although we do not do that properly right
  47  // now.
  48  
  49  
  50  use middle::ty::{FloatVar, FnSig, IntVar, TyVar};
  51  use middle::ty::{IntType, UintType, substs};
  52  use middle::ty::{BuiltinBounds};
  53  use middle::ty;
  54  use middle::typeck::infer::{then, ToUres};
  55  use middle::typeck::infer::glb::Glb;
  56  use middle::typeck::infer::lub::Lub;
  57  use middle::typeck::infer::sub::Sub;
  58  use middle::typeck::infer::to_str::InferStr;
  59  use middle::typeck::infer::unify::InferCtxtMethods;
  60  use middle::typeck::infer::{InferCtxt, cres, ures};
  61  use middle::typeck::infer::{TypeTrace};
  62  use util::common::indent;
  63  use util::ppaux::Repr;
  64  
  65  use std::result;
  66  
  67  use syntax::ast::{Onceness, FnStyle};
  68  use syntax::ast;
  69  use syntax::owned_slice::OwnedSlice;
  70  use syntax::abi;
  71  
  72  pub trait Combine {
  73      fn infcx<'a>(&'a self) -> &'a InferCtxt<'a>;
  74      fn tag(&self) -> ~str;
  75      fn a_is_expected(&self) -> bool;
  76      fn trace(&self) -> TypeTrace;
  77  
  78      fn sub<'a>(&'a self) -> Sub<'a>;
  79      fn lub<'a>(&'a self) -> Lub<'a>;
  80      fn glb<'a>(&'a self) -> Glb<'a>;
  81  
  82      fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt>;
  83      fn contratys(&self, a: ty::t, b: ty::t) -> cres<ty::t>;
  84      fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t>;
  85  
  86      fn tps(&self, as_&[ty::t], bs&[ty::t]) -> cres<Vec<ty::t> > {
  87  
  88          // Note: type parameters are always treated as *invariant*
  89          // (otherwise the type system would be unsound).  In the
  90          // future we could allow type parameters to declare a
  91          // variance.
  92  
  93          if as_.len() == bs.len() {
  94              result::fold_(as_.iter().zip(bs.iter())
  95                            .map(|(a, b)| eq_tys(self, *a, *b)))
  96                  .then(|| Ok(Vec::from_slice(as_)))
  97          } else {
  98              Err(ty::terr_ty_param_size(expected_found(self,
  99                                                        as_.len(),
 100                                                        bs.len())))
 101          }
 102      }
 103  
 104      fn self_tys(&self, aOption<ty::t>, bOption<ty::t>)
 105                 -> cres<Option<ty::t>> {
 106  
 107          match (a, b) {
 108              (None, None) => {
 109                  Ok(None)
 110              }
 111              (Some(a), Some(b)) => {
 112                  // FIXME(#5781) this should be eq_tys
 113                  // eq_tys(self, a, b).then(|| Ok(Some(a)) )
 114                  self.contratys(a, b).and_then(|t| Ok(Some(t)))
 115              }
 116              (None, Some(_)) |
 117                  (Some(_), None) => {
 118                  // I think it should never happen that we unify two
 119                  // substs and one of them has a self_ty and one
 120                  // doesn't...? I could be wrong about this.
 121                  self.infcx().tcx.sess.bug(
 122                                            format!("substitution a had a self_ty \
 123                                                 and substitution b didn't, \
 124                                                 or vice versa"));
 125              }
 126          }
 127      }
 128  
 129      fn substs(&self,
 130                item_def_idast::DefId,
 131                as_&ty::substs,
 132                bs&ty::substs) -> cres<ty::substs> {
 133  
 134          fn relate_region_params<C:Combine>(this&C,
 135                                             item_def_idast::DefId,
 136                                             a&ty::RegionSubsts,
 137                                             b&ty::RegionSubsts)
 138                                             -> cres<ty::RegionSubsts> {
 139              let tcx = this.infcx().tcx;
 140              match (a, b) {
 141                  (&ty::ErasedRegions, _) | (_, &ty::ErasedRegions) => {
 142                      Ok(ty::ErasedRegions)
 143                  }
 144  
 145                  (&ty::NonerasedRegions(ref a_rs),
 146                   &ty::NonerasedRegions(ref b_rs)) => {
 147                      let variances = ty::item_variances(tcx, item_def_id);
 148                      let region_params = &variances.region_params;
 149                      let num_region_params = region_params.len();
 150  
 151                      debug!("relate_region_params(\
 152                              item_def_id={}, \
 153                              a_rs={}, \
 154                              b_rs={},
 155                              region_params={})",
 156                              item_def_id.repr(tcx),
 157                              a_rs.repr(tcx),
 158                              b_rs.repr(tcx),
 159                              region_params.repr(tcx));
 160  
 161                      assert_eq!(num_region_params, a_rs.len());
 162                      assert_eq!(num_region_params, b_rs.len());
 163                      let mut rs = vec!();
 164                      for i in range(0, num_region_params) {
 165                          let a_r = *a_rs.get(i);
 166                          let b_r = *b_rs.get(i);
 167                          let variance = *region_params.get(i);
 168                          let r = match variance {
 169                              ty::Invariant => {
 170                                  eq_regions(this, a_r, b_r)
 171                                      .and_then(|()| Ok(a_r))
 172                              }
 173                              ty::Covariant => this.regions(a_r, b_r),
 174                              ty::Contravariant => this.contraregions(a_r, b_r),
 175                              ty::Bivariant => Ok(a_r),
 176                          };
 177                          rs.push(if_ok!(r));
 178                      }
 179                      Ok(ty::NonerasedRegions(OwnedSlice::from_vec(rs)))
 180                  }
 181              }
 182          }
 183  
 184          let tps = if_ok!(self.tps(as_.tps.as_slice(), bs.tps.as_slice()));
 185          let self_ty = if_ok!(self.self_tys(as_.self_ty, bs.self_ty));
 186          let regions = if_ok!(relate_region_params(self,
 187                                                    item_def_id,
 188                                                    &as_.regions,
 189                                                    &bs.regions));
 190          Ok(substs { regions: regions,
 191                      self_ty: self_ty,
 192                      tps: tps.clone() })
 193      }
 194  
 195      fn bare_fn_tys(&self, a&ty::BareFnTy,
 196                     b&ty::BareFnTy) -> cres<ty::BareFnTy> {
 197          let fn_style = if_ok!(self.fn_styles(a.fn_style, b.fn_style));
 198          let abi = if_ok!(self.abi(a.abi, b.abi));
 199          let sig = if_ok!(self.fn_sigs(&a.sig, &b.sig));
 200          Ok(ty::BareFnTy {fn_style: fn_style,
 201                  abi: abi,
 202                  sig: sig})
 203      }
 204  
 205      fn closure_tys(&self, a&ty::ClosureTy,
 206                     b&ty::ClosureTy) -> cres<ty::ClosureTy> {
 207  
 208          let store = match (a.store, b.store) {
 209              (ty::RegionTraitStore(a_r, a_m),
 210               ty::RegionTraitStore(b_r, b_m)) if a_m == b_m => {
 211                  let r = if_ok!(self.contraregions(a_r, b_r));
 212                  ty::RegionTraitStore(r, a_m)
 213              }
 214  
 215              _ if a.store == b.store => {
 216                  a.store
 217              }
 218  
 219              _ => {
 220                  return Err(ty::terr_sigil_mismatch(expected_found(self, a.store, b.store)))
 221              }
 222          };
 223          let fn_style = if_ok!(self.fn_styles(a.fn_style, b.fn_style));
 224          let onceness = if_ok!(self.oncenesses(a.onceness, b.onceness));
 225          let bounds = if_ok!(self.bounds(a.bounds, b.bounds));
 226          let sig = if_ok!(self.fn_sigs(&a.sig, &b.sig));
 227          Ok(ty::ClosureTy {
 228              fn_style: fn_style,
 229              onceness: onceness,
 230              store: store,
 231              bounds: bounds,
 232              sig: sig
 233          })
 234      }
 235  
 236      fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig>;
 237  
 238      fn args(&self, aty::t, bty::t) -> cres<ty::t> {
 239          self.contratys(a, b).and_then(|t| Ok(t))
 240      }
 241  
 242      fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<FnStyle>;
 243  
 244      fn abi(&self, aabi::Abi, babi::Abi) -> cres<abi::Abi> {
 245          if a == b {
 246              Ok(a)
 247          } else {
 248              Err(ty::terr_abi_mismatch(expected_found(self, a, b)))
 249          }
 250      }
 251  
 252      fn oncenesses(&self, a: Onceness, b: Onceness) -> cres<Onceness>;
 253      fn bounds(&self, a: BuiltinBounds, b: BuiltinBounds) -> cres<BuiltinBounds>;
 254      fn contraregions(&self, a: ty::Region, b: ty::Region)
 255                    -> cres<ty::Region>;
 256      fn regions(&self, a: ty::Region, b: ty::Region) -> cres<ty::Region>;
 257  
 258      fn trait_stores(&self,
 259                      vkty::terr_vstore_kind,
 260                      aty::TraitStore,
 261                      bty::TraitStore)
 262                      -> cres<ty::TraitStore> {
 263          debug!("{}.trait_stores(a={:?}, b={:?})", self.tag(), a, b);
 264  
 265          match (a, b) {
 266              (ty::RegionTraitStore(a_r, a_m),
 267               ty::RegionTraitStore(b_r, b_m)) if a_m == b_m => {
 268                  self.contraregions(a_r, b_r).and_then(|r| {
 269                      Ok(ty::RegionTraitStore(r, a_m))
 270                  })
 271              }
 272  
 273              _ if a == b => {
 274                  Ok(a)
 275              }
 276  
 277              _ => {
 278                  Err(ty::terr_trait_stores_differ(vk, expected_found(self, a, b)))
 279              }
 280          }
 281  
 282      }
 283  
 284      fn trait_refs(&self,
 285                    a&ty::TraitRef,
 286                    b&ty::TraitRef)
 287                    -> cres<ty::TraitRef> {
 288          // Different traits cannot be related
 289  
 290          // - NOTE in the future, expand out subtraits!
 291  
 292          if a.def_id != b.def_id {
 293              Err(ty::terr_traits(
 294                                  expected_found(self, a.def_id, b.def_id)))
 295          } else {
 296              let substs = if_ok!(self.substs(a.def_id, &a.substs, &b.substs));
 297              Ok(ty::TraitRef { def_id: a.def_id,
 298                                substs: substs })
 299          }
 300      }
 301  }
 302  
 303  #[deriving(Clone)]
 304  pub struct CombineFields<'a> {
 305      pub infcx: &'a InferCtxt<'a>,
 306      pub a_is_expected: bool,
 307      pub trace: TypeTrace,
 308  }
 309  
 310  pub fn expected_found<C:Combine,T>(
 311          this: &C, aT, bT) -> ty::expected_found<T> {
 312      if this.a_is_expected() {
 313          ty::expected_found {expected: a, found: b}
 314      } else {
 315          ty::expected_found {expected: b, found: a}
 316      }
 317  }
 318  
 319  pub fn eq_tys<C:Combine>(this: &C, aty::t, bty::t) -> ures {
 320      let suber = this.sub();
 321      this.infcx().try(|| {
 322          suber.tys(a, b).and_then(|_ok| suber.contratys(a, b)).to_ures()
 323      })
 324  }
 325  
 326  pub fn eq_regions<C:Combine>(this: &C, aty::Region, bty::Region)
 327                            -> ures {
 328      debug!("eq_regions({}, {})",
 329              a.repr(this.infcx().tcx),
 330              b.repr(this.infcx().tcx));
 331      let sub = this.sub();
 332      indent(|| {
 333          this.infcx().try(|| {
 334              sub.regions(a, b).and_then(|_r| sub.contraregions(a, b))
 335          }).or_else(|e| {
 336              // substitute a better error, but use the regions
 337              // found in the original error
 338              match e {
 339                ty::terr_regions_does_not_outlive(a1, b1) =>
 340                  Err(ty::terr_regions_not_same(a1, b1)),
 341                _ => Err(e)
 342              }
 343          }).to_ures()
 344      })
 345  }
 346  
 347  pub fn super_fn_sigs<C:Combine>(this: &C, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
 348  
 349      fn argvecs<C:Combine>(this: &C, a_args: &[ty::t], b_args: &[ty::t]) -> cres<Vec<ty::t> > {
 350          if a_args.len() == b_args.len() {
 351              result::collect(a_args.iter().zip(b_args.iter())
 352                              .map(|(a, b)| this.args(*a, *b)))
 353          } else {
 354              Err(ty::terr_arg_count)
 355          }
 356      }
 357  
 358      if a.variadic != b.variadic {
 359          return Err(ty::terr_variadic_mismatch(expected_found(this, a.variadic, b.variadic)));
 360      }
 361  
 362      let inputs = if_ok!(argvecs(this,
 363                                  a.inputs.as_slice(),
 364                                  b.inputs.as_slice()));
 365      let output = if_ok!(this.tys(a.output, b.output));
 366      Ok(FnSig {binder_id: a.binder_id,
 367                inputs: inputs,
 368                output: output,
 369                variadic: a.variadic})
 370  }
 371  
 372  pub fn super_tys<C:Combine>(this: &C, aty::t, bty::t) -> cres<ty::t> {
 373  
 374      // This is a horible hack - historically, [T] was not treated as a type,
 375      // so, for example, &T and &[U] should not unify. In fact the only thing
 376      // &[U] should unify with is &[T]. We preserve that behaviour with this
 377      // check.
 378      fn check_ptr_to_vec<C:Combine>(this&C,
 379                                     aty::t,
 380                                     bty::t,
 381                                     a_innerty::t,
 382                                     b_innerty::t,
 383                                     resultty::t) -> cres<ty::t> {
 384          match (&ty::get(a_inner).sty, &ty::get(b_inner).sty) {
 385              (&ty::ty_vec(_, None), &ty::ty_vec(_, None)) |
 386              (&ty::ty_str, &ty::ty_str) => Ok(result),
 387              (&ty::ty_vec(_, None), _) | (_, &ty::ty_vec(_, None)) |
 388              (&ty::ty_str, _) | (_, &ty::ty_str)
 389                  => Err(ty::terr_sorts(expected_found(this, a, b))),
 390              _ => Ok(result),
 391          }
 392      }
 393  
 394      let tcx = this.infcx().tcx;
 395      let a_sty = &ty::get(a).sty;
 396      let b_sty = &ty::get(b).sty;
 397      debug!("super_tys: a_sty={:?} b_sty={:?}", a_sty, b_sty);
 398      return match (a_sty, b_sty) {
 399        // The "subtype" ought to be handling cases involving bot or var:
 400        (&ty::ty_bot, _) |
 401        (_, &ty::ty_bot) |
 402        (&ty::ty_infer(TyVar(_)), _) |
 403        (_, &ty::ty_infer(TyVar(_))) => {
 404          tcx.sess.bug(
 405              format!("{}: bot and var types should have been handled ({},{})",
 406                   this.tag(),
 407                   a.inf_str(this.infcx()),
 408                   b.inf_str(this.infcx())));
 409        }
 410  
 411          // Relate integral variables to other types
 412          (&ty::ty_infer(IntVar(a_id)), &ty::ty_infer(IntVar(b_id))) => {
 413              if_ok!(this.infcx().simple_vars(this.a_is_expected(),
 414                                              a_id, b_id));
 415              Ok(a)
 416          }
 417          (&ty::ty_infer(IntVar(v_id)), &ty::ty_int(v)) => {
 418              unify_integral_variable(this, this.a_is_expected(),
 419                                      v_id, IntType(v))
 420          }
 421          (&ty::ty_int(v), &ty::ty_infer(IntVar(v_id))) => {
 422              unify_integral_variable(this, !this.a_is_expected(),
 423                                      v_id, IntType(v))
 424          }
 425          (&ty::ty_infer(IntVar(v_id)), &ty::ty_uint(v)) => {
 426              unify_integral_variable(this, this.a_is_expected(),
 427                                      v_id, UintType(v))
 428          }
 429          (&ty::ty_uint(v), &ty::ty_infer(IntVar(v_id))) => {
 430              unify_integral_variable(this, !this.a_is_expected(),
 431                                      v_id, UintType(v))
 432          }
 433  
 434          // Relate floating-point variables to other types
 435          (&ty::ty_infer(FloatVar(a_id)), &ty::ty_infer(FloatVar(b_id))) => {
 436              if_ok!(this.infcx().simple_vars(this.a_is_expected(),
 437                                              a_id, b_id));
 438              Ok(a)
 439          }
 440          (&ty::ty_infer(FloatVar(v_id)), &ty::ty_float(v)) => {
 441              unify_float_variable(this, this.a_is_expected(), v_id, v)
 442          }
 443          (&ty::ty_float(v), &ty::ty_infer(FloatVar(v_id))) => {
 444              unify_float_variable(this, !this.a_is_expected(), v_id, v)
 445          }
 446  
 447        (&ty::ty_char, _) |
 448        (&ty::ty_nil, _) |
 449        (&ty::ty_bool, _) |
 450        (&ty::ty_int(_), _) |
 451        (&ty::ty_uint(_), _) |
 452        (&ty::ty_float(_), _) => {
 453          if ty::get(a).sty == ty::get(b).sty {
 454              Ok(a)
 455          } else {
 456              Err(ty::terr_sorts(expected_found(this, a, b)))
 457          }
 458        }
 459  
 460        (&ty::ty_param(ref a_p), &ty::ty_param(ref b_p)) if a_p.idx == b_p.idx => {
 461          Ok(a)
 462        }
 463  
 464        (&ty::ty_enum(a_id, ref a_substs),
 465         &ty::ty_enum(b_id, ref b_substs))
 466        if a_id == b_id => {
 467            let substs = if_ok!(this.substs(a_id,
 468                                            a_substs,
 469                                            b_substs));
 470            Ok(ty::mk_enum(tcx, a_id, substs))
 471        }
 472  
 473        (&ty::ty_trait(ref a_),
 474         &ty::ty_trait(ref b_))
 475        if a_.def_id == b_.def_id => {
 476            debug!("Trying to match traits {:?} and {:?}", a, b);
 477            let substs = if_ok!(this.substs(a_.def_id, &a_.substs, &b_.substs));
 478            let s = if_ok!(this.trait_stores(ty::terr_trait, a_.store, b_.store));
 479            let bounds = if_ok!(this.bounds(a_.bounds, b_.bounds));
 480            Ok(ty::mk_trait(tcx,
 481                            a_.def_id,
 482                            substs.clone(),
 483                            s,
 484                            bounds))
 485        }
 486  
 487        (&ty::ty_struct(a_id, ref a_substs), &ty::ty_struct(b_id, ref b_substs))
 488        if a_id == b_id => {
 489              let substs = if_ok!(this.substs(a_id, a_substs, b_substs));
 490              Ok(ty::mk_struct(tcx, a_id, substs))
 491        }
 492  
 493        (&ty::ty_box(a_inner), &ty::ty_box(b_inner)) => {
 494          this.tys(a_inner, b_inner).and_then(|typ| Ok(ty::mk_box(tcx, typ)))
 495        }
 496  
 497        (&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) => {
 498              let typ = if_ok!(this.tys(a_inner, b_inner));
 499              check_ptr_to_vec(this, a, b, a_inner, b_inner, ty::mk_uniq(tcx, typ))
 500        }
 501  
 502        (&ty::ty_ptr(ref a_mt), &ty::ty_ptr(ref b_mt)) => {
 503              let mt = if_ok!(this.mts(a_mt, b_mt));
 504              check_ptr_to_vec(this, a, b, a_mt.ty, b_mt.ty, ty::mk_ptr(tcx, mt))
 505        }
 506  
 507        (&ty::ty_rptr(a_r, ref a_mt), &ty::ty_rptr(b_r, ref b_mt)) => {
 508              let r = if_ok!(this.contraregions(a_r, b_r));
 509              let mt = if_ok!(this.mts(a_mt, b_mt));
 510              check_ptr_to_vec(this, a, b, a_mt.ty, b_mt.ty, ty::mk_rptr(tcx, r, mt))
 511        }
 512  
 513        (&ty::ty_vec(ref a_mt, sz_a), &ty::ty_vec(ref b_mt, sz_b)) => {
 514          this.mts(a_mt, b_mt).and_then(|mt| {
 515              if sz_a == sz_b {
 516                  Ok(ty::mk_vec(tcx, mt, sz_a))
 517              } else {
 518                  Err(ty::terr_sorts(expected_found(this, a, b)))
 519              }
 520          })
 521        }
 522  
 523        (&ty::ty_str, &ty::ty_str) => {
 524              Ok(ty::mk_str(tcx))
 525        }
 526  
 527        (&ty::ty_tup(ref as_), &ty::ty_tup(ref bs)) => {
 528          if as_.len() == bs.len() {
 529              result::collect(as_.iter().zip(bs.iter())
 530                              .map(|(a, b)| this.tys(*a, *b)))
 531                      .and_then(|ts| Ok(ty::mk_tup(tcx, ts)) )
 532          } else {
 533              Err(ty::terr_tuple_size(
 534                  expected_found(this, as_.len(), bs.len())))
 535          }
 536        }
 537  
 538        (&ty::ty_bare_fn(ref a_fty), &ty::ty_bare_fn(ref b_fty)) => {
 539          this.bare_fn_tys(a_fty, b_fty).and_then(|fty| {
 540              Ok(ty::mk_bare_fn(tcx, fty))
 541          })
 542        }
 543  
 544        (&ty::ty_closure(ref a_fty), &ty::ty_closure(ref b_fty)) => {
 545          this.closure_tys(*a_fty, *b_fty).and_then(|fty| {
 546              Ok(ty::mk_closure(tcx, fty))
 547          })
 548        }
 549  
 550        _ => Err(ty::terr_sorts(expected_found(this, a, b)))
 551      };
 552  
 553      fn unify_integral_variable<C:Combine>(
 554          this&C,
 555          vid_is_expectedbool,
 556          vidty::IntVid,
 557          valty::IntVarValue) -> cres<ty::t>
 558      {
 559          if_ok!(this.infcx().simple_var_t(vid_is_expected, vid, val));
 560          match val {
 561              IntType(v) => Ok(ty::mk_mach_int(v)),
 562              UintType(v) => Ok(ty::mk_mach_uint(v))
 563          }
 564      }
 565  
 566      fn unify_float_variable<C:Combine>(
 567          this&C,
 568          vid_is_expectedbool,
 569          vidty::FloatVid,
 570          valast::FloatTy) -> cres<ty::t>
 571      {
 572          if_ok!(this.infcx().simple_var_t(vid_is_expected, vid, val));
 573          Ok(ty::mk_mach_float(val))
 574      }
 575  }


librustc/middle/typeck/infer/combine.rs:378:4-378:4 -fn- definition:
    fn check_ptr_to_vec<C:Combine>(this: &C,
                                   a: ty::t,
                                   b: ty::t,
references:- 3
498:             let typ = if_ok!(this.tys(a_inner, b_inner));
499:             check_ptr_to_vec(this, a, b, a_inner, b_inner, ty::mk_uniq(tcx, typ))
500:       }
--
503:             let mt = if_ok!(this.mts(a_mt, b_mt));
504:             check_ptr_to_vec(this, a, b, a_mt.ty, b_mt.ty, ty::mk_ptr(tcx, mt))
505:       }
--
509:             let mt = if_ok!(this.mts(a_mt, b_mt));
510:             check_ptr_to_vec(this, a, b, a_mt.ty, b_mt.ty, ty::mk_rptr(tcx, r, mt))
511:       }


librustc/middle/typeck/infer/combine.rs:371:1-371:1 -fn- definition:
pub fn super_tys<C:Combine>(this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
    // This is a horible hack - historically, [T] was not treated as a type,
    // so, for example, &T and &[U] should not unify. In fact the only thing
references:- 2
librustc/middle/typeck/infer/sub.rs:
144:             _ => {
145:                 super_tys(self, a, b)
146:             }
librustc/middle/typeck/infer/lattice.rs:
404:         _ => {
405:             return super_tys(this, a, b);
406:         }


librustc/middle/typeck/infer/combine.rs:71:1-71:1 -trait- definition:
pub trait Combine {
    fn infcx<'a>(&'a self) -> &'a InferCtxt<'a>;
    fn tag(&self) -> ~str;
references:- 17
553:     fn unify_integral_variable<C:Combine>(
554:         this: &C,
--
566:     fn unify_float_variable<C:Combine>(
567:         this: &C,
librustc/middle/typeck/infer/glb.rs:
37: impl<'f> Combine for Glb<'f> {
38:     fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx }
librustc/middle/typeck/infer/lattice.rs:
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,
--
524: pub fn var_ids<T:Combine>(this: &T,
525:                           map: &HashMap<ty::BoundRegion, ty::Region>)
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 }
librustc/middle/typeck/infer/sub.rs:
36: impl<'f> Combine for Sub<'f> {
37:     fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx }
librustc/middle/typeck/infer/combine.rs:
377:     // check.
378:     fn check_ptr_to_vec<C:Combine>(this: &C,
379:                                    a: ty::t,


librustc/middle/typeck/infer/combine.rs:566:4-566:4 -fn- definition:
    fn unify_float_variable<C:Combine>(
        this: &C,
        vid_is_expected: bool,
references:- 2
443:         (&ty::ty_float(v), &ty::ty_infer(FloatVar(v_id))) => {
444:             unify_float_variable(this, !this.a_is_expected(), v_id, v)
445:         }


librustc/middle/typeck/infer/combine.rs:553:4-553:4 -fn- definition:
    fn unify_integral_variable<C:Combine>(
        this: &C,
        vid_is_expected: bool,
references:- 4
417:         (&ty::ty_infer(IntVar(v_id)), &ty::ty_int(v)) => {
418:             unify_integral_variable(this, this.a_is_expected(),
419:                                     v_id, IntType(v))
--
429:         (&ty::ty_uint(v), &ty::ty_infer(IntVar(v_id))) => {
430:             unify_integral_variable(this, !this.a_is_expected(),
431:                                     v_id, UintType(v))


librustc/middle/typeck/infer/combine.rs:303:19-303:19 -struct- definition:
pub struct CombineFields<'a> {
    pub infcx: &'a InferCtxt<'a>,
    pub a_is_expected: bool,
references:- 27
304: pub struct CombineFields<'a> {
librustc/middle/typeck/infer/sub.rs:
55:                     -> cres<ty::Region> {
56:         let opp = CombineFields {
57:             a_is_expected: !self.get_ref().a_is_expected,
librustc/middle/typeck/infer/combine.rs:
304: pub struct CombineFields<'a> {
librustc/middle/typeck/infer/mod.rs:
501:                               -> CombineFields<'a> {
502:         CombineFields {infcx: self,
503:                        a_is_expected: a_is_expected,
librustc/middle/typeck/infer/combine.rs:
304: pub struct CombineFields<'a> {
librustc/middle/typeck/infer/glb.rs:
31: pub struct Glb<'f>(pub CombineFields<'f>);  // "greatest lower bound" (common subtype)
--
33: impl<'f> Glb<'f> {
34:     pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> { let Glb(ref v) = *self; v }
35: }
librustc/middle/typeck/infer/lattice.rs:
50: trait LatticeValue {
51:     fn sub(cf: CombineFields, a: &Self, b: &Self) -> ures;
52:     fn lub(cf: CombineFields, a: &Self, b: &Self) -> cres<Self>;
--
56: pub type LatticeOp<'a, T> =
57:     |cf: CombineFields, a: &T, b: &T|: 'a -> cres<T>;
--
113: impl<'f> CombineFieldsLatticeMethods for CombineFields<'f> {
114:     fn var_sub_var<T:Clone + InferStr + LatticeValue,
--
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() }
--
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() }
librustc/middle/typeck/infer/lub.rs:
32: impl<'f> Lub<'f> {
33:     pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> { let Lub(ref v) = *self; v }
34: }
librustc/middle/typeck/infer/sub.rs:
30: pub struct Sub<'f>(pub CombineFields<'f>);  // "subtype", "subregion" etc
--
32: impl<'f> Sub<'f> {
33:     pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> { let Sub(ref v) = *self; v }
34: }
librustc/middle/typeck/infer/coercion.rs:
87: impl<'f> Coerce<'f> {
88:     pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> {
89:         let Coerce(ref v) = *self; v
librustc/middle/typeck/infer/mod.rs:
500:     pub fn combine_fields<'a>(&'a self, a_is_expected: bool, trace: TypeTrace)
501:                               -> CombineFields<'a> {
502:         CombineFields {infcx: self,
librustc/middle/typeck/infer/lattice.rs:
329: pub trait LatticeDir {
330:     fn combine_fields<'a>(&'a self) -> CombineFields<'a>;
331:     fn bnd<T:Clone>(&self, b: &Bounds<T>) -> Option<T>;


librustc/middle/typeck/infer/combine.rs:309:1-309:1 -fn- definition:
pub fn expected_found<C:Combine,T>(
        this: &C, a: T, b: T) -> ty::expected_found<T> {
    if this.a_is_expected() {
references:- 15
97:         } else {
98:             Err(ty::terr_ty_param_size(expected_found(self,
99:                                                       as_.len(),
--
533:             Err(ty::terr_tuple_size(
534:                 expected_found(this, as_.len(), bs.len())))
535:         }
--
550:       _ => Err(ty::terr_sorts(expected_found(this, a, b)))
551:     };
librustc/middle/typeck/infer/sub.rs:
99:         self.lub().oncenesses(a, b).compare(b, || {
100:             ty::terr_onceness_mismatch(expected_found(self, a, b))
101:         })
--
112:         } else {
113:             Err(ty::terr_builtin_bounds(expected_found(self, a, b)))
114:         }
--
140:             (_, &ty::ty_bot) => {
141:                 Err(ty::terr_sorts(expected_found(self, a, b)))
142:             }
librustc/middle/typeck/infer/combine.rs:
247:         } else {
248:             Err(ty::terr_abi_mismatch(expected_found(self, a, b)))
249:         }


librustc/middle/typeck/infer/combine.rs:346:1-346:1 -fn- definition:
pub fn super_fn_sigs<C:Combine>(this: &C, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
    fn argvecs<C:Combine>(this: &C, a_args: &[ty::t], b_args: &[ty::t]) -> cres<Vec<ty::t> > {
        if a_args.len() == b_args.len() {
references:- 3
librustc/middle/typeck/infer/glb.rs:
146:         // Collect constraints.
147:         let sig0 = if_ok!(super_fn_sigs(self, &a_with_fresh, &b_with_fresh));
148:         debug!("sig0 = {}", sig0.inf_str(self.get_ref().infcx));
librustc/middle/typeck/infer/sub.rs:
189:         // Compare types now that bound regions have been replaced.
190:         let sig = if_ok!(super_fn_sigs(self, &a_sig, &b_sig));
librustc/middle/typeck/infer/lub.rs:
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));


librustc/middle/typeck/infer/combine.rs:318:1-318:1 -fn- definition:
pub fn eq_tys<C:Combine>(this: &C, a: ty::t, b: ty::t) -> ures {
    let suber = this.sub();
    this.infcx().try(|| {
references:- 5
94:             result::fold_(as_.iter().zip(bs.iter())
95:                           .map(|(a, b)| eq_tys(self, *a, *b)))
96:                 .then(|| Ok(Vec::from_slice(as_)))
librustc/middle/typeck/infer/glb.rs:
58:           (MutMutable, MutMutable) => {
59:             eq_tys(self, a.ty, b.ty).then(|| {
60:                 Ok(ty::mt {ty: a.ty, mutbl: MutMutable})
librustc/middle/typeck/infer/lub.rs:
65:             self.get_ref().infcx.try(|| {
66:                 eq_tys(self, a.ty, b.ty).then(|| {
67:                     Ok(ty::mt {ty: a.ty, mutbl: m})
librustc/middle/typeck/infer/mod.rs:
369:             let suber = cx.sub(a_is_expected, trace);
370:             eq_tys(&suber, a, b)
371:         })
librustc/middle/typeck/infer/sub.rs:
82:             // (i.e., invariant if mut):
83:             eq_tys(self, a.ty, b.ty).then(|| Ok(*a))
84:           }