]>
Commit | Line | Data |
---|---|---|
c34b1796 AL |
1 | // Copyright 2012-2013 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 | //! Generalized type relating mechanism. A type relation R relates a | |
12 | //! pair of values (A, B). A and B are usually types or regions but | |
13 | //! can be other things. Examples of type relations are subtyping, | |
14 | //! type equality, etc. | |
15 | ||
54a0048b | 16 | use hir::def_id::DefId; |
9e0c209e | 17 | use ty::subst::{Kind, Substs}; |
54a0048b SL |
18 | use ty::{self, Ty, TyCtxt, TypeFoldable}; |
19 | use ty::error::{ExpectedFound, TypeError}; | |
c34b1796 AL |
20 | use std::rc::Rc; |
21 | use syntax::abi; | |
54a0048b | 22 | use hir as ast; |
c34b1796 | 23 | |
e9174d1e | 24 | pub type RelateResult<'tcx, T> = Result<T, TypeError<'tcx>>; |
c34b1796 | 25 | |
62682a34 SL |
26 | #[derive(Clone, Debug)] |
27 | pub enum Cause { | |
c1a9b12d | 28 | ExistentialRegionBound, // relating an existential region bound |
62682a34 SL |
29 | } |
30 | ||
a7813a04 XL |
31 | pub trait TypeRelation<'a, 'gcx: 'a+'tcx, 'tcx: 'a> : Sized { |
32 | fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx>; | |
c34b1796 AL |
33 | |
34 | /// Returns a static string we can use for printouts. | |
35 | fn tag(&self) -> &'static str; | |
36 | ||
37 | /// Returns true if the value `a` is the "expected" type in the | |
38 | /// relation. Just affects error messages. | |
39 | fn a_is_expected(&self) -> bool; | |
40 | ||
62682a34 SL |
41 | fn with_cause<F,R>(&mut self, _cause: Cause, f: F) -> R |
42 | where F: FnOnce(&mut Self) -> R | |
43 | { | |
44 | f(self) | |
45 | } | |
46 | ||
c34b1796 | 47 | /// Generic relation routine suitable for most anything. |
a7813a04 | 48 | fn relate<T: Relate<'tcx>>(&mut self, a: &T, b: &T) -> RelateResult<'tcx, T> { |
c34b1796 AL |
49 | Relate::relate(self, a, b) |
50 | } | |
51 | ||
c1a9b12d | 52 | /// Relete elements of two slices pairwise. |
a7813a04 | 53 | fn relate_zip<T: Relate<'tcx>>(&mut self, a: &[T], b: &[T]) -> RelateResult<'tcx, Vec<T>> { |
c1a9b12d SL |
54 | assert_eq!(a.len(), b.len()); |
55 | a.iter().zip(b).map(|(a, b)| self.relate(a, b)).collect() | |
56 | } | |
57 | ||
c34b1796 | 58 | /// Switch variance for the purpose of relating `a` and `b`. |
a7813a04 XL |
59 | fn relate_with_variance<T: Relate<'tcx>>(&mut self, |
60 | variance: ty::Variance, | |
61 | a: &T, | |
62 | b: &T) | |
63 | -> RelateResult<'tcx, T>; | |
c34b1796 AL |
64 | |
65 | // Overrideable relations. You shouldn't typically call these | |
66 | // directly, instead call `relate()`, which in turn calls | |
67 | // these. This is both more uniform but also allows us to add | |
68 | // additional hooks for other types in the future if needed | |
69 | // without making older code, which called `relate`, obsolete. | |
70 | ||
71 | fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) | |
72 | -> RelateResult<'tcx, Ty<'tcx>>; | |
73 | ||
9e0c209e SL |
74 | fn regions(&mut self, a: &'tcx ty::Region, b: &'tcx ty::Region) |
75 | -> RelateResult<'tcx, &'tcx ty::Region>; | |
c34b1796 AL |
76 | |
77 | fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>) | |
78 | -> RelateResult<'tcx, ty::Binder<T>> | |
a7813a04 | 79 | where T: Relate<'tcx>; |
c34b1796 AL |
80 | } |
81 | ||
a7813a04 XL |
82 | pub trait Relate<'tcx>: TypeFoldable<'tcx> { |
83 | fn relate<'a, 'gcx, R>(relation: &mut R, a: &Self, b: &Self) | |
84 | -> RelateResult<'tcx, Self> | |
85 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a; | |
c34b1796 AL |
86 | } |
87 | ||
88 | /////////////////////////////////////////////////////////////////////////// | |
89 | // Relate impls | |
90 | ||
a7813a04 XL |
91 | impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> { |
92 | fn relate<'a, 'gcx, R>(relation: &mut R, | |
93 | a: &ty::TypeAndMut<'tcx>, | |
94 | b: &ty::TypeAndMut<'tcx>) | |
95 | -> RelateResult<'tcx, ty::TypeAndMut<'tcx>> | |
96 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
c34b1796 | 97 | { |
62682a34 | 98 | debug!("{}.mts({:?}, {:?})", |
c34b1796 | 99 | relation.tag(), |
62682a34 SL |
100 | a, |
101 | b); | |
c34b1796 | 102 | if a.mutbl != b.mutbl { |
c1a9b12d | 103 | Err(TypeError::Mutability) |
c34b1796 AL |
104 | } else { |
105 | let mutbl = a.mutbl; | |
106 | let variance = match mutbl { | |
7453a54e SL |
107 | ast::Mutability::MutImmutable => ty::Covariant, |
108 | ast::Mutability::MutMutable => ty::Invariant, | |
c34b1796 | 109 | }; |
54a0048b | 110 | let ty = relation.relate_with_variance(variance, &a.ty, &b.ty)?; |
c1a9b12d | 111 | Ok(ty::TypeAndMut {ty: ty, mutbl: mutbl}) |
c34b1796 AL |
112 | } |
113 | } | |
114 | } | |
115 | ||
116 | // substitutions are not themselves relatable without more context, | |
117 | // but they is an important subroutine for things that ARE relatable, | |
118 | // like traits etc. | |
a7813a04 XL |
119 | fn relate_item_substs<'a, 'gcx, 'tcx, R>(relation: &mut R, |
120 | item_def_id: DefId, | |
121 | a_subst: &'tcx Substs<'tcx>, | |
122 | b_subst: &'tcx Substs<'tcx>) | |
123 | -> RelateResult<'tcx, &'tcx Substs<'tcx>> | |
124 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
c34b1796 | 125 | { |
62682a34 SL |
126 | debug!("substs: item_def_id={:?} a_subst={:?} b_subst={:?}", |
127 | item_def_id, | |
128 | a_subst, | |
129 | b_subst); | |
c34b1796 AL |
130 | |
131 | let variances; | |
132 | let opt_variances = if relation.tcx().variance_computed.get() { | |
c1a9b12d | 133 | variances = relation.tcx().item_variances(item_def_id); |
c34b1796 AL |
134 | Some(&*variances) |
135 | } else { | |
136 | None | |
137 | }; | |
138 | relate_substs(relation, opt_variances, a_subst, b_subst) | |
139 | } | |
140 | ||
a7813a04 | 141 | pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R, |
9e0c209e | 142 | variances: Option<&Vec<ty::Variance>>, |
a7813a04 XL |
143 | a_subst: &'tcx Substs<'tcx>, |
144 | b_subst: &'tcx Substs<'tcx>) | |
145 | -> RelateResult<'tcx, &'tcx Substs<'tcx>> | |
146 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
c34b1796 | 147 | { |
9e0c209e | 148 | let tcx = relation.tcx(); |
c34b1796 | 149 | |
9e0c209e SL |
150 | let params = a_subst.params().iter().zip(b_subst.params()).enumerate().map(|(i, (a, b))| { |
151 | let variance = variances.map_or(ty::Invariant, |v| v[i]); | |
152 | if let (Some(a_ty), Some(b_ty)) = (a.as_type(), b.as_type()) { | |
153 | Ok(Kind::from(relation.relate_with_variance(variance, &a_ty, &b_ty)?)) | |
154 | } else if let (Some(a_r), Some(b_r)) = (a.as_region(), b.as_region()) { | |
155 | Ok(Kind::from(relation.relate_with_variance(variance, &a_r, &b_r)?)) | |
156 | } else { | |
157 | bug!() | |
158 | } | |
159 | }); | |
c34b1796 | 160 | |
9e0c209e | 161 | Substs::maybe_new(tcx, params) |
c34b1796 AL |
162 | } |
163 | ||
a7813a04 XL |
164 | impl<'tcx> Relate<'tcx> for &'tcx ty::BareFnTy<'tcx> { |
165 | fn relate<'a, 'gcx, R>(relation: &mut R, | |
166 | a: &&'tcx ty::BareFnTy<'tcx>, | |
167 | b: &&'tcx ty::BareFnTy<'tcx>) | |
168 | -> RelateResult<'tcx, &'tcx ty::BareFnTy<'tcx>> | |
169 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
c34b1796 | 170 | { |
54a0048b SL |
171 | let unsafety = relation.relate(&a.unsafety, &b.unsafety)?; |
172 | let abi = relation.relate(&a.abi, &b.abi)?; | |
173 | let sig = relation.relate(&a.sig, &b.sig)?; | |
a7813a04 XL |
174 | Ok(relation.tcx().mk_bare_fn(ty::BareFnTy { |
175 | unsafety: unsafety, | |
176 | abi: abi, | |
177 | sig: sig | |
178 | })) | |
c34b1796 AL |
179 | } |
180 | } | |
181 | ||
a7813a04 XL |
182 | impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { |
183 | fn relate<'a, 'gcx, R>(relation: &mut R, | |
184 | a: &ty::FnSig<'tcx>, | |
185 | b: &ty::FnSig<'tcx>) | |
186 | -> RelateResult<'tcx, ty::FnSig<'tcx>> | |
187 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
c34b1796 AL |
188 | { |
189 | if a.variadic != b.variadic { | |
c1a9b12d | 190 | return Err(TypeError::VariadicMismatch( |
c34b1796 AL |
191 | expected_found(relation, &a.variadic, &b.variadic))); |
192 | } | |
193 | ||
54a0048b SL |
194 | let inputs = relate_arg_vecs(relation, |
195 | &a.inputs, | |
196 | &b.inputs)?; | |
5bcae85e | 197 | let output = relation.relate(&a.output, &b.output)?; |
c34b1796 | 198 | |
5bcae85e SL |
199 | Ok(ty::FnSig {inputs: inputs, |
200 | output: output, | |
201 | variadic: a.variadic}) | |
c34b1796 AL |
202 | } |
203 | } | |
204 | ||
a7813a04 XL |
205 | fn relate_arg_vecs<'a, 'gcx, 'tcx, R>(relation: &mut R, |
206 | a_args: &[Ty<'tcx>], | |
207 | b_args: &[Ty<'tcx>]) | |
208 | -> RelateResult<'tcx, Vec<Ty<'tcx>>> | |
209 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
c34b1796 AL |
210 | { |
211 | if a_args.len() != b_args.len() { | |
c1a9b12d | 212 | return Err(TypeError::ArgCount); |
c34b1796 AL |
213 | } |
214 | ||
62682a34 | 215 | a_args.iter().zip(b_args) |
c34b1796 AL |
216 | .map(|(a, b)| relation.relate_with_variance(ty::Contravariant, a, b)) |
217 | .collect() | |
218 | } | |
219 | ||
a7813a04 XL |
220 | impl<'tcx> Relate<'tcx> for ast::Unsafety { |
221 | fn relate<'a, 'gcx, R>(relation: &mut R, | |
222 | a: &ast::Unsafety, | |
223 | b: &ast::Unsafety) | |
224 | -> RelateResult<'tcx, ast::Unsafety> | |
225 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
c34b1796 AL |
226 | { |
227 | if a != b { | |
c1a9b12d | 228 | Err(TypeError::UnsafetyMismatch(expected_found(relation, a, b))) |
c34b1796 AL |
229 | } else { |
230 | Ok(*a) | |
231 | } | |
232 | } | |
233 | } | |
234 | ||
a7813a04 XL |
235 | impl<'tcx> Relate<'tcx> for abi::Abi { |
236 | fn relate<'a, 'gcx, R>(relation: &mut R, | |
237 | a: &abi::Abi, | |
238 | b: &abi::Abi) | |
239 | -> RelateResult<'tcx, abi::Abi> | |
240 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
c34b1796 AL |
241 | { |
242 | if a == b { | |
243 | Ok(*a) | |
244 | } else { | |
c1a9b12d | 245 | Err(TypeError::AbiMismatch(expected_found(relation, a, b))) |
c34b1796 AL |
246 | } |
247 | } | |
248 | } | |
249 | ||
a7813a04 XL |
250 | impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> { |
251 | fn relate<'a, 'gcx, R>(relation: &mut R, | |
252 | a: &ty::ProjectionTy<'tcx>, | |
253 | b: &ty::ProjectionTy<'tcx>) | |
254 | -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> | |
255 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
c34b1796 AL |
256 | { |
257 | if a.item_name != b.item_name { | |
c1a9b12d | 258 | Err(TypeError::ProjectionNameMismatched( |
c34b1796 AL |
259 | expected_found(relation, &a.item_name, &b.item_name))) |
260 | } else { | |
54a0048b | 261 | let trait_ref = relation.relate(&a.trait_ref, &b.trait_ref)?; |
d9579d0f | 262 | Ok(ty::ProjectionTy { trait_ref: trait_ref, item_name: a.item_name }) |
c34b1796 AL |
263 | } |
264 | } | |
265 | } | |
266 | ||
9e0c209e | 267 | impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { |
a7813a04 | 268 | fn relate<'a, 'gcx, R>(relation: &mut R, |
9e0c209e SL |
269 | a: &ty::ExistentialProjection<'tcx>, |
270 | b: &ty::ExistentialProjection<'tcx>) | |
271 | -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> | |
a7813a04 | 272 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a |
c34b1796 | 273 | { |
9e0c209e SL |
274 | if a.item_name != b.item_name { |
275 | Err(TypeError::ProjectionNameMismatched( | |
276 | expected_found(relation, &a.item_name, &b.item_name))) | |
277 | } else { | |
278 | let trait_ref = relation.relate(&a.trait_ref, &b.trait_ref)?; | |
279 | let ty = relation.relate(&a.ty, &b.ty)?; | |
280 | Ok(ty::ExistentialProjection { | |
281 | trait_ref: trait_ref, | |
282 | item_name: a.item_name, | |
283 | ty: ty | |
284 | }) | |
285 | } | |
c34b1796 AL |
286 | } |
287 | } | |
288 | ||
9e0c209e | 289 | impl<'tcx> Relate<'tcx> for Vec<ty::PolyExistentialProjection<'tcx>> { |
a7813a04 | 290 | fn relate<'a, 'gcx, R>(relation: &mut R, |
9e0c209e SL |
291 | a: &Vec<ty::PolyExistentialProjection<'tcx>>, |
292 | b: &Vec<ty::PolyExistentialProjection<'tcx>>) | |
293 | -> RelateResult<'tcx, Vec<ty::PolyExistentialProjection<'tcx>>> | |
a7813a04 | 294 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a |
c34b1796 AL |
295 | { |
296 | // To be compatible, `a` and `b` must be for precisely the | |
297 | // same set of traits and item names. We always require that | |
298 | // projection bounds lists are sorted by trait-def-id and item-name, | |
299 | // so we can just iterate through the lists pairwise, so long as they are the | |
300 | // same length. | |
301 | if a.len() != b.len() { | |
c1a9b12d | 302 | Err(TypeError::ProjectionBoundsLength(expected_found(relation, &a.len(), &b.len()))) |
c34b1796 | 303 | } else { |
62682a34 | 304 | a.iter().zip(b) |
c34b1796 AL |
305 | .map(|(a, b)| relation.relate(a, b)) |
306 | .collect() | |
307 | } | |
308 | } | |
309 | } | |
310 | ||
a7813a04 XL |
311 | impl<'tcx> Relate<'tcx> for ty::BuiltinBounds { |
312 | fn relate<'a, 'gcx, R>(relation: &mut R, | |
313 | a: &ty::BuiltinBounds, | |
314 | b: &ty::BuiltinBounds) | |
315 | -> RelateResult<'tcx, ty::BuiltinBounds> | |
316 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
c34b1796 AL |
317 | { |
318 | // Two sets of builtin bounds are only relatable if they are | |
319 | // precisely the same (but see the coercion code). | |
320 | if a != b { | |
c1a9b12d | 321 | Err(TypeError::BuiltinBoundsMismatch(expected_found(relation, a, b))) |
c34b1796 AL |
322 | } else { |
323 | Ok(*a) | |
324 | } | |
325 | } | |
326 | } | |
327 | ||
a7813a04 XL |
328 | impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { |
329 | fn relate<'a, 'gcx, R>(relation: &mut R, | |
330 | a: &ty::TraitRef<'tcx>, | |
331 | b: &ty::TraitRef<'tcx>) | |
332 | -> RelateResult<'tcx, ty::TraitRef<'tcx>> | |
333 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
c34b1796 AL |
334 | { |
335 | // Different traits cannot be related | |
336 | if a.def_id != b.def_id { | |
c1a9b12d | 337 | Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) |
c34b1796 | 338 | } else { |
54a0048b | 339 | let substs = relate_item_substs(relation, a.def_id, a.substs, b.substs)?; |
a7813a04 | 340 | Ok(ty::TraitRef { def_id: a.def_id, substs: substs }) |
c34b1796 AL |
341 | } |
342 | } | |
343 | } | |
344 | ||
9e0c209e SL |
345 | impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { |
346 | fn relate<'a, 'gcx, R>(relation: &mut R, | |
347 | a: &ty::ExistentialTraitRef<'tcx>, | |
348 | b: &ty::ExistentialTraitRef<'tcx>) | |
349 | -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>> | |
350 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
351 | { | |
352 | // Different traits cannot be related | |
353 | if a.def_id != b.def_id { | |
354 | Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) | |
355 | } else { | |
356 | let substs = relate_item_substs(relation, a.def_id, a.substs, b.substs)?; | |
357 | Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs }) | |
358 | } | |
359 | } | |
360 | } | |
361 | ||
a7813a04 XL |
362 | impl<'tcx> Relate<'tcx> for Ty<'tcx> { |
363 | fn relate<'a, 'gcx, R>(relation: &mut R, | |
364 | a: &Ty<'tcx>, | |
365 | b: &Ty<'tcx>) | |
366 | -> RelateResult<'tcx, Ty<'tcx>> | |
367 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
c34b1796 AL |
368 | { |
369 | relation.tys(a, b) | |
370 | } | |
371 | } | |
372 | ||
373 | /// The main "type relation" routine. Note that this does not handle | |
374 | /// inference artifacts, so you should filter those out before calling | |
375 | /// it. | |
a7813a04 XL |
376 | pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, |
377 | a: Ty<'tcx>, | |
378 | b: Ty<'tcx>) | |
379 | -> RelateResult<'tcx, Ty<'tcx>> | |
380 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
c34b1796 AL |
381 | { |
382 | let tcx = relation.tcx(); | |
383 | let a_sty = &a.sty; | |
384 | let b_sty = &b.sty; | |
385 | debug!("super_tys: a_sty={:?} b_sty={:?}", a_sty, b_sty); | |
386 | match (a_sty, b_sty) { | |
62682a34 SL |
387 | (&ty::TyInfer(_), _) | |
388 | (_, &ty::TyInfer(_)) => | |
c34b1796 AL |
389 | { |
390 | // The caller should handle these cases! | |
54a0048b | 391 | bug!("var types encountered in super_relate_tys") |
c34b1796 AL |
392 | } |
393 | ||
62682a34 | 394 | (&ty::TyError, _) | (_, &ty::TyError) => |
c34b1796 AL |
395 | { |
396 | Ok(tcx.types.err) | |
397 | } | |
398 | ||
5bcae85e | 399 | (&ty::TyNever, _) | |
62682a34 SL |
400 | (&ty::TyChar, _) | |
401 | (&ty::TyBool, _) | | |
402 | (&ty::TyInt(_), _) | | |
403 | (&ty::TyUint(_), _) | | |
404 | (&ty::TyFloat(_), _) | | |
405 | (&ty::TyStr, _) | |
c34b1796 AL |
406 | if a == b => |
407 | { | |
408 | Ok(a) | |
409 | } | |
410 | ||
62682a34 | 411 | (&ty::TyParam(ref a_p), &ty::TyParam(ref b_p)) |
9e0c209e | 412 | if a_p.idx == b_p.idx => |
c34b1796 AL |
413 | { |
414 | Ok(a) | |
415 | } | |
416 | ||
9e0c209e | 417 | (&ty::TyAdt(a_def, a_substs), &ty::TyAdt(b_def, b_substs)) |
e9174d1e | 418 | if a_def == b_def => |
c34b1796 | 419 | { |
54a0048b | 420 | let substs = relate_item_substs(relation, a_def.did, a_substs, b_substs)?; |
9e0c209e | 421 | Ok(tcx.mk_adt(a_def, substs)) |
c34b1796 AL |
422 | } |
423 | ||
9e0c209e | 424 | (&ty::TyTrait(ref a_obj), &ty::TyTrait(ref b_obj)) => |
c34b1796 | 425 | { |
9e0c209e SL |
426 | let principal = relation.relate(&a_obj.principal, &b_obj.principal)?; |
427 | let r = | |
428 | relation.with_cause( | |
429 | Cause::ExistentialRegionBound, | |
430 | |relation| relation.relate_with_variance(ty::Contravariant, | |
431 | &a_obj.region_bound, | |
432 | &b_obj.region_bound))?; | |
433 | let nb = relation.relate(&a_obj.builtin_bounds, &b_obj.builtin_bounds)?; | |
434 | let pb = relation.relate(&a_obj.projection_bounds, &b_obj.projection_bounds)?; | |
435 | Ok(tcx.mk_trait(ty::TraitObject { | |
436 | principal: principal, | |
437 | region_bound: r, | |
438 | builtin_bounds: nb, | |
439 | projection_bounds: pb | |
440 | })) | |
c34b1796 AL |
441 | } |
442 | ||
a7813a04 XL |
443 | (&ty::TyClosure(a_id, a_substs), |
444 | &ty::TyClosure(b_id, b_substs)) | |
c34b1796 AL |
445 | if a_id == b_id => |
446 | { | |
62682a34 | 447 | // All TyClosure types with the same id represent |
c34b1796 AL |
448 | // the (anonymous) type of the same closure expression. So |
449 | // all of their regions should be equated. | |
a7813a04 | 450 | let substs = relation.relate(&a_substs, &b_substs)?; |
c1a9b12d | 451 | Ok(tcx.mk_closure_from_closure_substs(a_id, substs)) |
c34b1796 AL |
452 | } |
453 | ||
62682a34 | 454 | (&ty::TyBox(a_inner), &ty::TyBox(b_inner)) => |
c34b1796 | 455 | { |
54a0048b | 456 | let typ = relation.relate(&a_inner, &b_inner)?; |
c1a9b12d | 457 | Ok(tcx.mk_box(typ)) |
c34b1796 AL |
458 | } |
459 | ||
62682a34 | 460 | (&ty::TyRawPtr(ref a_mt), &ty::TyRawPtr(ref b_mt)) => |
c34b1796 | 461 | { |
54a0048b | 462 | let mt = relation.relate(a_mt, b_mt)?; |
c1a9b12d | 463 | Ok(tcx.mk_ptr(mt)) |
c34b1796 AL |
464 | } |
465 | ||
62682a34 | 466 | (&ty::TyRef(a_r, ref a_mt), &ty::TyRef(b_r, ref b_mt)) => |
c34b1796 | 467 | { |
9e0c209e | 468 | let r = relation.relate_with_variance(ty::Contravariant, &a_r, &b_r)?; |
54a0048b | 469 | let mt = relation.relate(a_mt, b_mt)?; |
9e0c209e | 470 | Ok(tcx.mk_ref(r, mt)) |
c34b1796 AL |
471 | } |
472 | ||
62682a34 | 473 | (&ty::TyArray(a_t, sz_a), &ty::TyArray(b_t, sz_b)) => |
c34b1796 | 474 | { |
54a0048b | 475 | let t = relation.relate(&a_t, &b_t)?; |
c34b1796 | 476 | if sz_a == sz_b { |
c1a9b12d | 477 | Ok(tcx.mk_array(t, sz_a)) |
c34b1796 | 478 | } else { |
c1a9b12d | 479 | Err(TypeError::FixedArraySize(expected_found(relation, &sz_a, &sz_b))) |
c34b1796 AL |
480 | } |
481 | } | |
482 | ||
62682a34 | 483 | (&ty::TySlice(a_t), &ty::TySlice(b_t)) => |
c34b1796 | 484 | { |
54a0048b | 485 | let t = relation.relate(&a_t, &b_t)?; |
c1a9b12d | 486 | Ok(tcx.mk_slice(t)) |
c34b1796 AL |
487 | } |
488 | ||
a7813a04 | 489 | (&ty::TyTuple(as_), &ty::TyTuple(bs)) => |
c34b1796 AL |
490 | { |
491 | if as_.len() == bs.len() { | |
54a0048b SL |
492 | let ts = as_.iter().zip(bs) |
493 | .map(|(a, b)| relation.relate(a, b)) | |
494 | .collect::<Result<_, _>>()?; | |
c1a9b12d | 495 | Ok(tcx.mk_tup(ts)) |
9346a6ac | 496 | } else if !(as_.is_empty() || bs.is_empty()) { |
c1a9b12d | 497 | Err(TypeError::TupleSize( |
c34b1796 AL |
498 | expected_found(relation, &as_.len(), &bs.len()))) |
499 | } else { | |
c1a9b12d | 500 | Err(TypeError::Sorts(expected_found(relation, &a, &b))) |
c34b1796 AL |
501 | } |
502 | } | |
503 | ||
54a0048b SL |
504 | (&ty::TyFnDef(a_def_id, a_substs, a_fty), |
505 | &ty::TyFnDef(b_def_id, b_substs, b_fty)) | |
506 | if a_def_id == b_def_id => | |
507 | { | |
508 | let substs = relate_substs(relation, None, a_substs, b_substs)?; | |
a7813a04 XL |
509 | let fty = relation.relate(&a_fty, &b_fty)?; |
510 | Ok(tcx.mk_fn_def(a_def_id, substs, fty)) | |
54a0048b SL |
511 | } |
512 | ||
513 | (&ty::TyFnPtr(a_fty), &ty::TyFnPtr(b_fty)) => | |
c34b1796 | 514 | { |
a7813a04 | 515 | let fty = relation.relate(&a_fty, &b_fty)?; |
54a0048b | 516 | Ok(tcx.mk_fn_ptr(fty)) |
c34b1796 AL |
517 | } |
518 | ||
62682a34 | 519 | (&ty::TyProjection(ref a_data), &ty::TyProjection(ref b_data)) => |
c34b1796 | 520 | { |
54a0048b | 521 | let projection_ty = relation.relate(a_data, b_data)?; |
c1a9b12d | 522 | Ok(tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name)) |
c34b1796 AL |
523 | } |
524 | ||
5bcae85e SL |
525 | (&ty::TyAnon(a_def_id, a_substs), &ty::TyAnon(b_def_id, b_substs)) |
526 | if a_def_id == b_def_id => | |
527 | { | |
528 | let substs = relate_substs(relation, None, a_substs, b_substs)?; | |
529 | Ok(tcx.mk_anon(a_def_id, substs)) | |
530 | } | |
531 | ||
c34b1796 AL |
532 | _ => |
533 | { | |
c1a9b12d | 534 | Err(TypeError::Sorts(expected_found(relation, &a, &b))) |
c34b1796 AL |
535 | } |
536 | } | |
537 | } | |
538 | ||
a7813a04 XL |
539 | impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> { |
540 | fn relate<'a, 'gcx, R>(relation: &mut R, | |
541 | a: &ty::ClosureSubsts<'tcx>, | |
542 | b: &ty::ClosureSubsts<'tcx>) | |
543 | -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>> | |
544 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
c1a9b12d | 545 | { |
a7813a04 | 546 | let substs = relate_substs(relation, None, a.func_substs, b.func_substs)?; |
54a0048b | 547 | let upvar_tys = relation.relate_zip(&a.upvar_tys, &b.upvar_tys)?; |
a7813a04 XL |
548 | Ok(ty::ClosureSubsts { |
549 | func_substs: substs, | |
550 | upvar_tys: relation.tcx().mk_type_list(upvar_tys) | |
551 | }) | |
c1a9b12d SL |
552 | } |
553 | } | |
554 | ||
a7813a04 XL |
555 | impl<'tcx> Relate<'tcx> for &'tcx Substs<'tcx> { |
556 | fn relate<'a, 'gcx, R>(relation: &mut R, | |
557 | a: &&'tcx Substs<'tcx>, | |
558 | b: &&'tcx Substs<'tcx>) | |
559 | -> RelateResult<'tcx, &'tcx Substs<'tcx>> | |
560 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
54a0048b SL |
561 | { |
562 | relate_substs(relation, None, a, b) | |
563 | } | |
564 | } | |
565 | ||
9e0c209e | 566 | impl<'tcx> Relate<'tcx> for &'tcx ty::Region { |
a7813a04 | 567 | fn relate<'a, 'gcx, R>(relation: &mut R, |
9e0c209e SL |
568 | a: &&'tcx ty::Region, |
569 | b: &&'tcx ty::Region) | |
570 | -> RelateResult<'tcx, &'tcx ty::Region> | |
a7813a04 | 571 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a |
c34b1796 AL |
572 | { |
573 | relation.regions(*a, *b) | |
574 | } | |
575 | } | |
576 | ||
a7813a04 XL |
577 | impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder<T> { |
578 | fn relate<'a, 'gcx, R>(relation: &mut R, | |
579 | a: &ty::Binder<T>, | |
580 | b: &ty::Binder<T>) | |
581 | -> RelateResult<'tcx, ty::Binder<T>> | |
582 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
c34b1796 AL |
583 | { |
584 | relation.binders(a, b) | |
585 | } | |
586 | } | |
587 | ||
a7813a04 XL |
588 | impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for Rc<T> { |
589 | fn relate<'a, 'gcx, R>(relation: &mut R, | |
590 | a: &Rc<T>, | |
591 | b: &Rc<T>) | |
592 | -> RelateResult<'tcx, Rc<T>> | |
593 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
c34b1796 AL |
594 | { |
595 | let a: &T = a; | |
596 | let b: &T = b; | |
54a0048b | 597 | Ok(Rc::new(relation.relate(a, b)?)) |
c34b1796 AL |
598 | } |
599 | } | |
600 | ||
a7813a04 XL |
601 | impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for Box<T> { |
602 | fn relate<'a, 'gcx, R>(relation: &mut R, | |
603 | a: &Box<T>, | |
604 | b: &Box<T>) | |
605 | -> RelateResult<'tcx, Box<T>> | |
606 | where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a | |
c34b1796 AL |
607 | { |
608 | let a: &T = a; | |
609 | let b: &T = b; | |
54a0048b | 610 | Ok(Box::new(relation.relate(a, b)?)) |
c34b1796 AL |
611 | } |
612 | } | |
613 | ||
614 | /////////////////////////////////////////////////////////////////////////// | |
615 | // Error handling | |
616 | ||
a7813a04 XL |
617 | pub fn expected_found<'a, 'gcx, 'tcx, R, T>(relation: &mut R, |
618 | a: &T, | |
619 | b: &T) | |
620 | -> ExpectedFound<T> | |
621 | where R: TypeRelation<'a, 'gcx, 'tcx>, T: Clone, 'gcx: 'a+'tcx, 'tcx: 'a | |
c34b1796 AL |
622 | { |
623 | expected_found_bool(relation.a_is_expected(), a, b) | |
624 | } | |
625 | ||
626 | pub fn expected_found_bool<T>(a_is_expected: bool, | |
627 | a: &T, | |
628 | b: &T) | |
e9174d1e | 629 | -> ExpectedFound<T> |
c34b1796 AL |
630 | where T: Clone |
631 | { | |
632 | let a = a.clone(); | |
633 | let b = b.clone(); | |
634 | if a_is_expected { | |
e9174d1e | 635 | ExpectedFound {expected: a, found: b} |
c34b1796 | 636 | } else { |
e9174d1e | 637 | ExpectedFound {expected: b, found: a} |
c34b1796 AL |
638 | } |
639 | } |