]> git.proxmox.com Git - rustc.git/blame - src/librustc/ty/relate.rs
New upstream version 1.13.0+dfsg1
[rustc.git] / src / librustc / ty / relate.rs
CommitLineData
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 16use hir::def_id::DefId;
9e0c209e 17use ty::subst::{Kind, Substs};
54a0048b
SL
18use ty::{self, Ty, TyCtxt, TypeFoldable};
19use ty::error::{ExpectedFound, TypeError};
c34b1796
AL
20use std::rc::Rc;
21use syntax::abi;
54a0048b 22use hir as ast;
c34b1796 23
e9174d1e 24pub type RelateResult<'tcx, T> = Result<T, TypeError<'tcx>>;
c34b1796 25
62682a34
SL
26#[derive(Clone, Debug)]
27pub enum Cause {
c1a9b12d 28 ExistentialRegionBound, // relating an existential region bound
62682a34
SL
29}
30
a7813a04
XL
31pub 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
82pub 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
91impl<'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
119fn 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 141pub 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
164impl<'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
182impl<'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
205fn 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
220impl<'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
235impl<'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
250impl<'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 267impl<'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 289impl<'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
311impl<'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
328impl<'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
345impl<'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
362impl<'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
376pub 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
539impl<'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
555impl<'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 566impl<'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
577impl<'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
588impl<'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
601impl<'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
617pub 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
626pub 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}