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