]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/infer/lattice.rs
Auto merge of #30696 - steveklabnik:gh30655, r=brson
[rust.git] / src / librustc / middle / infer / lattice.rs
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 //! # Lattice Variables
12 //!
13 //! This file contains generic code for operating on inference variables
14 //! that are characterized by an upper- and lower-bound.  The logic and
15 //! reasoning is explained in detail in the large comment in `infer.rs`.
16 //!
17 //! The code in here is defined quite generically so that it can be
18 //! applied both to type variables, which represent types being inferred,
19 //! and fn variables, which represent function types being inferred.
20 //! It may eventually be applied to their types as well, who knows.
21 //! In some cases, the functions are also generic with respect to the
22 //! operation on the lattice (GLB vs LUB).
23 //!
24 //! Although all the functions are generic, we generally write the
25 //! comments in a way that is specific to type variables and the LUB
26 //! operation.  It's just easier that way.
27 //!
28 //! In general all of the functions are defined parametrically
29 //! over a `LatticeValue`, which is a value defined with respect to
30 //! a lattice.
31
32 use super::combine;
33 use super::InferCtxt;
34
35 use middle::ty::TyVar;
36 use middle::ty::{self, Ty};
37 use middle::ty::relate::{RelateResult, TypeRelation};
38
39 pub trait LatticeDir<'f,'tcx> : TypeRelation<'f,'tcx> {
40     fn infcx(&self) -> &'f InferCtxt<'f, 'tcx>;
41
42     // Relates the type `v` to `a` and `b` such that `v` represents
43     // the LUB/GLB of `a` and `b` as appropriate.
44     fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>;
45 }
46
47 pub fn super_lattice_tys<'a,'tcx,L:LatticeDir<'a,'tcx>>(this: &mut L,
48                                                         a: Ty<'tcx>,
49                                                         b: Ty<'tcx>)
50                                                         -> RelateResult<'tcx, Ty<'tcx>>
51     where 'tcx: 'a
52 {
53     debug!("{}.lattice_tys({:?}, {:?})",
54            this.tag(),
55            a,
56            b);
57
58     if a == b {
59         return Ok(a);
60     }
61
62     let infcx = this.infcx();
63     let a = infcx.type_variables.borrow().replace_if_possible(a);
64     let b = infcx.type_variables.borrow().replace_if_possible(b);
65     match (&a.sty, &b.sty) {
66         (&ty::TyInfer(TyVar(..)), &ty::TyInfer(TyVar(..)))
67             if infcx.type_var_diverges(a) && infcx.type_var_diverges(b) => {
68             let v = infcx.next_diverging_ty_var();
69             try!(this.relate_bound(v, a, b));
70             Ok(v)
71         }
72
73         (&ty::TyInfer(TyVar(..)), _) |
74         (_, &ty::TyInfer(TyVar(..))) => {
75             let v = infcx.next_ty_var();
76             try!(this.relate_bound(v, a, b));
77             Ok(v)
78         }
79
80         _ => {
81             combine::super_combine_tys(this.infcx(), this, a, b)
82         }
83     }
84 }