]>
Commit | Line | Data |
---|---|---|
0731742a XL |
1 | //! Generalized type relating mechanism. |
2 | //! | |
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. | |
c34b1796 | 6 | |
dfeec247 | 7 | use crate::ty::error::{ExpectedFound, TypeError}; |
a2a8927a | 8 | use crate::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; |
f2b60f7d | 9 | use crate::ty::{self, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable}; |
dfeec247 XL |
10 | use rustc_hir as ast; |
11 | use rustc_hir::def_id::DefId; | |
f9f354fc | 12 | use rustc_span::DUMMY_SP; |
83c7162d | 13 | use rustc_target::spec::abi; |
dfeec247 | 14 | use std::iter; |
c34b1796 | 15 | |
e9174d1e | 16 | pub type RelateResult<'tcx, T> = Result<T, TypeError<'tcx>>; |
c34b1796 | 17 | |
62682a34 SL |
18 | #[derive(Clone, Debug)] |
19 | pub enum Cause { | |
c1a9b12d | 20 | ExistentialRegionBound, // relating an existential region bound |
62682a34 SL |
21 | } |
22 | ||
dc9dc135 XL |
23 | pub trait TypeRelation<'tcx>: Sized { |
24 | fn tcx(&self) -> TyCtxt<'tcx>; | |
c34b1796 | 25 | |
416331ca XL |
26 | fn param_env(&self) -> ty::ParamEnv<'tcx>; |
27 | ||
c34b1796 AL |
28 | /// Returns a static string we can use for printouts. |
29 | fn tag(&self) -> &'static str; | |
30 | ||
9fa01778 | 31 | /// Returns `true` if the value `a` is the "expected" type in the |
c34b1796 AL |
32 | /// relation. Just affects error messages. |
33 | fn a_is_expected(&self) -> bool; | |
34 | ||
dfeec247 XL |
35 | fn with_cause<F, R>(&mut self, _cause: Cause, f: F) -> R |
36 | where | |
37 | F: FnOnce(&mut Self) -> R, | |
62682a34 SL |
38 | { |
39 | f(self) | |
40 | } | |
41 | ||
c34b1796 | 42 | /// Generic relation routine suitable for most anything. |
f035d41b | 43 | fn relate<T: Relate<'tcx>>(&mut self, a: T, b: T) -> RelateResult<'tcx, T> { |
c34b1796 AL |
44 | Relate::relate(self, a, b) |
45 | } | |
46 | ||
cc61c64b XL |
47 | /// Relate the two substitutions for the given item. The default |
48 | /// is to look up the variance for the item and proceed | |
49 | /// accordingly. | |
dfeec247 XL |
50 | fn relate_item_substs( |
51 | &mut self, | |
52 | item_def_id: DefId, | |
53 | a_subst: SubstsRef<'tcx>, | |
54 | b_subst: SubstsRef<'tcx>, | |
55 | ) -> RelateResult<'tcx, SubstsRef<'tcx>> { | |
56 | debug!( | |
57 | "relate_item_substs(item_def_id={:?}, a_subst={:?}, b_subst={:?})", | |
58 | item_def_id, a_subst, b_subst | |
59 | ); | |
cc61c64b | 60 | |
a2a8927a XL |
61 | let tcx = self.tcx(); |
62 | let opt_variances = tcx.variances_of(item_def_id); | |
04454e1e | 63 | relate_substs_with_variances(self, item_def_id, opt_variances, a_subst, b_subst) |
cc61c64b XL |
64 | } |
65 | ||
c34b1796 | 66 | /// Switch variance for the purpose of relating `a` and `b`. |
dfeec247 XL |
67 | fn relate_with_variance<T: Relate<'tcx>>( |
68 | &mut self, | |
69 | variance: ty::Variance, | |
17df50a5 | 70 | info: ty::VarianceDiagInfo<'tcx>, |
f035d41b XL |
71 | a: T, |
72 | b: T, | |
dfeec247 | 73 | ) -> RelateResult<'tcx, T>; |
c34b1796 | 74 | |
74b04a01 | 75 | // Overridable relations. You shouldn't typically call these |
c34b1796 AL |
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. | |
80 | ||
48663c56 | 81 | fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>>; |
c34b1796 | 82 | |
48663c56 XL |
83 | fn regions( |
84 | &mut self, | |
85 | a: ty::Region<'tcx>, | |
dfeec247 | 86 | b: ty::Region<'tcx>, |
48663c56 XL |
87 | ) -> RelateResult<'tcx, ty::Region<'tcx>>; |
88 | ||
89 | fn consts( | |
90 | &mut self, | |
5099ac24 FG |
91 | a: ty::Const<'tcx>, |
92 | b: ty::Const<'tcx>, | |
93 | ) -> RelateResult<'tcx, ty::Const<'tcx>>; | |
c34b1796 | 94 | |
dfeec247 XL |
95 | fn binders<T>( |
96 | &mut self, | |
cdc7bbd5 XL |
97 | a: ty::Binder<'tcx, T>, |
98 | b: ty::Binder<'tcx, T>, | |
99 | ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> | |
dfeec247 XL |
100 | where |
101 | T: Relate<'tcx>; | |
c34b1796 AL |
102 | } |
103 | ||
f035d41b | 104 | pub trait Relate<'tcx>: TypeFoldable<'tcx> + Copy { |
dc9dc135 XL |
105 | fn relate<R: TypeRelation<'tcx>>( |
106 | relation: &mut R, | |
f035d41b XL |
107 | a: Self, |
108 | b: Self, | |
dc9dc135 | 109 | ) -> RelateResult<'tcx, Self>; |
c34b1796 AL |
110 | } |
111 | ||
112 | /////////////////////////////////////////////////////////////////////////// | |
113 | // Relate impls | |
114 | ||
17df50a5 XL |
115 | pub fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>( |
116 | relation: &mut R, | |
117 | a: ty::TypeAndMut<'tcx>, | |
118 | b: ty::TypeAndMut<'tcx>, | |
a2a8927a | 119 | base_ty: Ty<'tcx>, |
17df50a5 XL |
120 | ) -> RelateResult<'tcx, ty::TypeAndMut<'tcx>> { |
121 | debug!("{}.mts({:?}, {:?})", relation.tag(), a, b); | |
122 | if a.mutbl != b.mutbl { | |
123 | Err(TypeError::Mutability) | |
124 | } else { | |
125 | let mutbl = a.mutbl; | |
126 | let (variance, info) = match mutbl { | |
127 | ast::Mutability::Not => (ty::Covariant, ty::VarianceDiagInfo::None), | |
a2a8927a XL |
128 | ast::Mutability::Mut => { |
129 | (ty::Invariant, ty::VarianceDiagInfo::Invariant { ty: base_ty, param_index: 0 }) | |
130 | } | |
17df50a5 XL |
131 | }; |
132 | let ty = relation.relate_with_variance(variance, info, a.ty, b.ty)?; | |
133 | Ok(ty::TypeAndMut { ty, mutbl }) | |
c34b1796 AL |
134 | } |
135 | } | |
136 | ||
04454e1e | 137 | #[inline] |
a2a8927a | 138 | pub fn relate_substs<'tcx, R: TypeRelation<'tcx>>( |
dc9dc135 | 139 | relation: &mut R, |
04454e1e FG |
140 | a_subst: SubstsRef<'tcx>, |
141 | b_subst: SubstsRef<'tcx>, | |
142 | ) -> RelateResult<'tcx, SubstsRef<'tcx>> { | |
143 | relation.tcx().mk_substs(iter::zip(a_subst, b_subst).map(|(a, b)| { | |
144 | relation.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b) | |
145 | })) | |
146 | } | |
147 | ||
148 | pub fn relate_substs_with_variances<'tcx, R: TypeRelation<'tcx>>( | |
149 | relation: &mut R, | |
150 | ty_def_id: DefId, | |
151 | variances: &[ty::Variance], | |
dc9dc135 XL |
152 | a_subst: SubstsRef<'tcx>, |
153 | b_subst: SubstsRef<'tcx>, | |
154 | ) -> RelateResult<'tcx, SubstsRef<'tcx>> { | |
9e0c209e | 155 | let tcx = relation.tcx(); |
c34b1796 | 156 | |
04454e1e | 157 | let mut cached_ty = None; |
cdc7bbd5 | 158 | let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| { |
04454e1e FG |
159 | let variance = variances[i]; |
160 | let variance_info = if variance == ty::Invariant { | |
161 | let ty = | |
162 | *cached_ty.get_or_insert_with(|| tcx.bound_type_of(ty_def_id).subst(tcx, a_subst)); | |
163 | ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() } | |
164 | } else { | |
165 | ty::VarianceDiagInfo::default() | |
a2a8927a XL |
166 | }; |
167 | relation.relate_with_variance(variance, variance_info, a, b) | |
9e0c209e | 168 | }); |
c34b1796 | 169 | |
6a06907d | 170 | tcx.mk_substs(params) |
c34b1796 AL |
171 | } |
172 | ||
a7813a04 | 173 | impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { |
dc9dc135 XL |
174 | fn relate<R: TypeRelation<'tcx>>( |
175 | relation: &mut R, | |
f035d41b XL |
176 | a: ty::FnSig<'tcx>, |
177 | b: ty::FnSig<'tcx>, | |
dc9dc135 | 178 | ) -> RelateResult<'tcx, ty::FnSig<'tcx>> { |
94b46f34 XL |
179 | let tcx = relation.tcx(); |
180 | ||
532ac7d7 | 181 | if a.c_variadic != b.c_variadic { |
dfeec247 XL |
182 | return Err(TypeError::VariadicMismatch(expected_found( |
183 | relation, | |
f035d41b XL |
184 | a.c_variadic, |
185 | b.c_variadic, | |
dfeec247 | 186 | ))); |
c34b1796 | 187 | } |
f035d41b XL |
188 | let unsafety = relation.relate(a.unsafety, b.unsafety)?; |
189 | let abi = relation.relate(a.abi, b.abi)?; | |
c34b1796 | 190 | |
476ff2be SL |
191 | if a.inputs().len() != b.inputs().len() { |
192 | return Err(TypeError::ArgCount); | |
193 | } | |
c34b1796 | 194 | |
cdc7bbd5 XL |
195 | let inputs_and_output = iter::zip(a.inputs(), b.inputs()) |
196 | .map(|(&a, &b)| ((a, b), false)) | |
476ff2be SL |
197 | .chain(iter::once(((a.output(), b.output()), true))) |
198 | .map(|((a, b), is_output)| { | |
199 | if is_output { | |
f035d41b | 200 | relation.relate(a, b) |
476ff2be | 201 | } else { |
17df50a5 XL |
202 | relation.relate_with_variance( |
203 | ty::Contravariant, | |
204 | ty::VarianceDiagInfo::default(), | |
205 | a, | |
206 | b, | |
207 | ) | |
476ff2be | 208 | } |
cdc7bbd5 XL |
209 | }) |
210 | .enumerate() | |
211 | .map(|(i, r)| match r { | |
3c0e092e XL |
212 | Err(TypeError::Sorts(exp_found) | TypeError::ArgumentSorts(exp_found, _)) => { |
213 | Err(TypeError::ArgumentSorts(exp_found, i)) | |
214 | } | |
215 | Err(TypeError::Mutability | TypeError::ArgumentMutability(_)) => { | |
216 | Err(TypeError::ArgumentMutability(i)) | |
217 | } | |
cdc7bbd5 | 218 | r => r, |
94b46f34 | 219 | }); |
476ff2be | 220 | Ok(ty::FnSig { |
94b46f34 | 221 | inputs_and_output: tcx.mk_type_list(inputs_and_output)?, |
532ac7d7 | 222 | c_variadic: a.c_variadic, |
041b39d2 XL |
223 | unsafety, |
224 | abi, | |
476ff2be | 225 | }) |
c34b1796 | 226 | } |
c34b1796 AL |
227 | } |
228 | ||
94222f64 XL |
229 | impl<'tcx> Relate<'tcx> for ty::BoundConstness { |
230 | fn relate<R: TypeRelation<'tcx>>( | |
231 | relation: &mut R, | |
232 | a: ty::BoundConstness, | |
233 | b: ty::BoundConstness, | |
234 | ) -> RelateResult<'tcx, ty::BoundConstness> { | |
235 | if a != b { | |
236 | Err(TypeError::ConstnessMismatch(expected_found(relation, a, b))) | |
237 | } else { | |
238 | Ok(a) | |
239 | } | |
240 | } | |
241 | } | |
242 | ||
a7813a04 | 243 | impl<'tcx> Relate<'tcx> for ast::Unsafety { |
dc9dc135 XL |
244 | fn relate<R: TypeRelation<'tcx>>( |
245 | relation: &mut R, | |
f035d41b XL |
246 | a: ast::Unsafety, |
247 | b: ast::Unsafety, | |
dc9dc135 | 248 | ) -> RelateResult<'tcx, ast::Unsafety> { |
c34b1796 | 249 | if a != b { |
c1a9b12d | 250 | Err(TypeError::UnsafetyMismatch(expected_found(relation, a, b))) |
c34b1796 | 251 | } else { |
f035d41b | 252 | Ok(a) |
c34b1796 AL |
253 | } |
254 | } | |
255 | } | |
256 | ||
a7813a04 | 257 | impl<'tcx> Relate<'tcx> for abi::Abi { |
dc9dc135 XL |
258 | fn relate<R: TypeRelation<'tcx>>( |
259 | relation: &mut R, | |
f035d41b XL |
260 | a: abi::Abi, |
261 | b: abi::Abi, | |
dc9dc135 | 262 | ) -> RelateResult<'tcx, abi::Abi> { |
f035d41b | 263 | if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(expected_found(relation, a, b))) } |
c34b1796 AL |
264 | } |
265 | } | |
266 | ||
a7813a04 | 267 | impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> { |
dc9dc135 XL |
268 | fn relate<R: TypeRelation<'tcx>>( |
269 | relation: &mut R, | |
f035d41b XL |
270 | a: ty::ProjectionTy<'tcx>, |
271 | b: ty::ProjectionTy<'tcx>, | |
dc9dc135 | 272 | ) -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> { |
041b39d2 | 273 | if a.item_def_id != b.item_def_id { |
dfeec247 XL |
274 | Err(TypeError::ProjectionMismatched(expected_found( |
275 | relation, | |
f035d41b XL |
276 | a.item_def_id, |
277 | b.item_def_id, | |
dfeec247 | 278 | ))) |
c34b1796 | 279 | } else { |
f035d41b | 280 | let substs = relation.relate(a.substs, b.substs)?; |
dfeec247 | 281 | Ok(ty::ProjectionTy { item_def_id: a.item_def_id, substs: &substs }) |
c34b1796 AL |
282 | } |
283 | } | |
284 | } | |
285 | ||
9e0c209e | 286 | impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { |
dc9dc135 XL |
287 | fn relate<R: TypeRelation<'tcx>>( |
288 | relation: &mut R, | |
f035d41b XL |
289 | a: ty::ExistentialProjection<'tcx>, |
290 | b: ty::ExistentialProjection<'tcx>, | |
dc9dc135 | 291 | ) -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> { |
041b39d2 | 292 | if a.item_def_id != b.item_def_id { |
dfeec247 XL |
293 | Err(TypeError::ProjectionMismatched(expected_found( |
294 | relation, | |
f035d41b XL |
295 | a.item_def_id, |
296 | b.item_def_id, | |
dfeec247 | 297 | ))) |
9e0c209e | 298 | } else { |
5099ac24 | 299 | let term = relation.relate_with_variance( |
17df50a5 XL |
300 | ty::Invariant, |
301 | ty::VarianceDiagInfo::default(), | |
5099ac24 FG |
302 | a.term, |
303 | b.term, | |
17df50a5 XL |
304 | )?; |
305 | let substs = relation.relate_with_variance( | |
306 | ty::Invariant, | |
307 | ty::VarianceDiagInfo::default(), | |
308 | a.substs, | |
309 | b.substs, | |
310 | )?; | |
5099ac24 | 311 | Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, term }) |
9e0c209e | 312 | } |
c34b1796 AL |
313 | } |
314 | } | |
315 | ||
a7813a04 | 316 | impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { |
dc9dc135 XL |
317 | fn relate<R: TypeRelation<'tcx>>( |
318 | relation: &mut R, | |
f035d41b XL |
319 | a: ty::TraitRef<'tcx>, |
320 | b: ty::TraitRef<'tcx>, | |
dc9dc135 | 321 | ) -> RelateResult<'tcx, ty::TraitRef<'tcx>> { |
60c5eb7d | 322 | // Different traits cannot be related. |
c34b1796 | 323 | if a.def_id != b.def_id { |
f035d41b | 324 | Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id))) |
c34b1796 | 325 | } else { |
04454e1e | 326 | let substs = relate_substs(relation, a.substs, b.substs)?; |
74b04a01 | 327 | Ok(ty::TraitRef { def_id: a.def_id, substs }) |
c34b1796 AL |
328 | } |
329 | } | |
330 | } | |
331 | ||
9e0c209e | 332 | impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { |
dc9dc135 XL |
333 | fn relate<R: TypeRelation<'tcx>>( |
334 | relation: &mut R, | |
f035d41b XL |
335 | a: ty::ExistentialTraitRef<'tcx>, |
336 | b: ty::ExistentialTraitRef<'tcx>, | |
dc9dc135 | 337 | ) -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>> { |
60c5eb7d | 338 | // Different traits cannot be related. |
9e0c209e | 339 | if a.def_id != b.def_id { |
f035d41b | 340 | Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id))) |
9e0c209e | 341 | } else { |
04454e1e | 342 | let substs = relate_substs(relation, a.substs, b.substs)?; |
74b04a01 | 343 | Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs }) |
9e0c209e SL |
344 | } |
345 | } | |
346 | } | |
347 | ||
064997fb | 348 | #[derive(Copy, Debug, Clone, TypeFoldable, TypeVisitable)] |
b7449926 | 349 | struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>); |
2c00a5a8 | 350 | |
2c00a5a8 | 351 | impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> { |
dc9dc135 XL |
352 | fn relate<R: TypeRelation<'tcx>>( |
353 | relation: &mut R, | |
f035d41b XL |
354 | a: GeneratorWitness<'tcx>, |
355 | b: GeneratorWitness<'tcx>, | |
dc9dc135 | 356 | ) -> RelateResult<'tcx, GeneratorWitness<'tcx>> { |
0bf4aa26 | 357 | assert_eq!(a.0.len(), b.0.len()); |
2c00a5a8 | 358 | let tcx = relation.tcx(); |
cdc7bbd5 | 359 | let types = tcx.mk_type_list(iter::zip(a.0, b.0).map(|(a, b)| relation.relate(a, b)))?; |
2c00a5a8 XL |
360 | Ok(GeneratorWitness(types)) |
361 | } | |
362 | } | |
363 | ||
5e7ed085 FG |
364 | impl<'tcx> Relate<'tcx> for ImplSubject<'tcx> { |
365 | #[inline] | |
366 | fn relate<R: TypeRelation<'tcx>>( | |
367 | relation: &mut R, | |
368 | a: ImplSubject<'tcx>, | |
369 | b: ImplSubject<'tcx>, | |
370 | ) -> RelateResult<'tcx, ImplSubject<'tcx>> { | |
371 | match (a, b) { | |
372 | (ImplSubject::Trait(trait_ref_a), ImplSubject::Trait(trait_ref_b)) => { | |
373 | let trait_ref = ty::TraitRef::relate(relation, trait_ref_a, trait_ref_b)?; | |
374 | Ok(ImplSubject::Trait(trait_ref)) | |
375 | } | |
376 | (ImplSubject::Inherent(ty_a), ImplSubject::Inherent(ty_b)) => { | |
377 | let ty = Ty::relate(relation, ty_a, ty_b)?; | |
378 | Ok(ImplSubject::Inherent(ty)) | |
379 | } | |
380 | (ImplSubject::Trait(_), ImplSubject::Inherent(_)) | |
381 | | (ImplSubject::Inherent(_), ImplSubject::Trait(_)) => { | |
382 | bug!("can not relate TraitRef and Ty"); | |
383 | } | |
384 | } | |
385 | } | |
386 | } | |
387 | ||
a7813a04 | 388 | impl<'tcx> Relate<'tcx> for Ty<'tcx> { |
f035d41b | 389 | #[inline] |
dc9dc135 XL |
390 | fn relate<R: TypeRelation<'tcx>>( |
391 | relation: &mut R, | |
f035d41b XL |
392 | a: Ty<'tcx>, |
393 | b: Ty<'tcx>, | |
dc9dc135 | 394 | ) -> RelateResult<'tcx, Ty<'tcx>> { |
c34b1796 AL |
395 | relation.tys(a, b) |
396 | } | |
397 | } | |
398 | ||
399 | /// The main "type relation" routine. Note that this does not handle | |
400 | /// inference artifacts, so you should filter those out before calling | |
401 | /// it. | |
a2a8927a | 402 | pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( |
dc9dc135 XL |
403 | relation: &mut R, |
404 | a: Ty<'tcx>, | |
405 | b: Ty<'tcx>, | |
406 | ) -> RelateResult<'tcx, Ty<'tcx>> { | |
c34b1796 | 407 | let tcx = relation.tcx(); |
532ac7d7 | 408 | debug!("super_relate_tys: a={:?} b={:?}", a, b); |
1b1a35ee | 409 | match (a.kind(), b.kind()) { |
dfeec247 | 410 | (&ty::Infer(_), _) | (_, &ty::Infer(_)) => { |
c34b1796 | 411 | // The caller should handle these cases! |
54a0048b | 412 | bug!("var types encountered in super_relate_tys") |
c34b1796 AL |
413 | } |
414 | ||
a1dfa0c6 XL |
415 | (ty::Bound(..), _) | (_, ty::Bound(..)) => { |
416 | bug!("bound types encountered in super_relate_tys") | |
417 | } | |
418 | ||
f035d41b | 419 | (&ty::Error(_), _) | (_, &ty::Error(_)) => Ok(tcx.ty_error()), |
c34b1796 | 420 | |
dfeec247 XL |
421 | (&ty::Never, _) |
422 | | (&ty::Char, _) | |
423 | | (&ty::Bool, _) | |
424 | | (&ty::Int(_), _) | |
425 | | (&ty::Uint(_), _) | |
426 | | (&ty::Float(_), _) | |
427 | | (&ty::Str, _) | |
c34b1796 AL |
428 | if a == b => |
429 | { | |
430 | Ok(a) | |
431 | } | |
432 | ||
dfeec247 | 433 | (&ty::Param(ref a_p), &ty::Param(ref b_p)) if a_p.index == b_p.index => Ok(a), |
c34b1796 | 434 | |
dfeec247 | 435 | (ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a), |
a1dfa0c6 | 436 | |
dfeec247 | 437 | (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs)) if a_def == b_def => { |
5e7ed085 | 438 | let substs = relation.relate_item_substs(a_def.did(), a_substs, b_substs)?; |
9e0c209e | 439 | Ok(tcx.mk_adt(a_def, substs)) |
c34b1796 AL |
440 | } |
441 | ||
dfeec247 | 442 | (&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(tcx.mk_foreign(a_id)), |
abe05a73 | 443 | |
f2b60f7d FG |
444 | (&ty::Dynamic(a_obj, a_region, a_repr), &ty::Dynamic(b_obj, b_region, b_repr)) |
445 | if a_repr == b_repr => | |
446 | { | |
dfeec247 | 447 | let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| { |
17df50a5 XL |
448 | relation.relate_with_variance( |
449 | ty::Contravariant, | |
450 | ty::VarianceDiagInfo::default(), | |
451 | a_region, | |
452 | b_region, | |
453 | ) | |
dfeec247 | 454 | })?; |
f2b60f7d | 455 | Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound, a_repr)) |
c34b1796 AL |
456 | } |
457 | ||
dfeec247 | 458 | (&ty::Generator(a_id, a_substs, movability), &ty::Generator(b_id, b_substs, _)) |
ea8adc8c XL |
459 | if a_id == b_id => |
460 | { | |
b7449926 | 461 | // All Generator types with the same id represent |
ea8adc8c XL |
462 | // the (anonymous) type of the same generator expression. So |
463 | // all of their regions should be equated. | |
f035d41b | 464 | let substs = relation.relate(a_substs, b_substs)?; |
94b46f34 | 465 | Ok(tcx.mk_generator(a_id, substs, movability)) |
ea8adc8c XL |
466 | } |
467 | ||
dfeec247 | 468 | (&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => { |
2c00a5a8 XL |
469 | // Wrap our types with a temporary GeneratorWitness struct |
470 | // inside the binder so we can related them | |
83c7162d XL |
471 | let a_types = a_types.map_bound(GeneratorWitness); |
472 | let b_types = b_types.map_bound(GeneratorWitness); | |
2c00a5a8 | 473 | // Then remove the GeneratorWitness for the result |
f035d41b | 474 | let types = relation.relate(a_types, b_types)?.map_bound(|witness| witness.0); |
2c00a5a8 XL |
475 | Ok(tcx.mk_generator_witness(types)) |
476 | } | |
477 | ||
dfeec247 | 478 | (&ty::Closure(a_id, a_substs), &ty::Closure(b_id, b_substs)) if a_id == b_id => { |
b7449926 | 479 | // All Closure types with the same id represent |
c34b1796 AL |
480 | // the (anonymous) type of the same closure expression. So |
481 | // all of their regions should be equated. | |
f035d41b | 482 | let substs = relation.relate(a_substs, b_substs)?; |
e74abb32 | 483 | Ok(tcx.mk_closure(a_id, &substs)) |
c34b1796 AL |
484 | } |
485 | ||
f035d41b | 486 | (&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => { |
a2a8927a | 487 | let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?; |
c1a9b12d | 488 | Ok(tcx.mk_ptr(mt)) |
c34b1796 AL |
489 | } |
490 | ||
dfeec247 | 491 | (&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => { |
17df50a5 XL |
492 | let r = relation.relate_with_variance( |
493 | ty::Contravariant, | |
494 | ty::VarianceDiagInfo::default(), | |
495 | a_r, | |
496 | b_r, | |
497 | )?; | |
94b46f34 XL |
498 | let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl }; |
499 | let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl }; | |
a2a8927a | 500 | let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?; |
9e0c209e | 501 | Ok(tcx.mk_ref(r, mt)) |
c34b1796 AL |
502 | } |
503 | ||
dfeec247 | 504 | (&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => { |
f035d41b XL |
505 | let t = relation.relate(a_t, b_t)?; |
506 | match relation.relate(sz_a, sz_b) { | |
dc9dc135 XL |
507 | Ok(sz) => Ok(tcx.mk_ty(ty::Array(t, sz))), |
508 | Err(err) => { | |
509 | // Check whether the lengths are both concrete/known values, | |
510 | // but are unequal, for better diagnostics. | |
6a06907d XL |
511 | // |
512 | // It might seem dubious to eagerly evaluate these constants here, | |
513 | // we however cannot end up with errors in `Relate` during both | |
514 | // `type_of` and `predicates_of`. This means that evaluating the | |
515 | // constants should not cause cycle errors here. | |
416331ca XL |
516 | let sz_a = sz_a.try_eval_usize(tcx, relation.param_env()); |
517 | let sz_b = sz_b.try_eval_usize(tcx, relation.param_env()); | |
518 | match (sz_a, sz_b) { | |
cdc7bbd5 XL |
519 | (Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => Err( |
520 | TypeError::FixedArraySize(expected_found(relation, sz_a_val, sz_b_val)), | |
521 | ), | |
ba9703b0 | 522 | _ => Err(err), |
ea8adc8c | 523 | } |
ea8adc8c | 524 | } |
c34b1796 AL |
525 | } |
526 | } | |
527 | ||
dfeec247 | 528 | (&ty::Slice(a_t), &ty::Slice(b_t)) => { |
f035d41b | 529 | let t = relation.relate(a_t, b_t)?; |
c1a9b12d | 530 | Ok(tcx.mk_slice(t)) |
c34b1796 AL |
531 | } |
532 | ||
dfeec247 | 533 | (&ty::Tuple(as_), &ty::Tuple(bs)) => { |
c34b1796 | 534 | if as_.len() == bs.len() { |
5e7ed085 | 535 | Ok(tcx.mk_tup(iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)))?) |
9346a6ac | 536 | } else if !(as_.is_empty() || bs.is_empty()) { |
f035d41b | 537 | Err(TypeError::TupleSize(expected_found(relation, as_.len(), bs.len()))) |
c34b1796 | 538 | } else { |
f035d41b | 539 | Err(TypeError::Sorts(expected_found(relation, a, b))) |
c34b1796 AL |
540 | } |
541 | } | |
542 | ||
b7449926 | 543 | (&ty::FnDef(a_def_id, a_substs), &ty::FnDef(b_def_id, b_substs)) |
54a0048b SL |
544 | if a_def_id == b_def_id => |
545 | { | |
041b39d2 XL |
546 | let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?; |
547 | Ok(tcx.mk_fn_def(a_def_id, substs)) | |
54a0048b SL |
548 | } |
549 | ||
dfeec247 | 550 | (&ty::FnPtr(a_fty), &ty::FnPtr(b_fty)) => { |
f035d41b | 551 | let fty = relation.relate(a_fty, b_fty)?; |
54a0048b | 552 | Ok(tcx.mk_fn_ptr(fty)) |
c34b1796 AL |
553 | } |
554 | ||
a1dfa0c6 | 555 | // these two are already handled downstream in case of lazy normalization |
f035d41b | 556 | (&ty::Projection(a_data), &ty::Projection(b_data)) => { |
54a0048b | 557 | let projection_ty = relation.relate(a_data, b_data)?; |
041b39d2 | 558 | Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs)) |
c34b1796 AL |
559 | } |
560 | ||
b7449926 | 561 | (&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs)) |
5bcae85e SL |
562 | if a_def_id == b_def_id => |
563 | { | |
04454e1e | 564 | let substs = relate_substs(relation, a_substs, b_substs)?; |
b7449926 | 565 | Ok(tcx.mk_opaque(a_def_id, substs)) |
5bcae85e SL |
566 | } |
567 | ||
f035d41b | 568 | _ => Err(TypeError::Sorts(expected_found(relation, a, b))), |
c34b1796 AL |
569 | } |
570 | } | |
571 | ||
48663c56 XL |
572 | /// The main "const relation" routine. Note that this does not handle |
573 | /// inference artifacts, so you should filter those out before calling | |
574 | /// it. | |
a2a8927a | 575 | pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( |
48663c56 | 576 | relation: &mut R, |
f2b60f7d FG |
577 | mut a: ty::Const<'tcx>, |
578 | mut b: ty::Const<'tcx>, | |
5099ac24 | 579 | ) -> RelateResult<'tcx, ty::Const<'tcx>> { |
f9f354fc | 580 | debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b); |
48663c56 XL |
581 | let tcx = relation.tcx(); |
582 | ||
923072b8 FG |
583 | let a_ty; |
584 | let b_ty; | |
585 | if relation.tcx().features().adt_const_params { | |
586 | a_ty = tcx.normalize_erasing_regions(relation.param_env(), a.ty()); | |
587 | b_ty = tcx.normalize_erasing_regions(relation.param_env(), b.ty()); | |
588 | } else { | |
589 | a_ty = tcx.erase_regions(a.ty()); | |
590 | b_ty = tcx.erase_regions(b.ty()); | |
591 | } | |
6a06907d XL |
592 | if a_ty != b_ty { |
593 | relation.tcx().sess.delay_span_bug( | |
594 | DUMMY_SP, | |
595 | &format!("cannot relate constants of different types: {} != {}", a_ty, b_ty), | |
596 | ); | |
597 | } | |
dc9dc135 | 598 | |
f2b60f7d FG |
599 | // HACK(const_generics): We still need to eagerly evaluate consts when |
600 | // relating them because during `normalize_param_env_or_error`, | |
601 | // we may relate an evaluated constant in a obligation against | |
602 | // an unnormalized (i.e. unevaluated) const in the param-env. | |
603 | // FIXME(generic_const_exprs): Once we always lazily unify unevaluated constants | |
604 | // these `eval` calls can be removed. | |
605 | if !relation.tcx().features().generic_const_exprs { | |
606 | a = a.eval(tcx, relation.param_env()); | |
607 | b = b.eval(tcx, relation.param_env()); | |
608 | } | |
ba9703b0 | 609 | |
e74abb32 XL |
610 | // Currently, the values that can be unified are primitive types, |
611 | // and those that derive both `PartialEq` and `Eq`, corresponding | |
ba9703b0 | 612 | // to structural-match types. |
923072b8 | 613 | let is_match = match (a.kind(), b.kind()) { |
60c5eb7d | 614 | (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => { |
48663c56 XL |
615 | // The caller should handle these cases! |
616 | bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b) | |
617 | } | |
ba9703b0 | 618 | |
6a06907d XL |
619 | (ty::ConstKind::Error(_), _) => return Ok(a), |
620 | (_, ty::ConstKind::Error(_)) => return Ok(b), | |
ba9703b0 | 621 | |
6a06907d XL |
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, | |
923072b8 | 624 | (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => a_val == b_val, |
48663c56 | 625 | |
cdc7bbd5 | 626 | (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) |
94222f64 | 627 | if tcx.features().generic_const_exprs => |
cdc7bbd5 | 628 | { |
f2b60f7d | 629 | tcx.try_unify_abstract_consts(relation.param_env().and((au, bu))) |
1b1a35ee XL |
630 | } |
631 | ||
632 | // While this is slightly incorrect, it shouldn't matter for `min_const_generics` | |
94222f64 | 633 | // and is the better alternative to waiting until `generic_const_exprs` can |
1b1a35ee | 634 | // be stabilized. |
cdc7bbd5 XL |
635 | (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) |
636 | if au.def == bu.def && au.promoted == bu.promoted => | |
637 | { | |
f2b60f7d FG |
638 | assert_eq!(au.promoted, ()); |
639 | ||
17df50a5 XL |
640 | let substs = relation.relate_with_variance( |
641 | ty::Variance::Invariant, | |
642 | ty::VarianceDiagInfo::default(), | |
5099ac24 FG |
643 | au.substs, |
644 | bu.substs, | |
17df50a5 | 645 | )?; |
5099ac24 | 646 | return Ok(tcx.mk_const(ty::ConstS { |
923072b8 | 647 | kind: ty::ConstKind::Unevaluated(ty::Unevaluated { |
cdc7bbd5 | 648 | def: au.def, |
5099ac24 | 649 | substs, |
f2b60f7d | 650 | promoted: (), |
cdc7bbd5 | 651 | }), |
5099ac24 | 652 | ty: a.ty(), |
6a06907d | 653 | })); |
e74abb32 | 654 | } |
6a06907d | 655 | _ => false, |
e74abb32 | 656 | }; |
6a06907d XL |
657 | if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(expected_found(relation, a, b))) } |
658 | } | |
659 | ||
cdc7bbd5 | 660 | impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>> { |
dc9dc135 XL |
661 | fn relate<R: TypeRelation<'tcx>>( |
662 | relation: &mut R, | |
f035d41b XL |
663 | a: Self, |
664 | b: Self, | |
dc9dc135 | 665 | ) -> RelateResult<'tcx, Self> { |
f9f354fc XL |
666 | let tcx = relation.tcx(); |
667 | ||
668 | // FIXME: this is wasteful, but want to do a perf run to see how slow it is. | |
669 | // We need to perform this deduplication as we sometimes generate duplicate projections | |
670 | // in `a`. | |
671 | let mut a_v: Vec<_> = a.into_iter().collect(); | |
672 | let mut b_v: Vec<_> = b.into_iter().collect(); | |
fc512014 XL |
673 | // `skip_binder` here is okay because `stable_cmp` doesn't look at binders |
674 | a_v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder())); | |
f9f354fc | 675 | a_v.dedup(); |
fc512014 | 676 | b_v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder())); |
f9f354fc XL |
677 | b_v.dedup(); |
678 | if a_v.len() != b_v.len() { | |
476ff2be SL |
679 | return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))); |
680 | } | |
681 | ||
cdc7bbd5 | 682 | let v = iter::zip(a_v, b_v).map(|(ep_a, ep_b)| { |
9fa01778 | 683 | use crate::ty::ExistentialPredicate::*; |
fc512014 | 684 | match (ep_a.skip_binder(), ep_b.skip_binder()) { |
cdc7bbd5 XL |
685 | (Trait(a), Trait(b)) => Ok(ep_a |
686 | .rebind(Trait(relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder()))), | |
687 | (Projection(a), Projection(b)) => Ok(ep_a.rebind(Projection( | |
fc512014 XL |
688 | relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(), |
689 | ))), | |
690 | (AutoTrait(a), AutoTrait(b)) if a == b => Ok(ep_a.rebind(AutoTrait(a))), | |
dfeec247 | 691 | _ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))), |
476ff2be SL |
692 | } |
693 | }); | |
6a06907d | 694 | tcx.mk_poly_existential_predicates(v) |
476ff2be SL |
695 | } |
696 | } | |
697 | ||
a7813a04 | 698 | impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> { |
dc9dc135 XL |
699 | fn relate<R: TypeRelation<'tcx>>( |
700 | relation: &mut R, | |
f035d41b XL |
701 | a: ty::ClosureSubsts<'tcx>, |
702 | b: ty::ClosureSubsts<'tcx>, | |
dc9dc135 | 703 | ) -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>> { |
04454e1e | 704 | let substs = relate_substs(relation, a.substs, b.substs)?; |
94b46f34 | 705 | Ok(ty::ClosureSubsts { substs }) |
c1a9b12d SL |
706 | } |
707 | } | |
708 | ||
94b46f34 | 709 | impl<'tcx> Relate<'tcx> for ty::GeneratorSubsts<'tcx> { |
dc9dc135 XL |
710 | fn relate<R: TypeRelation<'tcx>>( |
711 | relation: &mut R, | |
f035d41b XL |
712 | a: ty::GeneratorSubsts<'tcx>, |
713 | b: ty::GeneratorSubsts<'tcx>, | |
dc9dc135 | 714 | ) -> RelateResult<'tcx, ty::GeneratorSubsts<'tcx>> { |
04454e1e | 715 | let substs = relate_substs(relation, a.substs, b.substs)?; |
94b46f34 | 716 | Ok(ty::GeneratorSubsts { substs }) |
ea8adc8c XL |
717 | } |
718 | } | |
719 | ||
532ac7d7 | 720 | impl<'tcx> Relate<'tcx> for SubstsRef<'tcx> { |
dc9dc135 XL |
721 | fn relate<R: TypeRelation<'tcx>>( |
722 | relation: &mut R, | |
f035d41b XL |
723 | a: SubstsRef<'tcx>, |
724 | b: SubstsRef<'tcx>, | |
dc9dc135 | 725 | ) -> RelateResult<'tcx, SubstsRef<'tcx>> { |
04454e1e | 726 | relate_substs(relation, a, b) |
54a0048b SL |
727 | } |
728 | } | |
729 | ||
7cac9316 | 730 | impl<'tcx> Relate<'tcx> for ty::Region<'tcx> { |
dc9dc135 XL |
731 | fn relate<R: TypeRelation<'tcx>>( |
732 | relation: &mut R, | |
f035d41b XL |
733 | a: ty::Region<'tcx>, |
734 | b: ty::Region<'tcx>, | |
dc9dc135 | 735 | ) -> RelateResult<'tcx, ty::Region<'tcx>> { |
f035d41b | 736 | relation.regions(a, b) |
c34b1796 AL |
737 | } |
738 | } | |
739 | ||
5099ac24 | 740 | impl<'tcx> Relate<'tcx> for ty::Const<'tcx> { |
dc9dc135 XL |
741 | fn relate<R: TypeRelation<'tcx>>( |
742 | relation: &mut R, | |
5099ac24 FG |
743 | a: ty::Const<'tcx>, |
744 | b: ty::Const<'tcx>, | |
745 | ) -> RelateResult<'tcx, ty::Const<'tcx>> { | |
f035d41b | 746 | relation.consts(a, b) |
48663c56 XL |
747 | } |
748 | } | |
749 | ||
cdc7bbd5 | 750 | impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder<'tcx, T> { |
dc9dc135 XL |
751 | fn relate<R: TypeRelation<'tcx>>( |
752 | relation: &mut R, | |
cdc7bbd5 XL |
753 | a: ty::Binder<'tcx, T>, |
754 | b: ty::Binder<'tcx, T>, | |
755 | ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> { | |
c34b1796 AL |
756 | relation.binders(a, b) |
757 | } | |
758 | } | |
759 | ||
e74abb32 | 760 | impl<'tcx> Relate<'tcx> for GenericArg<'tcx> { |
dc9dc135 | 761 | fn relate<R: TypeRelation<'tcx>>( |
0531ce1d | 762 | relation: &mut R, |
f035d41b XL |
763 | a: GenericArg<'tcx>, |
764 | b: GenericArg<'tcx>, | |
e74abb32 | 765 | ) -> RelateResult<'tcx, GenericArg<'tcx>> { |
0531ce1d | 766 | match (a.unpack(), b.unpack()) { |
e74abb32 | 767 | (GenericArgKind::Lifetime(a_lt), GenericArgKind::Lifetime(b_lt)) => { |
f035d41b | 768 | Ok(relation.relate(a_lt, b_lt)?.into()) |
0531ce1d | 769 | } |
e74abb32 | 770 | (GenericArgKind::Type(a_ty), GenericArgKind::Type(b_ty)) => { |
f035d41b | 771 | Ok(relation.relate(a_ty, b_ty)?.into()) |
0531ce1d | 772 | } |
e74abb32 | 773 | (GenericArgKind::Const(a_ct), GenericArgKind::Const(b_ct)) => { |
f035d41b | 774 | Ok(relation.relate(a_ct, b_ct)?.into()) |
48663c56 | 775 | } |
e74abb32 | 776 | (GenericArgKind::Lifetime(unpacked), x) => { |
0bf4aa26 XL |
777 | bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x) |
778 | } | |
e74abb32 | 779 | (GenericArgKind::Type(unpacked), x) => { |
0bf4aa26 XL |
780 | bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x) |
781 | } | |
e74abb32 | 782 | (GenericArgKind::Const(unpacked), x) => { |
48663c56 | 783 | bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x) |
532ac7d7 | 784 | } |
0531ce1d XL |
785 | } |
786 | } | |
787 | } | |
788 | ||
3c0e092e XL |
789 | impl<'tcx> Relate<'tcx> for ty::ImplPolarity { |
790 | fn relate<R: TypeRelation<'tcx>>( | |
791 | relation: &mut R, | |
792 | a: ty::ImplPolarity, | |
793 | b: ty::ImplPolarity, | |
794 | ) -> RelateResult<'tcx, ty::ImplPolarity> { | |
795 | if a != b { | |
796 | Err(TypeError::PolarityMismatch(expected_found(relation, a, b))) | |
797 | } else { | |
798 | Ok(a) | |
799 | } | |
800 | } | |
801 | } | |
802 | ||
a1dfa0c6 | 803 | impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> { |
dc9dc135 | 804 | fn relate<R: TypeRelation<'tcx>>( |
a1dfa0c6 | 805 | relation: &mut R, |
f035d41b XL |
806 | a: ty::TraitPredicate<'tcx>, |
807 | b: ty::TraitPredicate<'tcx>, | |
dc9dc135 | 808 | ) -> RelateResult<'tcx, ty::TraitPredicate<'tcx>> { |
94222f64 XL |
809 | Ok(ty::TraitPredicate { |
810 | trait_ref: relation.relate(a.trait_ref, b.trait_ref)?, | |
811 | constness: relation.relate(a.constness, b.constness)?, | |
3c0e092e | 812 | polarity: relation.relate(a.polarity, b.polarity)?, |
94222f64 | 813 | }) |
a1dfa0c6 XL |
814 | } |
815 | } | |
816 | ||
f2b60f7d | 817 | impl<'tcx> Relate<'tcx> for Term<'tcx> { |
5099ac24 FG |
818 | fn relate<R: TypeRelation<'tcx>>( |
819 | relation: &mut R, | |
820 | a: Self, | |
821 | b: Self, | |
822 | ) -> RelateResult<'tcx, Self> { | |
f2b60f7d FG |
823 | Ok(match (a.unpack(), b.unpack()) { |
824 | (TermKind::Ty(a), TermKind::Ty(b)) => relation.relate(a, b)?.into(), | |
825 | (TermKind::Const(a), TermKind::Const(b)) => relation.relate(a, b)?.into(), | |
5099ac24 FG |
826 | _ => return Err(TypeError::Mismatch), |
827 | }) | |
828 | } | |
829 | } | |
830 | ||
a1dfa0c6 | 831 | impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> { |
dc9dc135 | 832 | fn relate<R: TypeRelation<'tcx>>( |
a1dfa0c6 | 833 | relation: &mut R, |
f035d41b XL |
834 | a: ty::ProjectionPredicate<'tcx>, |
835 | b: ty::ProjectionPredicate<'tcx>, | |
dc9dc135 | 836 | ) -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>> { |
a1dfa0c6 | 837 | Ok(ty::ProjectionPredicate { |
f035d41b | 838 | projection_ty: relation.relate(a.projection_ty, b.projection_ty)?, |
5099ac24 | 839 | term: relation.relate(a.term, b.term)?, |
a1dfa0c6 XL |
840 | }) |
841 | } | |
842 | } | |
843 | ||
c34b1796 AL |
844 | /////////////////////////////////////////////////////////////////////////// |
845 | // Error handling | |
846 | ||
a2a8927a | 847 | pub fn expected_found<'tcx, R, T>(relation: &mut R, a: T, b: T) -> ExpectedFound<T> |
dc9dc135 XL |
848 | where |
849 | R: TypeRelation<'tcx>, | |
c34b1796 | 850 | { |
a2a8927a | 851 | ExpectedFound::new(relation.a_is_expected(), a, b) |
c34b1796 | 852 | } |