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