1 //! Generalized type relating mechanism.
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.
7 use crate::mir
::interpret
::{get_slice_bytes, ConstValue}
;
9 use crate::ty
::error
::{ExpectedFound, TypeError}
;
10 use crate::ty
::subst
::{GenericArg, GenericArgKind, SubstsRef}
;
11 use crate::ty
::{self, Ty, TyCtxt, TypeFoldable}
;
13 use rustc_hir
::def_id
::DefId
;
14 use rustc_target
::spec
::abi
;
18 pub type RelateResult
<'tcx
, T
> = Result
<T
, TypeError
<'tcx
>>;
20 #[derive(Clone, Debug)]
22 ExistentialRegionBound
, // relating an existential region bound
25 pub trait TypeRelation
<'tcx
>: Sized
{
26 fn tcx(&self) -> TyCtxt
<'tcx
>;
28 fn param_env(&self) -> ty
::ParamEnv
<'tcx
>;
30 /// Returns a static string we can use for printouts.
31 fn tag(&self) -> &'
static str;
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
;
37 fn with_cause
<F
, R
>(&mut self, _cause
: Cause
, f
: F
) -> R
39 F
: FnOnce(&mut Self) -> R
,
44 /// Generic relation routine suitable for most anything.
45 fn relate
<T
: Relate
<'tcx
>>(&mut self, a
: &T
, b
: &T
) -> RelateResult
<'tcx
, T
> {
46 Relate
::relate(self, a
, b
)
49 /// Relate the two substitutions for the given item. The default
50 /// is to look up the variance for the item and proceed
52 fn relate_item_substs(
55 a_subst
: SubstsRef
<'tcx
>,
56 b_subst
: SubstsRef
<'tcx
>,
57 ) -> RelateResult
<'tcx
, SubstsRef
<'tcx
>> {
59 "relate_item_substs(item_def_id={:?}, a_subst={:?}, b_subst={:?})",
60 item_def_id
, a_subst
, b_subst
63 let opt_variances
= self.tcx().variances_of(item_def_id
);
64 relate_substs(self, Some(opt_variances
), a_subst
, b_subst
)
67 /// Switch variance for the purpose of relating `a` and `b`.
68 fn relate_with_variance
<T
: Relate
<'tcx
>>(
70 variance
: ty
::Variance
,
73 ) -> RelateResult
<'tcx
, T
>;
75 // Overridable relations. You shouldn't typically call these
76 // directly, instead call `relate()`, which in turn calls
77 // these. This is both more uniform but also allows us to add
78 // additional hooks for other types in the future if needed
79 // without making older code, which called `relate`, obsolete.
81 fn tys(&mut self, a
: Ty
<'tcx
>, b
: Ty
<'tcx
>) -> RelateResult
<'tcx
, Ty
<'tcx
>>;
87 ) -> RelateResult
<'tcx
, ty
::Region
<'tcx
>>;
91 a
: &'tcx ty
::Const
<'tcx
>,
92 b
: &'tcx ty
::Const
<'tcx
>,
93 ) -> RelateResult
<'tcx
, &'tcx ty
::Const
<'tcx
>>;
99 ) -> RelateResult
<'tcx
, ty
::Binder
<T
>>
104 pub trait Relate
<'tcx
>: TypeFoldable
<'tcx
> {
105 fn relate
<R
: TypeRelation
<'tcx
>>(
109 ) -> RelateResult
<'tcx
, Self>;
112 ///////////////////////////////////////////////////////////////////////////
115 impl<'tcx
> Relate
<'tcx
> for ty
::TypeAndMut
<'tcx
> {
116 fn relate
<R
: TypeRelation
<'tcx
>>(
118 a
: &ty
::TypeAndMut
<'tcx
>,
119 b
: &ty
::TypeAndMut
<'tcx
>,
120 ) -> RelateResult
<'tcx
, ty
::TypeAndMut
<'tcx
>> {
121 debug
!("{}.mts({:?}, {:?})", relation
.tag(), a
, b
);
122 if a
.mutbl
!= b
.mutbl
{
123 Err(TypeError
::Mutability
)
126 let variance
= match mutbl
{
127 ast
::Mutability
::Not
=> ty
::Covariant
,
128 ast
::Mutability
::Mut
=> ty
::Invariant
,
130 let ty
= relation
.relate_with_variance(variance
, &a
.ty
, &b
.ty
)?
;
131 Ok(ty
::TypeAndMut { ty, mutbl }
)
136 pub fn relate_substs
<R
: TypeRelation
<'tcx
>>(
138 variances
: Option
<&[ty
::Variance
]>,
139 a_subst
: SubstsRef
<'tcx
>,
140 b_subst
: SubstsRef
<'tcx
>,
141 ) -> RelateResult
<'tcx
, SubstsRef
<'tcx
>> {
142 let tcx
= relation
.tcx();
144 let params
= a_subst
.iter().zip(b_subst
).enumerate().map(|(i
, (a
, b
))| {
145 let variance
= variances
.map_or(ty
::Invariant
, |v
| v
[i
]);
146 relation
.relate_with_variance(variance
, a
, b
)
149 Ok(tcx
.mk_substs(params
)?
)
152 impl<'tcx
> Relate
<'tcx
> for ty
::FnSig
<'tcx
> {
153 fn relate
<R
: TypeRelation
<'tcx
>>(
157 ) -> RelateResult
<'tcx
, ty
::FnSig
<'tcx
>> {
158 let tcx
= relation
.tcx();
160 if a
.c_variadic
!= b
.c_variadic
{
161 return Err(TypeError
::VariadicMismatch(expected_found(
167 let unsafety
= relation
.relate(&a
.unsafety
, &b
.unsafety
)?
;
168 let abi
= relation
.relate(&a
.abi
, &b
.abi
)?
;
170 if a
.inputs().len() != b
.inputs().len() {
171 return Err(TypeError
::ArgCount
);
174 let inputs_and_output
= a
178 .zip(b
.inputs().iter().cloned())
180 .chain(iter
::once(((a
.output(), b
.output()), true)))
181 .map(|((a
, b
), is_output
)| {
183 relation
.relate(&a
, &b
)
185 relation
.relate_with_variance(ty
::Contravariant
, &a
, &b
)
189 inputs_and_output
: tcx
.mk_type_list(inputs_and_output
)?
,
190 c_variadic
: a
.c_variadic
,
197 impl<'tcx
> Relate
<'tcx
> for ast
::Unsafety
{
198 fn relate
<R
: TypeRelation
<'tcx
>>(
202 ) -> RelateResult
<'tcx
, ast
::Unsafety
> {
204 Err(TypeError
::UnsafetyMismatch(expected_found(relation
, a
, b
)))
211 impl<'tcx
> Relate
<'tcx
> for abi
::Abi
{
212 fn relate
<R
: TypeRelation
<'tcx
>>(
216 ) -> RelateResult
<'tcx
, abi
::Abi
> {
217 if a
== b { Ok(*a) }
else { Err(TypeError::AbiMismatch(expected_found(relation, a, b))) }
221 impl<'tcx
> Relate
<'tcx
> for ty
::ProjectionTy
<'tcx
> {
222 fn relate
<R
: TypeRelation
<'tcx
>>(
224 a
: &ty
::ProjectionTy
<'tcx
>,
225 b
: &ty
::ProjectionTy
<'tcx
>,
226 ) -> RelateResult
<'tcx
, ty
::ProjectionTy
<'tcx
>> {
227 if a
.item_def_id
!= b
.item_def_id
{
228 Err(TypeError
::ProjectionMismatched(expected_found(
234 let substs
= relation
.relate(&a
.substs
, &b
.substs
)?
;
235 Ok(ty
::ProjectionTy { item_def_id: a.item_def_id, substs: &substs }
)
240 impl<'tcx
> Relate
<'tcx
> for ty
::ExistentialProjection
<'tcx
> {
241 fn relate
<R
: TypeRelation
<'tcx
>>(
243 a
: &ty
::ExistentialProjection
<'tcx
>,
244 b
: &ty
::ExistentialProjection
<'tcx
>,
245 ) -> RelateResult
<'tcx
, ty
::ExistentialProjection
<'tcx
>> {
246 if a
.item_def_id
!= b
.item_def_id
{
247 Err(TypeError
::ProjectionMismatched(expected_found(
253 let ty
= relation
.relate(&a
.ty
, &b
.ty
)?
;
254 let substs
= relation
.relate(&a
.substs
, &b
.substs
)?
;
255 Ok(ty
::ExistentialProjection { item_def_id: a.item_def_id, substs, ty }
)
260 impl<'tcx
> Relate
<'tcx
> for Vec
<ty
::PolyExistentialProjection
<'tcx
>> {
261 fn relate
<R
: TypeRelation
<'tcx
>>(
263 a
: &Vec
<ty
::PolyExistentialProjection
<'tcx
>>,
264 b
: &Vec
<ty
::PolyExistentialProjection
<'tcx
>>,
265 ) -> RelateResult
<'tcx
, Vec
<ty
::PolyExistentialProjection
<'tcx
>>> {
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
271 if a
.len() != b
.len() {
272 Err(TypeError
::ProjectionBoundsLength(expected_found(relation
, &a
.len(), &b
.len())))
274 a
.iter().zip(b
).map(|(a
, b
)| relation
.relate(a
, b
)).collect()
279 impl<'tcx
> Relate
<'tcx
> for ty
::TraitRef
<'tcx
> {
280 fn relate
<R
: TypeRelation
<'tcx
>>(
282 a
: &ty
::TraitRef
<'tcx
>,
283 b
: &ty
::TraitRef
<'tcx
>,
284 ) -> RelateResult
<'tcx
, ty
::TraitRef
<'tcx
>> {
285 // Different traits cannot be related.
286 if a
.def_id
!= b
.def_id
{
287 Err(TypeError
::Traits(expected_found(relation
, &a
.def_id
, &b
.def_id
)))
289 let substs
= relate_substs(relation
, None
, a
.substs
, b
.substs
)?
;
290 Ok(ty
::TraitRef { def_id: a.def_id, substs }
)
295 impl<'tcx
> Relate
<'tcx
> for ty
::ExistentialTraitRef
<'tcx
> {
296 fn relate
<R
: TypeRelation
<'tcx
>>(
298 a
: &ty
::ExistentialTraitRef
<'tcx
>,
299 b
: &ty
::ExistentialTraitRef
<'tcx
>,
300 ) -> RelateResult
<'tcx
, ty
::ExistentialTraitRef
<'tcx
>> {
301 // Different traits cannot be related.
302 if a
.def_id
!= b
.def_id
{
303 Err(TypeError
::Traits(expected_found(relation
, &a
.def_id
, &b
.def_id
)))
305 let substs
= relate_substs(relation
, None
, a
.substs
, b
.substs
)?
;
306 Ok(ty
::ExistentialTraitRef { def_id: a.def_id, substs }
)
311 #[derive(Debug, Clone, TypeFoldable)]
312 struct GeneratorWitness
<'tcx
>(&'tcx ty
::List
<Ty
<'tcx
>>);
314 impl<'tcx
> Relate
<'tcx
> for GeneratorWitness
<'tcx
> {
315 fn relate
<R
: TypeRelation
<'tcx
>>(
317 a
: &GeneratorWitness
<'tcx
>,
318 b
: &GeneratorWitness
<'tcx
>,
319 ) -> RelateResult
<'tcx
, GeneratorWitness
<'tcx
>> {
320 assert_eq
!(a
.0.len(), b
.0.len());
321 let tcx
= relation
.tcx();
322 let types
= tcx
.mk_type_list(a
.0.iter
().zip(b
.0).map(|(a
, b
)| relation
.relate(a
, b
)))?
;
323 Ok(GeneratorWitness(types
))
327 impl<'tcx
> Relate
<'tcx
> for Ty
<'tcx
> {
328 fn relate
<R
: TypeRelation
<'tcx
>>(
332 ) -> RelateResult
<'tcx
, Ty
<'tcx
>> {
337 /// The main "type relation" routine. Note that this does not handle
338 /// inference artifacts, so you should filter those out before calling
340 pub fn super_relate_tys
<R
: TypeRelation
<'tcx
>>(
344 ) -> RelateResult
<'tcx
, Ty
<'tcx
>> {
345 let tcx
= relation
.tcx();
346 debug
!("super_relate_tys: a={:?} b={:?}", a
, b
);
347 match (&a
.kind
, &b
.kind
) {
348 (&ty
::Infer(_
), _
) | (_
, &ty
::Infer(_
)) => {
349 // The caller should handle these cases!
350 bug
!("var types encountered in super_relate_tys")
353 (ty
::Bound(..), _
) | (_
, ty
::Bound(..)) => {
354 bug
!("bound types encountered in super_relate_tys")
357 (&ty
::Error
, _
) | (_
, &ty
::Error
) => Ok(tcx
.types
.err
),
371 (&ty
::Param(ref a_p
), &ty
::Param(ref b_p
)) if a_p
.index
== b_p
.index
=> Ok(a
),
373 (ty
::Placeholder(p1
), ty
::Placeholder(p2
)) if p1
== p2
=> Ok(a
),
375 (&ty
::Adt(a_def
, a_substs
), &ty
::Adt(b_def
, b_substs
)) if a_def
== b_def
=> {
376 let substs
= relation
.relate_item_substs(a_def
.did
, a_substs
, b_substs
)?
;
377 Ok(tcx
.mk_adt(a_def
, substs
))
380 (&ty
::Foreign(a_id
), &ty
::Foreign(b_id
)) if a_id
== b_id
=> Ok(tcx
.mk_foreign(a_id
)),
382 (&ty
::Dynamic(ref a_obj
, ref a_region
), &ty
::Dynamic(ref b_obj
, ref b_region
)) => {
383 let region_bound
= relation
.with_cause(Cause
::ExistentialRegionBound
, |relation
| {
384 relation
.relate_with_variance(ty
::Contravariant
, a_region
, b_region
)
386 Ok(tcx
.mk_dynamic(relation
.relate(a_obj
, b_obj
)?
, region_bound
))
389 (&ty
::Generator(a_id
, a_substs
, movability
), &ty
::Generator(b_id
, b_substs
, _
))
392 // All Generator types with the same id represent
393 // the (anonymous) type of the same generator expression. So
394 // all of their regions should be equated.
395 let substs
= relation
.relate(&a_substs
, &b_substs
)?
;
396 Ok(tcx
.mk_generator(a_id
, substs
, movability
))
399 (&ty
::GeneratorWitness(a_types
), &ty
::GeneratorWitness(b_types
)) => {
400 // Wrap our types with a temporary GeneratorWitness struct
401 // inside the binder so we can related them
402 let a_types
= a_types
.map_bound(GeneratorWitness
);
403 let b_types
= b_types
.map_bound(GeneratorWitness
);
404 // Then remove the GeneratorWitness for the result
405 let types
= relation
.relate(&a_types
, &b_types
)?
.map_bound(|witness
| witness
.0);
406 Ok(tcx
.mk_generator_witness(types
))
409 (&ty
::Closure(a_id
, a_substs
), &ty
::Closure(b_id
, b_substs
)) if a_id
== b_id
=> {
410 // All Closure types with the same id represent
411 // the (anonymous) type of the same closure expression. So
412 // all of their regions should be equated.
413 let substs
= relation
.relate(&a_substs
, &b_substs
)?
;
414 Ok(tcx
.mk_closure(a_id
, &substs
))
417 (&ty
::RawPtr(ref a_mt
), &ty
::RawPtr(ref b_mt
)) => {
418 let mt
= relation
.relate(a_mt
, b_mt
)?
;
422 (&ty
::Ref(a_r
, a_ty
, a_mutbl
), &ty
::Ref(b_r
, b_ty
, b_mutbl
)) => {
423 let r
= relation
.relate_with_variance(ty
::Contravariant
, &a_r
, &b_r
)?
;
424 let a_mt
= ty
::TypeAndMut { ty: a_ty, mutbl: a_mutbl }
;
425 let b_mt
= ty
::TypeAndMut { ty: b_ty, mutbl: b_mutbl }
;
426 let mt
= relation
.relate(&a_mt
, &b_mt
)?
;
427 Ok(tcx
.mk_ref(r
, mt
))
430 (&ty
::Array(a_t
, sz_a
), &ty
::Array(b_t
, sz_b
)) => {
431 let t
= relation
.relate(&a_t
, &b_t
)?
;
432 match relation
.relate(&sz_a
, &sz_b
) {
433 Ok(sz
) => Ok(tcx
.mk_ty(ty
::Array(t
, sz
))),
435 // Check whether the lengths are both concrete/known values,
436 // but are unequal, for better diagnostics.
437 let sz_a
= sz_a
.try_eval_usize(tcx
, relation
.param_env());
438 let sz_b
= sz_b
.try_eval_usize(tcx
, relation
.param_env());
440 (Some(sz_a_val
), Some(sz_b_val
)) => Err(TypeError
::FixedArraySize(
441 expected_found(relation
, &sz_a_val
, &sz_b_val
),
443 _
=> return Err(err
),
449 (&ty
::Slice(a_t
), &ty
::Slice(b_t
)) => {
450 let t
= relation
.relate(&a_t
, &b_t
)?
;
454 (&ty
::Tuple(as_
), &ty
::Tuple(bs
)) => {
455 if as_
.len() == bs
.len() {
459 .map(|(a
, b
)| relation
.relate(&a
.expect_ty(), &b
.expect_ty())),
461 } else if !(as_
.is_empty() || bs
.is_empty()) {
462 Err(TypeError
::TupleSize(expected_found(relation
, &as_
.len(), &bs
.len())))
464 Err(TypeError
::Sorts(expected_found(relation
, &a
, &b
)))
468 (&ty
::FnDef(a_def_id
, a_substs
), &ty
::FnDef(b_def_id
, b_substs
))
469 if a_def_id
== b_def_id
=>
471 let substs
= relation
.relate_item_substs(a_def_id
, a_substs
, b_substs
)?
;
472 Ok(tcx
.mk_fn_def(a_def_id
, substs
))
475 (&ty
::FnPtr(a_fty
), &ty
::FnPtr(b_fty
)) => {
476 let fty
= relation
.relate(&a_fty
, &b_fty
)?
;
477 Ok(tcx
.mk_fn_ptr(fty
))
480 (ty
::UnnormalizedProjection(a_data
), ty
::UnnormalizedProjection(b_data
)) => {
481 let projection_ty
= relation
.relate(a_data
, b_data
)?
;
482 Ok(tcx
.mk_ty(ty
::UnnormalizedProjection(projection_ty
)))
485 // these two are already handled downstream in case of lazy normalization
486 (ty
::Projection(a_data
), ty
::Projection(b_data
)) => {
487 let projection_ty
= relation
.relate(a_data
, b_data
)?
;
488 Ok(tcx
.mk_projection(projection_ty
.item_def_id
, projection_ty
.substs
))
491 (&ty
::Opaque(a_def_id
, a_substs
), &ty
::Opaque(b_def_id
, b_substs
))
492 if a_def_id
== b_def_id
=>
494 let substs
= relate_substs(relation
, None
, a_substs
, b_substs
)?
;
495 Ok(tcx
.mk_opaque(a_def_id
, substs
))
498 _
=> Err(TypeError
::Sorts(expected_found(relation
, &a
, &b
))),
502 /// The main "const relation" routine. Note that this does not handle
503 /// inference artifacts, so you should filter those out before calling
505 pub fn super_relate_consts
<R
: TypeRelation
<'tcx
>>(
507 a
: &'tcx ty
::Const
<'tcx
>,
508 b
: &'tcx ty
::Const
<'tcx
>,
509 ) -> RelateResult
<'tcx
, &'tcx ty
::Const
<'tcx
>> {
510 let tcx
= relation
.tcx();
512 let eagerly_eval
= |x
: &'tcx ty
::Const
<'tcx
>| {
513 if !x
.val
.has_local_value() {
514 return x
.eval(tcx
, relation
.param_env()).val
;
519 // Currently, the values that can be unified are primitive types,
520 // and those that derive both `PartialEq` and `Eq`, corresponding
521 // to `structural_match` types.
522 let new_const_val
= match (eagerly_eval(a
), eagerly_eval(b
)) {
523 (ty
::ConstKind
::Infer(_
), _
) | (_
, ty
::ConstKind
::Infer(_
)) => {
524 // The caller should handle these cases!
525 bug
!("var types encountered in super_relate_consts: {:?} {:?}", a
, b
)
527 (ty
::ConstKind
::Param(a_p
), ty
::ConstKind
::Param(b_p
)) if a_p
.index
== b_p
.index
=> {
530 (ty
::ConstKind
::Placeholder(p1
), ty
::ConstKind
::Placeholder(p2
)) if p1
== p2
=> {
533 (ty
::ConstKind
::Value(a_val
), ty
::ConstKind
::Value(b_val
)) => {
534 let new_val
= match (a_val
, b_val
) {
535 (ConstValue
::Scalar(a_val
), ConstValue
::Scalar(b_val
)) if a
.ty
== b
.ty
=> {
537 Ok(ConstValue
::Scalar(a_val
))
538 } else if let ty
::FnPtr(_
) = a
.ty
.kind
{
539 let alloc_map
= tcx
.alloc_map
.lock();
540 let a_instance
= alloc_map
.unwrap_fn(a_val
.assert_ptr().alloc_id
);
541 let b_instance
= alloc_map
.unwrap_fn(b_val
.assert_ptr().alloc_id
);
542 if a_instance
== b_instance
{
543 Ok(ConstValue
::Scalar(a_val
))
545 Err(TypeError
::ConstMismatch(expected_found(relation
, &a
, &b
)))
548 Err(TypeError
::ConstMismatch(expected_found(relation
, &a
, &b
)))
552 (a_val @ ConstValue
::Slice { .. }
, b_val @ ConstValue
::Slice { .. }
) => {
553 let a_bytes
= get_slice_bytes(&tcx
, a_val
);
554 let b_bytes
= get_slice_bytes(&tcx
, b_val
);
555 if a_bytes
== b_bytes
{
558 Err(TypeError
::ConstMismatch(expected_found(relation
, &a
, &b
)))
562 // FIXME(const_generics): handle `ConstValue::ByRef`.
563 _
=> Err(TypeError
::ConstMismatch(expected_found(relation
, &a
, &b
))),
566 new_val
.map(ty
::ConstKind
::Value
)
569 // FIXME(const_generics): this is wrong, as it is a projection
571 ty
::ConstKind
::Unevaluated(a_def_id
, a_substs
, a_promoted
),
572 ty
::ConstKind
::Unevaluated(b_def_id
, b_substs
, b_promoted
),
573 ) if a_def_id
== b_def_id
&& a_promoted
== b_promoted
=> {
575 relation
.relate_with_variance(ty
::Variance
::Invariant
, &a_substs
, &b_substs
)?
;
576 Ok(ty
::ConstKind
::Unevaluated(a_def_id
, &substs
, a_promoted
))
578 _
=> Err(TypeError
::ConstMismatch(expected_found(relation
, &a
, &b
))),
580 new_const_val
.map(|val
| tcx
.mk_const(ty
::Const { val, ty: a.ty }
))
583 impl<'tcx
> Relate
<'tcx
> for &'tcx ty
::List
<ty
::ExistentialPredicate
<'tcx
>> {
584 fn relate
<R
: TypeRelation
<'tcx
>>(
588 ) -> RelateResult
<'tcx
, Self> {
589 if a
.len() != b
.len() {
590 return Err(TypeError
::ExistentialMismatch(expected_found(relation
, a
, b
)));
593 let tcx
= relation
.tcx();
594 let v
= a
.iter().zip(b
.iter()).map(|(ep_a
, ep_b
)| {
595 use crate::ty
::ExistentialPredicate
::*;
596 match (*ep_a
, *ep_b
) {
597 (Trait(ref a
), Trait(ref b
)) => Ok(Trait(relation
.relate(a
, b
)?
)),
598 (Projection(ref a
), Projection(ref b
)) => Ok(Projection(relation
.relate(a
, b
)?
)),
599 (AutoTrait(ref a
), AutoTrait(ref b
)) if a
== b
=> Ok(AutoTrait(*a
)),
600 _
=> Err(TypeError
::ExistentialMismatch(expected_found(relation
, a
, b
))),
603 Ok(tcx
.mk_existential_predicates(v
)?
)
607 impl<'tcx
> Relate
<'tcx
> for ty
::ClosureSubsts
<'tcx
> {
608 fn relate
<R
: TypeRelation
<'tcx
>>(
610 a
: &ty
::ClosureSubsts
<'tcx
>,
611 b
: &ty
::ClosureSubsts
<'tcx
>,
612 ) -> RelateResult
<'tcx
, ty
::ClosureSubsts
<'tcx
>> {
613 let substs
= relate_substs(relation
, None
, a
.substs
, b
.substs
)?
;
614 Ok(ty
::ClosureSubsts { substs }
)
618 impl<'tcx
> Relate
<'tcx
> for ty
::GeneratorSubsts
<'tcx
> {
619 fn relate
<R
: TypeRelation
<'tcx
>>(
621 a
: &ty
::GeneratorSubsts
<'tcx
>,
622 b
: &ty
::GeneratorSubsts
<'tcx
>,
623 ) -> RelateResult
<'tcx
, ty
::GeneratorSubsts
<'tcx
>> {
624 let substs
= relate_substs(relation
, None
, a
.substs
, b
.substs
)?
;
625 Ok(ty
::GeneratorSubsts { substs }
)
629 impl<'tcx
> Relate
<'tcx
> for SubstsRef
<'tcx
> {
630 fn relate
<R
: TypeRelation
<'tcx
>>(
634 ) -> RelateResult
<'tcx
, SubstsRef
<'tcx
>> {
635 relate_substs(relation
, None
, a
, b
)
639 impl<'tcx
> Relate
<'tcx
> for ty
::Region
<'tcx
> {
640 fn relate
<R
: TypeRelation
<'tcx
>>(
642 a
: &ty
::Region
<'tcx
>,
643 b
: &ty
::Region
<'tcx
>,
644 ) -> RelateResult
<'tcx
, ty
::Region
<'tcx
>> {
645 relation
.regions(*a
, *b
)
649 impl<'tcx
> Relate
<'tcx
> for &'tcx ty
::Const
<'tcx
> {
650 fn relate
<R
: TypeRelation
<'tcx
>>(
652 a
: &&'tcx ty
::Const
<'tcx
>,
653 b
: &&'tcx ty
::Const
<'tcx
>,
654 ) -> RelateResult
<'tcx
, &'tcx ty
::Const
<'tcx
>> {
655 relation
.consts(*a
, *b
)
659 impl<'tcx
, T
: Relate
<'tcx
>> Relate
<'tcx
> for ty
::Binder
<T
> {
660 fn relate
<R
: TypeRelation
<'tcx
>>(
664 ) -> RelateResult
<'tcx
, ty
::Binder
<T
>> {
665 relation
.binders(a
, b
)
669 impl<'tcx
, T
: Relate
<'tcx
>> Relate
<'tcx
> for Rc
<T
> {
670 fn relate
<R
: TypeRelation
<'tcx
>>(
674 ) -> RelateResult
<'tcx
, Rc
<T
>> {
677 Ok(Rc
::new(relation
.relate(a
, b
)?
))
681 impl<'tcx
, T
: Relate
<'tcx
>> Relate
<'tcx
> for Box
<T
> {
682 fn relate
<R
: TypeRelation
<'tcx
>>(
686 ) -> RelateResult
<'tcx
, Box
<T
>> {
689 Ok(Box
::new(relation
.relate(a
, b
)?
))
693 impl<'tcx
> Relate
<'tcx
> for GenericArg
<'tcx
> {
694 fn relate
<R
: TypeRelation
<'tcx
>>(
696 a
: &GenericArg
<'tcx
>,
697 b
: &GenericArg
<'tcx
>,
698 ) -> RelateResult
<'tcx
, GenericArg
<'tcx
>> {
699 match (a
.unpack(), b
.unpack()) {
700 (GenericArgKind
::Lifetime(a_lt
), GenericArgKind
::Lifetime(b_lt
)) => {
701 Ok(relation
.relate(&a_lt
, &b_lt
)?
.into())
703 (GenericArgKind
::Type(a_ty
), GenericArgKind
::Type(b_ty
)) => {
704 Ok(relation
.relate(&a_ty
, &b_ty
)?
.into())
706 (GenericArgKind
::Const(a_ct
), GenericArgKind
::Const(b_ct
)) => {
707 Ok(relation
.relate(&a_ct
, &b_ct
)?
.into())
709 (GenericArgKind
::Lifetime(unpacked
), x
) => {
710 bug
!("impossible case reached: can't relate: {:?} with {:?}", unpacked
, x
)
712 (GenericArgKind
::Type(unpacked
), x
) => {
713 bug
!("impossible case reached: can't relate: {:?} with {:?}", unpacked
, x
)
715 (GenericArgKind
::Const(unpacked
), x
) => {
716 bug
!("impossible case reached: can't relate: {:?} with {:?}", unpacked
, x
)
722 impl<'tcx
> Relate
<'tcx
> for ty
::TraitPredicate
<'tcx
> {
723 fn relate
<R
: TypeRelation
<'tcx
>>(
725 a
: &ty
::TraitPredicate
<'tcx
>,
726 b
: &ty
::TraitPredicate
<'tcx
>,
727 ) -> RelateResult
<'tcx
, ty
::TraitPredicate
<'tcx
>> {
728 Ok(ty
::TraitPredicate { trait_ref: relation.relate(&a.trait_ref, &b.trait_ref)? }
)
732 impl<'tcx
> Relate
<'tcx
> for ty
::ProjectionPredicate
<'tcx
> {
733 fn relate
<R
: TypeRelation
<'tcx
>>(
735 a
: &ty
::ProjectionPredicate
<'tcx
>,
736 b
: &ty
::ProjectionPredicate
<'tcx
>,
737 ) -> RelateResult
<'tcx
, ty
::ProjectionPredicate
<'tcx
>> {
738 Ok(ty
::ProjectionPredicate
{
739 projection_ty
: relation
.relate(&a
.projection_ty
, &b
.projection_ty
)?
,
740 ty
: relation
.relate(&a
.ty
, &b
.ty
)?
,
745 impl<'tcx
> Relate
<'tcx
> for traits
::WhereClause
<'tcx
> {
746 fn relate
<R
: TypeRelation
<'tcx
>>(
748 a
: &traits
::WhereClause
<'tcx
>,
749 b
: &traits
::WhereClause
<'tcx
>,
750 ) -> RelateResult
<'tcx
, traits
::WhereClause
<'tcx
>> {
751 use crate::traits
::WhereClause
::*;
753 (Implemented(a_pred
), Implemented(b_pred
)) => {
754 Ok(Implemented(relation
.relate(a_pred
, b_pred
)?
))
757 (ProjectionEq(a_pred
), ProjectionEq(b_pred
)) => {
758 Ok(ProjectionEq(relation
.relate(a_pred
, b_pred
)?
))
761 (RegionOutlives(a_pred
), RegionOutlives(b_pred
)) => {
762 Ok(RegionOutlives(ty
::OutlivesPredicate(
763 relation
.relate(&a_pred
.0, &b_pred
.0)?
,
764 relation
.relate(&a_pred
.1, &b_pred
.1)?
,
768 (TypeOutlives(a_pred
), TypeOutlives(b_pred
)) => {
769 Ok(TypeOutlives(ty
::OutlivesPredicate(
770 relation
.relate(&a_pred
.0, &b_pred
.0)?
,
771 relation
.relate(&a_pred
.1, &b_pred
.1)?
,
775 _
=> Err(TypeError
::Mismatch
),
780 impl<'tcx
> Relate
<'tcx
> for traits
::WellFormed
<'tcx
> {
781 fn relate
<R
: TypeRelation
<'tcx
>>(
783 a
: &traits
::WellFormed
<'tcx
>,
784 b
: &traits
::WellFormed
<'tcx
>,
785 ) -> RelateResult
<'tcx
, traits
::WellFormed
<'tcx
>> {
786 use crate::traits
::WellFormed
::*;
788 (Trait(a_pred
), Trait(b_pred
)) => Ok(Trait(relation
.relate(a_pred
, b_pred
)?
)),
789 (Ty(a_ty
), Ty(b_ty
)) => Ok(Ty(relation
.relate(a_ty
, b_ty
)?
)),
790 _
=> Err(TypeError
::Mismatch
),
795 impl<'tcx
> Relate
<'tcx
> for traits
::FromEnv
<'tcx
> {
796 fn relate
<R
: TypeRelation
<'tcx
>>(
798 a
: &traits
::FromEnv
<'tcx
>,
799 b
: &traits
::FromEnv
<'tcx
>,
800 ) -> RelateResult
<'tcx
, traits
::FromEnv
<'tcx
>> {
801 use crate::traits
::FromEnv
::*;
803 (Trait(a_pred
), Trait(b_pred
)) => Ok(Trait(relation
.relate(a_pred
, b_pred
)?
)),
804 (Ty(a_ty
), Ty(b_ty
)) => Ok(Ty(relation
.relate(a_ty
, b_ty
)?
)),
805 _
=> Err(TypeError
::Mismatch
),
810 impl<'tcx
> Relate
<'tcx
> for traits
::DomainGoal
<'tcx
> {
811 fn relate
<R
: TypeRelation
<'tcx
>>(
813 a
: &traits
::DomainGoal
<'tcx
>,
814 b
: &traits
::DomainGoal
<'tcx
>,
815 ) -> RelateResult
<'tcx
, traits
::DomainGoal
<'tcx
>> {
816 use crate::traits
::DomainGoal
::*;
818 (Holds(a_wc
), Holds(b_wc
)) => Ok(Holds(relation
.relate(a_wc
, b_wc
)?
)),
819 (WellFormed(a_wf
), WellFormed(b_wf
)) => Ok(WellFormed(relation
.relate(a_wf
, b_wf
)?
)),
820 (FromEnv(a_fe
), FromEnv(b_fe
)) => Ok(FromEnv(relation
.relate(a_fe
, b_fe
)?
)),
822 (Normalize(a_pred
), Normalize(b_pred
)) => {
823 Ok(Normalize(relation
.relate(a_pred
, b_pred
)?
))
826 _
=> Err(TypeError
::Mismatch
),
831 impl<'tcx
> Relate
<'tcx
> for traits
::Goal
<'tcx
> {
832 fn relate
<R
: TypeRelation
<'tcx
>>(
834 a
: &traits
::Goal
<'tcx
>,
835 b
: &traits
::Goal
<'tcx
>,
836 ) -> RelateResult
<'tcx
, traits
::Goal
<'tcx
>> {
837 use crate::traits
::GoalKind
::*;
839 (Implies(a_clauses
, a_goal
), Implies(b_clauses
, b_goal
)) => {
840 let clauses
= relation
.relate(a_clauses
, b_clauses
)?
;
841 let goal
= relation
.relate(a_goal
, b_goal
)?
;
842 Ok(relation
.tcx().mk_goal(Implies(clauses
, goal
)))
845 (And(a_left
, a_right
), And(b_left
, b_right
)) => {
846 let left
= relation
.relate(a_left
, b_left
)?
;
847 let right
= relation
.relate(a_right
, b_right
)?
;
848 Ok(relation
.tcx().mk_goal(And(left
, right
)))
851 (Not(a_goal
), Not(b_goal
)) => {
852 let goal
= relation
.relate(a_goal
, b_goal
)?
;
853 Ok(relation
.tcx().mk_goal(Not(goal
)))
856 (DomainGoal(a_goal
), DomainGoal(b_goal
)) => {
857 let goal
= relation
.relate(a_goal
, b_goal
)?
;
858 Ok(relation
.tcx().mk_goal(DomainGoal(goal
)))
861 (Quantified(a_qkind
, a_goal
), Quantified(b_qkind
, b_goal
)) if a_qkind
== b_qkind
=> {
862 let goal
= relation
.relate(a_goal
, b_goal
)?
;
863 Ok(relation
.tcx().mk_goal(Quantified(*a_qkind
, goal
)))
866 (CannotProve
, CannotProve
) => Ok(*a
),
868 _
=> Err(TypeError
::Mismatch
),
873 impl<'tcx
> Relate
<'tcx
> for traits
::Goals
<'tcx
> {
874 fn relate
<R
: TypeRelation
<'tcx
>>(
876 a
: &traits
::Goals
<'tcx
>,
877 b
: &traits
::Goals
<'tcx
>,
878 ) -> RelateResult
<'tcx
, traits
::Goals
<'tcx
>> {
879 if a
.len() != b
.len() {
880 return Err(TypeError
::Mismatch
);
883 let tcx
= relation
.tcx();
884 let goals
= a
.iter().zip(b
.iter()).map(|(a
, b
)| relation
.relate(a
, b
));
885 Ok(tcx
.mk_goals(goals
)?
)
889 impl<'tcx
> Relate
<'tcx
> for traits
::Clause
<'tcx
> {
890 fn relate
<R
: TypeRelation
<'tcx
>>(
892 a
: &traits
::Clause
<'tcx
>,
893 b
: &traits
::Clause
<'tcx
>,
894 ) -> RelateResult
<'tcx
, traits
::Clause
<'tcx
>> {
895 use crate::traits
::Clause
::*;
897 (Implies(a_clause
), Implies(b_clause
)) => {
898 let clause
= relation
.relate(a_clause
, b_clause
)?
;
902 (ForAll(a_clause
), ForAll(b_clause
)) => {
903 let clause
= relation
.relate(a_clause
, b_clause
)?
;
907 _
=> Err(TypeError
::Mismatch
),
912 impl<'tcx
> Relate
<'tcx
> for traits
::Clauses
<'tcx
> {
913 fn relate
<R
: TypeRelation
<'tcx
>>(
915 a
: &traits
::Clauses
<'tcx
>,
916 b
: &traits
::Clauses
<'tcx
>,
917 ) -> RelateResult
<'tcx
, traits
::Clauses
<'tcx
>> {
918 if a
.len() != b
.len() {
919 return Err(TypeError
::Mismatch
);
922 let tcx
= relation
.tcx();
923 let clauses
= a
.iter().zip(b
.iter()).map(|(a
, b
)| relation
.relate(a
, b
));
924 Ok(tcx
.mk_clauses(clauses
)?
)
928 impl<'tcx
> Relate
<'tcx
> for traits
::ProgramClause
<'tcx
> {
929 fn relate
<R
: TypeRelation
<'tcx
>>(
931 a
: &traits
::ProgramClause
<'tcx
>,
932 b
: &traits
::ProgramClause
<'tcx
>,
933 ) -> RelateResult
<'tcx
, traits
::ProgramClause
<'tcx
>> {
934 Ok(traits
::ProgramClause
{
935 goal
: relation
.relate(&a
.goal
, &b
.goal
)?
,
936 hypotheses
: relation
.relate(&a
.hypotheses
, &b
.hypotheses
)?
,
937 category
: traits
::ProgramClauseCategory
::Other
,
942 impl<'tcx
> Relate
<'tcx
> for traits
::Environment
<'tcx
> {
943 fn relate
<R
: TypeRelation
<'tcx
>>(
945 a
: &traits
::Environment
<'tcx
>,
946 b
: &traits
::Environment
<'tcx
>,
947 ) -> RelateResult
<'tcx
, traits
::Environment
<'tcx
>> {
948 Ok(traits
::Environment { clauses: relation.relate(&a.clauses, &b.clauses)? }
)
952 impl<'tcx
, G
> Relate
<'tcx
> for traits
::InEnvironment
<'tcx
, G
>
956 fn relate
<R
: TypeRelation
<'tcx
>>(
958 a
: &traits
::InEnvironment
<'tcx
, G
>,
959 b
: &traits
::InEnvironment
<'tcx
, G
>,
960 ) -> RelateResult
<'tcx
, traits
::InEnvironment
<'tcx
, G
>> {
961 Ok(traits
::InEnvironment
{
962 environment
: relation
.relate(&a
.environment
, &b
.environment
)?
,
963 goal
: relation
.relate(&a
.goal
, &b
.goal
)?
,
968 ///////////////////////////////////////////////////////////////////////////
971 pub fn expected_found
<R
, T
>(relation
: &mut R
, a
: &T
, b
: &T
) -> ExpectedFound
<T
>
973 R
: TypeRelation
<'tcx
>,
976 expected_found_bool(relation
.a_is_expected(), a
, b
)
979 pub fn expected_found_bool
<T
>(a_is_expected
: bool
, a
: &T
, b
: &T
) -> ExpectedFound
<T
>
986 ExpectedFound { expected: a, found: b }
988 ExpectedFound { expected: b, found: a }