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