1use std::iter;
2
3use rustc_span::bug;
4pub use rustc_type_ir::relate::*;
5
6use crate::ty::error::{ExpectedFound, TypeError};
7use crate::ty::{self as ty, Ty, TyCtxt};
8pub type RelateResult<'tcx, T> = rustc_type_ir::relate::RelateResult<TyCtxt<'tcx>, T>;
9
10impl<'tcx> Relate<TyCtxt<'tcx>> for Ty<'tcx> {
11 #[inline]
12 fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
13 relation: &mut R,
14 a: Ty<'tcx>,
15 b: Ty<'tcx>,
16 ) -> RelateResult<'tcx, Ty<'tcx>> {
17 relation.tys(a, b)
18 }
19}
20
21impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Pattern<'tcx> {
22 #[inline]
23 fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
24 relation: &mut R,
25 a: Self,
26 b: Self,
27 ) -> RelateResult<'tcx, Self> {
28 let tcx = relation.cx();
29 match (&*a, &*b) {
30 (
31 &ty::PatternKind::Range { start: start_a, end: end_a },
32 &ty::PatternKind::Range { start: start_b, end: end_b },
33 ) => {
34 let start = relation.relate(start_a, start_b)?;
35 let end = relation.relate(end_a, end_b)?;
36 Ok(tcx.mk_pat(ty::PatternKind::Range { start, end }))
37 }
38 (ty::PatternKind::NotNull, ty::PatternKind::NotNull) => Ok(a),
39 (&ty::PatternKind::Or(a), &ty::PatternKind::Or(b)) => {
40 if a.len() != b.len() {
41 return Err(TypeError::Mismatch);
42 }
43 let v = iter::zip(a, b).map(|(a, b)| relation.relate(a, b));
44 let patterns = tcx.mk_patterns_from_iter(v)?;
45 Ok(tcx.mk_pat(ty::PatternKind::Or(patterns)))
46 }
47 (
48 ty::PatternKind::NotNull | ty::PatternKind::Range { .. } | ty::PatternKind::Or(_),
49 _,
50 ) => Err(TypeError::Mismatch),
51 }
52 }
53}
54
55impl<'tcx> Relate<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
56 fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
57 relation: &mut R,
58 a: Self,
59 b: Self,
60 ) -> RelateResult<'tcx, Self> {
61 let tcx = relation.cx();
62 if a.len() != b.len() {
66 return Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b)));
67 }
68 let v =
69 iter::zip(a, b).map(|(ep_a, ep_b)| match (ep_a.skip_binder(), ep_b.skip_binder()) {
70 (ty::ExistentialPredicate::Trait(a), ty::ExistentialPredicate::Trait(b)) => {
71 Ok(ep_a.rebind(ty::ExistentialPredicate::Trait(
72 relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
73 )))
74 }
75 (
76 ty::ExistentialPredicate::Projection(a),
77 ty::ExistentialPredicate::Projection(b),
78 ) => Ok(ep_a.rebind(ty::ExistentialPredicate::Projection(
79 relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
80 ))),
81 (
82 ty::ExistentialPredicate::AutoTrait(a),
83 ty::ExistentialPredicate::AutoTrait(b),
84 ) if a == b => Ok(ep_a.rebind(ty::ExistentialPredicate::AutoTrait(a))),
85 _ => Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b))),
86 });
87 tcx.mk_poly_existential_predicates_from_iter(v)
88 }
89}
90
91impl<'tcx> Relate<TyCtxt<'tcx>> for ty::GenericArgsRef<'tcx> {
92 fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
93 relation: &mut R,
94 a: ty::GenericArgsRef<'tcx>,
95 b: ty::GenericArgsRef<'tcx>,
96 ) -> RelateResult<'tcx, ty::GenericArgsRef<'tcx>> {
97 relate_args_invariantly(relation, a, b)
98 }
99}
100
101impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Expr<'tcx> {
102 fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
103 relation: &mut R,
104 ae: ty::Expr<'tcx>,
105 be: ty::Expr<'tcx>,
106 ) -> RelateResult<'tcx, ty::Expr<'tcx>> {
107 match (ae.kind, be.kind) {
114 (ty::ExprKind::Binop(a_binop), ty::ExprKind::Binop(b_binop)) if a_binop == b_binop => {}
115 (ty::ExprKind::UnOp(a_unop), ty::ExprKind::UnOp(b_unop)) if a_unop == b_unop => {}
116 (ty::ExprKind::FunctionCall, ty::ExprKind::FunctionCall) => {}
117 (ty::ExprKind::Cast(a_kind), ty::ExprKind::Cast(b_kind)) if a_kind == b_kind => {}
118 _ => return Err(TypeError::Mismatch),
119 }
120
121 let args = relation.relate(ae.args(), be.args())?;
122 Ok(ty::Expr::new(ae.kind, args))
123 }
124}
125
126impl<'tcx> Relate<TyCtxt<'tcx>> for ty::GenericArg<'tcx> {
127 fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
128 relation: &mut R,
129 a: ty::GenericArg<'tcx>,
130 b: ty::GenericArg<'tcx>,
131 ) -> RelateResult<'tcx, ty::GenericArg<'tcx>> {
132 match (a.kind(), b.kind()) {
133 (ty::GenericArgKind::Lifetime(a_lt), ty::GenericArgKind::Lifetime(b_lt)) => {
134 Ok(relation.relate(a_lt, b_lt)?.into())
135 }
136 (ty::GenericArgKind::Type(a_ty), ty::GenericArgKind::Type(b_ty)) => {
137 Ok(relation.relate(a_ty, b_ty)?.into())
138 }
139 (ty::GenericArgKind::Const(a_ct), ty::GenericArgKind::Const(b_ct)) => {
140 Ok(relation.relate(a_ct, b_ct)?.into())
141 }
142 _ => ::rustc_span::macros::bug_impl(None,
format_args!("impossible case reached: can\'t relate: {0:?} with {1:?}",
a, b), Location::caller())bug!("impossible case reached: can't relate: {a:?} with {b:?}"),
143 }
144 }
145}
146
147impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Term<'tcx> {
148 fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
149 relation: &mut R,
150 a: Self,
151 b: Self,
152 ) -> RelateResult<'tcx, Self> {
153 Ok(match (a.kind(), b.kind()) {
154 (ty::TermKind::Ty(a), ty::TermKind::Ty(b)) => relation.relate(a, b)?.into(),
155 (ty::TermKind::Const(a), ty::TermKind::Const(b)) => relation.relate(a, b)?.into(),
156 _ => return Err(TypeError::Mismatch),
157 })
158 }
159}