2012-12-03 18:48:01 -06:00
|
|
|
// 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.
|
|
|
|
|
2014-11-25 20:17:11 -06:00
|
|
|
//! # 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.
|
2013-01-08 16:00:45 -06:00
|
|
|
|
2014-11-25 15:59:02 -06:00
|
|
|
use super::*;
|
|
|
|
use super::combine::*;
|
|
|
|
use super::glb::Glb;
|
|
|
|
use super::lub::Lub;
|
|
|
|
|
2014-11-15 16:09:51 -06:00
|
|
|
use middle::ty::{TyVar};
|
2015-01-03 21:42:21 -06:00
|
|
|
use middle::ty::{self, Ty};
|
2014-06-20 05:35:06 -05:00
|
|
|
use util::ppaux::Repr;
|
2012-08-13 17:06:13 -05:00
|
|
|
|
2014-09-29 14:11:30 -05:00
|
|
|
pub trait LatticeDir<'tcx> {
|
2014-07-22 06:46:36 -05:00
|
|
|
// Relates the type `v` to `a` and `b` such that `v` represents
|
|
|
|
// the LUB/GLB of `a` and `b` as appropriate.
|
2014-09-29 14:11:30 -05:00
|
|
|
fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, ()>;
|
2013-01-08 16:00:45 -06:00
|
|
|
}
|
|
|
|
|
2014-09-29 14:11:30 -05:00
|
|
|
impl<'a, 'tcx> LatticeDir<'tcx> for Lub<'a, 'tcx> {
|
|
|
|
fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, ()> {
|
2014-07-22 06:46:36 -05:00
|
|
|
let sub = self.sub();
|
|
|
|
try!(sub.tys(a, v));
|
|
|
|
try!(sub.tys(b, v));
|
|
|
|
Ok(())
|
2012-08-13 17:06:13 -05:00
|
|
|
}
|
2013-01-08 16:00:45 -06:00
|
|
|
}
|
|
|
|
|
2014-09-29 14:11:30 -05:00
|
|
|
impl<'a, 'tcx> LatticeDir<'tcx> for Glb<'a, 'tcx> {
|
|
|
|
fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, ()> {
|
2014-07-22 06:46:36 -05:00
|
|
|
let sub = self.sub();
|
|
|
|
try!(sub.tys(v, a));
|
|
|
|
try!(sub.tys(v, b));
|
|
|
|
Ok(())
|
|
|
|
}
|
2012-08-13 17:06:13 -05:00
|
|
|
}
|
|
|
|
|
2014-09-29 14:11:30 -05:00
|
|
|
pub fn super_lattice_tys<'tcx, L:LatticeDir<'tcx>+Combine<'tcx>>(this: &L,
|
|
|
|
a: Ty<'tcx>,
|
|
|
|
b: Ty<'tcx>)
|
|
|
|
-> cres<'tcx, Ty<'tcx>>
|
2014-07-22 06:46:36 -05:00
|
|
|
{
|
2014-06-20 05:35:06 -05:00
|
|
|
debug!("{}.lattice_tys({}, {})",
|
|
|
|
this.tag(),
|
|
|
|
a.repr(this.infcx().tcx),
|
|
|
|
b.repr(this.infcx().tcx));
|
2013-01-08 16:00:45 -06:00
|
|
|
|
|
|
|
if a == b {
|
|
|
|
return Ok(a);
|
|
|
|
}
|
|
|
|
|
2014-07-22 06:46:36 -05:00
|
|
|
let infcx = this.infcx();
|
|
|
|
let a = infcx.type_variables.borrow().replace_if_possible(a);
|
|
|
|
let b = infcx.type_variables.borrow().replace_if_possible(b);
|
2014-10-31 03:51:16 -05:00
|
|
|
match (&a.sty, &b.sty) {
|
2014-10-24 14:14:37 -05:00
|
|
|
(&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)
|
|
|
|
}
|
2014-07-22 06:46:36 -05:00
|
|
|
|
|
|
|
(&ty::ty_infer(TyVar(..)), _) |
|
|
|
|
(_, &ty::ty_infer(TyVar(..))) => {
|
|
|
|
let v = infcx.next_ty_var();
|
|
|
|
try!(this.relate_bound(v, a, b));
|
|
|
|
Ok(v)
|
2013-01-08 16:00:45 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
_ => {
|
2014-07-22 06:46:36 -05:00
|
|
|
super_tys(this, a, b)
|
2012-08-13 17:06:13 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|