]> git.lizzy.rs Git - rust.git/blob - src/librustc/infer/lattice.rs
Remove ty::BrFresh and new_bound
[rust.git] / src / librustc / infer / lattice.rs
1 //! # Lattice Variables
2 //!
3 //! This file contains generic code for operating on inference variables
4 //! that are characterized by an upper- and lower-bound. The logic and
5 //! reasoning is explained in detail in the large comment in `infer.rs`.
6 //!
7 //! The code in here is defined quite generically so that it can be
8 //! applied both to type variables, which represent types being inferred,
9 //! and fn variables, which represent function types being inferred.
10 //! It may eventually be applied to their types as well, who knows.
11 //! In some cases, the functions are also generic with respect to the
12 //! operation on the lattice (GLB vs LUB).
13 //!
14 //! Although all the functions are generic, we generally write the
15 //! comments in a way that is specific to type variables and the LUB
16 //! operation. It's just easier that way.
17 //!
18 //! In general all of the functions are defined parametrically
19 //! over a `LatticeValue`, which is a value defined with respect to
20 //! a lattice.
21
22 use super::InferCtxt;
23 use super::type_variable::TypeVariableOrigin;
24
25 use crate::traits::ObligationCause;
26 use crate::ty::TyVar;
27 use crate::ty::{self, Ty};
28 use crate::ty::relate::{RelateResult, TypeRelation};
29
30 pub trait LatticeDir<'f, 'gcx: 'f+'tcx, 'tcx: 'f> : TypeRelation<'f, 'gcx, 'tcx> {
31     fn infcx(&self) -> &'f InferCtxt<'f, 'gcx, 'tcx>;
32
33     fn cause(&self) -> &ObligationCause<'tcx>;
34
35     // Relates the type `v` to `a` and `b` such that `v` represents
36     // the LUB/GLB of `a` and `b` as appropriate.
37     //
38     // Subtle hack: ordering *may* be significant here. This method
39     // relates `v` to `a` first, which may help us to avoid unnecessary
40     // type variable obligations. See caller for details.
41     fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>;
42 }
43
44 pub fn super_lattice_tys<'a, 'gcx, 'tcx, L>(this: &mut L,
45                                             a: Ty<'tcx>,
46                                             b: Ty<'tcx>)
47                                             -> RelateResult<'tcx, Ty<'tcx>>
48     where L: LatticeDir<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
49 {
50     debug!("{}.lattice_tys({:?}, {:?})",
51            this.tag(),
52            a,
53            b);
54
55     if a == b {
56         return Ok(a);
57     }
58
59     let infcx = this.infcx();
60     let a = infcx.type_variables.borrow_mut().replace_if_possible(a);
61     let b = infcx.type_variables.borrow_mut().replace_if_possible(b);
62     match (&a.sty, &b.sty) {
63         // If one side is known to be a variable and one is not,
64         // create a variable (`v`) to represent the LUB. Make sure to
65         // relate `v` to the non-type-variable first (by passing it
66         // first to `relate_bound`). Otherwise, we would produce a
67         // subtype obligation that must then be processed.
68         //
69         // Example: if the LHS is a type variable, and RHS is
70         // `Box<i32>`, then we current compare `v` to the RHS first,
71         // which will instantiate `v` with `Box<i32>`.  Then when `v`
72         // is compared to the LHS, we instantiate LHS with `Box<i32>`.
73         // But if we did in reverse order, we would create a `v <:
74         // LHS` (or vice versa) constraint and then instantiate
75         // `v`. This would require further processing to achieve same
76         // end-result; in partiular, this screws up some of the logic
77         // in coercion, which expects LUB to figure out that the LHS
78         // is (e.g.) `Box<i32>`. A more obvious solution might be to
79         // iterate on the subtype obligations that are returned, but I
80         // think this suffices. -nmatsakis
81         (&ty::Infer(TyVar(..)), _) => {
82             let v = infcx.next_ty_var(TypeVariableOrigin::LatticeVariable(this.cause().span));
83             this.relate_bound(v, b, a)?;
84             Ok(v)
85         }
86         (_, &ty::Infer(TyVar(..))) => {
87             let v = infcx.next_ty_var(TypeVariableOrigin::LatticeVariable(this.cause().span));
88             this.relate_bound(v, a, b)?;
89             Ok(v)
90         }
91
92         _ => {
93             infcx.super_combine_tys(this, a, b)
94         }
95     }
96 }