]> git.lizzy.rs Git - rust.git/blob - src/librustc/ty/relate.rs
Rollup merge of #60444 - nikomatsakis:issue-60010-cycle-error-investigation, r=pnkfelix
[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, Scalar};
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::Const<'tcx>,
90         b: &'tcx ty::Const<'tcx>
91     ) -> RelateResult<'tcx, &'tcx ty::Const<'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, 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.index == b_p.index =>
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                     // FIXME(const_generics): this doesn't work right now,
480                     // because it tries to relate an `Infer` to a `Param`.
481                     ConstValue::Unevaluated(def_id, substs) => {
482                         // FIXME(eddyb) get the right param_env.
483                         let param_env = ty::ParamEnv::empty();
484                         if let Some(substs) = tcx.lift_to_global(&substs) {
485                             let instance = ty::Instance::resolve(
486                                 tcx.global_tcx(),
487                                 param_env,
488                                 def_id,
489                                 substs,
490                             );
491                             if let Some(instance) = instance {
492                                 let cid = GlobalId {
493                                     instance,
494                                     promoted: None,
495                                 };
496                                 if let Some(s) = tcx.const_eval(param_env.and(cid))
497                                                     .ok()
498                                                     .map(|c| c.unwrap_usize(tcx)) {
499                                     return Ok(s)
500                                 }
501                             }
502                         }
503                         tcx.sess.delay_span_bug(tcx.def_span(def_id),
504                             "array length could not be evaluated");
505                         Err(ErrorReported)
506                     }
507                     _ => x.assert_usize(tcx).ok_or_else(|| {
508                         tcx.sess.delay_span_bug(DUMMY_SP,
509                             "array length could not be evaluated");
510                         ErrorReported
511                     })
512                 }
513             };
514             match (to_u64(*sz_a), to_u64(*sz_b)) {
515                 (Ok(sz_a_u64), Ok(sz_b_u64)) => {
516                     if sz_a_u64 == sz_b_u64 {
517                         Ok(tcx.mk_ty(ty::Array(t, sz_a)))
518                     } else {
519                         Err(TypeError::FixedArraySize(
520                             expected_found(relation, &sz_a_u64, &sz_b_u64)))
521                     }
522                 }
523                 // We reported an error or will ICE, so we can return Error.
524                 (Err(ErrorReported), _) | (_, Err(ErrorReported)) => {
525                     Ok(tcx.types.err)
526                 }
527             }
528         }
529
530         (&ty::Slice(a_t), &ty::Slice(b_t)) =>
531         {
532             let t = relation.relate(&a_t, &b_t)?;
533             Ok(tcx.mk_slice(t))
534         }
535
536         (&ty::Tuple(as_), &ty::Tuple(bs)) =>
537         {
538             if as_.len() == bs.len() {
539                 Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| {
540                     relation.relate(&a.expect_ty(), &b.expect_ty())
541                 }))?)
542             } else if !(as_.is_empty() || bs.is_empty()) {
543                 Err(TypeError::TupleSize(
544                     expected_found(relation, &as_.len(), &bs.len())))
545             } else {
546                 Err(TypeError::Sorts(expected_found(relation, &a, &b)))
547             }
548         }
549
550         (&ty::FnDef(a_def_id, a_substs), &ty::FnDef(b_def_id, b_substs))
551             if a_def_id == b_def_id =>
552         {
553             let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?;
554             Ok(tcx.mk_fn_def(a_def_id, substs))
555         }
556
557         (&ty::FnPtr(a_fty), &ty::FnPtr(b_fty)) =>
558         {
559             let fty = relation.relate(&a_fty, &b_fty)?;
560             Ok(tcx.mk_fn_ptr(fty))
561         }
562
563         (ty::UnnormalizedProjection(a_data), ty::UnnormalizedProjection(b_data)) => {
564             let projection_ty = relation.relate(a_data, b_data)?;
565             Ok(tcx.mk_ty(ty::UnnormalizedProjection(projection_ty)))
566         }
567
568         // these two are already handled downstream in case of lazy normalization
569         (ty::Projection(a_data), ty::Projection(b_data)) => {
570             let projection_ty = relation.relate(a_data, b_data)?;
571             Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs))
572         }
573
574         (&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
575             if a_def_id == b_def_id =>
576         {
577             let substs = relate_substs(relation, None, a_substs, b_substs)?;
578             Ok(tcx.mk_opaque(a_def_id, substs))
579         }
580
581         _ =>
582         {
583             Err(TypeError::Sorts(expected_found(relation, &a, &b)))
584         }
585     }
586 }
587
588 /// The main "const relation" routine. Note that this does not handle
589 /// inference artifacts, so you should filter those out before calling
590 /// it.
591 pub fn super_relate_consts<'a, 'gcx, 'tcx, R>(
592     relation: &mut R,
593     a: &'tcx ty::Const<'tcx>,
594     b: &'tcx ty::Const<'tcx>
595 ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>>
596 where
597     R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
598 {
599     let tcx = relation.tcx();
600
601     // Currently, the values that can be unified are those that
602     // implement both `PartialEq` and `Eq`, corresponding to
603     // `structural_match` types.
604     // FIXME(const_generics): check for `structural_match` synthetic attribute.
605     match (a.val, b.val) {
606         (ConstValue::Infer(_), _) | (_, ConstValue::Infer(_)) => {
607             // The caller should handle these cases!
608             bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b)
609         }
610         (ConstValue::Param(a_p), ConstValue::Param(b_p)) if a_p.index == b_p.index => {
611             Ok(a)
612         }
613         (ConstValue::Placeholder(p1), ConstValue::Placeholder(p2)) if p1 == p2 => {
614             Ok(a)
615         }
616         (ConstValue::Scalar(Scalar::Bits { .. }), _) if a == b => {
617             Ok(a)
618         }
619         (ConstValue::ByRef(..), _) => {
620             bug!(
621                 "non-Scalar ConstValue encountered in super_relate_consts {:?} {:?}",
622                 a,
623                 b,
624             );
625         }
626
627         // FIXME(const_generics): this is wrong, as it is a projection
628         (ConstValue::Unevaluated(a_def_id, a_substs),
629             ConstValue::Unevaluated(b_def_id, b_substs)) if a_def_id == b_def_id => {
630                 let substs =
631                     relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?;
632                 Ok(tcx.mk_const(ty::Const {
633                     val: ConstValue::Unevaluated(a_def_id, &substs),
634                     ty: a.ty,
635                 }))
636             }
637
638             _ => {
639             Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
640         }
641     }
642 }
643
644 impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
645     fn relate<'a, 'gcx, R>(relation: &mut R,
646                            a: &Self,
647                            b: &Self)
648         -> RelateResult<'tcx, Self>
649             where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a {
650
651         if a.len() != b.len() {
652             return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)));
653         }
654
655         let tcx = relation.tcx();
656         let v = a.iter().zip(b.iter()).map(|(ep_a, ep_b)| {
657             use crate::ty::ExistentialPredicate::*;
658             match (*ep_a, *ep_b) {
659                 (Trait(ref a), Trait(ref b)) => Ok(Trait(relation.relate(a, b)?)),
660                 (Projection(ref a), Projection(ref b)) => Ok(Projection(relation.relate(a, b)?)),
661                 (AutoTrait(ref a), AutoTrait(ref b)) if a == b => Ok(AutoTrait(*a)),
662                 _ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)))
663             }
664         });
665         Ok(tcx.mk_existential_predicates(v)?)
666     }
667 }
668
669 impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> {
670     fn relate<'a, 'gcx, R>(relation: &mut R,
671                            a: &ty::ClosureSubsts<'tcx>,
672                            b: &ty::ClosureSubsts<'tcx>)
673                            -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>>
674         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
675     {
676         let substs = relate_substs(relation, None, a.substs, b.substs)?;
677         Ok(ty::ClosureSubsts { substs })
678     }
679 }
680
681 impl<'tcx> Relate<'tcx> for ty::GeneratorSubsts<'tcx> {
682     fn relate<'a, 'gcx, R>(relation: &mut R,
683                            a: &ty::GeneratorSubsts<'tcx>,
684                            b: &ty::GeneratorSubsts<'tcx>)
685                            -> RelateResult<'tcx, ty::GeneratorSubsts<'tcx>>
686         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
687     {
688         let substs = relate_substs(relation, None, a.substs, b.substs)?;
689         Ok(ty::GeneratorSubsts { substs })
690     }
691 }
692
693 impl<'tcx> Relate<'tcx> for SubstsRef<'tcx> {
694     fn relate<'a, 'gcx, R>(relation: &mut R,
695                            a: &SubstsRef<'tcx>,
696                            b: &SubstsRef<'tcx>)
697                            -> RelateResult<'tcx, SubstsRef<'tcx>>
698         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
699     {
700         relate_substs(relation, None, a, b)
701     }
702 }
703
704 impl<'tcx> Relate<'tcx> for ty::Region<'tcx> {
705     fn relate<'a, 'gcx, R>(relation: &mut R,
706                            a: &ty::Region<'tcx>,
707                            b: &ty::Region<'tcx>)
708                            -> RelateResult<'tcx, ty::Region<'tcx>>
709         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
710     {
711         relation.regions(*a, *b)
712     }
713 }
714
715 impl<'tcx> Relate<'tcx> for &'tcx ty::Const<'tcx> {
716     fn relate<'a, 'gcx, R>(relation: &mut R,
717                            a: &&'tcx ty::Const<'tcx>,
718                            b: &&'tcx ty::Const<'tcx>)
719                            -> RelateResult<'tcx, &'tcx ty::Const<'tcx>>
720         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
721     {
722         relation.consts(*a, *b)
723     }
724 }
725
726 impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder<T> {
727     fn relate<'a, 'gcx, R>(relation: &mut R,
728                            a: &ty::Binder<T>,
729                            b: &ty::Binder<T>)
730                            -> RelateResult<'tcx, ty::Binder<T>>
731         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
732     {
733         relation.binders(a, b)
734     }
735 }
736
737 impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for Rc<T> {
738     fn relate<'a, 'gcx, R>(relation: &mut R,
739                            a: &Rc<T>,
740                            b: &Rc<T>)
741                            -> RelateResult<'tcx, Rc<T>>
742         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
743     {
744         let a: &T = a;
745         let b: &T = b;
746         Ok(Rc::new(relation.relate(a, b)?))
747     }
748 }
749
750 impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for Box<T> {
751     fn relate<'a, 'gcx, R>(relation: &mut R,
752                            a: &Box<T>,
753                            b: &Box<T>)
754                            -> RelateResult<'tcx, Box<T>>
755         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
756     {
757         let a: &T = a;
758         let b: &T = b;
759         Ok(Box::new(relation.relate(a, b)?))
760     }
761 }
762
763 impl<'tcx> Relate<'tcx> for Kind<'tcx> {
764     fn relate<'a, 'gcx, R>(
765         relation: &mut R,
766         a: &Kind<'tcx>,
767         b: &Kind<'tcx>
768     ) -> RelateResult<'tcx, Kind<'tcx>>
769     where
770         R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a,
771     {
772         match (a.unpack(), b.unpack()) {
773             (UnpackedKind::Lifetime(a_lt), UnpackedKind::Lifetime(b_lt)) => {
774                 Ok(relation.relate(&a_lt, &b_lt)?.into())
775             }
776             (UnpackedKind::Type(a_ty), UnpackedKind::Type(b_ty)) => {
777                 Ok(relation.relate(&a_ty, &b_ty)?.into())
778             }
779             (UnpackedKind::Const(a_ct), UnpackedKind::Const(b_ct)) => {
780                 Ok(relation.relate(&a_ct, &b_ct)?.into())
781             }
782             (UnpackedKind::Lifetime(unpacked), x) => {
783                 bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
784             }
785             (UnpackedKind::Type(unpacked), x) => {
786                 bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
787             }
788             (UnpackedKind::Const(unpacked), x) => {
789                 bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
790             }
791         }
792     }
793 }
794
795 impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> {
796     fn relate<'a, 'gcx, R>(
797         relation: &mut R,
798         a: &ty::TraitPredicate<'tcx>,
799         b: &ty::TraitPredicate<'tcx>
800     ) -> RelateResult<'tcx, ty::TraitPredicate<'tcx>>
801         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
802     {
803         Ok(ty::TraitPredicate {
804             trait_ref: relation.relate(&a.trait_ref, &b.trait_ref)?,
805         })
806     }
807 }
808
809 impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> {
810     fn relate<'a, 'gcx, R>(
811         relation: &mut R,
812         a: &ty::ProjectionPredicate<'tcx>,
813         b: &ty::ProjectionPredicate<'tcx>,
814     ) -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>>
815         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
816     {
817         Ok(ty::ProjectionPredicate {
818             projection_ty: relation.relate(&a.projection_ty, &b.projection_ty)?,
819             ty: relation.relate(&a.ty, &b.ty)?,
820         })
821     }
822 }
823
824 impl<'tcx> Relate<'tcx> for traits::WhereClause<'tcx> {
825     fn relate<'a, 'gcx, R>(
826         relation: &mut R,
827         a: &traits::WhereClause<'tcx>,
828         b: &traits::WhereClause<'tcx>
829     ) -> RelateResult<'tcx, traits::WhereClause<'tcx>>
830         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
831     {
832         use crate::traits::WhereClause::*;
833         match (a, b) {
834             (Implemented(a_pred), Implemented(b_pred)) => {
835                 Ok(Implemented(relation.relate(a_pred, b_pred)?))
836             }
837
838             (ProjectionEq(a_pred), ProjectionEq(b_pred)) => {
839                 Ok(ProjectionEq(relation.relate(a_pred, b_pred)?))
840             }
841
842             (RegionOutlives(a_pred), RegionOutlives(b_pred)) => {
843                 Ok(RegionOutlives(ty::OutlivesPredicate(
844                     relation.relate(&a_pred.0, &b_pred.0)?,
845                     relation.relate(&a_pred.1, &b_pred.1)?,
846                 )))
847             }
848
849             (TypeOutlives(a_pred), TypeOutlives(b_pred)) => {
850                 Ok(TypeOutlives(ty::OutlivesPredicate(
851                     relation.relate(&a_pred.0, &b_pred.0)?,
852                     relation.relate(&a_pred.1, &b_pred.1)?,
853                 )))
854             }
855
856             _ =>  Err(TypeError::Mismatch),
857         }
858     }
859 }
860
861 impl<'tcx> Relate<'tcx> for traits::WellFormed<'tcx> {
862     fn relate<'a, 'gcx, R>(
863         relation: &mut R,
864         a: &traits::WellFormed<'tcx>,
865         b: &traits::WellFormed<'tcx>
866     ) -> RelateResult<'tcx, traits::WellFormed<'tcx>>
867         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
868     {
869         use crate::traits::WellFormed::*;
870         match (a, b) {
871             (Trait(a_pred), Trait(b_pred)) => Ok(Trait(relation.relate(a_pred, b_pred)?)),
872             (Ty(a_ty), Ty(b_ty)) => Ok(Ty(relation.relate(a_ty, b_ty)?)),
873             _ =>  Err(TypeError::Mismatch),
874         }
875     }
876 }
877
878 impl<'tcx> Relate<'tcx> for traits::FromEnv<'tcx> {
879     fn relate<'a, 'gcx, R>(
880         relation: &mut R,
881         a: &traits::FromEnv<'tcx>,
882         b: &traits::FromEnv<'tcx>
883     ) -> RelateResult<'tcx, traits::FromEnv<'tcx>>
884         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
885     {
886         use crate::traits::FromEnv::*;
887         match (a, b) {
888             (Trait(a_pred), Trait(b_pred)) => Ok(Trait(relation.relate(a_pred, b_pred)?)),
889             (Ty(a_ty), Ty(b_ty)) => Ok(Ty(relation.relate(a_ty, b_ty)?)),
890             _ =>  Err(TypeError::Mismatch),
891         }
892     }
893 }
894
895 impl<'tcx> Relate<'tcx> for traits::DomainGoal<'tcx> {
896     fn relate<'a, 'gcx, R>(
897         relation: &mut R,
898         a: &traits::DomainGoal<'tcx>,
899         b: &traits::DomainGoal<'tcx>
900     ) -> RelateResult<'tcx, traits::DomainGoal<'tcx>>
901         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
902     {
903         use crate::traits::DomainGoal::*;
904         match (a, b) {
905             (Holds(a_wc), Holds(b_wc)) => Ok(Holds(relation.relate(a_wc, b_wc)?)),
906             (WellFormed(a_wf), WellFormed(b_wf)) => Ok(WellFormed(relation.relate(a_wf, b_wf)?)),
907             (FromEnv(a_fe), FromEnv(b_fe)) => Ok(FromEnv(relation.relate(a_fe, b_fe)?)),
908
909             (Normalize(a_pred), Normalize(b_pred)) => {
910                 Ok(Normalize(relation.relate(a_pred, b_pred)?))
911             }
912
913             _ =>  Err(TypeError::Mismatch),
914         }
915     }
916 }
917
918 impl<'tcx> Relate<'tcx> for traits::Goal<'tcx> {
919     fn relate<'a, 'gcx, R>(
920         relation: &mut R,
921         a: &traits::Goal<'tcx>,
922         b: &traits::Goal<'tcx>
923     ) -> RelateResult<'tcx, traits::Goal<'tcx>>
924         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
925     {
926         use crate::traits::GoalKind::*;
927         match (a, b) {
928             (Implies(a_clauses, a_goal), Implies(b_clauses, b_goal)) => {
929                 let clauses = relation.relate(a_clauses, b_clauses)?;
930                 let goal = relation.relate(a_goal, b_goal)?;
931                 Ok(relation.tcx().mk_goal(Implies(clauses, goal)))
932             }
933
934             (And(a_left, a_right), And(b_left, b_right)) => {
935                 let left = relation.relate(a_left, b_left)?;
936                 let right = relation.relate(a_right, b_right)?;
937                 Ok(relation.tcx().mk_goal(And(left, right)))
938             }
939
940             (Not(a_goal), Not(b_goal)) => {
941                 let goal = relation.relate(a_goal, b_goal)?;
942                 Ok(relation.tcx().mk_goal(Not(goal)))
943             }
944
945             (DomainGoal(a_goal), DomainGoal(b_goal)) => {
946                 let goal = relation.relate(a_goal, b_goal)?;
947                 Ok(relation.tcx().mk_goal(DomainGoal(goal)))
948             }
949
950             (Quantified(a_qkind, a_goal), Quantified(b_qkind, b_goal))
951                 if a_qkind == b_qkind =>
952             {
953                 let goal = relation.relate(a_goal, b_goal)?;
954                 Ok(relation.tcx().mk_goal(Quantified(*a_qkind, goal)))
955             }
956
957             (CannotProve, CannotProve) => Ok(*a),
958
959             _ => Err(TypeError::Mismatch),
960         }
961     }
962 }
963
964 impl<'tcx> Relate<'tcx> for traits::Goals<'tcx> {
965     fn relate<'a, 'gcx, R>(
966         relation: &mut R,
967         a: &traits::Goals<'tcx>,
968         b: &traits::Goals<'tcx>
969     ) -> RelateResult<'tcx, traits::Goals<'tcx>>
970         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
971     {
972         if a.len() != b.len() {
973             return Err(TypeError::Mismatch);
974         }
975
976         let tcx = relation.tcx();
977         let goals = a.iter().zip(b.iter()).map(|(a, b)| relation.relate(a, b));
978         Ok(tcx.mk_goals(goals)?)
979     }
980 }
981
982 impl<'tcx> Relate<'tcx> for traits::Clause<'tcx> {
983     fn relate<'a, 'gcx, R>(
984         relation: &mut R,
985         a: &traits::Clause<'tcx>,
986         b: &traits::Clause<'tcx>
987     ) -> RelateResult<'tcx, traits::Clause<'tcx>>
988         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
989     {
990         use crate::traits::Clause::*;
991         match (a, b) {
992             (Implies(a_clause), Implies(b_clause)) => {
993                 let clause = relation.relate(a_clause, b_clause)?;
994                 Ok(Implies(clause))
995             }
996
997             (ForAll(a_clause), ForAll(b_clause)) => {
998                 let clause = relation.relate(a_clause, b_clause)?;
999                 Ok(ForAll(clause))
1000             }
1001
1002             _ => Err(TypeError::Mismatch),
1003         }
1004     }
1005 }
1006
1007 impl<'tcx> Relate<'tcx> for traits::Clauses<'tcx> {
1008     fn relate<'a, 'gcx, R>(
1009         relation: &mut R,
1010         a: &traits::Clauses<'tcx>,
1011         b: &traits::Clauses<'tcx>
1012     ) -> RelateResult<'tcx, traits::Clauses<'tcx>>
1013         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
1014     {
1015         if a.len() != b.len() {
1016             return Err(TypeError::Mismatch);
1017         }
1018
1019         let tcx = relation.tcx();
1020         let clauses = a.iter().zip(b.iter()).map(|(a, b)| relation.relate(a, b));
1021         Ok(tcx.mk_clauses(clauses)?)
1022     }
1023 }
1024
1025 impl<'tcx> Relate<'tcx> for traits::ProgramClause<'tcx> {
1026     fn relate<'a, 'gcx, R>(
1027         relation: &mut R,
1028         a: &traits::ProgramClause<'tcx>,
1029         b: &traits::ProgramClause<'tcx>
1030     ) -> RelateResult<'tcx, traits::ProgramClause<'tcx>>
1031         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
1032     {
1033         Ok(traits::ProgramClause {
1034             goal: relation.relate(&a.goal, &b.goal)?,
1035             hypotheses: relation.relate(&a.hypotheses, &b.hypotheses)?,
1036             category: traits::ProgramClauseCategory::Other,
1037         })
1038     }
1039 }
1040
1041 impl<'tcx> Relate<'tcx> for traits::Environment<'tcx> {
1042     fn relate<'a, 'gcx, R>(
1043         relation: &mut R,
1044         a: &traits::Environment<'tcx>,
1045         b: &traits::Environment<'tcx>
1046     ) -> RelateResult<'tcx, traits::Environment<'tcx>>
1047         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
1048     {
1049         Ok(traits::Environment {
1050             clauses: relation.relate(&a.clauses, &b.clauses)?,
1051         })
1052     }
1053 }
1054
1055 impl<'tcx, G> Relate<'tcx> for traits::InEnvironment<'tcx, G>
1056     where G: Relate<'tcx>
1057 {
1058     fn relate<'a, 'gcx, R>(
1059         relation: &mut R,
1060         a: &traits::InEnvironment<'tcx, G>,
1061         b: &traits::InEnvironment<'tcx, G>
1062     ) -> RelateResult<'tcx, traits::InEnvironment<'tcx, G>>
1063         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
1064     {
1065         Ok(traits::InEnvironment {
1066             environment: relation.relate(&a.environment, &b.environment)?,
1067             goal: relation.relate(&a.goal, &b.goal)?,
1068         })
1069     }
1070 }
1071
1072 ///////////////////////////////////////////////////////////////////////////
1073 // Error handling
1074
1075 pub fn expected_found<'a, 'gcx, 'tcx, R, T>(relation: &mut R,
1076                                             a: &T,
1077                                             b: &T)
1078                                             -> ExpectedFound<T>
1079     where R: TypeRelation<'a, 'gcx, 'tcx>, T: Clone, 'gcx: 'a+'tcx, 'tcx: 'a
1080 {
1081     expected_found_bool(relation.a_is_expected(), a, b)
1082 }
1083
1084 pub fn expected_found_bool<T>(a_is_expected: bool,
1085                               a: &T,
1086                               b: &T)
1087                               -> ExpectedFound<T>
1088     where T: Clone
1089 {
1090     let a = a.clone();
1091     let b = b.clone();
1092     if a_is_expected {
1093         ExpectedFound {expected: a, found: b}
1094     } else {
1095         ExpectedFound {expected: b, found: a}
1096     }
1097 }