1use std::iter;
2
3use derive_where::derive_where;
4use rustc_ast_ir::Mutability;
5use tracing::{instrument, trace};
6
7use crate::error::{ExpectedFound, TypeError};
8use crate::fold::TypeFoldable;
9use crate::inherent::*;
10use crate::{self as ty, Interner, Region};
11
12pub mod combine;
13pub mod solver_relating;
14
15pub type RelateResult<I, T> = Result<T, TypeError<I>>;
16
17#[automatically_derived]
impl<I: Interner> ::core::default::Default for VarianceDiagInfo<I> where
I: Interner {
fn default() -> Self { VarianceDiagInfo::None }
}#[derive_where(Clone, Copy, PartialEq, Debug, Default; I: Interner)]
25pub enum VarianceDiagInfo<I: Interner> {
26 #[derive_where(default)]
29 None,
30 Invariant {
33 ty: I::Ty,
36 param_index: u32,
39 },
40}
41
42impl<I: Interner> Eq for VarianceDiagInfo<I> {}
43
44impl<I: Interner> VarianceDiagInfo<I> {
45 pub fn xform(self, other: VarianceDiagInfo<I>) -> VarianceDiagInfo<I> {
48 match self {
50 VarianceDiagInfo::None => other,
51 VarianceDiagInfo::Invariant { .. } => self,
52 }
53 }
54}
55
56pub trait TypeRelation<I: Interner>: Sized {
57 fn cx(&self) -> I;
58
59 fn relate<T: Relate<I>>(&mut self, a: T, b: T) -> RelateResult<I, T> {
61 Relate::relate(self, a, b)
62 }
63
64 fn relate_ty_args(
65 &mut self,
66 a_ty: I::Ty,
67 b_ty: I::Ty,
68 ty_def_id: I::DefId,
69 a_arg: I::GenericArgs,
70 b_arg: I::GenericArgs,
71 mk: impl FnOnce(I::GenericArgs) -> I::Ty,
72 ) -> RelateResult<I, I::Ty>;
73
74 fn relate_with_variance<T: Relate<I>>(
76 &mut self,
77 variance: ty::Variance,
78 info: VarianceDiagInfo<I>,
79 a: T,
80 b: T,
81 ) -> RelateResult<I, T>;
82
83 fn tys(&mut self, a: I::Ty, b: I::Ty) -> RelateResult<I, I::Ty>;
90
91 fn regions(&mut self, a: Region<I>, b: Region<I>) -> RelateResult<I, Region<I>>;
92
93 fn consts(&mut self, a: I::Const, b: I::Const) -> RelateResult<I, I::Const>;
94
95 fn binders<T>(
96 &mut self,
97 a: ty::Binder<I, T>,
98 b: ty::Binder<I, T>,
99 ) -> RelateResult<I, ty::Binder<I, T>>
100 where
101 T: Relate<I>;
102}
103
104pub trait Relate<I: Interner>: TypeFoldable<I> + PartialEq + Copy {
105 fn relate<R: TypeRelation<I>>(relation: &mut R, a: Self, b: Self) -> RelateResult<I, Self>;
106}
107
108#[inline]
112pub fn relate_args_invariantly<I: Interner, R: TypeRelation<I>>(
113 relation: &mut R,
114 a_arg: I::GenericArgs,
115 b_arg: I::GenericArgs,
116) -> RelateResult<I, I::GenericArgs> {
117 relation.cx().mk_args_from_iter(iter::zip(a_arg.iter(), b_arg.iter()).map(|(a, b)| {
118 relation.relate_with_variance(ty::Invariant, VarianceDiagInfo::default(), a, b)
119 }))
120}
121
122pub fn relate_args_with_variances<I: Interner, R: TypeRelation<I>>(
123 relation: &mut R,
124 variances: I::VariancesOf,
125 a_args: I::GenericArgs,
126 b_args: I::GenericArgs,
127) -> RelateResult<I, I::GenericArgs> {
128 let cx = relation.cx();
129 let args = iter::zip(a_args.iter(), b_args.iter()).enumerate().map(|(i, (a, b))| {
130 let variance = variances.get(i).unwrap();
131 relation.relate_with_variance(variance, VarianceDiagInfo::None, a, b)
132 });
133 cx.mk_args_from_iter(args)
135}
136
137impl<I: Interner> Relate<I> for ty::FnSig<I> {
138 fn relate<R: TypeRelation<I>>(
139 relation: &mut R,
140 a: ty::FnSig<I>,
141 b: ty::FnSig<I>,
142 ) -> RelateResult<I, ty::FnSig<I>> {
143 let cx = relation.cx();
144
145 if a.c_variadic() != b.c_variadic() {
146 return Err(TypeError::VariadicMismatch(ExpectedFound::new(
147 a.c_variadic(),
148 b.c_variadic(),
149 )));
150 }
151
152 if a.safety() != b.safety() {
153 return Err(TypeError::SafetyMismatch(ExpectedFound::new(a.safety(), b.safety())));
154 }
155
156 if a.abi() != b.abi() {
157 return Err(TypeError::AbiMismatch(ExpectedFound::new(a.abi(), b.abi())));
158 };
159
160 if a.splatted() != b.splatted() {
161 return Err(TypeError::SplatMismatch(ExpectedFound::new(a.splatted(), b.splatted())));
162 }
163
164 let a_inputs = a.inputs();
165 let b_inputs = b.inputs();
166 if a_inputs.len() != b_inputs.len() {
167 return Err(TypeError::ArgCount);
168 }
169
170 let inputs_and_output = iter::zip(a_inputs.iter(), b_inputs.iter())
171 .map(|(a, b)| ((a, b), 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(
178 ty::Contravariant,
179 VarianceDiagInfo::default(),
180 a,
181 b,
182 )
183 }
184 })
185 .enumerate()
186 .map(|(i, r)| match r {
187 Err(TypeError::Sorts(exp_found) | TypeError::ArgumentSorts(exp_found, _)) => {
188 Err(TypeError::ArgumentSorts(exp_found, i))
189 }
190 Err(TypeError::Mutability | TypeError::ArgumentMutability(_)) => {
191 Err(TypeError::ArgumentMutability(i))
192 }
193 r => r,
194 });
195 Ok(ty::FnSig {
196 inputs_and_output: cx.mk_type_list_from_iter(inputs_and_output)?,
197 fn_sig_kind: a.fn_sig_kind,
198 })
199 }
200}
201
202impl<I: Interner> Relate<I> for ty::AliasTy<I> {
203 fn relate<R: TypeRelation<I>>(
204 relation: &mut R,
205 a: ty::AliasTy<I>,
206 b: ty::AliasTy<I>,
207 ) -> RelateResult<I, ty::AliasTy<I>> {
208 if a.kind != b.kind {
209 Err(TypeError::ProjectionMismatched(ExpectedFound::new(a.kind.into(), b.kind.into())))
210 } else {
211 let cx = relation.cx();
212 let args = if let Some(variances) = cx.opt_alias_variances(a.kind) {
213 relate_args_with_variances(relation, variances, a.args, b.args)?
214 } else {
215 relate_args_invariantly(relation, a.args, b.args)?
216 };
217 Ok(ty::AliasTy::new_from_args(relation.cx(), a.kind, args))
218 }
219 }
220}
221
222impl<I: Interner> Relate<I> for ty::AliasConst<I> {
223 fn relate<R: TypeRelation<I>>(
224 relation: &mut R,
225 a: ty::AliasConst<I>,
226 b: ty::AliasConst<I>,
227 ) -> RelateResult<I, ty::AliasConst<I>> {
228 let cx = relation.cx();
229 if a.kind != b.kind {
230 Err(TypeError::ConstMismatch(ExpectedFound::new(
231 Const::new_alias(cx, ty::IsRigid::yes_if_next_solver(cx), a),
232 Const::new_alias(cx, ty::IsRigid::yes_if_next_solver(cx), b),
233 )))
234 } else {
235 if true {
{
match (&a.type_of(cx).skip_norm_wip(), &b.type_of(cx).skip_norm_wip())
{
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};debug_assert_eq!(a.type_of(cx).skip_norm_wip(), b.type_of(cx).skip_norm_wip());
237
238 let args = relate_args_invariantly(relation, a.args, b.args)?;
239
240 Ok(ty::AliasConst::new(cx, a.kind, args))
241 }
242 }
243}
244
245impl<I: Interner> Relate<I> for ty::AliasTerm<I> {
246 fn relate<R: TypeRelation<I>>(
247 relation: &mut R,
248 a: ty::AliasTerm<I>,
249 b: ty::AliasTerm<I>,
250 ) -> RelateResult<I, ty::AliasTerm<I>> {
251 if a.kind != b.kind {
252 Err(TypeError::ProjectionMismatched(ExpectedFound::new(a.kind, b.kind)))
253 } else {
254 let args = match a.kind {
255 ty::AliasTermKind::OpaqueTy { def_id } => relate_args_with_variances(
256 relation,
257 relation.cx().variances_of(def_id.into()),
258 a.args,
259 b.args,
260 )?,
261 ty::AliasTermKind::ProjectionTy { .. }
262 | ty::AliasTermKind::FreeConst { .. }
263 | ty::AliasTermKind::FreeTy { .. }
264 | ty::AliasTermKind::InherentTy { .. }
265 | ty::AliasTermKind::InherentConst { .. }
266 | ty::AliasTermKind::AnonConst { .. }
267 | ty::AliasTermKind::ProjectionConst { .. } => {
268 relate_args_invariantly(relation, a.args, b.args)?
269 }
270 };
271 Ok(a.with_args(relation.cx(), args))
272 }
273 }
274}
275
276impl<I: Interner> Relate<I> for ty::ExistentialProjection<I> {
277 fn relate<R: TypeRelation<I>>(
278 relation: &mut R,
279 a: ty::ExistentialProjection<I>,
280 b: ty::ExistentialProjection<I>,
281 ) -> RelateResult<I, ty::ExistentialProjection<I>> {
282 if a.def_id != b.def_id {
283 Err(TypeError::ProjectionMismatched(ExpectedFound::new(
284 relation.cx().alias_term_kind_from_def_id(a.def_id.into()),
285 relation.cx().alias_term_kind_from_def_id(b.def_id.into()),
286 )))
287 } else {
288 let term = relation.relate_with_variance(
289 ty::Invariant,
290 VarianceDiagInfo::default(),
291 a.term,
292 b.term,
293 )?;
294 let args = relation.relate_with_variance(
295 ty::Invariant,
296 VarianceDiagInfo::default(),
297 a.args,
298 b.args,
299 )?;
300 Ok(ty::ExistentialProjection::new_from_args(relation.cx(), a.def_id, args, term))
301 }
302 }
303}
304
305impl<I: Interner> Relate<I> for ty::TraitRef<I> {
306 fn relate<R: TypeRelation<I>>(
307 relation: &mut R,
308 a: ty::TraitRef<I>,
309 b: ty::TraitRef<I>,
310 ) -> RelateResult<I, ty::TraitRef<I>> {
311 if a.def_id != b.def_id {
313 Err(TypeError::Traits({
314 let a = a.def_id;
315 let b = b.def_id;
316 ExpectedFound::new(a, b)
317 }))
318 } else {
319 let args = relate_args_invariantly(relation, a.args, b.args)?;
320 Ok(ty::TraitRef::new_from_args(relation.cx(), a.def_id, args))
321 }
322 }
323}
324
325impl<I: Interner> Relate<I> for ty::ExistentialTraitRef<I> {
326 fn relate<R: TypeRelation<I>>(
327 relation: &mut R,
328 a: ty::ExistentialTraitRef<I>,
329 b: ty::ExistentialTraitRef<I>,
330 ) -> RelateResult<I, ty::ExistentialTraitRef<I>> {
331 if a.def_id != b.def_id {
333 Err(TypeError::Traits({
334 let a = a.def_id;
335 let b = b.def_id;
336 ExpectedFound::new(a, b)
337 }))
338 } else {
339 let args = relate_args_invariantly(relation, a.args, b.args)?;
340 Ok(ty::ExistentialTraitRef::new_from_args(relation.cx(), a.def_id, args))
341 }
342 }
343}
344
345x;#[instrument(level = "trace", skip(relation), ret)]
349pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
350 relation: &mut R,
351 a: I::Ty,
352 b: I::Ty,
353) -> RelateResult<I, I::Ty> {
354 let cx = relation.cx();
355 match (a.kind(), b.kind()) {
356 (ty::Infer(_), _) | (_, ty::Infer(_)) => {
357 panic!("var types encountered in structurally_relate_tys")
359 }
360
361 (ty::Bound(..), _) | (_, ty::Bound(..)) => {
362 panic!("bound types encountered in structurally_relate_tys")
363 }
364
365 (ty::Error(guar), _) | (_, ty::Error(guar)) => Ok(Ty::new_error(cx, guar)),
366
367 (ty::Never, _)
368 | (ty::Char, _)
369 | (ty::Bool, _)
370 | (ty::Int(_), _)
371 | (ty::Uint(_), _)
372 | (ty::Float(_), _)
373 | (ty::Str, _)
374 if a == b =>
375 {
376 Ok(a)
377 }
378
379 (ty::Param(a_p), ty::Param(b_p)) if a_p.index() == b_p.index() => {
380 Ok(a)
383 }
384
385 (ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a),
386
387 (ty::Adt(a_def, a_args), ty::Adt(b_def, b_args)) if a_def == b_def => {
388 if a_args.is_empty() {
389 Ok(a)
390 } else {
391 relation.relate_ty_args(a, b, a_def.def_id().into(), a_args, b_args, |args| {
392 Ty::new_adt(cx, a_def, args)
393 })
394 }
395 }
396
397 (ty::Foreign(a_id), ty::Foreign(b_id)) if a_id == b_id => Ok(Ty::new_foreign(cx, a_id)),
398
399 (ty::Dynamic(a_obj, a_region), ty::Dynamic(b_obj, b_region)) => Ok(Ty::new_dynamic(
400 cx,
401 relation.relate(a_obj, b_obj)?,
402 relation.relate(a_region, b_region)?,
403 )),
404
405 (ty::Coroutine(a_id, a_args), ty::Coroutine(b_id, b_args)) if a_id == b_id => {
406 let args = relate_args_invariantly(relation, a_args, b_args)?;
410 Ok(Ty::new_coroutine(cx, a_id, args))
411 }
412
413 (ty::CoroutineWitness(a_id, a_args), ty::CoroutineWitness(b_id, b_args))
414 if a_id == b_id =>
415 {
416 let args = relate_args_invariantly(relation, a_args, b_args)?;
420 Ok(Ty::new_coroutine_witness(cx, a_id, args))
421 }
422
423 (ty::Closure(a_id, a_args), ty::Closure(b_id, b_args)) if a_id == b_id => {
424 let args = relate_args_invariantly(relation, a_args, b_args)?;
428 Ok(Ty::new_closure(cx, a_id, args))
429 }
430
431 (ty::CoroutineClosure(a_id, a_args), ty::CoroutineClosure(b_id, b_args))
432 if a_id == b_id =>
433 {
434 let args = relate_args_invariantly(relation, a_args, b_args)?;
435 Ok(Ty::new_coroutine_closure(cx, a_id, args))
436 }
437
438 (ty::RawPtr(a_ty, a_mutbl), ty::RawPtr(b_ty, b_mutbl)) => {
439 if a_mutbl != b_mutbl {
440 return Err(TypeError::Mutability);
441 }
442
443 let (variance, info) = match a_mutbl {
444 Mutability::Not => (ty::Covariant, VarianceDiagInfo::None),
445 Mutability::Mut => {
446 (ty::Invariant, VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
447 }
448 };
449
450 let ty = relation.relate_with_variance(variance, info, a_ty, b_ty)?;
451
452 Ok(Ty::new_ptr(cx, ty, a_mutbl))
453 }
454
455 (ty::Ref(a_r, a_ty, a_mutbl), ty::Ref(b_r, b_ty, b_mutbl)) => {
456 if a_mutbl != b_mutbl {
457 return Err(TypeError::Mutability);
458 }
459
460 let (variance, info) = match a_mutbl {
461 Mutability::Not => (ty::Covariant, VarianceDiagInfo::None),
462 Mutability::Mut => {
463 (ty::Invariant, VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
464 }
465 };
466
467 let r = relation.relate(a_r, b_r)?;
468 let ty = relation.relate_with_variance(variance, info, a_ty, b_ty)?;
469
470 Ok(Ty::new_ref(cx, r, ty, a_mutbl))
471 }
472
473 (ty::Array(a_t, sz_a), ty::Array(b_t, sz_b)) => {
474 let t = relation.relate(a_t, b_t)?;
475 match relation.relate(sz_a, sz_b) {
476 Ok(sz) => Ok(Ty::new_array_with_const_len(cx, t, sz)),
477 Err(TypeError::ConstMismatch(_)) => {
478 Err(TypeError::ArraySize(ExpectedFound::new(sz_a, sz_b)))
479 }
480 Err(e) => Err(e),
481 }
482 }
483
484 (ty::Slice(a_t), ty::Slice(b_t)) => {
485 let t = relation.relate(a_t, b_t)?;
486 Ok(Ty::new_slice(cx, t))
487 }
488
489 (ty::Tuple(as_), ty::Tuple(bs)) => {
490 if as_.len() == bs.len() {
491 Ok(Ty::new_tup_from_iter(
492 cx,
493 iter::zip(as_.iter(), bs.iter()).map(|(a, b)| relation.relate(a, b)),
494 )?)
495 } else if !(as_.is_empty() || bs.is_empty()) {
496 Err(TypeError::TupleSize(ExpectedFound::new(as_.len(), bs.len())))
497 } else {
498 Err(TypeError::Sorts(ExpectedFound::new(a, b)))
499 }
500 }
501
502 (ty::FnDef(a_def_id, a_args), ty::FnDef(b_def_id, b_args)) if a_def_id == b_def_id => {
503 if a_args.skip_binder().is_empty() {
504 Ok(a)
505 } else {
506 let a_args = a_args.no_bound_vars().unwrap();
507 let b_args = b_args.no_bound_vars().unwrap();
508 relation.relate_ty_args(a, b, a_def_id.into(), a_args, b_args, |args| {
509 Ty::new_fn_def(cx, a_def_id, ty::Binder::dummy(args))
511 })
512 }
513 }
514
515 (ty::FnPtr(a_sig_tys, a_hdr), ty::FnPtr(b_sig_tys, b_hdr)) => {
516 let fty = relation.relate(a_sig_tys.with(a_hdr), b_sig_tys.with(b_hdr))?;
517 Ok(Ty::new_fn_ptr(cx, fty))
518 }
519
520 (ty::Alias(is_rigid_a, alias_a), ty::Alias(is_rigid_b, alias_b)) => {
522 debug_assert_eq!(is_rigid_a, is_rigid_b, "{a:?} != {b:?}");
525 let alias_ty = relation.relate(alias_a, alias_b)?;
526 Ok(Ty::new_alias(cx, is_rigid_a, alias_ty))
527 }
528
529 (ty::Pat(a_ty, a_pat), ty::Pat(b_ty, b_pat)) => {
530 let ty = relation.relate(a_ty, b_ty)?;
531 let pat = relation.relate(a_pat, b_pat)?;
532 Ok(Ty::new_pat(cx, ty, pat))
533 }
534
535 (ty::UnsafeBinder(a_binder), ty::UnsafeBinder(b_binder)) => {
536 Ok(Ty::new_unsafe_binder(cx, relation.binders(*a_binder, *b_binder)?))
537 }
538
539 _ => Err(TypeError::Sorts(ExpectedFound::new(a, b))),
540 }
541}
542
543pub fn structurally_relate_consts<I: Interner, R: TypeRelation<I>>(
550 relation: &mut R,
551 mut a: I::Const,
552 mut b: I::Const,
553) -> RelateResult<I, I::Const> {
554 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_type_ir/src/relate.rs:554",
"rustc_type_ir::relate", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_type_ir/src/relate.rs"),
::tracing_core::__macro_support::Option::Some(554u32),
::tracing_core::__macro_support::Option::Some("rustc_type_ir::relate"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("structurally_relate_consts::<{0}>(a = {1:?}, b = {2:?})",
std::any::type_name::<R>(), a, b) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};trace!(
555 "structurally_relate_consts::<{}>(a = {:?}, b = {:?})",
556 std::any::type_name::<R>(),
557 a,
558 b
559 );
560 let cx = relation.cx();
561
562 if cx.features().generic_const_exprs() {
563 a = cx.expand_abstract_consts(a);
564 b = cx.expand_abstract_consts(b);
565 }
566
567 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_type_ir/src/relate.rs:567",
"rustc_type_ir::relate", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_type_ir/src/relate.rs"),
::tracing_core::__macro_support::Option::Some(567u32),
::tracing_core::__macro_support::Option::Some("rustc_type_ir::relate"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("structurally_relate_consts::<{0}>(normed_a = {1:?}, normed_b = {2:?})",
std::any::type_name::<R>(), a, b) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};trace!(
568 "structurally_relate_consts::<{}>(normed_a = {:?}, normed_b = {:?})",
569 std::any::type_name::<R>(),
570 a,
571 b
572 );
573
574 let is_match = match (a.kind(), b.kind()) {
578 (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
579 {
::core::panicking::panic_fmt(format_args!("var types encountered in structurally_relate_consts: {0:?} {1:?}",
a, b));
}panic!("var types encountered in structurally_relate_consts: {:?} {:?}", a, b)
581 }
582
583 (ty::ConstKind::Error(_), _) => return Ok(a),
584 (_, ty::ConstKind::Error(_)) => return Ok(b),
585
586 (ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) if a_p.index() == b_p.index() => {
587 true
590 }
591 (ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
592 (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => {
593 match (a_val.valtree().kind(), b_val.valtree().kind()) {
594 (ty::ValTreeKind::Leaf(scalar_a), ty::ValTreeKind::Leaf(scalar_b)) => {
595 scalar_a == scalar_b
596 }
597 (ty::ValTreeKind::Branch(branches_a), ty::ValTreeKind::Branch(branches_b))
598 if branches_a.len() == branches_b.len() =>
599 {
600 branches_a
601 .iter()
602 .zip(branches_b.iter())
603 .all(|(a, b)| relation.relate(a, b).is_ok())
604 }
605 _ => false,
606 }
607 }
608
609 (ty::ConstKind::Alias(is_rigid_a, au), ty::ConstKind::Alias(is_rigid_b, bu)) => {
613 if true {
{
match (&is_rigid_a, &is_rigid_b) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val,
::core::option::Option::Some(format_args!("{0:?} != {1:?}",
a, b)));
}
}
}
};
};debug_assert_eq!(is_rigid_a, is_rigid_b, "{a:?} != {b:?}");
616 return Ok(Const::new_alias(cx, is_rigid_a, relation.relate(au, bu)?));
617 }
618 (ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => {
619 let expr = relation.relate(ae, be)?;
620 return Ok(Const::new_expr(cx, expr));
621 }
622 _ => false,
623 };
624 if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(ExpectedFound::new(a, b))) }
625}
626
627impl<I: Interner, T: Relate<I>> Relate<I> for ty::Binder<I, T> {
628 fn relate<R: TypeRelation<I>>(
629 relation: &mut R,
630 a: ty::Binder<I, T>,
631 b: ty::Binder<I, T>,
632 ) -> RelateResult<I, ty::Binder<I, T>> {
633 relation.binders(a, b)
634 }
635}
636
637impl<I: Interner> Relate<I> for ty::TraitPredicate<I> {
638 fn relate<R: TypeRelation<I>>(
639 relation: &mut R,
640 a: ty::TraitPredicate<I>,
641 b: ty::TraitPredicate<I>,
642 ) -> RelateResult<I, ty::TraitPredicate<I>> {
643 let trait_ref = relation.relate(a.trait_ref, b.trait_ref)?;
644 if a.polarity != b.polarity {
645 return Err(TypeError::PolarityMismatch(ExpectedFound::new(a.polarity, b.polarity)));
646 }
647 Ok(ty::TraitPredicate { trait_ref, polarity: a.polarity })
648 }
649}