]> git.proxmox.com Git - rustc.git/blame - src/librustc/ty/relate.rs
New upstream version 1.14.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
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
76pub 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
85impl<'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
113fn 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 135pub 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
158impl<'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
176impl<'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
199fn 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
214impl<'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
229impl<'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
244impl<'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 261impl<'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 283impl<'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
305impl<'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
322impl<'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
339impl<'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
356impl<'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
370pub 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
530impl<'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
547impl<'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 558impl<'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
569impl<'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
580impl<'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
593impl<'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
609pub 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
618pub 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}