]>
Commit | Line | Data |
---|---|---|
c34b1796 AL |
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 | use middle::ty::{self, Ty}; | |
12 | use middle::ty_relate::{self, Relate, TypeRelation, RelateResult}; | |
c34b1796 AL |
13 | |
14 | /// A type "A" *matches* "B" if the fresh types in B could be | |
15 | /// substituted with values so as to make it equal to A. Matching is | |
16 | /// intended to be used only on freshened types, and it basically | |
17 | /// indicates if the non-freshened versions of A and B could have been | |
18 | /// unified. | |
19 | /// | |
20 | /// It is only an approximation. If it yields false, unification would | |
21 | /// definitely fail, but a true result doesn't mean unification would | |
22 | /// succeed. This is because we don't track the "side-constraints" on | |
23 | /// type variables, nor do we track if the same freshened type appears | |
24 | /// more than once. To some extent these approximations could be | |
25 | /// fixed, given effort. | |
26 | /// | |
27 | /// Like subtyping, matching is really a binary relation, so the only | |
28 | /// important thing about the result is Ok/Err. Also, matching never | |
29 | /// affects any type variables or unification state. | |
30 | pub struct Match<'a, 'tcx: 'a> { | |
31 | tcx: &'a ty::ctxt<'tcx> | |
32 | } | |
33 | ||
34 | impl<'a, 'tcx> Match<'a, 'tcx> { | |
35 | pub fn new(tcx: &'a ty::ctxt<'tcx>) -> Match<'a, 'tcx> { | |
36 | Match { tcx: tcx } | |
37 | } | |
38 | } | |
39 | ||
40 | impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Match<'a, 'tcx> { | |
41 | fn tag(&self) -> &'static str { "Match" } | |
42 | fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.tcx } | |
43 | fn a_is_expected(&self) -> bool { true } // irrelevant | |
44 | ||
45 | fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self, | |
46 | _: ty::Variance, | |
47 | a: &T, | |
48 | b: &T) | |
49 | -> RelateResult<'tcx, T> | |
50 | { | |
51 | self.relate(a, b) | |
52 | } | |
53 | ||
54 | fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> { | |
62682a34 | 55 | debug!("{}.regions({:?}, {:?})", |
c34b1796 | 56 | self.tag(), |
62682a34 SL |
57 | a, |
58 | b); | |
c34b1796 AL |
59 | Ok(a) |
60 | } | |
61 | ||
62 | fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { | |
62682a34 SL |
63 | debug!("{}.tys({:?}, {:?})", self.tag(), |
64 | a, b); | |
c34b1796 AL |
65 | if a == b { return Ok(a); } |
66 | ||
67 | match (&a.sty, &b.sty) { | |
62682a34 SL |
68 | (_, &ty::TyInfer(ty::FreshTy(_))) | |
69 | (_, &ty::TyInfer(ty::FreshIntTy(_))) | | |
70 | (_, &ty::TyInfer(ty::FreshFloatTy(_))) => { | |
c34b1796 AL |
71 | Ok(a) |
72 | } | |
73 | ||
62682a34 SL |
74 | (&ty::TyInfer(_), _) | |
75 | (_, &ty::TyInfer(_)) => { | |
c1a9b12d | 76 | Err(ty::TypeError::Sorts(ty_relate::expected_found(self, &a, &b))) |
c34b1796 AL |
77 | } |
78 | ||
62682a34 | 79 | (&ty::TyError, _) | (_, &ty::TyError) => { |
c34b1796 AL |
80 | Ok(self.tcx().types.err) |
81 | } | |
82 | ||
83 | _ => { | |
84 | ty_relate::super_relate_tys(self, a, b) | |
85 | } | |
86 | } | |
87 | } | |
88 | ||
89 | fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>) | |
90 | -> RelateResult<'tcx, ty::Binder<T>> | |
91 | where T: Relate<'a,'tcx> | |
92 | { | |
93 | Ok(ty::Binder(try!(self.relate(a.skip_binder(), b.skip_binder())))) | |
94 | } | |
95 | } |