1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! # Lattice Variables //! //! This file contains generic code for operating on inference variables //! that are characterized by an upper- and lower-bound. The logic and //! reasoning is explained in detail in the large comment in `infer.rs`. //! //! The code in here is defined quite generically so that it can be //! applied both to type variables, which represent types being inferred, //! and fn variables, which represent function types being inferred. //! It may eventually be applied to their types as well, who knows. //! In some cases, the functions are also generic with respect to the //! operation on the lattice (GLB vs LUB). //! //! Although all the functions are generic, we generally write the //! comments in a way that is specific to type variables and the LUB //! operation. It's just easier that way. //! //! In general all of the functions are defined parametrically //! over a `LatticeValue`, which is a value defined with respect to //! a lattice. use super::combine; use super::InferCtxt; use middle::ty::TyVar; use middle::ty::{self, Ty}; use middle::ty_relate::{RelateResult, TypeRelation}; use util::ppaux::Repr; pub trait LatticeDir<'f,'tcx> : TypeRelation<'f,'tcx> { fn infcx(&self) -> &'f InferCtxt<'f, 'tcx>; // Relates the type `v` to `a` and `b` such that `v` represents // the LUB/GLB of `a` and `b` as appropriate. fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>; } pub fn super_lattice_tys<'a,'tcx,L:LatticeDir<'a,'tcx>>(this: &mut L, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> where 'tcx: 'a { debug!("{}.lattice_tys({}, {})", this.tag(), a.repr(this.tcx()), b.repr(this.tcx())); if a == b { return Ok(a); } let infcx = this.infcx(); let a = infcx.type_variables.borrow().replace_if_possible(a); let b = infcx.type_variables.borrow().replace_if_possible(b); match (&a.sty, &b.sty) { (&ty::ty_infer(TyVar(..)), &ty::ty_infer(TyVar(..))) if infcx.type_var_diverges(a) && infcx.type_var_diverges(b) => { let v = infcx.next_diverging_ty_var(); try!(this.relate_bound(v, a, b)); Ok(v) } (&ty::ty_infer(TyVar(..)), _) | (_, &ty::ty_infer(TyVar(..))) => { let v = infcx.next_ty_var(); try!(this.relate_bound(v, a, b)); Ok(v) } _ => { combine::super_combine_tys(this.infcx(), this, a, b) } } }