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};
11
12pub mod combine;
13pub mod solver_relating;
14
15pub type RelateResult<I, T> = Result<T, TypeError<I>>;
16
17#[derive(Debug, Copy, Clone)]
24pub enum StructurallyRelateAliases {
25 Yes,
26 No,
27}
28
29#[derive_where(Clone, Copy, PartialEq, Debug, Default; I: Interner)]
37pub enum VarianceDiagInfo<I: Interner> {
38 #[derive_where(default)]
41 None,
42 Invariant {
45 ty: I::Ty,
48 param_index: u32,
51 },
52}
53
54impl<I: Interner> Eq for VarianceDiagInfo<I> {}
55
56impl<I: Interner> VarianceDiagInfo<I> {
57 pub fn xform(self, other: VarianceDiagInfo<I>) -> VarianceDiagInfo<I> {
60 match self {
62 VarianceDiagInfo::None => other,
63 VarianceDiagInfo::Invariant { .. } => self,
64 }
65 }
66}
67
68pub trait TypeRelation<I: Interner>: Sized {
69 fn cx(&self) -> I;
70
71 fn relate<T: Relate<I>>(&mut self, a: T, b: T) -> RelateResult<I, T> {
73 Relate::relate(self, a, b)
74 }
75
76 #[instrument(skip(self), level = "trace")]
80 fn relate_item_args(
81 &mut self,
82 item_def_id: I::DefId,
83 a_arg: I::GenericArgs,
84 b_arg: I::GenericArgs,
85 ) -> RelateResult<I, I::GenericArgs> {
86 let cx = self.cx();
87 let opt_variances = cx.variances_of(item_def_id);
88 relate_args_with_variances(self, item_def_id, opt_variances, a_arg, b_arg, true)
89 }
90
91 fn relate_with_variance<T: Relate<I>>(
93 &mut self,
94 variance: ty::Variance,
95 info: VarianceDiagInfo<I>,
96 a: T,
97 b: T,
98 ) -> RelateResult<I, T>;
99
100 fn tys(&mut self, a: I::Ty, b: I::Ty) -> RelateResult<I, I::Ty>;
107
108 fn regions(&mut self, a: I::Region, b: I::Region) -> RelateResult<I, I::Region>;
109
110 fn consts(&mut self, a: I::Const, b: I::Const) -> RelateResult<I, I::Const>;
111
112 fn binders<T>(
113 &mut self,
114 a: ty::Binder<I, T>,
115 b: ty::Binder<I, T>,
116 ) -> RelateResult<I, ty::Binder<I, T>>
117 where
118 T: Relate<I>;
119}
120
121pub trait Relate<I: Interner>: TypeFoldable<I> + PartialEq + Copy {
122 fn relate<R: TypeRelation<I>>(relation: &mut R, a: Self, b: Self) -> RelateResult<I, Self>;
123}
124
125#[inline]
129pub fn relate_args_invariantly<I: Interner, R: TypeRelation<I>>(
130 relation: &mut R,
131 a_arg: I::GenericArgs,
132 b_arg: I::GenericArgs,
133) -> RelateResult<I, I::GenericArgs> {
134 relation.cx().mk_args_from_iter(iter::zip(a_arg.iter(), b_arg.iter()).map(|(a, b)| {
135 relation.relate_with_variance(ty::Invariant, VarianceDiagInfo::default(), a, b)
136 }))
137}
138
139pub fn relate_args_with_variances<I: Interner, R: TypeRelation<I>>(
140 relation: &mut R,
141 ty_def_id: I::DefId,
142 variances: I::VariancesOf,
143 a_arg: I::GenericArgs,
144 b_arg: I::GenericArgs,
145 fetch_ty_for_diag: bool,
146) -> RelateResult<I, I::GenericArgs> {
147 let cx = relation.cx();
148
149 let mut cached_ty = None;
150 let params = iter::zip(a_arg.iter(), b_arg.iter()).enumerate().map(|(i, (a, b))| {
151 let variance = variances.get(i).unwrap();
152 let variance_info = if variance == ty::Invariant && fetch_ty_for_diag {
153 let ty = *cached_ty.get_or_insert_with(|| cx.type_of(ty_def_id).instantiate(cx, a_arg));
154 VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
155 } else {
156 VarianceDiagInfo::default()
157 };
158 relation.relate_with_variance(variance, variance_info, a, b)
159 });
160
161 cx.mk_args_from_iter(params)
162}
163
164impl<I: Interner> Relate<I> for ty::FnSig<I> {
165 fn relate<R: TypeRelation<I>>(
166 relation: &mut R,
167 a: ty::FnSig<I>,
168 b: ty::FnSig<I>,
169 ) -> RelateResult<I, ty::FnSig<I>> {
170 let cx = relation.cx();
171
172 if a.c_variadic != b.c_variadic {
173 return Err(TypeError::VariadicMismatch({
174 let a = a.c_variadic;
175 let b = b.c_variadic;
176 ExpectedFound::new(a, b)
177 }));
178 }
179
180 if a.safety != b.safety {
181 return Err(TypeError::SafetyMismatch(ExpectedFound::new(a.safety, b.safety)));
182 }
183
184 if a.abi != b.abi {
185 return Err(TypeError::AbiMismatch(ExpectedFound::new(a.abi, b.abi)));
186 };
187
188 let a_inputs = a.inputs();
189 let b_inputs = b.inputs();
190 if a_inputs.len() != b_inputs.len() {
191 return Err(TypeError::ArgCount);
192 }
193
194 let inputs_and_output = iter::zip(a_inputs.iter(), b_inputs.iter())
195 .map(|(a, b)| ((a, b), false))
196 .chain(iter::once(((a.output(), b.output()), true)))
197 .map(|((a, b), is_output)| {
198 if is_output {
199 relation.relate(a, b)
200 } else {
201 relation.relate_with_variance(
202 ty::Contravariant,
203 VarianceDiagInfo::default(),
204 a,
205 b,
206 )
207 }
208 })
209 .enumerate()
210 .map(|(i, r)| match r {
211 Err(TypeError::Sorts(exp_found) | TypeError::ArgumentSorts(exp_found, _)) => {
212 Err(TypeError::ArgumentSorts(exp_found, i))
213 }
214 Err(TypeError::Mutability | TypeError::ArgumentMutability(_)) => {
215 Err(TypeError::ArgumentMutability(i))
216 }
217 r => r,
218 });
219 Ok(ty::FnSig {
220 inputs_and_output: cx.mk_type_list_from_iter(inputs_and_output)?,
221 c_variadic: a.c_variadic,
222 safety: a.safety,
223 abi: a.abi,
224 })
225 }
226}
227
228impl<I: Interner> Relate<I> for ty::AliasTy<I> {
229 fn relate<R: TypeRelation<I>>(
230 relation: &mut R,
231 a: ty::AliasTy<I>,
232 b: ty::AliasTy<I>,
233 ) -> RelateResult<I, ty::AliasTy<I>> {
234 if a.def_id != b.def_id {
235 Err(TypeError::ProjectionMismatched({
236 let a = a.def_id;
237 let b = b.def_id;
238 ExpectedFound::new(a, b)
239 }))
240 } else {
241 let cx = relation.cx();
242 let args = if let Some(variances) = cx.opt_alias_variances(a.kind(cx), a.def_id) {
243 relate_args_with_variances(
244 relation, a.def_id, variances, a.args, b.args,
245 false, )?
247 } else {
248 relate_args_invariantly(relation, a.args, b.args)?
249 };
250 Ok(ty::AliasTy::new_from_args(relation.cx(), a.def_id, args))
251 }
252 }
253}
254
255impl<I: Interner> Relate<I> for ty::AliasTerm<I> {
256 fn relate<R: TypeRelation<I>>(
257 relation: &mut R,
258 a: ty::AliasTerm<I>,
259 b: ty::AliasTerm<I>,
260 ) -> RelateResult<I, ty::AliasTerm<I>> {
261 if a.def_id != b.def_id {
262 Err(TypeError::ProjectionMismatched({
263 let a = a.def_id;
264 let b = b.def_id;
265 ExpectedFound::new(a, b)
266 }))
267 } else {
268 let args = match a.kind(relation.cx()) {
269 ty::AliasTermKind::OpaqueTy => relate_args_with_variances(
270 relation,
271 a.def_id,
272 relation.cx().variances_of(a.def_id),
273 a.args,
274 b.args,
275 false, )?,
277 ty::AliasTermKind::ProjectionTy
278 | ty::AliasTermKind::FreeConst
279 | ty::AliasTermKind::FreeTy
280 | ty::AliasTermKind::InherentTy
281 | ty::AliasTermKind::InherentConst
282 | ty::AliasTermKind::UnevaluatedConst
283 | ty::AliasTermKind::ProjectionConst => {
284 relate_args_invariantly(relation, a.args, b.args)?
285 }
286 };
287 Ok(ty::AliasTerm::new_from_args(relation.cx(), a.def_id, args))
288 }
289 }
290}
291
292impl<I: Interner> Relate<I> for ty::ExistentialProjection<I> {
293 fn relate<R: TypeRelation<I>>(
294 relation: &mut R,
295 a: ty::ExistentialProjection<I>,
296 b: ty::ExistentialProjection<I>,
297 ) -> RelateResult<I, ty::ExistentialProjection<I>> {
298 if a.def_id != b.def_id {
299 Err(TypeError::ProjectionMismatched({
300 let a = a.def_id;
301 let b = b.def_id;
302 ExpectedFound::new(a, b)
303 }))
304 } else {
305 let term = relation.relate_with_variance(
306 ty::Invariant,
307 VarianceDiagInfo::default(),
308 a.term,
309 b.term,
310 )?;
311 let args = relation.relate_with_variance(
312 ty::Invariant,
313 VarianceDiagInfo::default(),
314 a.args,
315 b.args,
316 )?;
317 Ok(ty::ExistentialProjection::new_from_args(relation.cx(), a.def_id, args, term))
318 }
319 }
320}
321
322impl<I: Interner> Relate<I> for ty::TraitRef<I> {
323 fn relate<R: TypeRelation<I>>(
324 relation: &mut R,
325 a: ty::TraitRef<I>,
326 b: ty::TraitRef<I>,
327 ) -> RelateResult<I, ty::TraitRef<I>> {
328 if a.def_id != b.def_id {
330 Err(TypeError::Traits({
331 let a = a.def_id;
332 let b = b.def_id;
333 ExpectedFound::new(a, b)
334 }))
335 } else {
336 let args = relate_args_invariantly(relation, a.args, b.args)?;
337 Ok(ty::TraitRef::new_from_args(relation.cx(), a.def_id, args))
338 }
339 }
340}
341
342impl<I: Interner> Relate<I> for ty::ExistentialTraitRef<I> {
343 fn relate<R: TypeRelation<I>>(
344 relation: &mut R,
345 a: ty::ExistentialTraitRef<I>,
346 b: ty::ExistentialTraitRef<I>,
347 ) -> RelateResult<I, ty::ExistentialTraitRef<I>> {
348 if a.def_id != b.def_id {
350 Err(TypeError::Traits({
351 let a = a.def_id;
352 let b = b.def_id;
353 ExpectedFound::new(a, b)
354 }))
355 } else {
356 let args = relate_args_invariantly(relation, a.args, b.args)?;
357 Ok(ty::ExistentialTraitRef::new_from_args(relation.cx(), a.def_id, args))
358 }
359 }
360}
361
362#[instrument(level = "trace", skip(relation), ret)]
366pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
367 relation: &mut R,
368 a: I::Ty,
369 b: I::Ty,
370) -> RelateResult<I, I::Ty> {
371 let cx = relation.cx();
372 match (a.kind(), b.kind()) {
373 (ty::Infer(_), _) | (_, ty::Infer(_)) => {
374 panic!("var types encountered in structurally_relate_tys")
376 }
377
378 (ty::Bound(..), _) | (_, ty::Bound(..)) => {
379 panic!("bound types encountered in structurally_relate_tys")
380 }
381
382 (ty::Error(guar), _) | (_, ty::Error(guar)) => Ok(Ty::new_error(cx, guar)),
383
384 (ty::Never, _)
385 | (ty::Char, _)
386 | (ty::Bool, _)
387 | (ty::Int(_), _)
388 | (ty::Uint(_), _)
389 | (ty::Float(_), _)
390 | (ty::Str, _)
391 if a == b =>
392 {
393 Ok(a)
394 }
395
396 (ty::Param(a_p), ty::Param(b_p)) if a_p.index() == b_p.index() => {
397 Ok(a)
400 }
401
402 (ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a),
403
404 (ty::Adt(a_def, a_args), ty::Adt(b_def, b_args)) if a_def == b_def => {
405 Ok(if a_args.is_empty() {
406 a
407 } else {
408 let args = relation.relate_item_args(a_def.def_id().into(), a_args, b_args)?;
409 if args == a_args { a } else { Ty::new_adt(cx, a_def, args) }
410 })
411 }
412
413 (ty::Foreign(a_id), ty::Foreign(b_id)) if a_id == b_id => Ok(Ty::new_foreign(cx, a_id)),
414
415 (ty::Dynamic(a_obj, a_region, a_repr), ty::Dynamic(b_obj, b_region, b_repr))
416 if a_repr == b_repr =>
417 {
418 Ok(Ty::new_dynamic(
419 cx,
420 relation.relate(a_obj, b_obj)?,
421 relation.relate(a_region, b_region)?,
422 a_repr,
423 ))
424 }
425
426 (ty::Coroutine(a_id, a_args), ty::Coroutine(b_id, b_args)) if a_id == b_id => {
427 let args = relate_args_invariantly(relation, a_args, b_args)?;
431 Ok(Ty::new_coroutine(cx, a_id, args))
432 }
433
434 (ty::CoroutineWitness(a_id, a_args), ty::CoroutineWitness(b_id, b_args))
435 if a_id == b_id =>
436 {
437 let args = relate_args_invariantly(relation, a_args, b_args)?;
441 Ok(Ty::new_coroutine_witness(cx, a_id, args))
442 }
443
444 (ty::Closure(a_id, a_args), ty::Closure(b_id, b_args)) if a_id == b_id => {
445 let args = relate_args_invariantly(relation, a_args, b_args)?;
449 Ok(Ty::new_closure(cx, a_id, args))
450 }
451
452 (ty::CoroutineClosure(a_id, a_args), ty::CoroutineClosure(b_id, b_args))
453 if a_id == b_id =>
454 {
455 let args = relate_args_invariantly(relation, a_args, b_args)?;
456 Ok(Ty::new_coroutine_closure(cx, a_id, args))
457 }
458
459 (ty::RawPtr(a_ty, a_mutbl), ty::RawPtr(b_ty, b_mutbl)) => {
460 if a_mutbl != b_mutbl {
461 return Err(TypeError::Mutability);
462 }
463
464 let (variance, info) = match a_mutbl {
465 Mutability::Not => (ty::Covariant, VarianceDiagInfo::None),
466 Mutability::Mut => {
467 (ty::Invariant, VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
468 }
469 };
470
471 let ty = relation.relate_with_variance(variance, info, a_ty, b_ty)?;
472
473 Ok(Ty::new_ptr(cx, ty, a_mutbl))
474 }
475
476 (ty::Ref(a_r, a_ty, a_mutbl), ty::Ref(b_r, b_ty, b_mutbl)) => {
477 if a_mutbl != b_mutbl {
478 return Err(TypeError::Mutability);
479 }
480
481 let (variance, info) = match a_mutbl {
482 Mutability::Not => (ty::Covariant, VarianceDiagInfo::None),
483 Mutability::Mut => {
484 (ty::Invariant, VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
485 }
486 };
487
488 let r = relation.relate(a_r, b_r)?;
489 let ty = relation.relate_with_variance(variance, info, a_ty, b_ty)?;
490
491 Ok(Ty::new_ref(cx, r, ty, a_mutbl))
492 }
493
494 (ty::Array(a_t, sz_a), ty::Array(b_t, sz_b)) => {
495 let t = relation.relate(a_t, b_t)?;
496 match relation.relate(sz_a, sz_b) {
497 Ok(sz) => Ok(Ty::new_array_with_const_len(cx, t, sz)),
498 Err(TypeError::ConstMismatch(_)) => {
499 Err(TypeError::ArraySize(ExpectedFound::new(sz_a, sz_b)))
500 }
501 Err(e) => Err(e),
502 }
503 }
504
505 (ty::Slice(a_t), ty::Slice(b_t)) => {
506 let t = relation.relate(a_t, b_t)?;
507 Ok(Ty::new_slice(cx, t))
508 }
509
510 (ty::Tuple(as_), ty::Tuple(bs)) => {
511 if as_.len() == bs.len() {
512 Ok(Ty::new_tup_from_iter(
513 cx,
514 iter::zip(as_.iter(), bs.iter()).map(|(a, b)| relation.relate(a, b)),
515 )?)
516 } else if !(as_.is_empty() || bs.is_empty()) {
517 Err(TypeError::TupleSize(ExpectedFound::new(as_.len(), bs.len())))
518 } else {
519 Err(TypeError::Sorts(ExpectedFound::new(a, b)))
520 }
521 }
522
523 (ty::FnDef(a_def_id, a_args), ty::FnDef(b_def_id, b_args)) if a_def_id == b_def_id => {
524 Ok(if a_args.is_empty() {
525 a
526 } else {
527 let args = relation.relate_item_args(a_def_id.into(), a_args, b_args)?;
528 if args == a_args { a } else { Ty::new_fn_def(cx, a_def_id, args) }
529 })
530 }
531
532 (ty::FnPtr(a_sig_tys, a_hdr), ty::FnPtr(b_sig_tys, b_hdr)) => {
533 let fty = relation.relate(a_sig_tys.with(a_hdr), b_sig_tys.with(b_hdr))?;
534 Ok(Ty::new_fn_ptr(cx, fty))
535 }
536
537 (ty::Alias(a_kind, a_data), ty::Alias(b_kind, b_data)) => {
539 let alias_ty = relation.relate(a_data, b_data)?;
540 assert_eq!(a_kind, b_kind);
541 Ok(Ty::new_alias(cx, a_kind, alias_ty))
542 }
543
544 (ty::Pat(a_ty, a_pat), ty::Pat(b_ty, b_pat)) => {
545 let ty = relation.relate(a_ty, b_ty)?;
546 let pat = relation.relate(a_pat, b_pat)?;
547 Ok(Ty::new_pat(cx, ty, pat))
548 }
549
550 (ty::UnsafeBinder(a_binder), ty::UnsafeBinder(b_binder)) => {
551 Ok(Ty::new_unsafe_binder(cx, relation.binders(*a_binder, *b_binder)?))
552 }
553
554 _ => Err(TypeError::Sorts(ExpectedFound::new(a, b))),
555 }
556}
557
558pub fn structurally_relate_consts<I: Interner, R: TypeRelation<I>>(
565 relation: &mut R,
566 mut a: I::Const,
567 mut b: I::Const,
568) -> RelateResult<I, I::Const> {
569 trace!(
570 "structurally_relate_consts::<{}>(a = {:?}, b = {:?})",
571 std::any::type_name::<R>(),
572 a,
573 b
574 );
575 let cx = relation.cx();
576
577 if cx.features().generic_const_exprs() {
578 a = cx.expand_abstract_consts(a);
579 b = cx.expand_abstract_consts(b);
580 }
581
582 trace!(
583 "structurally_relate_consts::<{}>(normed_a = {:?}, normed_b = {:?})",
584 std::any::type_name::<R>(),
585 a,
586 b
587 );
588
589 let is_match = match (a.kind(), b.kind()) {
593 (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
594 panic!("var types encountered in structurally_relate_consts: {:?} {:?}", a, b)
596 }
597
598 (ty::ConstKind::Error(_), _) => return Ok(a),
599 (_, ty::ConstKind::Error(_)) => return Ok(b),
600
601 (ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) if a_p.index() == b_p.index() => {
602 true
605 }
606 (ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
607 (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => {
608 a_val.valtree() == b_val.valtree()
609 }
610
611 (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => {
615 if cfg!(debug_assertions) {
616 let a_ty = cx.type_of(au.def).instantiate(cx, au.args);
617 let b_ty = cx.type_of(bu.def).instantiate(cx, bu.args);
618 assert_eq!(a_ty, b_ty);
619 }
620
621 let args = relation.relate_with_variance(
622 ty::Invariant,
623 VarianceDiagInfo::default(),
624 au.args,
625 bu.args,
626 )?;
627 return Ok(Const::new_unevaluated(cx, ty::UnevaluatedConst { def: au.def, args }));
628 }
629 (ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => {
630 let expr = relation.relate(ae, be)?;
631 return Ok(Const::new_expr(cx, expr));
632 }
633 _ => false,
634 };
635 if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(ExpectedFound::new(a, b))) }
636}
637
638impl<I: Interner, T: Relate<I>> Relate<I> for ty::Binder<I, T> {
639 fn relate<R: TypeRelation<I>>(
640 relation: &mut R,
641 a: ty::Binder<I, T>,
642 b: ty::Binder<I, T>,
643 ) -> RelateResult<I, ty::Binder<I, T>> {
644 relation.binders(a, b)
645 }
646}
647
648impl<I: Interner> Relate<I> for ty::TraitPredicate<I> {
649 fn relate<R: TypeRelation<I>>(
650 relation: &mut R,
651 a: ty::TraitPredicate<I>,
652 b: ty::TraitPredicate<I>,
653 ) -> RelateResult<I, ty::TraitPredicate<I>> {
654 let trait_ref = relation.relate(a.trait_ref, b.trait_ref)?;
655 if a.polarity != b.polarity {
656 return Err(TypeError::PolarityMismatch(ExpectedFound::new(a.polarity, b.polarity)));
657 }
658 Ok(ty::TraitPredicate { trait_ref, polarity: a.polarity })
659 }
660}