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::ty
::error
::{ExpectedFound, TypeError}
;
8 use crate::ty
::{self, Expr, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable}
;
9 use crate::ty
::{GenericArg, GenericArgKind, SubstsRef}
;
11 use rustc_hir
::def_id
::DefId
;
12 use rustc_target
::spec
::abi
;
15 pub type RelateResult
<'tcx
, T
> = Result
<T
, TypeError
<'tcx
>>;
17 #[derive(Clone, Debug)]
19 ExistentialRegionBound
, // relating an existential region bound
22 pub trait TypeRelation
<'tcx
>: Sized
{
23 fn tcx(&self) -> TyCtxt
<'tcx
>;
25 fn param_env(&self) -> ty
::ParamEnv
<'tcx
>;
27 /// Returns a static string we can use for printouts.
28 fn tag(&self) -> &'
static str;
30 /// Returns `true` if the value `a` is the "expected" type in the
31 /// relation. Just affects error messages.
32 fn a_is_expected(&self) -> bool
;
34 fn with_cause
<F
, R
>(&mut self, _cause
: Cause
, f
: F
) -> R
36 F
: FnOnce(&mut Self) -> R
,
41 /// Generic relation routine suitable for most anything.
42 fn relate
<T
: Relate
<'tcx
>>(&mut self, a
: T
, b
: T
) -> RelateResult
<'tcx
, T
> {
43 Relate
::relate(self, a
, b
)
46 /// Relate the two substitutions for the given item. The default
47 /// is to look up the variance for the item and proceed
49 fn relate_item_substs(
52 a_subst
: SubstsRef
<'tcx
>,
53 b_subst
: SubstsRef
<'tcx
>,
54 ) -> RelateResult
<'tcx
, SubstsRef
<'tcx
>> {
56 "relate_item_substs(item_def_id={:?}, a_subst={:?}, b_subst={:?})",
57 item_def_id
, a_subst
, b_subst
61 let opt_variances
= tcx
.variances_of(item_def_id
);
62 relate_substs_with_variances(self, item_def_id
, opt_variances
, a_subst
, b_subst
, true)
65 /// Switch variance for the purpose of relating `a` and `b`.
66 fn relate_with_variance
<T
: Relate
<'tcx
>>(
68 variance
: ty
::Variance
,
69 info
: ty
::VarianceDiagInfo
<'tcx
>,
72 ) -> RelateResult
<'tcx
, T
>;
74 // Overridable relations. You shouldn't typically call these
75 // directly, instead call `relate()`, which in turn calls
76 // these. This is both more uniform but also allows us to add
77 // additional hooks for other types in the future if needed
78 // without making older code, which called `relate`, obsolete.
80 fn tys(&mut self, a
: Ty
<'tcx
>, b
: Ty
<'tcx
>) -> RelateResult
<'tcx
, Ty
<'tcx
>>;
86 ) -> RelateResult
<'tcx
, ty
::Region
<'tcx
>>;
92 ) -> RelateResult
<'tcx
, ty
::Const
<'tcx
>>;
96 a
: ty
::Binder
<'tcx
, T
>,
97 b
: ty
::Binder
<'tcx
, T
>,
98 ) -> RelateResult
<'tcx
, ty
::Binder
<'tcx
, T
>>
103 pub trait Relate
<'tcx
>: TypeFoldable
<TyCtxt
<'tcx
>> + PartialEq
+ Copy
{
104 fn relate
<R
: TypeRelation
<'tcx
>>(
108 ) -> RelateResult
<'tcx
, Self>;
111 ///////////////////////////////////////////////////////////////////////////
114 pub fn relate_type_and_mut
<'tcx
, R
: TypeRelation
<'tcx
>>(
116 a
: ty
::TypeAndMut
<'tcx
>,
117 b
: ty
::TypeAndMut
<'tcx
>,
119 ) -> RelateResult
<'tcx
, ty
::TypeAndMut
<'tcx
>> {
120 debug
!("{}.mts({:?}, {:?})", relation
.tag(), a
, b
);
121 if a
.mutbl
!= b
.mutbl
{
122 Err(TypeError
::Mutability
)
125 let (variance
, info
) = match mutbl
{
126 hir
::Mutability
::Not
=> (ty
::Covariant
, ty
::VarianceDiagInfo
::None
),
127 hir
::Mutability
::Mut
=> {
128 (ty
::Invariant
, ty
::VarianceDiagInfo
::Invariant { ty: base_ty, param_index: 0 }
)
131 let ty
= relation
.relate_with_variance(variance
, info
, a
.ty
, b
.ty
)?
;
132 Ok(ty
::TypeAndMut { ty, mutbl }
)
137 pub fn relate_substs
<'tcx
, R
: TypeRelation
<'tcx
>>(
139 a_subst
: SubstsRef
<'tcx
>,
140 b_subst
: SubstsRef
<'tcx
>,
141 ) -> RelateResult
<'tcx
, SubstsRef
<'tcx
>> {
142 relation
.tcx().mk_substs_from_iter(iter
::zip(a_subst
, b_subst
).map(|(a
, b
)| {
143 relation
.relate_with_variance(ty
::Invariant
, ty
::VarianceDiagInfo
::default(), a
, b
)
147 pub fn relate_substs_with_variances
<'tcx
, R
: TypeRelation
<'tcx
>>(
150 variances
: &[ty
::Variance
],
151 a_subst
: SubstsRef
<'tcx
>,
152 b_subst
: SubstsRef
<'tcx
>,
153 fetch_ty_for_diag
: bool
,
154 ) -> RelateResult
<'tcx
, SubstsRef
<'tcx
>> {
155 let tcx
= relation
.tcx();
157 let mut cached_ty
= None
;
158 let params
= iter
::zip(a_subst
, b_subst
).enumerate().map(|(i
, (a
, b
))| {
159 let variance
= variances
[i
];
160 let variance_info
= if variance
== ty
::Invariant
&& fetch_ty_for_diag
{
161 let ty
= *cached_ty
.get_or_insert_with(|| tcx
.type_of(ty_def_id
).subst(tcx
, a_subst
));
162 ty
::VarianceDiagInfo
::Invariant { ty, param_index: i.try_into().unwrap() }
164 ty
::VarianceDiagInfo
::default()
166 relation
.relate_with_variance(variance
, variance_info
, a
, b
)
169 tcx
.mk_substs_from_iter(params
)
172 impl<'tcx
> Relate
<'tcx
> for ty
::FnSig
<'tcx
> {
173 fn relate
<R
: TypeRelation
<'tcx
>>(
177 ) -> RelateResult
<'tcx
, ty
::FnSig
<'tcx
>> {
178 let tcx
= relation
.tcx();
180 if a
.c_variadic
!= b
.c_variadic
{
181 return Err(TypeError
::VariadicMismatch(expected_found(
187 let unsafety
= relation
.relate(a
.unsafety
, b
.unsafety
)?
;
188 let abi
= relation
.relate(a
.abi
, b
.abi
)?
;
190 if a
.inputs().len() != b
.inputs().len() {
191 return Err(TypeError
::ArgCount
);
194 let inputs_and_output
= iter
::zip(a
.inputs(), b
.inputs())
195 .map(|(&a
, &b
)| ((a
, b
), false))
196 .chain(iter
::once(((a
.output(), b
.output()), true)))
197 .map(|((a
, b
), is_output
)| {
199 relation
.relate(a
, b
)
201 relation
.relate_with_variance(
203 ty
::VarianceDiagInfo
::default(),
210 .map(|(i
, r
)| match r
{
211 Err(TypeError
::Sorts(exp_found
) | TypeError
::ArgumentSorts(exp_found
, _
)) => {
212 Err(TypeError
::ArgumentSorts(exp_found
, i
))
214 Err(TypeError
::Mutability
| TypeError
::ArgumentMutability(_
)) => {
215 Err(TypeError
::ArgumentMutability(i
))
220 inputs_and_output
: tcx
.mk_type_list_from_iter(inputs_and_output
)?
,
221 c_variadic
: a
.c_variadic
,
228 impl<'tcx
> Relate
<'tcx
> for ty
::BoundConstness
{
229 fn relate
<R
: TypeRelation
<'tcx
>>(
231 a
: ty
::BoundConstness
,
232 b
: ty
::BoundConstness
,
233 ) -> RelateResult
<'tcx
, ty
::BoundConstness
> {
235 Err(TypeError
::ConstnessMismatch(expected_found(relation
, a
, b
)))
242 impl<'tcx
> Relate
<'tcx
> for hir
::Unsafety
{
243 fn relate
<R
: TypeRelation
<'tcx
>>(
247 ) -> RelateResult
<'tcx
, hir
::Unsafety
> {
249 Err(TypeError
::UnsafetyMismatch(expected_found(relation
, a
, b
)))
256 impl<'tcx
> Relate
<'tcx
> for abi
::Abi
{
257 fn relate
<R
: TypeRelation
<'tcx
>>(
261 ) -> RelateResult
<'tcx
, abi
::Abi
> {
262 if a
== b { Ok(a) }
else { Err(TypeError::AbiMismatch(expected_found(relation, a, b))) }
266 impl<'tcx
> Relate
<'tcx
> for ty
::AliasTy
<'tcx
> {
267 fn relate
<R
: TypeRelation
<'tcx
>>(
269 a
: ty
::AliasTy
<'tcx
>,
270 b
: ty
::AliasTy
<'tcx
>,
271 ) -> RelateResult
<'tcx
, ty
::AliasTy
<'tcx
>> {
272 if a
.def_id
!= b
.def_id
{
273 Err(TypeError
::ProjectionMismatched(expected_found(relation
, a
.def_id
, b
.def_id
)))
275 let substs
= relation
.relate(a
.substs
, b
.substs
)?
;
276 Ok(relation
.tcx().mk_alias_ty(a
.def_id
, substs
))
281 impl<'tcx
> Relate
<'tcx
> for ty
::ExistentialProjection
<'tcx
> {
282 fn relate
<R
: TypeRelation
<'tcx
>>(
284 a
: ty
::ExistentialProjection
<'tcx
>,
285 b
: ty
::ExistentialProjection
<'tcx
>,
286 ) -> RelateResult
<'tcx
, ty
::ExistentialProjection
<'tcx
>> {
287 if a
.def_id
!= b
.def_id
{
288 Err(TypeError
::ProjectionMismatched(expected_found(relation
, a
.def_id
, b
.def_id
)))
290 let term
= relation
.relate_with_variance(
292 ty
::VarianceDiagInfo
::default(),
296 let substs
= relation
.relate_with_variance(
298 ty
::VarianceDiagInfo
::default(),
302 Ok(ty
::ExistentialProjection { def_id: a.def_id, substs, term }
)
307 impl<'tcx
> Relate
<'tcx
> for ty
::TraitRef
<'tcx
> {
308 fn relate
<R
: TypeRelation
<'tcx
>>(
310 a
: ty
::TraitRef
<'tcx
>,
311 b
: ty
::TraitRef
<'tcx
>,
312 ) -> RelateResult
<'tcx
, ty
::TraitRef
<'tcx
>> {
313 // Different traits cannot be related.
314 if a
.def_id
!= b
.def_id
{
315 Err(TypeError
::Traits(expected_found(relation
, a
.def_id
, b
.def_id
)))
317 let substs
= relate_substs(relation
, a
.substs
, b
.substs
)?
;
318 Ok(ty
::TraitRef
::new(relation
.tcx(), a
.def_id
, substs
))
323 impl<'tcx
> Relate
<'tcx
> for ty
::ExistentialTraitRef
<'tcx
> {
324 fn relate
<R
: TypeRelation
<'tcx
>>(
326 a
: ty
::ExistentialTraitRef
<'tcx
>,
327 b
: ty
::ExistentialTraitRef
<'tcx
>,
328 ) -> RelateResult
<'tcx
, ty
::ExistentialTraitRef
<'tcx
>> {
329 // Different traits cannot be related.
330 if a
.def_id
!= b
.def_id
{
331 Err(TypeError
::Traits(expected_found(relation
, a
.def_id
, b
.def_id
)))
333 let substs
= relate_substs(relation
, a
.substs
, b
.substs
)?
;
334 Ok(ty
::ExistentialTraitRef { def_id: a.def_id, substs }
)
339 #[derive(PartialEq, Copy, Debug, Clone, TypeFoldable, TypeVisitable)]
340 struct GeneratorWitness
<'tcx
>(&'tcx ty
::List
<Ty
<'tcx
>>);
342 impl<'tcx
> Relate
<'tcx
> for GeneratorWitness
<'tcx
> {
343 fn relate
<R
: TypeRelation
<'tcx
>>(
345 a
: GeneratorWitness
<'tcx
>,
346 b
: GeneratorWitness
<'tcx
>,
347 ) -> RelateResult
<'tcx
, GeneratorWitness
<'tcx
>> {
348 assert_eq
!(a
.0.len(), b
.0.len());
349 let tcx
= relation
.tcx();
351 tcx
.mk_type_list_from_iter(iter
::zip(a
.0, b
.0).map(|(a
, b
)| relation
.relate(a
, b
)))?
;
352 Ok(GeneratorWitness(types
))
356 impl<'tcx
> Relate
<'tcx
> for ImplSubject
<'tcx
> {
358 fn relate
<R
: TypeRelation
<'tcx
>>(
360 a
: ImplSubject
<'tcx
>,
361 b
: ImplSubject
<'tcx
>,
362 ) -> RelateResult
<'tcx
, ImplSubject
<'tcx
>> {
364 (ImplSubject
::Trait(trait_ref_a
), ImplSubject
::Trait(trait_ref_b
)) => {
365 let trait_ref
= ty
::TraitRef
::relate(relation
, trait_ref_a
, trait_ref_b
)?
;
366 Ok(ImplSubject
::Trait(trait_ref
))
368 (ImplSubject
::Inherent(ty_a
), ImplSubject
::Inherent(ty_b
)) => {
369 let ty
= Ty
::relate(relation
, ty_a
, ty_b
)?
;
370 Ok(ImplSubject
::Inherent(ty
))
372 (ImplSubject
::Trait(_
), ImplSubject
::Inherent(_
))
373 | (ImplSubject
::Inherent(_
), ImplSubject
::Trait(_
)) => {
374 bug
!("can not relate TraitRef and Ty");
380 impl<'tcx
> Relate
<'tcx
> for Ty
<'tcx
> {
382 fn relate
<R
: TypeRelation
<'tcx
>>(
386 ) -> RelateResult
<'tcx
, Ty
<'tcx
>> {
391 /// Relates `a` and `b` structurally, calling the relation for all nested values.
392 /// Any semantic equality, e.g. of projections, and inference variables have to be
393 /// handled by the caller.
394 pub fn structurally_relate_tys
<'tcx
, R
: TypeRelation
<'tcx
>>(
398 ) -> RelateResult
<'tcx
, Ty
<'tcx
>> {
399 let tcx
= relation
.tcx();
400 debug
!("structurally_relate_tys: a={:?} b={:?}", a
, b
);
401 match (a
.kind(), b
.kind()) {
402 (&ty
::Infer(_
), _
) | (_
, &ty
::Infer(_
)) => {
403 // The caller should handle these cases!
404 bug
!("var types encountered in structurally_relate_tys")
407 (ty
::Bound(..), _
) | (_
, ty
::Bound(..)) => {
408 bug
!("bound types encountered in structurally_relate_tys")
411 (&ty
::Error(guar
), _
) | (_
, &ty
::Error(guar
)) => Ok(tcx
.ty_error(guar
)),
425 (ty
::Param(a_p
), ty
::Param(b_p
)) if a_p
.index
== b_p
.index
=> Ok(a
),
427 (ty
::Placeholder(p1
), ty
::Placeholder(p2
)) if p1
== p2
=> Ok(a
),
429 (&ty
::Adt(a_def
, a_substs
), &ty
::Adt(b_def
, b_substs
)) if a_def
== b_def
=> {
430 let substs
= relation
.relate_item_substs(a_def
.did(), a_substs
, b_substs
)?
;
431 Ok(tcx
.mk_adt(a_def
, substs
))
434 (&ty
::Foreign(a_id
), &ty
::Foreign(b_id
)) if a_id
== b_id
=> Ok(tcx
.mk_foreign(a_id
)),
436 (&ty
::Dynamic(a_obj
, a_region
, a_repr
), &ty
::Dynamic(b_obj
, b_region
, b_repr
))
437 if a_repr
== b_repr
=>
439 let region_bound
= relation
.with_cause(Cause
::ExistentialRegionBound
, |relation
| {
440 relation
.relate(a_region
, b_region
)
442 Ok(tcx
.mk_dynamic(relation
.relate(a_obj
, b_obj
)?
, region_bound
, a_repr
))
445 (&ty
::Generator(a_id
, a_substs
, movability
), &ty
::Generator(b_id
, b_substs
, _
))
448 // All Generator types with the same id represent
449 // the (anonymous) type of the same generator expression. So
450 // all of their regions should be equated.
451 let substs
= relation
.relate(a_substs
, b_substs
)?
;
452 Ok(tcx
.mk_generator(a_id
, substs
, movability
))
455 (&ty
::GeneratorWitness(a_types
), &ty
::GeneratorWitness(b_types
)) => {
456 // Wrap our types with a temporary GeneratorWitness struct
457 // inside the binder so we can related them
458 let a_types
= a_types
.map_bound(GeneratorWitness
);
459 let b_types
= b_types
.map_bound(GeneratorWitness
);
460 // Then remove the GeneratorWitness for the result
461 let types
= relation
.relate(a_types
, b_types
)?
.map_bound(|witness
| witness
.0);
462 Ok(tcx
.mk_generator_witness(types
))
465 (&ty
::GeneratorWitnessMIR(a_id
, a_substs
), &ty
::GeneratorWitnessMIR(b_id
, b_substs
))
468 // All GeneratorWitness types with the same id represent
469 // the (anonymous) type of the same generator expression. So
470 // all of their regions should be equated.
471 let substs
= relation
.relate(a_substs
, b_substs
)?
;
472 Ok(tcx
.mk_generator_witness_mir(a_id
, substs
))
475 (&ty
::Closure(a_id
, a_substs
), &ty
::Closure(b_id
, b_substs
)) if a_id
== b_id
=> {
476 // All Closure types with the same id represent
477 // the (anonymous) type of the same closure expression. So
478 // all of their regions should be equated.
479 let substs
= relation
.relate(a_substs
, b_substs
)?
;
480 Ok(tcx
.mk_closure(a_id
, &substs
))
483 (&ty
::RawPtr(a_mt
), &ty
::RawPtr(b_mt
)) => {
484 let mt
= relate_type_and_mut(relation
, a_mt
, b_mt
, a
)?
;
488 (&ty
::Ref(a_r
, a_ty
, a_mutbl
), &ty
::Ref(b_r
, b_ty
, b_mutbl
)) => {
489 let r
= relation
.relate(a_r
, b_r
)?
;
490 let a_mt
= ty
::TypeAndMut { ty: a_ty, mutbl: a_mutbl }
;
491 let b_mt
= ty
::TypeAndMut { ty: b_ty, mutbl: b_mutbl }
;
492 let mt
= relate_type_and_mut(relation
, a_mt
, b_mt
, a
)?
;
493 Ok(tcx
.mk_ref(r
, mt
))
496 (&ty
::Array(a_t
, sz_a
), &ty
::Array(b_t
, sz_b
)) => {
497 let t
= relation
.relate(a_t
, b_t
)?
;
498 match relation
.relate(sz_a
, sz_b
) {
499 Ok(sz
) => Ok(tcx
.mk_array_with_const_len(t
, sz
)),
501 // Check whether the lengths are both concrete/known values,
502 // but are unequal, for better diagnostics.
504 // It might seem dubious to eagerly evaluate these constants here,
505 // we however cannot end up with errors in `Relate` during both
506 // `type_of` and `predicates_of`. This means that evaluating the
507 // constants should not cause cycle errors here.
508 let sz_a
= sz_a
.try_eval_target_usize(tcx
, relation
.param_env());
509 let sz_b
= sz_b
.try_eval_target_usize(tcx
, relation
.param_env());
511 (Some(sz_a_val
), Some(sz_b_val
)) if sz_a_val
!= sz_b_val
=> Err(
512 TypeError
::FixedArraySize(expected_found(relation
, sz_a_val
, sz_b_val
)),
520 (&ty
::Slice(a_t
), &ty
::Slice(b_t
)) => {
521 let t
= relation
.relate(a_t
, b_t
)?
;
525 (&ty
::Tuple(as_
), &ty
::Tuple(bs
)) => {
526 if as_
.len() == bs
.len() {
527 Ok(tcx
.mk_tup_from_iter(iter
::zip(as_
, bs
).map(|(a
, b
)| relation
.relate(a
, b
)))?
)
528 } else if !(as_
.is_empty() || bs
.is_empty()) {
529 Err(TypeError
::TupleSize(expected_found(relation
, as_
.len(), bs
.len())))
531 Err(TypeError
::Sorts(expected_found(relation
, a
, b
)))
535 (&ty
::FnDef(a_def_id
, a_substs
), &ty
::FnDef(b_def_id
, b_substs
))
536 if a_def_id
== b_def_id
=>
538 let substs
= relation
.relate_item_substs(a_def_id
, a_substs
, b_substs
)?
;
539 Ok(tcx
.mk_fn_def(a_def_id
, substs
))
542 (&ty
::FnPtr(a_fty
), &ty
::FnPtr(b_fty
)) => {
543 let fty
= relation
.relate(a_fty
, b_fty
)?
;
544 Ok(tcx
.mk_fn_ptr(fty
))
547 // these two are already handled downstream in case of lazy normalization
548 (&ty
::Alias(ty
::Projection
, a_data
), &ty
::Alias(ty
::Projection
, b_data
)) => {
549 let projection_ty
= relation
.relate(a_data
, b_data
)?
;
550 Ok(tcx
.mk_projection(projection_ty
.def_id
, projection_ty
.substs
))
553 (&ty
::Alias(ty
::Inherent
, a_data
), &ty
::Alias(ty
::Inherent
, b_data
)) => {
554 let alias_ty
= relation
.relate(a_data
, b_data
)?
;
555 Ok(tcx
.mk_alias(ty
::Inherent
, tcx
.mk_alias_ty(alias_ty
.def_id
, alias_ty
.substs
)))
559 &ty
::Alias(ty
::Opaque
, ty
::AliasTy { def_id: a_def_id, substs: a_substs, .. }
),
560 &ty
::Alias(ty
::Opaque
, ty
::AliasTy { def_id: b_def_id, substs: b_substs, .. }
),
561 ) if a_def_id
== b_def_id
=> {
562 let opt_variances
= tcx
.variances_of(a_def_id
);
563 let substs
= relate_substs_with_variances(
569 false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
571 Ok(tcx
.mk_opaque(a_def_id
, substs
))
574 _
=> Err(TypeError
::Sorts(expected_found(relation
, a
, b
))),
578 /// Relates `a` and `b` structurally, calling the relation for all nested values.
579 /// Any semantic equality, e.g. of unevaluated consts, and inference variables have
580 /// to be handled by the caller.
582 /// FIXME: This is not totally structual, which probably should be fixed.
583 /// See the HACKs below.
584 pub fn structurally_relate_consts
<'tcx
, R
: TypeRelation
<'tcx
>>(
586 mut a
: ty
::Const
<'tcx
>,
587 mut b
: ty
::Const
<'tcx
>,
588 ) -> RelateResult
<'tcx
, ty
::Const
<'tcx
>> {
589 debug
!("{}.structurally_relate_consts(a = {:?}, b = {:?})", relation
.tag(), a
, b
);
590 let tcx
= relation
.tcx();
592 // HACK(const_generics): We still need to eagerly evaluate consts when
593 // relating them because during `normalize_param_env_or_error`,
594 // we may relate an evaluated constant in a obligation against
595 // an unnormalized (i.e. unevaluated) const in the param-env.
596 // FIXME(generic_const_exprs): Once we always lazily unify unevaluated constants
597 // these `eval` calls can be removed.
598 if !tcx
.features().generic_const_exprs
{
599 a
= a
.eval(tcx
, relation
.param_env());
600 b
= b
.eval(tcx
, relation
.param_env());
603 if tcx
.features().generic_const_exprs
{
604 a
= tcx
.expand_abstract_consts(a
);
605 b
= tcx
.expand_abstract_consts(b
);
608 debug
!("{}.structurally_relate_consts(normed_a = {:?}, normed_b = {:?})", relation
.tag(), a
, b
);
610 // Currently, the values that can be unified are primitive types,
611 // and those that derive both `PartialEq` and `Eq`, corresponding
612 // to structural-match types.
613 let is_match
= match (a
.kind(), b
.kind()) {
614 (ty
::ConstKind
::Infer(_
), _
) | (_
, ty
::ConstKind
::Infer(_
)) => {
615 // The caller should handle these cases!
616 bug
!("var types encountered in structurally_relate_consts: {:?} {:?}", a
, b
)
619 (ty
::ConstKind
::Error(_
), _
) => return Ok(a
),
620 (_
, ty
::ConstKind
::Error(_
)) => return Ok(b
),
622 (ty
::ConstKind
::Param(a_p
), ty
::ConstKind
::Param(b_p
)) => a_p
.index
== b_p
.index
,
623 (ty
::ConstKind
::Placeholder(p1
), ty
::ConstKind
::Placeholder(p2
)) => p1
== p2
,
624 (ty
::ConstKind
::Value(a_val
), ty
::ConstKind
::Value(b_val
)) => a_val
== b_val
,
626 // While this is slightly incorrect, it shouldn't matter for `min_const_generics`
627 // and is the better alternative to waiting until `generic_const_exprs` can
629 (ty
::ConstKind
::Unevaluated(au
), ty
::ConstKind
::Unevaluated(bu
)) if au
.def
== bu
.def
=> {
630 assert_eq
!(a
.ty(), b
.ty());
631 let substs
= relation
.relate_with_variance(
632 ty
::Variance
::Invariant
,
633 ty
::VarianceDiagInfo
::default(),
637 return Ok(tcx
.mk_const(ty
::UnevaluatedConst { def: au.def, substs }
, a
.ty()));
639 // Before calling relate on exprs, it is necessary to ensure that the nested consts
640 // have identical types.
641 (ty
::ConstKind
::Expr(ae
), ty
::ConstKind
::Expr(be
)) => {
644 // FIXME(generic_const_exprs): is it possible to relate two consts which are not identical
645 // exprs? Should we care about that?
646 // FIXME(generic_const_exprs): relating the `ty()`s is a little weird since it is supposed to
647 // ICE If they mismatch. Unfortunately `ConstKind::Expr` is a little special and can be thought
648 // of as being generic over the argument types, however this is implicit so these types don't get
649 // related when we relate the substs of the item this const arg is for.
650 let expr
= match (ae
, be
) {
651 (Expr
::Binop(a_op
, al
, ar
), Expr
::Binop(b_op
, bl
, br
)) if a_op
== b_op
=> {
652 r
.relate(al
.ty(), bl
.ty())?
;
653 r
.relate(ar
.ty(), br
.ty())?
;
654 Expr
::Binop(a_op
, r
.consts(al
, bl
)?
, r
.consts(ar
, br
)?
)
656 (Expr
::UnOp(a_op
, av
), Expr
::UnOp(b_op
, bv
)) if a_op
== b_op
=> {
657 r
.relate(av
.ty(), bv
.ty())?
;
658 Expr
::UnOp(a_op
, r
.consts(av
, bv
)?
)
660 (Expr
::Cast(ak
, av
, at
), Expr
::Cast(bk
, bv
, bt
)) if ak
== bk
=> {
661 r
.relate(av
.ty(), bv
.ty())?
;
662 Expr
::Cast(ak
, r
.consts(av
, bv
)?
, r
.tys(at
, bt
)?
)
664 (Expr
::FunctionCall(af
, aa
), Expr
::FunctionCall(bf
, ba
))
665 if aa
.len() == ba
.len() =>
667 r
.relate(af
.ty(), bf
.ty())?
;
668 let func
= r
.consts(af
, bf
)?
;
669 let mut related_args
= Vec
::with_capacity(aa
.len());
670 for (a_arg
, b_arg
) in aa
.iter().zip(ba
.iter()) {
671 related_args
.push(r
.consts(a_arg
, b_arg
)?
);
673 let related_args
= tcx
.mk_const_list(&related_args
);
674 Expr
::FunctionCall(func
, related_args
)
676 _
=> return Err(TypeError
::ConstMismatch(expected_found(r
, a
, b
))),
678 let kind
= ty
::ConstKind
::Expr(expr
);
679 return Ok(tcx
.mk_const(kind
, a
.ty()));
683 if is_match { Ok(a) }
else { Err(TypeError::ConstMismatch(expected_found(relation, a, b))) }
686 impl<'tcx
> Relate
<'tcx
> for &'tcx ty
::List
<ty
::PolyExistentialPredicate
<'tcx
>> {
687 fn relate
<R
: TypeRelation
<'tcx
>>(
691 ) -> RelateResult
<'tcx
, Self> {
692 let tcx
= relation
.tcx();
694 // FIXME: this is wasteful, but want to do a perf run to see how slow it is.
695 // We need to perform this deduplication as we sometimes generate duplicate projections
697 let mut a_v
: Vec
<_
> = a
.into_iter().collect();
698 let mut b_v
: Vec
<_
> = b
.into_iter().collect();
699 // `skip_binder` here is okay because `stable_cmp` doesn't look at binders
700 a_v
.sort_by(|a
, b
| a
.skip_binder().stable_cmp(tcx
, &b
.skip_binder()));
702 b_v
.sort_by(|a
, b
| a
.skip_binder().stable_cmp(tcx
, &b
.skip_binder()));
704 if a_v
.len() != b_v
.len() {
705 return Err(TypeError
::ExistentialMismatch(expected_found(relation
, a
, b
)));
708 let v
= iter
::zip(a_v
, b_v
).map(|(ep_a
, ep_b
)| {
709 use crate::ty
::ExistentialPredicate
::*;
710 match (ep_a
.skip_binder(), ep_b
.skip_binder()) {
711 (Trait(a
), Trait(b
)) => Ok(ep_a
712 .rebind(Trait(relation
.relate(ep_a
.rebind(a
), ep_b
.rebind(b
))?
.skip_binder()))),
713 (Projection(a
), Projection(b
)) => Ok(ep_a
.rebind(Projection(
714 relation
.relate(ep_a
.rebind(a
), ep_b
.rebind(b
))?
.skip_binder(),
716 (AutoTrait(a
), AutoTrait(b
)) if a
== b
=> Ok(ep_a
.rebind(AutoTrait(a
))),
717 _
=> Err(TypeError
::ExistentialMismatch(expected_found(relation
, a
, b
))),
720 tcx
.mk_poly_existential_predicates_from_iter(v
)
724 impl<'tcx
> Relate
<'tcx
> for ty
::ClosureSubsts
<'tcx
> {
725 fn relate
<R
: TypeRelation
<'tcx
>>(
727 a
: ty
::ClosureSubsts
<'tcx
>,
728 b
: ty
::ClosureSubsts
<'tcx
>,
729 ) -> RelateResult
<'tcx
, ty
::ClosureSubsts
<'tcx
>> {
730 let substs
= relate_substs(relation
, a
.substs
, b
.substs
)?
;
731 Ok(ty
::ClosureSubsts { substs }
)
735 impl<'tcx
> Relate
<'tcx
> for ty
::GeneratorSubsts
<'tcx
> {
736 fn relate
<R
: TypeRelation
<'tcx
>>(
738 a
: ty
::GeneratorSubsts
<'tcx
>,
739 b
: ty
::GeneratorSubsts
<'tcx
>,
740 ) -> RelateResult
<'tcx
, ty
::GeneratorSubsts
<'tcx
>> {
741 let substs
= relate_substs(relation
, a
.substs
, b
.substs
)?
;
742 Ok(ty
::GeneratorSubsts { substs }
)
746 impl<'tcx
> Relate
<'tcx
> for SubstsRef
<'tcx
> {
747 fn relate
<R
: TypeRelation
<'tcx
>>(
751 ) -> RelateResult
<'tcx
, SubstsRef
<'tcx
>> {
752 relate_substs(relation
, a
, b
)
756 impl<'tcx
> Relate
<'tcx
> for ty
::Region
<'tcx
> {
757 fn relate
<R
: TypeRelation
<'tcx
>>(
761 ) -> RelateResult
<'tcx
, ty
::Region
<'tcx
>> {
762 relation
.regions(a
, b
)
766 impl<'tcx
> Relate
<'tcx
> for ty
::Const
<'tcx
> {
767 fn relate
<R
: TypeRelation
<'tcx
>>(
771 ) -> RelateResult
<'tcx
, ty
::Const
<'tcx
>> {
772 relation
.consts(a
, b
)
776 impl<'tcx
, T
: Relate
<'tcx
>> Relate
<'tcx
> for ty
::Binder
<'tcx
, T
> {
777 fn relate
<R
: TypeRelation
<'tcx
>>(
779 a
: ty
::Binder
<'tcx
, T
>,
780 b
: ty
::Binder
<'tcx
, T
>,
781 ) -> RelateResult
<'tcx
, ty
::Binder
<'tcx
, T
>> {
782 relation
.binders(a
, b
)
786 impl<'tcx
> Relate
<'tcx
> for GenericArg
<'tcx
> {
787 fn relate
<R
: TypeRelation
<'tcx
>>(
791 ) -> RelateResult
<'tcx
, GenericArg
<'tcx
>> {
792 match (a
.unpack(), b
.unpack()) {
793 (GenericArgKind
::Lifetime(a_lt
), GenericArgKind
::Lifetime(b_lt
)) => {
794 Ok(relation
.relate(a_lt
, b_lt
)?
.into())
796 (GenericArgKind
::Type(a_ty
), GenericArgKind
::Type(b_ty
)) => {
797 Ok(relation
.relate(a_ty
, b_ty
)?
.into())
799 (GenericArgKind
::Const(a_ct
), GenericArgKind
::Const(b_ct
)) => {
800 Ok(relation
.relate(a_ct
, b_ct
)?
.into())
802 (GenericArgKind
::Lifetime(unpacked
), x
) => {
803 bug
!("impossible case reached: can't relate: {:?} with {:?}", unpacked
, x
)
805 (GenericArgKind
::Type(unpacked
), x
) => {
806 bug
!("impossible case reached: can't relate: {:?} with {:?}", unpacked
, x
)
808 (GenericArgKind
::Const(unpacked
), x
) => {
809 bug
!("impossible case reached: can't relate: {:?} with {:?}", unpacked
, x
)
815 impl<'tcx
> Relate
<'tcx
> for ty
::ImplPolarity
{
816 fn relate
<R
: TypeRelation
<'tcx
>>(
820 ) -> RelateResult
<'tcx
, ty
::ImplPolarity
> {
822 Err(TypeError
::PolarityMismatch(expected_found(relation
, a
, b
)))
829 impl<'tcx
> Relate
<'tcx
> for ty
::TraitPredicate
<'tcx
> {
830 fn relate
<R
: TypeRelation
<'tcx
>>(
832 a
: ty
::TraitPredicate
<'tcx
>,
833 b
: ty
::TraitPredicate
<'tcx
>,
834 ) -> RelateResult
<'tcx
, ty
::TraitPredicate
<'tcx
>> {
835 Ok(ty
::TraitPredicate
{
836 trait_ref
: relation
.relate(a
.trait_ref
, b
.trait_ref
)?
,
837 constness
: relation
.relate(a
.constness
, b
.constness
)?
,
838 polarity
: relation
.relate(a
.polarity
, b
.polarity
)?
,
843 impl<'tcx
> Relate
<'tcx
> for Term
<'tcx
> {
844 fn relate
<R
: TypeRelation
<'tcx
>>(
848 ) -> RelateResult
<'tcx
, Self> {
849 Ok(match (a
.unpack(), b
.unpack()) {
850 (TermKind
::Ty(a
), TermKind
::Ty(b
)) => relation
.relate(a
, b
)?
.into(),
851 (TermKind
::Const(a
), TermKind
::Const(b
)) => relation
.relate(a
, b
)?
.into(),
852 _
=> return Err(TypeError
::Mismatch
),
857 impl<'tcx
> Relate
<'tcx
> for ty
::ProjectionPredicate
<'tcx
> {
858 fn relate
<R
: TypeRelation
<'tcx
>>(
860 a
: ty
::ProjectionPredicate
<'tcx
>,
861 b
: ty
::ProjectionPredicate
<'tcx
>,
862 ) -> RelateResult
<'tcx
, ty
::ProjectionPredicate
<'tcx
>> {
863 Ok(ty
::ProjectionPredicate
{
864 projection_ty
: relation
.relate(a
.projection_ty
, b
.projection_ty
)?
,
865 term
: relation
.relate(a
.term
, b
.term
)?
,
870 ///////////////////////////////////////////////////////////////////////////
873 pub fn expected_found
<'tcx
, R
, T
>(relation
: &mut R
, a
: T
, b
: T
) -> ExpectedFound
<T
>
875 R
: TypeRelation
<'tcx
>,
877 ExpectedFound
::new(relation
.a_is_expected(), a
, b
)