]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
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 | ||
c34b1796 | 11 | use super::combine::{self, CombineFields}; |
1a4d82fc | 12 | use super::higher_ranked::HigherRankedRelations; |
62682a34 | 13 | use super::SubregionOrigin; |
1a4d82fc JJ |
14 | use super::type_variable::{SubtypeOf, SupertypeOf}; |
15 | ||
1a4d82fc JJ |
16 | use middle::ty::{self, Ty}; |
17 | use middle::ty::TyVar; | |
e9174d1e | 18 | use middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; |
62682a34 | 19 | use std::mem; |
1a4d82fc | 20 | |
b039eaaf | 21 | /// Ensures `a` is made a subtype of `b`. Returns `a` on success. |
c34b1796 | 22 | pub struct Sub<'a, 'tcx: 'a> { |
62682a34 | 23 | fields: CombineFields<'a, 'tcx>, |
1a4d82fc JJ |
24 | } |
25 | ||
c34b1796 AL |
26 | impl<'a, 'tcx> Sub<'a, 'tcx> { |
27 | pub fn new(f: CombineFields<'a, 'tcx>) -> Sub<'a, 'tcx> { | |
28 | Sub { fields: f } | |
29 | } | |
1a4d82fc JJ |
30 | } |
31 | ||
c34b1796 AL |
32 | impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> { |
33 | fn tag(&self) -> &'static str { "Sub" } | |
34 | fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.infcx.tcx } | |
35 | fn a_is_expected(&self) -> bool { self.fields.a_is_expected } | |
85aaf69f | 36 | |
62682a34 SL |
37 | fn with_cause<F,R>(&mut self, cause: Cause, f: F) -> R |
38 | where F: FnOnce(&mut Self) -> R | |
39 | { | |
40 | debug!("sub with_cause={:?}", cause); | |
41 | let old_cause = mem::replace(&mut self.fields.cause, Some(cause)); | |
42 | let r = f(self); | |
43 | debug!("sub old_cause={:?}", old_cause); | |
44 | self.fields.cause = old_cause; | |
45 | r | |
46 | } | |
47 | ||
c34b1796 AL |
48 | fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self, |
49 | variance: ty::Variance, | |
50 | a: &T, | |
51 | b: &T) | |
52 | -> RelateResult<'tcx, T> | |
85aaf69f | 53 | { |
c34b1796 AL |
54 | match variance { |
55 | ty::Invariant => self.fields.equate().relate(a, b), | |
56 | ty::Covariant => self.relate(a, b), | |
57 | ty::Bivariant => self.fields.bivariate().relate(a, b), | |
58 | ty::Contravariant => self.fields.switch_expected().sub().relate(b, a), | |
85aaf69f | 59 | } |
1a4d82fc JJ |
60 | } |
61 | ||
c34b1796 | 62 | fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { |
62682a34 | 63 | debug!("{}.tys({:?}, {:?})", self.tag(), a, b); |
1a4d82fc | 64 | |
1a4d82fc JJ |
65 | if a == b { return Ok(a); } |
66 | ||
67 | let infcx = self.fields.infcx; | |
68 | let a = infcx.type_variables.borrow().replace_if_possible(a); | |
69 | let b = infcx.type_variables.borrow().replace_if_possible(b); | |
70 | match (&a.sty, &b.sty) { | |
62682a34 | 71 | (&ty::TyInfer(TyVar(a_id)), &ty::TyInfer(TyVar(b_id))) => { |
1a4d82fc JJ |
72 | infcx.type_variables |
73 | .borrow_mut() | |
74 | .relate_vars(a_id, SubtypeOf, b_id); | |
75 | Ok(a) | |
76 | } | |
62682a34 | 77 | (&ty::TyInfer(TyVar(a_id)), _) => { |
1a4d82fc | 78 | try!(self.fields |
c34b1796 AL |
79 | .switch_expected() |
80 | .instantiate(b, SupertypeOf, a_id)); | |
1a4d82fc JJ |
81 | Ok(a) |
82 | } | |
62682a34 | 83 | (_, &ty::TyInfer(TyVar(b_id))) => { |
1a4d82fc JJ |
84 | try!(self.fields.instantiate(a, SubtypeOf, b_id)); |
85 | Ok(a) | |
86 | } | |
87 | ||
62682a34 | 88 | (&ty::TyError, _) | (_, &ty::TyError) => { |
1a4d82fc JJ |
89 | Ok(self.tcx().types.err) |
90 | } | |
91 | ||
92 | _ => { | |
b039eaaf SL |
93 | try!(combine::super_combine_tys(self.fields.infcx, self, a, b)); |
94 | Ok(a) | |
1a4d82fc JJ |
95 | } |
96 | } | |
97 | } | |
98 | ||
c34b1796 | 99 | fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> { |
62682a34 SL |
100 | debug!("{}.regions({:?}, {:?}) self.cause={:?}", |
101 | self.tag(), a, b, self.fields.cause); | |
c1a9b12d SL |
102 | // FIXME -- we have more fine-grained information available |
103 | // from the "cause" field, we could perhaps give more tailored | |
104 | // error messages. | |
105 | let origin = SubregionOrigin::Subtype(self.fields.trace.clone()); | |
c34b1796 AL |
106 | self.fields.infcx.region_vars.make_subregion(origin, a, b); |
107 | Ok(a) | |
108 | } | |
109 | ||
110 | fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>) | |
111 | -> RelateResult<'tcx, ty::Binder<T>> | |
112 | where T: Relate<'a,'tcx> | |
1a4d82fc | 113 | { |
c34b1796 | 114 | self.fields.higher_ranked_sub(a, b) |
1a4d82fc JJ |
115 | } |
116 | } |