]> git.lizzy.rs Git - rust.git/blob - src/librustc/ty/relate.rs
2034795a0b58245d002027768d8c0a84e6e962f4
[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 /// The main "const relation" routine. Note that this does not handle
587 /// inference artifacts, so you should filter those out before calling
588 /// it.
589 pub fn super_relate_consts<'a, 'gcx, 'tcx, R>(
590     relation: &mut R,
591     a: &'tcx ty::LazyConst<'tcx>,
592     b: &'tcx ty::LazyConst<'tcx>
593 ) -> RelateResult<'tcx, &'tcx ty::LazyConst<'tcx>>
594 where
595     R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
596 {
597     let tcx = relation.tcx();
598
599     match (a, b) {
600         (ty::LazyConst::Evaluated(a_eval), ty::LazyConst::Evaluated(b_eval)) => {
601             // Only consts whose types are equal should be compared.
602             assert_eq!(a_eval.ty, b_eval.ty);
603
604             // Currently, the values that can be unified are those that
605             // implement both `PartialEq` and `Eq`, corresponding to
606             // `structural_match` types.
607             // FIXME(const_generics): check for `structural_match` synthetic attribute.
608             match (a_eval.val, b_eval.val) {
609                 (ConstValue::Infer(_), _) | (_, ConstValue::Infer(_)) => {
610                     // The caller should handle these cases!
611                     bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b)
612                 }
613                 (ConstValue::Param(a_p), ConstValue::Param(b_p)) if a_p.index == b_p.index => {
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                     Err(TypeError::ConstError(
628                         ConstError::Mismatch(expected_found(relation, &a, &b))
629                     ))
630                 }
631             }
632         }
633         // FIXME(const_generics): this is probably wrong (regarding TyProjection)
634         (
635             ty::LazyConst::Unevaluated(a_def_id, a_substs),
636             ty::LazyConst::Unevaluated(b_def_id, b_substs),
637         ) if a_def_id == b_def_id => {
638             let substs =
639                 relation.relate_with_variance(ty::Variance::Invariant, a_substs, b_substs)?;
640             Ok(tcx.mk_lazy_const(ty::LazyConst::Unevaluated(*a_def_id, substs)))
641         }
642         _ => {
643             Err(TypeError::ConstError(
644                 ConstError::Mismatch(expected_found(relation, &a, &b))
645             ))
646         }
647     }
648 }
649
650 impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
651     fn relate<'a, 'gcx, R>(relation: &mut R,
652                            a: &Self,
653                            b: &Self)
654         -> RelateResult<'tcx, Self>
655             where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a {
656
657         if a.len() != b.len() {
658             return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)));
659         }
660
661         let tcx = relation.tcx();
662         let v = a.iter().zip(b.iter()).map(|(ep_a, ep_b)| {
663             use crate::ty::ExistentialPredicate::*;
664             match (*ep_a, *ep_b) {
665                 (Trait(ref a), Trait(ref b)) => Ok(Trait(relation.relate(a, b)?)),
666                 (Projection(ref a), Projection(ref b)) => Ok(Projection(relation.relate(a, b)?)),
667                 (AutoTrait(ref a), AutoTrait(ref b)) if a == b => Ok(AutoTrait(*a)),
668                 _ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)))
669             }
670         });
671         Ok(tcx.mk_existential_predicates(v)?)
672     }
673 }
674
675 impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> {
676     fn relate<'a, 'gcx, R>(relation: &mut R,
677                            a: &ty::ClosureSubsts<'tcx>,
678                            b: &ty::ClosureSubsts<'tcx>)
679                            -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>>
680         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
681     {
682         let substs = relate_substs(relation, None, a.substs, b.substs)?;
683         Ok(ty::ClosureSubsts { substs })
684     }
685 }
686
687 impl<'tcx> Relate<'tcx> for ty::GeneratorSubsts<'tcx> {
688     fn relate<'a, 'gcx, R>(relation: &mut R,
689                            a: &ty::GeneratorSubsts<'tcx>,
690                            b: &ty::GeneratorSubsts<'tcx>)
691                            -> RelateResult<'tcx, ty::GeneratorSubsts<'tcx>>
692         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
693     {
694         let substs = relate_substs(relation, None, a.substs, b.substs)?;
695         Ok(ty::GeneratorSubsts { substs })
696     }
697 }
698
699 impl<'tcx> Relate<'tcx> for SubstsRef<'tcx> {
700     fn relate<'a, 'gcx, R>(relation: &mut R,
701                            a: &SubstsRef<'tcx>,
702                            b: &SubstsRef<'tcx>)
703                            -> RelateResult<'tcx, SubstsRef<'tcx>>
704         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
705     {
706         relate_substs(relation, None, a, b)
707     }
708 }
709
710 impl<'tcx> Relate<'tcx> for ty::Region<'tcx> {
711     fn relate<'a, 'gcx, R>(relation: &mut R,
712                            a: &ty::Region<'tcx>,
713                            b: &ty::Region<'tcx>)
714                            -> RelateResult<'tcx, ty::Region<'tcx>>
715         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
716     {
717         relation.regions(*a, *b)
718     }
719 }
720
721 impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder<T> {
722     fn relate<'a, 'gcx, R>(relation: &mut R,
723                            a: &ty::Binder<T>,
724                            b: &ty::Binder<T>)
725                            -> RelateResult<'tcx, ty::Binder<T>>
726         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
727     {
728         relation.binders(a, b)
729     }
730 }
731
732 impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for Rc<T> {
733     fn relate<'a, 'gcx, R>(relation: &mut R,
734                            a: &Rc<T>,
735                            b: &Rc<T>)
736                            -> RelateResult<'tcx, Rc<T>>
737         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
738     {
739         let a: &T = a;
740         let b: &T = b;
741         Ok(Rc::new(relation.relate(a, b)?))
742     }
743 }
744
745 impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for Box<T> {
746     fn relate<'a, 'gcx, R>(relation: &mut R,
747                            a: &Box<T>,
748                            b: &Box<T>)
749                            -> RelateResult<'tcx, Box<T>>
750         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
751     {
752         let a: &T = a;
753         let b: &T = b;
754         Ok(Box::new(relation.relate(a, b)?))
755     }
756 }
757
758 impl<'tcx> Relate<'tcx> for Kind<'tcx> {
759     fn relate<'a, 'gcx, R>(
760         relation: &mut R,
761         a: &Kind<'tcx>,
762         b: &Kind<'tcx>
763     ) -> RelateResult<'tcx, Kind<'tcx>>
764     where
765         R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a,
766     {
767         match (a.unpack(), b.unpack()) {
768             (UnpackedKind::Lifetime(a_lt), UnpackedKind::Lifetime(b_lt)) => {
769                 Ok(relation.relate(&a_lt, &b_lt)?.into())
770             }
771             (UnpackedKind::Type(a_ty), UnpackedKind::Type(b_ty)) => {
772                 Ok(relation.relate(&a_ty, &b_ty)?.into())
773             }
774             (UnpackedKind::Lifetime(unpacked), x) => {
775                 bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
776             }
777             (UnpackedKind::Type(unpacked), x) => {
778                 bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
779             }
780             (UnpackedKind::Const(_), _) => {
781                 unimplemented!() // FIXME(const_generics)
782             }
783         }
784     }
785 }
786
787 impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> {
788     fn relate<'a, 'gcx, R>(
789         relation: &mut R,
790         a: &ty::TraitPredicate<'tcx>,
791         b: &ty::TraitPredicate<'tcx>
792     ) -> RelateResult<'tcx, ty::TraitPredicate<'tcx>>
793         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
794     {
795         Ok(ty::TraitPredicate {
796             trait_ref: relation.relate(&a.trait_ref, &b.trait_ref)?,
797         })
798     }
799 }
800
801 impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> {
802     fn relate<'a, 'gcx, R>(
803         relation: &mut R,
804         a: &ty::ProjectionPredicate<'tcx>,
805         b: &ty::ProjectionPredicate<'tcx>,
806     ) -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>>
807         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
808     {
809         Ok(ty::ProjectionPredicate {
810             projection_ty: relation.relate(&a.projection_ty, &b.projection_ty)?,
811             ty: relation.relate(&a.ty, &b.ty)?,
812         })
813     }
814 }
815
816 impl<'tcx> Relate<'tcx> for traits::WhereClause<'tcx> {
817     fn relate<'a, 'gcx, R>(
818         relation: &mut R,
819         a: &traits::WhereClause<'tcx>,
820         b: &traits::WhereClause<'tcx>
821     ) -> RelateResult<'tcx, traits::WhereClause<'tcx>>
822         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
823     {
824         use crate::traits::WhereClause::*;
825         match (a, b) {
826             (Implemented(a_pred), Implemented(b_pred)) => {
827                 Ok(Implemented(relation.relate(a_pred, b_pred)?))
828             }
829
830             (ProjectionEq(a_pred), ProjectionEq(b_pred)) => {
831                 Ok(ProjectionEq(relation.relate(a_pred, b_pred)?))
832             }
833
834             (RegionOutlives(a_pred), RegionOutlives(b_pred)) => {
835                 Ok(RegionOutlives(ty::OutlivesPredicate(
836                     relation.relate(&a_pred.0, &b_pred.0)?,
837                     relation.relate(&a_pred.1, &b_pred.1)?,
838                 )))
839             }
840
841             (TypeOutlives(a_pred), TypeOutlives(b_pred)) => {
842                 Ok(TypeOutlives(ty::OutlivesPredicate(
843                     relation.relate(&a_pred.0, &b_pred.0)?,
844                     relation.relate(&a_pred.1, &b_pred.1)?,
845                 )))
846             }
847
848             _ =>  Err(TypeError::Mismatch),
849         }
850     }
851 }
852
853 impl<'tcx> Relate<'tcx> for traits::WellFormed<'tcx> {
854     fn relate<'a, 'gcx, R>(
855         relation: &mut R,
856         a: &traits::WellFormed<'tcx>,
857         b: &traits::WellFormed<'tcx>
858     ) -> RelateResult<'tcx, traits::WellFormed<'tcx>>
859         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
860     {
861         use crate::traits::WellFormed::*;
862         match (a, b) {
863             (Trait(a_pred), Trait(b_pred)) => Ok(Trait(relation.relate(a_pred, b_pred)?)),
864             (Ty(a_ty), Ty(b_ty)) => Ok(Ty(relation.relate(a_ty, b_ty)?)),
865             _ =>  Err(TypeError::Mismatch),
866         }
867     }
868 }
869
870 impl<'tcx> Relate<'tcx> for traits::FromEnv<'tcx> {
871     fn relate<'a, 'gcx, R>(
872         relation: &mut R,
873         a: &traits::FromEnv<'tcx>,
874         b: &traits::FromEnv<'tcx>
875     ) -> RelateResult<'tcx, traits::FromEnv<'tcx>>
876         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
877     {
878         use crate::traits::FromEnv::*;
879         match (a, b) {
880             (Trait(a_pred), Trait(b_pred)) => Ok(Trait(relation.relate(a_pred, b_pred)?)),
881             (Ty(a_ty), Ty(b_ty)) => Ok(Ty(relation.relate(a_ty, b_ty)?)),
882             _ =>  Err(TypeError::Mismatch),
883         }
884     }
885 }
886
887 impl<'tcx> Relate<'tcx> for traits::DomainGoal<'tcx> {
888     fn relate<'a, 'gcx, R>(
889         relation: &mut R,
890         a: &traits::DomainGoal<'tcx>,
891         b: &traits::DomainGoal<'tcx>
892     ) -> RelateResult<'tcx, traits::DomainGoal<'tcx>>
893         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
894     {
895         use crate::traits::DomainGoal::*;
896         match (a, b) {
897             (Holds(a_wc), Holds(b_wc)) => Ok(Holds(relation.relate(a_wc, b_wc)?)),
898             (WellFormed(a_wf), WellFormed(b_wf)) => Ok(WellFormed(relation.relate(a_wf, b_wf)?)),
899             (FromEnv(a_fe), FromEnv(b_fe)) => Ok(FromEnv(relation.relate(a_fe, b_fe)?)),
900
901             (Normalize(a_pred), Normalize(b_pred)) => {
902                 Ok(Normalize(relation.relate(a_pred, b_pred)?))
903             }
904
905             _ =>  Err(TypeError::Mismatch),
906         }
907     }
908 }
909
910 impl<'tcx> Relate<'tcx> for traits::Goal<'tcx> {
911     fn relate<'a, 'gcx, R>(
912         relation: &mut R,
913         a: &traits::Goal<'tcx>,
914         b: &traits::Goal<'tcx>
915     ) -> RelateResult<'tcx, traits::Goal<'tcx>>
916         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
917     {
918         use crate::traits::GoalKind::*;
919         match (a, b) {
920             (Implies(a_clauses, a_goal), Implies(b_clauses, b_goal)) => {
921                 let clauses = relation.relate(a_clauses, b_clauses)?;
922                 let goal = relation.relate(a_goal, b_goal)?;
923                 Ok(relation.tcx().mk_goal(Implies(clauses, goal)))
924             }
925
926             (And(a_left, a_right), And(b_left, b_right)) => {
927                 let left = relation.relate(a_left, b_left)?;
928                 let right = relation.relate(a_right, b_right)?;
929                 Ok(relation.tcx().mk_goal(And(left, right)))
930             }
931
932             (Not(a_goal), Not(b_goal)) => {
933                 let goal = relation.relate(a_goal, b_goal)?;
934                 Ok(relation.tcx().mk_goal(Not(goal)))
935             }
936
937             (DomainGoal(a_goal), DomainGoal(b_goal)) => {
938                 let goal = relation.relate(a_goal, b_goal)?;
939                 Ok(relation.tcx().mk_goal(DomainGoal(goal)))
940             }
941
942             (Quantified(a_qkind, a_goal), Quantified(b_qkind, b_goal))
943                 if a_qkind == b_qkind =>
944             {
945                 let goal = relation.relate(a_goal, b_goal)?;
946                 Ok(relation.tcx().mk_goal(Quantified(*a_qkind, goal)))
947             }
948
949             (CannotProve, CannotProve) => Ok(*a),
950
951             _ => Err(TypeError::Mismatch),
952         }
953     }
954 }
955
956 impl<'tcx> Relate<'tcx> for traits::Goals<'tcx> {
957     fn relate<'a, 'gcx, R>(
958         relation: &mut R,
959         a: &traits::Goals<'tcx>,
960         b: &traits::Goals<'tcx>
961     ) -> RelateResult<'tcx, traits::Goals<'tcx>>
962         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
963     {
964         if a.len() != b.len() {
965             return Err(TypeError::Mismatch);
966         }
967
968         let tcx = relation.tcx();
969         let goals = a.iter().zip(b.iter()).map(|(a, b)| relation.relate(a, b));
970         Ok(tcx.mk_goals(goals)?)
971     }
972 }
973
974 impl<'tcx> Relate<'tcx> for traits::Clause<'tcx> {
975     fn relate<'a, 'gcx, R>(
976         relation: &mut R,
977         a: &traits::Clause<'tcx>,
978         b: &traits::Clause<'tcx>
979     ) -> RelateResult<'tcx, traits::Clause<'tcx>>
980         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
981     {
982         use crate::traits::Clause::*;
983         match (a, b) {
984             (Implies(a_clause), Implies(b_clause)) => {
985                 let clause = relation.relate(a_clause, b_clause)?;
986                 Ok(Implies(clause))
987             }
988
989             (ForAll(a_clause), ForAll(b_clause)) => {
990                 let clause = relation.relate(a_clause, b_clause)?;
991                 Ok(ForAll(clause))
992             }
993
994             _ => Err(TypeError::Mismatch),
995         }
996     }
997 }
998
999 impl<'tcx> Relate<'tcx> for traits::Clauses<'tcx> {
1000     fn relate<'a, 'gcx, R>(
1001         relation: &mut R,
1002         a: &traits::Clauses<'tcx>,
1003         b: &traits::Clauses<'tcx>
1004     ) -> RelateResult<'tcx, traits::Clauses<'tcx>>
1005         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
1006     {
1007         if a.len() != b.len() {
1008             return Err(TypeError::Mismatch);
1009         }
1010
1011         let tcx = relation.tcx();
1012         let clauses = a.iter().zip(b.iter()).map(|(a, b)| relation.relate(a, b));
1013         Ok(tcx.mk_clauses(clauses)?)
1014     }
1015 }
1016
1017 impl<'tcx> Relate<'tcx> for traits::ProgramClause<'tcx> {
1018     fn relate<'a, 'gcx, R>(
1019         relation: &mut R,
1020         a: &traits::ProgramClause<'tcx>,
1021         b: &traits::ProgramClause<'tcx>
1022     ) -> RelateResult<'tcx, traits::ProgramClause<'tcx>>
1023         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
1024     {
1025         Ok(traits::ProgramClause {
1026             goal: relation.relate(&a.goal, &b.goal)?,
1027             hypotheses: relation.relate(&a.hypotheses, &b.hypotheses)?,
1028             category: traits::ProgramClauseCategory::Other,
1029         })
1030     }
1031 }
1032
1033 impl<'tcx> Relate<'tcx> for traits::Environment<'tcx> {
1034     fn relate<'a, 'gcx, R>(
1035         relation: &mut R,
1036         a: &traits::Environment<'tcx>,
1037         b: &traits::Environment<'tcx>
1038     ) -> RelateResult<'tcx, traits::Environment<'tcx>>
1039         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
1040     {
1041         Ok(traits::Environment {
1042             clauses: relation.relate(&a.clauses, &b.clauses)?,
1043         })
1044     }
1045 }
1046
1047 impl<'tcx, G> Relate<'tcx> for traits::InEnvironment<'tcx, G>
1048     where G: Relate<'tcx>
1049 {
1050     fn relate<'a, 'gcx, R>(
1051         relation: &mut R,
1052         a: &traits::InEnvironment<'tcx, G>,
1053         b: &traits::InEnvironment<'tcx, G>
1054     ) -> RelateResult<'tcx, traits::InEnvironment<'tcx, G>>
1055         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'tcx, 'tcx: 'a
1056     {
1057         Ok(traits::InEnvironment {
1058             environment: relation.relate(&a.environment, &b.environment)?,
1059             goal: relation.relate(&a.goal, &b.goal)?,
1060         })
1061     }
1062 }
1063
1064 ///////////////////////////////////////////////////////////////////////////
1065 // Error handling
1066
1067 pub fn expected_found<'a, 'gcx, 'tcx, R, T>(relation: &mut R,
1068                                             a: &T,
1069                                             b: &T)
1070                                             -> ExpectedFound<T>
1071     where R: TypeRelation<'a, 'gcx, 'tcx>, T: Clone, 'gcx: 'a+'tcx, 'tcx: 'a
1072 {
1073     expected_found_bool(relation.a_is_expected(), a, b)
1074 }
1075
1076 pub fn expected_found_bool<T>(a_is_expected: bool,
1077                               a: &T,
1078                               b: &T)
1079                               -> ExpectedFound<T>
1080     where T: Clone
1081 {
1082     let a = a.clone();
1083     let b = b.clone();
1084     if a_is_expected {
1085         ExpectedFound {expected: a, found: b}
1086     } else {
1087         ExpectedFound {expected: b, found: a}
1088     }
1089 }