]>
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 | ||
62682a34 SL |
45 | fn will_change(&mut self, _: bool, _: bool) -> bool { |
46 | // we're ignoring regions in this code | |
47 | false | |
48 | } | |
49 | ||
c34b1796 AL |
50 | fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self, |
51 | _: ty::Variance, | |
52 | a: &T, | |
53 | b: &T) | |
54 | -> RelateResult<'tcx, T> | |
55 | { | |
56 | self.relate(a, b) | |
57 | } | |
58 | ||
59 | fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> { | |
62682a34 | 60 | debug!("{}.regions({:?}, {:?})", |
c34b1796 | 61 | self.tag(), |
62682a34 SL |
62 | a, |
63 | b); | |
c34b1796 AL |
64 | Ok(a) |
65 | } | |
66 | ||
67 | fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { | |
62682a34 SL |
68 | debug!("{}.tys({:?}, {:?})", self.tag(), |
69 | a, b); | |
c34b1796 AL |
70 | if a == b { return Ok(a); } |
71 | ||
72 | match (&a.sty, &b.sty) { | |
62682a34 SL |
73 | (_, &ty::TyInfer(ty::FreshTy(_))) | |
74 | (_, &ty::TyInfer(ty::FreshIntTy(_))) | | |
75 | (_, &ty::TyInfer(ty::FreshFloatTy(_))) => { | |
c34b1796 AL |
76 | Ok(a) |
77 | } | |
78 | ||
62682a34 SL |
79 | (&ty::TyInfer(_), _) | |
80 | (_, &ty::TyInfer(_)) => { | |
c34b1796 AL |
81 | Err(ty::terr_sorts(ty_relate::expected_found(self, &a, &b))) |
82 | } | |
83 | ||
62682a34 | 84 | (&ty::TyError, _) | (_, &ty::TyError) => { |
c34b1796 AL |
85 | Ok(self.tcx().types.err) |
86 | } | |
87 | ||
88 | _ => { | |
89 | ty_relate::super_relate_tys(self, a, b) | |
90 | } | |
91 | } | |
92 | } | |
93 | ||
94 | fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>) | |
95 | -> RelateResult<'tcx, ty::Binder<T>> | |
96 | where T: Relate<'a,'tcx> | |
97 | { | |
98 | Ok(ty::Binder(try!(self.relate(a.skip_binder(), b.skip_binder())))) | |
99 | } | |
100 | } |