]> git.lizzy.rs Git - rust.git/blob - src/librustc/ty/relate.rs
Add `consts` to `TypeRelation`
[rust.git] / src / librustc / ty / relate.rs
1 //! Generalized type relating mechanism.
2 //!
3 //! A type relation `R` relates a pair of values `(A, B)`. `A and B` are usually
4 //! types or regions but can be other things. Examples of type relations are
5 //! subtyping, type equality, etc.
6
7 use crate::hir::def_id::DefId;
8 use crate::ty::subst::{Kind, UnpackedKind, SubstsRef};
9 use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
10 use crate::ty::error::{ExpectedFound, TypeError};
11 use crate::mir::interpret::{GlobalId, ConstValue};
12 use crate::util::common::ErrorReported;
13 use syntax_pos::DUMMY_SP;
14 use std::rc::Rc;
15 use std::iter;
16 use rustc_target::spec::abi;
17 use crate::hir as ast;
18 use crate::traits;
19
20 pub type RelateResult<'tcx, T> = Result<T, TypeError<'tcx>>;
21
22 #[derive(Clone, Debug)]
23 pub enum Cause {
24     ExistentialRegionBound, // relating an existential region bound
25 }
26
27 pub trait TypeRelation<'a, 'gcx: 'a+'tcx, 'tcx: 'a> : Sized {
28     fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx>;
29
30     /// Returns a static string we can use for printouts.
31     fn tag(&self) -> &'static str;
32
33     /// Returns `true` if the value `a` is the "expected" type in the
34     /// relation. Just affects error messages.
35     fn a_is_expected(&self) -> bool;
36
37     fn with_cause<F,R>(&mut self, _cause: Cause, f: F) -> R
38         where F: FnOnce(&mut Self) -> R
39     {
40         f(self)
41     }
42
43     /// Generic relation routine suitable for most anything.
44     fn relate<T: Relate<'tcx>>(&mut self, a: &T, b: &T) -> RelateResult<'tcx, T> {
45         Relate::relate(self, a, b)
46     }
47
48     /// Relate the two substitutions for the given item. The default
49     /// is to look up the variance for the item and proceed
50     /// accordingly.
51     fn relate_item_substs(&mut self,
52                           item_def_id: DefId,
53                           a_subst: SubstsRef<'tcx>,
54                           b_subst: SubstsRef<'tcx>)
55                           -> RelateResult<'tcx, SubstsRef<'tcx>>
56     {
57         debug!("relate_item_substs(item_def_id={:?}, a_subst={:?}, b_subst={:?})",
58                item_def_id,
59                a_subst,
60                b_subst);
61
62         let opt_variances = self.tcx().variances_of(item_def_id);
63         relate_substs(self, Some(opt_variances), a_subst, b_subst)
64     }
65
66     /// Switch variance for the purpose of relating `a` and `b`.
67     fn relate_with_variance<T: Relate<'tcx>>(&mut self,
68                                              variance: ty::Variance,
69                                              a: &T,
70                                              b: &T)
71                                              -> RelateResult<'tcx, T>;
72
73     // Overrideable relations. You shouldn't typically call these
74     // directly, instead call `relate()`, which in turn calls
75     // these. This is both more uniform but also allows us to add
76     // additional hooks for other types in the future if needed
77     // without making older code, which called `relate`, obsolete.
78
79     fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>>;
80
81     fn regions(
82         &mut self,
83         a: ty::Region<'tcx>,
84         b: ty::Region<'tcx>
85     ) -> RelateResult<'tcx, ty::Region<'tcx>>;
86
87     fn consts(
88         &mut self,
89         a: &'tcx ty::LazyConst<'tcx>,
90         b: &'tcx ty::LazyConst<'tcx>
91     ) -> RelateResult<'tcx, &'tcx ty::LazyConst<'tcx>>;
92
93     fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
94                   -> RelateResult<'tcx, ty::Binder<T>>
95         where T: Relate<'tcx>;
96 }
97
98 pub trait Relate<'tcx>: TypeFoldable<'tcx> {
99     fn relate<'a, 'gcx, R>(relation: &mut R, a: &Self, b: &Self)
100                            -> RelateResult<'tcx, Self>
101         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a;
102 }
103
104 ///////////////////////////////////////////////////////////////////////////
105 // Relate impls
106
107 impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> {
108     fn relate<'a, 'gcx, R>(relation: &mut R,
109                            a: &ty::TypeAndMut<'tcx>,
110                            b: &ty::TypeAndMut<'tcx>)
111                            -> RelateResult<'tcx, ty::TypeAndMut<'tcx>>
112         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
113     {
114         debug!("{}.mts({:?}, {:?})",
115                relation.tag(),
116                a,
117                b);
118         if a.mutbl != b.mutbl {
119             Err(TypeError::Mutability)
120         } else {
121             let mutbl = a.mutbl;
122             let variance = match mutbl {
123                 ast::Mutability::MutImmutable => ty::Covariant,
124                 ast::Mutability::MutMutable => ty::Invariant,
125             };
126             let ty = relation.relate_with_variance(variance, &a.ty, &b.ty)?;
127             Ok(ty::TypeAndMut {ty: ty, mutbl: mutbl})
128         }
129     }
130 }
131
132 pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R,
133                                         variances: Option<&[ty::Variance]>,
134                                         a_subst: SubstsRef<'tcx>,
135                                         b_subst: SubstsRef<'tcx>)
136                                         -> RelateResult<'tcx, SubstsRef<'tcx>>
137     where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
138 {
139     let tcx = relation.tcx();
140
141     let params = a_subst.iter().zip(b_subst).enumerate().map(|(i, (a, b))| {
142         let variance = variances.map_or(ty::Invariant, |v| v[i]);
143         relation.relate_with_variance(variance, a, b)
144     });
145
146     Ok(tcx.mk_substs(params)?)
147 }
148
149 impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
150     fn relate<'a, 'gcx, R>(relation: &mut R,
151                            a: &ty::FnSig<'tcx>,
152                            b: &ty::FnSig<'tcx>)
153                            -> RelateResult<'tcx, ty::FnSig<'tcx>>
154         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
155     {
156         let tcx = relation.tcx();
157
158         if a.c_variadic != b.c_variadic {
159             return Err(TypeError::VariadicMismatch(
160                 expected_found(relation, &a.c_variadic, &b.c_variadic)));
161         }
162         let unsafety = relation.relate(&a.unsafety, &b.unsafety)?;
163         let abi = relation.relate(&a.abi, &b.abi)?;
164
165         if a.inputs().len() != b.inputs().len() {
166             return Err(TypeError::ArgCount);
167         }
168
169         let inputs_and_output = a.inputs().iter().cloned()
170             .zip(b.inputs().iter().cloned())
171             .map(|x| (x, false))
172             .chain(iter::once(((a.output(), b.output()), true)))
173             .map(|((a, b), is_output)| {
174                 if is_output {
175                     relation.relate(&a, &b)
176                 } else {
177                     relation.relate_with_variance(ty::Contravariant, &a, &b)
178                 }
179             });
180         Ok(ty::FnSig {
181             inputs_and_output: tcx.mk_type_list(inputs_and_output)?,
182             c_variadic: a.c_variadic,
183             unsafety,
184             abi,
185         })
186     }
187 }
188
189 impl<'tcx> Relate<'tcx> for ast::Unsafety {
190     fn relate<'a, 'gcx, R>(relation: &mut R,
191                            a: &ast::Unsafety,
192                            b: &ast::Unsafety)
193                            -> RelateResult<'tcx, ast::Unsafety>
194         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
195     {
196         if a != b {
197             Err(TypeError::UnsafetyMismatch(expected_found(relation, a, b)))
198         } else {
199             Ok(*a)
200         }
201     }
202 }
203
204 impl<'tcx> Relate<'tcx> for abi::Abi {
205     fn relate<'a, 'gcx, R>(relation: &mut R,
206                            a: &abi::Abi,
207                            b: &abi::Abi)
208                            -> RelateResult<'tcx, abi::Abi>
209         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
210     {
211         if a == b {
212             Ok(*a)
213         } else {
214             Err(TypeError::AbiMismatch(expected_found(relation, a, b)))
215         }
216     }
217 }
218
219 impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> {
220     fn relate<'a, 'gcx, R>(relation: &mut R,
221                            a: &ty::ProjectionTy<'tcx>,
222                            b: &ty::ProjectionTy<'tcx>)
223                            -> RelateResult<'tcx, ty::ProjectionTy<'tcx>>
224         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
225     {
226         if a.item_def_id != b.item_def_id {
227             Err(TypeError::ProjectionMismatched(
228                 expected_found(relation, &a.item_def_id, &b.item_def_id)))
229         } else {
230             let substs = relation.relate(&a.substs, &b.substs)?;
231             Ok(ty::ProjectionTy {
232                 item_def_id: a.item_def_id,
233                 substs: &substs,
234             })
235         }
236     }
237 }
238
239 impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
240     fn relate<'a, 'gcx, R>(relation: &mut R,
241                            a: &ty::ExistentialProjection<'tcx>,
242                            b: &ty::ExistentialProjection<'tcx>)
243                            -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>>
244         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
245     {
246         if a.item_def_id != b.item_def_id {
247             Err(TypeError::ProjectionMismatched(
248                 expected_found(relation, &a.item_def_id, &b.item_def_id)))
249         } else {
250             let ty = relation.relate(&a.ty, &b.ty)?;
251             let substs = relation.relate(&a.substs, &b.substs)?;
252             Ok(ty::ExistentialProjection {
253                 item_def_id: a.item_def_id,
254                 substs,
255                 ty,
256             })
257         }
258     }
259 }
260
261 impl<'tcx> Relate<'tcx> for Vec<ty::PolyExistentialProjection<'tcx>> {
262     fn relate<'a, 'gcx, R>(relation: &mut R,
263                            a: &Vec<ty::PolyExistentialProjection<'tcx>>,
264                            b: &Vec<ty::PolyExistentialProjection<'tcx>>)
265                            -> RelateResult<'tcx, Vec<ty::PolyExistentialProjection<'tcx>>>
266         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
267     {
268         // To be compatible, `a` and `b` must be for precisely the
269         // same set of traits and item names. We always require that
270         // projection bounds lists are sorted by trait-def-id and item-name,
271         // so we can just iterate through the lists pairwise, so long as they are the
272         // same length.
273         if a.len() != b.len() {
274             Err(TypeError::ProjectionBoundsLength(expected_found(relation, &a.len(), &b.len())))
275         } else {
276             a.iter()
277              .zip(b)
278              .map(|(a, b)| relation.relate(a, b))
279              .collect()
280         }
281     }
282 }
283
284 impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
285     fn relate<'a, 'gcx, R>(relation: &mut R,
286                            a: &ty::TraitRef<'tcx>,
287                            b: &ty::TraitRef<'tcx>)
288                            -> RelateResult<'tcx, ty::TraitRef<'tcx>>
289         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
290     {
291         // Different traits cannot be related
292         if a.def_id != b.def_id {
293             Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
294         } else {
295             let substs = relate_substs(relation, None, a.substs, b.substs)?;
296             Ok(ty::TraitRef { def_id: a.def_id, substs: substs })
297         }
298     }
299 }
300
301 impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
302     fn relate<'a, 'gcx, R>(relation: &mut R,
303                            a: &ty::ExistentialTraitRef<'tcx>,
304                            b: &ty::ExistentialTraitRef<'tcx>)
305                            -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>>
306         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
307     {
308         // Different traits cannot be related
309         if a.def_id != b.def_id {
310             Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
311         } else {
312             let substs = relate_substs(relation, None, a.substs, b.substs)?;
313             Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs })
314         }
315     }
316 }
317
318 #[derive(Debug, Clone)]
319 struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
320
321 TupleStructTypeFoldableImpl! {
322     impl<'tcx> TypeFoldable<'tcx> for GeneratorWitness<'tcx> {
323         a
324     }
325 }
326
327 impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
328     fn relate<'a, 'gcx, R>(relation: &mut R,
329                            a: &GeneratorWitness<'tcx>,
330                            b: &GeneratorWitness<'tcx>)
331                            -> RelateResult<'tcx, GeneratorWitness<'tcx>>
332         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
333     {
334         assert_eq!(a.0.len(), b.0.len());
335         let tcx = relation.tcx();
336         let types = tcx.mk_type_list(a.0.iter().zip(b.0).map(|(a, b)| relation.relate(a, b)))?;
337         Ok(GeneratorWitness(types))
338     }
339 }
340
341 impl<'tcx> Relate<'tcx> for Ty<'tcx> {
342     fn relate<'a, 'gcx, R>(relation: &mut R,
343                            a: &Ty<'tcx>,
344                            b: &Ty<'tcx>)
345                            -> RelateResult<'tcx, Ty<'tcx>>
346         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
347     {
348         relation.tys(a, b)
349     }
350 }
351
352 /// The main "type relation" routine. Note that this does not handle
353 /// inference artifacts, so you should filter those out before calling
354 /// it.
355 pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
356                                            a: Ty<'tcx>,
357                                            b: Ty<'tcx>)
358                                            -> RelateResult<'tcx, Ty<'tcx>>
359     where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
360 {
361     let tcx = relation.tcx();
362     debug!("super_relate_tys: a={:?} b={:?}", a, b);
363     match (&a.sty, &b.sty) {
364         (&ty::Infer(_), _) |
365         (_, &ty::Infer(_)) =>
366         {
367             // The caller should handle these cases!
368             bug!("var types encountered in super_relate_tys")
369         }
370
371         (ty::Bound(..), _) | (_, ty::Bound(..)) => {
372             bug!("bound types encountered in super_relate_tys")
373         }
374
375         (&ty::Error, _) | (_, &ty::Error) =>
376         {
377             Ok(tcx.types.err)
378         }
379
380         (&ty::Never, _) |
381         (&ty::Char, _) |
382         (&ty::Bool, _) |
383         (&ty::Int(_), _) |
384         (&ty::Uint(_), _) |
385         (&ty::Float(_), _) |
386         (&ty::Str, _)
387             if a == b =>
388         {
389             Ok(a)
390         }
391
392         (&ty::Param(ref a_p), &ty::Param(ref b_p))
393             if a_p.idx == b_p.idx =>
394         {
395             Ok(a)
396         }
397
398         (ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => {
399             Ok(a)
400         }
401
402         (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs))
403             if a_def == b_def =>
404         {
405             let substs = relation.relate_item_substs(a_def.did, a_substs, b_substs)?;
406             Ok(tcx.mk_adt(a_def, substs))
407         }
408
409         (&ty::Foreign(a_id), &ty::Foreign(b_id))
410             if a_id == b_id =>
411         {
412             Ok(tcx.mk_foreign(a_id))
413         }
414
415         (&ty::Dynamic(ref a_obj, ref a_region), &ty::Dynamic(ref b_obj, ref b_region)) => {
416             let region_bound = relation.with_cause(Cause::ExistentialRegionBound,
417                                                        |relation| {
418                                                            relation.relate_with_variance(
419                                                                ty::Contravariant,
420                                                                a_region,
421                                                                b_region)
422                                                        })?;
423             Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound))
424         }
425
426         (&ty::Generator(a_id, a_substs, movability),
427          &ty::Generator(b_id, b_substs, _))
428             if a_id == b_id =>
429         {
430             // All Generator types with the same id represent
431             // the (anonymous) type of the same generator expression. So
432             // all of their regions should be equated.
433             let substs = relation.relate(&a_substs, &b_substs)?;
434             Ok(tcx.mk_generator(a_id, substs, movability))
435         }
436
437         (&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) =>
438         {
439             // Wrap our types with a temporary GeneratorWitness struct
440             // inside the binder so we can related them
441             let a_types = a_types.map_bound(GeneratorWitness);
442             let b_types = b_types.map_bound(GeneratorWitness);
443             // Then remove the GeneratorWitness for the result
444             let types = relation.relate(&a_types, &b_types)?.map_bound(|witness| witness.0);
445             Ok(tcx.mk_generator_witness(types))
446         }
447
448         (&ty::Closure(a_id, a_substs),
449          &ty::Closure(b_id, b_substs))
450             if a_id == b_id =>
451         {
452             // All Closure types with the same id represent
453             // the (anonymous) type of the same closure expression. So
454             // all of their regions should be equated.
455             let substs = relation.relate(&a_substs, &b_substs)?;
456             Ok(tcx.mk_closure(a_id, substs))
457         }
458
459         (&ty::RawPtr(ref a_mt), &ty::RawPtr(ref b_mt)) =>
460         {
461             let mt = relation.relate(a_mt, b_mt)?;
462             Ok(tcx.mk_ptr(mt))
463         }
464
465         (&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) =>
466         {
467             let r = relation.relate_with_variance(ty::Contravariant, &a_r, &b_r)?;
468             let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl };
469             let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl };
470             let mt = relation.relate(&a_mt, &b_mt)?;
471             Ok(tcx.mk_ref(r, mt))
472         }
473
474         (&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) =>
475         {
476             let t = relation.relate(&a_t, &b_t)?;
477             let to_u64 = |x: ty::Const<'tcx>| -> Result<u64, ErrorReported> {
478                 match x.val {
479                     ConstValue::Unevaluated(def_id, substs) => {
480                         // FIXME(eddyb) get the right param_env.
481                         let param_env = ty::ParamEnv::empty();
482                         if let Some(substs) = tcx.lift_to_global(&substs) {
483                             let instance = ty::Instance::resolve(
484                                 tcx.global_tcx(),
485                                 param_env,
486                                 def_id,
487                                 substs,
488                             );
489                             if let Some(instance) = instance {
490                                 let cid = GlobalId {
491                                     instance,
492                                     promoted: None
493                                 };
494                                 if let Some(s) = tcx.const_eval(param_env.and(cid))
495                                                     .ok()
496                                                     .map(|c| c.unwrap_usize(tcx)) {
497                                     return Ok(s)
498                                 }
499                             }
500                         }
501                         tcx.sess.delay_span_bug(tcx.def_span(def_id),
502                             "array length could not be evaluated");
503                         Err(ErrorReported)
504                     }
505                     _ => x.assert_usize(tcx).ok_or_else(|| {
506                         tcx.sess.delay_span_bug(DUMMY_SP,
507                             "array length could not be evaluated");
508                         ErrorReported
509                     })
510                 }
511             };
512             match (to_u64(*sz_a), to_u64(*sz_b)) {
513                 (Ok(sz_a_u64), Ok(sz_b_u64)) => {
514                     if sz_a_u64 == sz_b_u64 {
515                         Ok(tcx.mk_ty(ty::Array(t, sz_a)))
516                     } else {
517                         Err(TypeError::FixedArraySize(
518                             expected_found(relation, &sz_a_u64, &sz_b_u64)))
519                     }
520                 }
521                 // We reported an error or will ICE, so we can return Error.
522                 (Err(ErrorReported), _) | (_, Err(ErrorReported)) => {
523                     Ok(tcx.types.err)
524                 }
525             }
526         }
527
528         (&ty::Slice(a_t), &ty::Slice(b_t)) =>
529         {
530             let t = relation.relate(&a_t, &b_t)?;
531             Ok(tcx.mk_slice(t))
532         }
533
534         (&ty::Tuple(as_), &ty::Tuple(bs)) =>
535         {
536             if as_.len() == bs.len() {
537                 Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| {
538                     relation.relate(&a.expect_ty(), &b.expect_ty())
539                 }))?)
540             } else if !(as_.is_empty() || bs.is_empty()) {
541                 Err(TypeError::TupleSize(
542                     expected_found(relation, &as_.len(), &bs.len())))
543             } else {
544                 Err(TypeError::Sorts(expected_found(relation, &a, &b)))
545             }
546         }
547
548         (&ty::FnDef(a_def_id, a_substs), &ty::FnDef(b_def_id, b_substs))
549             if a_def_id == b_def_id =>
550         {
551             let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?;
552             Ok(tcx.mk_fn_def(a_def_id, substs))
553         }
554
555         (&ty::FnPtr(a_fty), &ty::FnPtr(b_fty)) =>
556         {
557             let fty = relation.relate(&a_fty, &b_fty)?;
558             Ok(tcx.mk_fn_ptr(fty))
559         }
560
561         (ty::UnnormalizedProjection(a_data), ty::UnnormalizedProjection(b_data)) => {
562             let projection_ty = relation.relate(a_data, b_data)?;
563             Ok(tcx.mk_ty(ty::UnnormalizedProjection(projection_ty)))
564         }
565
566         // these two are already handled downstream in case of lazy normalization
567         (ty::Projection(a_data), ty::Projection(b_data)) => {
568             let projection_ty = relation.relate(a_data, b_data)?;
569             Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs))
570         }
571
572         (&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
573             if a_def_id == b_def_id =>
574         {
575             let substs = relate_substs(relation, None, a_substs, b_substs)?;
576             Ok(tcx.mk_opaque(a_def_id, substs))
577         }
578
579         _ =>
580         {
581             Err(TypeError::Sorts(expected_found(relation, &a, &b)))
582         }
583     }
584 }
585
586 impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
587     fn relate<'a, 'gcx, R>(relation: &mut R,
588                            a: &Self,
589                            b: &Self)
590         -> RelateResult<'tcx, Self>
591             where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a {
592
593         if a.len() != b.len() {
594             return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)));
595         }
596
597         let tcx = relation.tcx();
598         let v = a.iter().zip(b.iter()).map(|(ep_a, ep_b)| {
599             use crate::ty::ExistentialPredicate::*;
600             match (*ep_a, *ep_b) {
601                 (Trait(ref a), Trait(ref b)) => Ok(Trait(relation.relate(a, b)?)),
602                 (Projection(ref a), Projection(ref b)) => Ok(Projection(relation.relate(a, b)?)),
603                 (AutoTrait(ref a), AutoTrait(ref b)) if a == b => Ok(AutoTrait(*a)),
604                 _ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)))
605             }
606         });
607         Ok(tcx.mk_existential_predicates(v)?)
608     }
609 }
610
611 impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> {
612     fn relate<'a, 'gcx, R>(relation: &mut R,
613                            a: &ty::ClosureSubsts<'tcx>,
614                            b: &ty::ClosureSubsts<'tcx>)
615                            -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>>
616         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
617     {
618         let substs = relate_substs(relation, None, a.substs, b.substs)?;
619         Ok(ty::ClosureSubsts { substs })
620     }
621 }
622
623 impl<'tcx> Relate<'tcx> for ty::GeneratorSubsts<'tcx> {
624     fn relate<'a, 'gcx, R>(relation: &mut R,
625                            a: &ty::GeneratorSubsts<'tcx>,
626                            b: &ty::GeneratorSubsts<'tcx>)
627                            -> RelateResult<'tcx, ty::GeneratorSubsts<'tcx>>
628         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
629     {
630         let substs = relate_substs(relation, None, a.substs, b.substs)?;
631         Ok(ty::GeneratorSubsts { substs })
632     }
633 }
634
635 impl<'tcx> Relate<'tcx> for SubstsRef<'tcx> {
636     fn relate<'a, 'gcx, R>(relation: &mut R,
637                            a: &SubstsRef<'tcx>,
638                            b: &SubstsRef<'tcx>)
639                            -> RelateResult<'tcx, SubstsRef<'tcx>>
640         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
641     {
642         relate_substs(relation, None, a, b)
643     }
644 }
645
646 impl<'tcx> Relate<'tcx> for ty::Region<'tcx> {
647     fn relate<'a, 'gcx, R>(relation: &mut R,
648                            a: &ty::Region<'tcx>,
649                            b: &ty::Region<'tcx>)
650                            -> RelateResult<'tcx, ty::Region<'tcx>>
651         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
652     {
653         relation.regions(*a, *b)
654     }
655 }
656
657 impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder<T> {
658     fn relate<'a, 'gcx, R>(relation: &mut R,
659                            a: &ty::Binder<T>,
660                            b: &ty::Binder<T>)
661                            -> RelateResult<'tcx, ty::Binder<T>>
662         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
663     {
664         relation.binders(a, b)
665     }
666 }
667
668 impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for Rc<T> {
669     fn relate<'a, 'gcx, R>(relation: &mut R,
670                            a: &Rc<T>,
671                            b: &Rc<T>)
672                            -> RelateResult<'tcx, Rc<T>>
673         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
674     {
675         let a: &T = a;
676         let b: &T = b;
677         Ok(Rc::new(relation.relate(a, b)?))
678     }
679 }
680
681 impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for Box<T> {
682     fn relate<'a, 'gcx, R>(relation: &mut R,
683                            a: &Box<T>,
684                            b: &Box<T>)
685                            -> RelateResult<'tcx, Box<T>>
686         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
687     {
688         let a: &T = a;
689         let b: &T = b;
690         Ok(Box::new(relation.relate(a, b)?))
691     }
692 }
693
694 impl<'tcx> Relate<'tcx> for Kind<'tcx> {
695     fn relate<'a, 'gcx, R>(
696         relation: &mut R,
697         a: &Kind<'tcx>,
698         b: &Kind<'tcx>
699     ) -> RelateResult<'tcx, Kind<'tcx>>
700     where
701         R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a,
702     {
703         match (a.unpack(), b.unpack()) {
704             (UnpackedKind::Lifetime(a_lt), UnpackedKind::Lifetime(b_lt)) => {
705                 Ok(relation.relate(&a_lt, &b_lt)?.into())
706             }
707             (UnpackedKind::Type(a_ty), UnpackedKind::Type(b_ty)) => {
708                 Ok(relation.relate(&a_ty, &b_ty)?.into())
709             }
710             (UnpackedKind::Lifetime(unpacked), x) => {
711                 bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
712             }
713             (UnpackedKind::Type(unpacked), x) => {
714                 bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
715             }
716             (UnpackedKind::Const(_), _) => {
717                 unimplemented!() // FIXME(const_generics)
718             }
719         }
720     }
721 }
722
723 impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> {
724     fn relate<'a, 'gcx, R>(
725         relation: &mut R,
726         a: &ty::TraitPredicate<'tcx>,
727         b: &ty::TraitPredicate<'tcx>
728     ) -> RelateResult<'tcx, ty::TraitPredicate<'tcx>>
729         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
730     {
731         Ok(ty::TraitPredicate {
732             trait_ref: relation.relate(&a.trait_ref, &b.trait_ref)?,
733         })
734     }
735 }
736
737 impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> {
738     fn relate<'a, 'gcx, R>(
739         relation: &mut R,
740         a: &ty::ProjectionPredicate<'tcx>,
741         b: &ty::ProjectionPredicate<'tcx>,
742     ) -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>>
743         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
744     {
745         Ok(ty::ProjectionPredicate {
746             projection_ty: relation.relate(&a.projection_ty, &b.projection_ty)?,
747             ty: relation.relate(&a.ty, &b.ty)?,
748         })
749     }
750 }
751
752 impl<'tcx> Relate<'tcx> for traits::WhereClause<'tcx> {
753     fn relate<'a, 'gcx, R>(
754         relation: &mut R,
755         a: &traits::WhereClause<'tcx>,
756         b: &traits::WhereClause<'tcx>
757     ) -> RelateResult<'tcx, traits::WhereClause<'tcx>>
758         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
759     {
760         use crate::traits::WhereClause::*;
761         match (a, b) {
762             (Implemented(a_pred), Implemented(b_pred)) => {
763                 Ok(Implemented(relation.relate(a_pred, b_pred)?))
764             }
765
766             (ProjectionEq(a_pred), ProjectionEq(b_pred)) => {
767                 Ok(ProjectionEq(relation.relate(a_pred, b_pred)?))
768             }
769
770             (RegionOutlives(a_pred), RegionOutlives(b_pred)) => {
771                 Ok(RegionOutlives(ty::OutlivesPredicate(
772                     relation.relate(&a_pred.0, &b_pred.0)?,
773                     relation.relate(&a_pred.1, &b_pred.1)?,
774                 )))
775             }
776
777             (TypeOutlives(a_pred), TypeOutlives(b_pred)) => {
778                 Ok(TypeOutlives(ty::OutlivesPredicate(
779                     relation.relate(&a_pred.0, &b_pred.0)?,
780                     relation.relate(&a_pred.1, &b_pred.1)?,
781                 )))
782             }
783
784             _ =>  Err(TypeError::Mismatch),
785         }
786     }
787 }
788
789 impl<'tcx> Relate<'tcx> for traits::WellFormed<'tcx> {
790     fn relate<'a, 'gcx, R>(
791         relation: &mut R,
792         a: &traits::WellFormed<'tcx>,
793         b: &traits::WellFormed<'tcx>
794     ) -> RelateResult<'tcx, traits::WellFormed<'tcx>>
795         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
796     {
797         use crate::traits::WellFormed::*;
798         match (a, b) {
799             (Trait(a_pred), Trait(b_pred)) => Ok(Trait(relation.relate(a_pred, b_pred)?)),
800             (Ty(a_ty), Ty(b_ty)) => Ok(Ty(relation.relate(a_ty, b_ty)?)),
801             _ =>  Err(TypeError::Mismatch),
802         }
803     }
804 }
805
806 impl<'tcx> Relate<'tcx> for traits::FromEnv<'tcx> {
807     fn relate<'a, 'gcx, R>(
808         relation: &mut R,
809         a: &traits::FromEnv<'tcx>,
810         b: &traits::FromEnv<'tcx>
811     ) -> RelateResult<'tcx, traits::FromEnv<'tcx>>
812         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
813     {
814         use crate::traits::FromEnv::*;
815         match (a, b) {
816             (Trait(a_pred), Trait(b_pred)) => Ok(Trait(relation.relate(a_pred, b_pred)?)),
817             (Ty(a_ty), Ty(b_ty)) => Ok(Ty(relation.relate(a_ty, b_ty)?)),
818             _ =>  Err(TypeError::Mismatch),
819         }
820     }
821 }
822
823 impl<'tcx> Relate<'tcx> for traits::DomainGoal<'tcx> {
824     fn relate<'a, 'gcx, R>(
825         relation: &mut R,
826         a: &traits::DomainGoal<'tcx>,
827         b: &traits::DomainGoal<'tcx>
828     ) -> RelateResult<'tcx, traits::DomainGoal<'tcx>>
829         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
830     {
831         use crate::traits::DomainGoal::*;
832         match (a, b) {
833             (Holds(a_wc), Holds(b_wc)) => Ok(Holds(relation.relate(a_wc, b_wc)?)),
834             (WellFormed(a_wf), WellFormed(b_wf)) => Ok(WellFormed(relation.relate(a_wf, b_wf)?)),
835             (FromEnv(a_fe), FromEnv(b_fe)) => Ok(FromEnv(relation.relate(a_fe, b_fe)?)),
836
837             (Normalize(a_pred), Normalize(b_pred)) => {
838                 Ok(Normalize(relation.relate(a_pred, b_pred)?))
839             }
840
841             _ =>  Err(TypeError::Mismatch),
842         }
843     }
844 }
845
846 impl<'tcx> Relate<'tcx> for traits::Goal<'tcx> {
847     fn relate<'a, 'gcx, R>(
848         relation: &mut R,
849         a: &traits::Goal<'tcx>,
850         b: &traits::Goal<'tcx>
851     ) -> RelateResult<'tcx, traits::Goal<'tcx>>
852         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
853     {
854         use crate::traits::GoalKind::*;
855         match (a, b) {
856             (Implies(a_clauses, a_goal), Implies(b_clauses, b_goal)) => {
857                 let clauses = relation.relate(a_clauses, b_clauses)?;
858                 let goal = relation.relate(a_goal, b_goal)?;
859                 Ok(relation.tcx().mk_goal(Implies(clauses, goal)))
860             }
861
862             (And(a_left, a_right), And(b_left, b_right)) => {
863                 let left = relation.relate(a_left, b_left)?;
864                 let right = relation.relate(a_right, b_right)?;
865                 Ok(relation.tcx().mk_goal(And(left, right)))
866             }
867
868             (Not(a_goal), Not(b_goal)) => {
869                 let goal = relation.relate(a_goal, b_goal)?;
870                 Ok(relation.tcx().mk_goal(Not(goal)))
871             }
872
873             (DomainGoal(a_goal), DomainGoal(b_goal)) => {
874                 let goal = relation.relate(a_goal, b_goal)?;
875                 Ok(relation.tcx().mk_goal(DomainGoal(goal)))
876             }
877
878             (Quantified(a_qkind, a_goal), Quantified(b_qkind, b_goal))
879                 if a_qkind == b_qkind =>
880             {
881                 let goal = relation.relate(a_goal, b_goal)?;
882                 Ok(relation.tcx().mk_goal(Quantified(*a_qkind, goal)))
883             }
884
885             (CannotProve, CannotProve) => Ok(*a),
886
887             _ => Err(TypeError::Mismatch),
888         }
889     }
890 }
891
892 impl<'tcx> Relate<'tcx> for traits::Goals<'tcx> {
893     fn relate<'a, 'gcx, R>(
894         relation: &mut R,
895         a: &traits::Goals<'tcx>,
896         b: &traits::Goals<'tcx>
897     ) -> RelateResult<'tcx, traits::Goals<'tcx>>
898         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
899     {
900         if a.len() != b.len() {
901             return Err(TypeError::Mismatch);
902         }
903
904         let tcx = relation.tcx();
905         let goals = a.iter().zip(b.iter()).map(|(a, b)| relation.relate(a, b));
906         Ok(tcx.mk_goals(goals)?)
907     }
908 }
909
910 impl<'tcx> Relate<'tcx> for traits::Clause<'tcx> {
911     fn relate<'a, 'gcx, R>(
912         relation: &mut R,
913         a: &traits::Clause<'tcx>,
914         b: &traits::Clause<'tcx>
915     ) -> RelateResult<'tcx, traits::Clause<'tcx>>
916         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
917     {
918         use crate::traits::Clause::*;
919         match (a, b) {
920             (Implies(a_clause), Implies(b_clause)) => {
921                 let clause = relation.relate(a_clause, b_clause)?;
922                 Ok(Implies(clause))
923             }
924
925             (ForAll(a_clause), ForAll(b_clause)) => {
926                 let clause = relation.relate(a_clause, b_clause)?;
927                 Ok(ForAll(clause))
928             }
929
930             _ => Err(TypeError::Mismatch),
931         }
932     }
933 }
934
935 impl<'tcx> Relate<'tcx> for traits::Clauses<'tcx> {
936     fn relate<'a, 'gcx, R>(
937         relation: &mut R,
938         a: &traits::Clauses<'tcx>,
939         b: &traits::Clauses<'tcx>
940     ) -> RelateResult<'tcx, traits::Clauses<'tcx>>
941         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
942     {
943         if a.len() != b.len() {
944             return Err(TypeError::Mismatch);
945         }
946
947         let tcx = relation.tcx();
948         let clauses = a.iter().zip(b.iter()).map(|(a, b)| relation.relate(a, b));
949         Ok(tcx.mk_clauses(clauses)?)
950     }
951 }
952
953 impl<'tcx> Relate<'tcx> for traits::ProgramClause<'tcx> {
954     fn relate<'a, 'gcx, R>(
955         relation: &mut R,
956         a: &traits::ProgramClause<'tcx>,
957         b: &traits::ProgramClause<'tcx>
958     ) -> RelateResult<'tcx, traits::ProgramClause<'tcx>>
959         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
960     {
961         Ok(traits::ProgramClause {
962             goal: relation.relate(&a.goal, &b.goal)?,
963             hypotheses: relation.relate(&a.hypotheses, &b.hypotheses)?,
964             category: traits::ProgramClauseCategory::Other,
965         })
966     }
967 }
968
969 impl<'tcx> Relate<'tcx> for traits::Environment<'tcx> {
970     fn relate<'a, 'gcx, R>(
971         relation: &mut R,
972         a: &traits::Environment<'tcx>,
973         b: &traits::Environment<'tcx>
974     ) -> RelateResult<'tcx, traits::Environment<'tcx>>
975         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
976     {
977         Ok(traits::Environment {
978             clauses: relation.relate(&a.clauses, &b.clauses)?,
979         })
980     }
981 }
982
983 impl<'tcx, G> Relate<'tcx> for traits::InEnvironment<'tcx, G>
984     where G: Relate<'tcx>
985 {
986     fn relate<'a, 'gcx, R>(
987         relation: &mut R,
988         a: &traits::InEnvironment<'tcx, G>,
989         b: &traits::InEnvironment<'tcx, G>
990     ) -> RelateResult<'tcx, traits::InEnvironment<'tcx, G>>
991         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
992     {
993         Ok(traits::InEnvironment {
994             environment: relation.relate(&a.environment, &b.environment)?,
995             goal: relation.relate(&a.goal, &b.goal)?,
996         })
997     }
998 }
999
1000 ///////////////////////////////////////////////////////////////////////////
1001 // Error handling
1002
1003 pub fn expected_found<'a, 'gcx, 'tcx, R, T>(relation: &mut R,
1004                                             a: &T,
1005                                             b: &T)
1006                                             -> ExpectedFound<T>
1007     where R: TypeRelation<'a, 'gcx, 'tcx>, T: Clone, 'gcx: 'a+'tcx, 'tcx: 'a
1008 {
1009     expected_found_bool(relation.a_is_expected(), a, b)
1010 }
1011
1012 pub fn expected_found_bool<T>(a_is_expected: bool,
1013                               a: &T,
1014                               b: &T)
1015                               -> ExpectedFound<T>
1016     where T: Clone
1017 {
1018     let a = a.clone();
1019     let b = b.clone();
1020     if a_is_expected {
1021         ExpectedFound {expected: a, found: b}
1022     } else {
1023         ExpectedFound {expected: b, found: a}
1024     }
1025 }