]>
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}; |
5e7ed085 | 9 | use crate::ty::{self, ImplSubject, Term, 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 | ||
f035d41b | 348 | #[derive(Copy, Debug, Clone, TypeFoldable)] |
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 | |
f035d41b | 444 | (&ty::Dynamic(a_obj, a_region), &ty::Dynamic(b_obj, b_region)) => { |
dfeec247 | 445 | let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| { |
17df50a5 XL |
446 | relation.relate_with_variance( |
447 | ty::Contravariant, | |
448 | ty::VarianceDiagInfo::default(), | |
449 | a_region, | |
450 | b_region, | |
451 | ) | |
dfeec247 | 452 | })?; |
476ff2be | 453 | Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound)) |
c34b1796 AL |
454 | } |
455 | ||
dfeec247 | 456 | (&ty::Generator(a_id, a_substs, movability), &ty::Generator(b_id, b_substs, _)) |
ea8adc8c XL |
457 | if a_id == b_id => |
458 | { | |
b7449926 | 459 | // All Generator types with the same id represent |
ea8adc8c XL |
460 | // the (anonymous) type of the same generator expression. So |
461 | // all of their regions should be equated. | |
f035d41b | 462 | let substs = relation.relate(a_substs, b_substs)?; |
94b46f34 | 463 | Ok(tcx.mk_generator(a_id, substs, movability)) |
ea8adc8c XL |
464 | } |
465 | ||
dfeec247 | 466 | (&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => { |
2c00a5a8 XL |
467 | // Wrap our types with a temporary GeneratorWitness struct |
468 | // inside the binder so we can related them | |
83c7162d XL |
469 | let a_types = a_types.map_bound(GeneratorWitness); |
470 | let b_types = b_types.map_bound(GeneratorWitness); | |
2c00a5a8 | 471 | // Then remove the GeneratorWitness for the result |
f035d41b | 472 | let types = relation.relate(a_types, b_types)?.map_bound(|witness| witness.0); |
2c00a5a8 XL |
473 | Ok(tcx.mk_generator_witness(types)) |
474 | } | |
475 | ||
dfeec247 | 476 | (&ty::Closure(a_id, a_substs), &ty::Closure(b_id, b_substs)) if a_id == b_id => { |
b7449926 | 477 | // All Closure types with the same id represent |
c34b1796 AL |
478 | // the (anonymous) type of the same closure expression. So |
479 | // all of their regions should be equated. | |
f035d41b | 480 | let substs = relation.relate(a_substs, b_substs)?; |
e74abb32 | 481 | Ok(tcx.mk_closure(a_id, &substs)) |
c34b1796 AL |
482 | } |
483 | ||
f035d41b | 484 | (&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => { |
a2a8927a | 485 | let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?; |
c1a9b12d | 486 | Ok(tcx.mk_ptr(mt)) |
c34b1796 AL |
487 | } |
488 | ||
dfeec247 | 489 | (&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => { |
17df50a5 XL |
490 | let r = relation.relate_with_variance( |
491 | ty::Contravariant, | |
492 | ty::VarianceDiagInfo::default(), | |
493 | a_r, | |
494 | b_r, | |
495 | )?; | |
94b46f34 XL |
496 | let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl }; |
497 | let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl }; | |
a2a8927a | 498 | let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?; |
9e0c209e | 499 | Ok(tcx.mk_ref(r, mt)) |
c34b1796 AL |
500 | } |
501 | ||
dfeec247 | 502 | (&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => { |
f035d41b XL |
503 | let t = relation.relate(a_t, b_t)?; |
504 | match relation.relate(sz_a, sz_b) { | |
dc9dc135 XL |
505 | Ok(sz) => Ok(tcx.mk_ty(ty::Array(t, sz))), |
506 | Err(err) => { | |
507 | // Check whether the lengths are both concrete/known values, | |
508 | // but are unequal, for better diagnostics. | |
6a06907d XL |
509 | // |
510 | // It might seem dubious to eagerly evaluate these constants here, | |
511 | // we however cannot end up with errors in `Relate` during both | |
512 | // `type_of` and `predicates_of`. This means that evaluating the | |
513 | // constants should not cause cycle errors here. | |
416331ca XL |
514 | let sz_a = sz_a.try_eval_usize(tcx, relation.param_env()); |
515 | let sz_b = sz_b.try_eval_usize(tcx, relation.param_env()); | |
516 | match (sz_a, sz_b) { | |
cdc7bbd5 XL |
517 | (Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => Err( |
518 | TypeError::FixedArraySize(expected_found(relation, sz_a_val, sz_b_val)), | |
519 | ), | |
ba9703b0 | 520 | _ => Err(err), |
ea8adc8c | 521 | } |
ea8adc8c | 522 | } |
c34b1796 AL |
523 | } |
524 | } | |
525 | ||
dfeec247 | 526 | (&ty::Slice(a_t), &ty::Slice(b_t)) => { |
f035d41b | 527 | let t = relation.relate(a_t, b_t)?; |
c1a9b12d | 528 | Ok(tcx.mk_slice(t)) |
c34b1796 AL |
529 | } |
530 | ||
dfeec247 | 531 | (&ty::Tuple(as_), &ty::Tuple(bs)) => { |
c34b1796 | 532 | if as_.len() == bs.len() { |
5e7ed085 | 533 | Ok(tcx.mk_tup(iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)))?) |
9346a6ac | 534 | } else if !(as_.is_empty() || bs.is_empty()) { |
f035d41b | 535 | Err(TypeError::TupleSize(expected_found(relation, as_.len(), bs.len()))) |
c34b1796 | 536 | } else { |
f035d41b | 537 | Err(TypeError::Sorts(expected_found(relation, a, b))) |
c34b1796 AL |
538 | } |
539 | } | |
540 | ||
b7449926 | 541 | (&ty::FnDef(a_def_id, a_substs), &ty::FnDef(b_def_id, b_substs)) |
54a0048b SL |
542 | if a_def_id == b_def_id => |
543 | { | |
041b39d2 XL |
544 | let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?; |
545 | Ok(tcx.mk_fn_def(a_def_id, substs)) | |
54a0048b SL |
546 | } |
547 | ||
dfeec247 | 548 | (&ty::FnPtr(a_fty), &ty::FnPtr(b_fty)) => { |
f035d41b | 549 | let fty = relation.relate(a_fty, b_fty)?; |
54a0048b | 550 | Ok(tcx.mk_fn_ptr(fty)) |
c34b1796 AL |
551 | } |
552 | ||
a1dfa0c6 | 553 | // these two are already handled downstream in case of lazy normalization |
f035d41b | 554 | (&ty::Projection(a_data), &ty::Projection(b_data)) => { |
54a0048b | 555 | let projection_ty = relation.relate(a_data, b_data)?; |
041b39d2 | 556 | Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs)) |
c34b1796 AL |
557 | } |
558 | ||
b7449926 | 559 | (&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs)) |
5bcae85e SL |
560 | if a_def_id == b_def_id => |
561 | { | |
04454e1e | 562 | let substs = relate_substs(relation, a_substs, b_substs)?; |
b7449926 | 563 | Ok(tcx.mk_opaque(a_def_id, substs)) |
5bcae85e SL |
564 | } |
565 | ||
f035d41b | 566 | _ => Err(TypeError::Sorts(expected_found(relation, a, b))), |
c34b1796 AL |
567 | } |
568 | } | |
569 | ||
48663c56 XL |
570 | /// The main "const relation" routine. Note that this does not handle |
571 | /// inference artifacts, so you should filter those out before calling | |
572 | /// it. | |
a2a8927a | 573 | pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( |
48663c56 | 574 | relation: &mut R, |
5099ac24 FG |
575 | a: ty::Const<'tcx>, |
576 | b: ty::Const<'tcx>, | |
577 | ) -> RelateResult<'tcx, ty::Const<'tcx>> { | |
f9f354fc | 578 | debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b); |
48663c56 XL |
579 | let tcx = relation.tcx(); |
580 | ||
923072b8 FG |
581 | let a_ty; |
582 | let b_ty; | |
583 | if relation.tcx().features().adt_const_params { | |
584 | a_ty = tcx.normalize_erasing_regions(relation.param_env(), a.ty()); | |
585 | b_ty = tcx.normalize_erasing_regions(relation.param_env(), b.ty()); | |
586 | } else { | |
587 | a_ty = tcx.erase_regions(a.ty()); | |
588 | b_ty = tcx.erase_regions(b.ty()); | |
589 | } | |
6a06907d XL |
590 | if a_ty != b_ty { |
591 | relation.tcx().sess.delay_span_bug( | |
592 | DUMMY_SP, | |
593 | &format!("cannot relate constants of different types: {} != {}", a_ty, b_ty), | |
594 | ); | |
595 | } | |
dc9dc135 | 596 | |
5099ac24 | 597 | let eagerly_eval = |x: ty::Const<'tcx>| x.eval(tcx, relation.param_env()); |
6a06907d XL |
598 | let a = eagerly_eval(a); |
599 | let b = eagerly_eval(b); | |
ba9703b0 | 600 | |
e74abb32 XL |
601 | // Currently, the values that can be unified are primitive types, |
602 | // and those that derive both `PartialEq` and `Eq`, corresponding | |
ba9703b0 | 603 | // to structural-match types. |
923072b8 | 604 | let is_match = match (a.kind(), b.kind()) { |
60c5eb7d | 605 | (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => { |
48663c56 XL |
606 | // The caller should handle these cases! |
607 | bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b) | |
608 | } | |
ba9703b0 | 609 | |
6a06907d XL |
610 | (ty::ConstKind::Error(_), _) => return Ok(a), |
611 | (_, ty::ConstKind::Error(_)) => return Ok(b), | |
ba9703b0 | 612 | |
6a06907d XL |
613 | (ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) => a_p.index == b_p.index, |
614 | (ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2, | |
923072b8 | 615 | (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => a_val == b_val, |
48663c56 | 616 | |
cdc7bbd5 | 617 | (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) |
94222f64 | 618 | if tcx.features().generic_const_exprs => |
cdc7bbd5 | 619 | { |
5e7ed085 | 620 | tcx.try_unify_abstract_consts(relation.param_env().and((au.shrink(), bu.shrink()))) |
1b1a35ee XL |
621 | } |
622 | ||
623 | // While this is slightly incorrect, it shouldn't matter for `min_const_generics` | |
94222f64 | 624 | // and is the better alternative to waiting until `generic_const_exprs` can |
1b1a35ee | 625 | // be stabilized. |
cdc7bbd5 XL |
626 | (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) |
627 | if au.def == bu.def && au.promoted == bu.promoted => | |
628 | { | |
17df50a5 XL |
629 | let substs = relation.relate_with_variance( |
630 | ty::Variance::Invariant, | |
631 | ty::VarianceDiagInfo::default(), | |
5099ac24 FG |
632 | au.substs, |
633 | bu.substs, | |
17df50a5 | 634 | )?; |
5099ac24 | 635 | return Ok(tcx.mk_const(ty::ConstS { |
923072b8 | 636 | kind: ty::ConstKind::Unevaluated(ty::Unevaluated { |
cdc7bbd5 | 637 | def: au.def, |
5099ac24 | 638 | substs, |
cdc7bbd5 XL |
639 | promoted: au.promoted, |
640 | }), | |
5099ac24 | 641 | ty: a.ty(), |
6a06907d | 642 | })); |
e74abb32 | 643 | } |
6a06907d | 644 | _ => false, |
e74abb32 | 645 | }; |
6a06907d XL |
646 | if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(expected_found(relation, a, b))) } |
647 | } | |
648 | ||
cdc7bbd5 | 649 | impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>> { |
dc9dc135 XL |
650 | fn relate<R: TypeRelation<'tcx>>( |
651 | relation: &mut R, | |
f035d41b XL |
652 | a: Self, |
653 | b: Self, | |
dc9dc135 | 654 | ) -> RelateResult<'tcx, Self> { |
f9f354fc XL |
655 | let tcx = relation.tcx(); |
656 | ||
657 | // FIXME: this is wasteful, but want to do a perf run to see how slow it is. | |
658 | // We need to perform this deduplication as we sometimes generate duplicate projections | |
659 | // in `a`. | |
660 | let mut a_v: Vec<_> = a.into_iter().collect(); | |
661 | let mut b_v: Vec<_> = b.into_iter().collect(); | |
fc512014 XL |
662 | // `skip_binder` here is okay because `stable_cmp` doesn't look at binders |
663 | a_v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder())); | |
f9f354fc | 664 | a_v.dedup(); |
fc512014 | 665 | b_v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder())); |
f9f354fc XL |
666 | b_v.dedup(); |
667 | if a_v.len() != b_v.len() { | |
476ff2be SL |
668 | return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))); |
669 | } | |
670 | ||
cdc7bbd5 | 671 | let v = iter::zip(a_v, b_v).map(|(ep_a, ep_b)| { |
9fa01778 | 672 | use crate::ty::ExistentialPredicate::*; |
fc512014 | 673 | match (ep_a.skip_binder(), ep_b.skip_binder()) { |
cdc7bbd5 XL |
674 | (Trait(a), Trait(b)) => Ok(ep_a |
675 | .rebind(Trait(relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder()))), | |
676 | (Projection(a), Projection(b)) => Ok(ep_a.rebind(Projection( | |
fc512014 XL |
677 | relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(), |
678 | ))), | |
679 | (AutoTrait(a), AutoTrait(b)) if a == b => Ok(ep_a.rebind(AutoTrait(a))), | |
dfeec247 | 680 | _ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))), |
476ff2be SL |
681 | } |
682 | }); | |
6a06907d | 683 | tcx.mk_poly_existential_predicates(v) |
476ff2be SL |
684 | } |
685 | } | |
686 | ||
a7813a04 | 687 | impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> { |
dc9dc135 XL |
688 | fn relate<R: TypeRelation<'tcx>>( |
689 | relation: &mut R, | |
f035d41b XL |
690 | a: ty::ClosureSubsts<'tcx>, |
691 | b: ty::ClosureSubsts<'tcx>, | |
dc9dc135 | 692 | ) -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>> { |
04454e1e | 693 | let substs = relate_substs(relation, a.substs, b.substs)?; |
94b46f34 | 694 | Ok(ty::ClosureSubsts { substs }) |
c1a9b12d SL |
695 | } |
696 | } | |
697 | ||
94b46f34 | 698 | impl<'tcx> Relate<'tcx> for ty::GeneratorSubsts<'tcx> { |
dc9dc135 XL |
699 | fn relate<R: TypeRelation<'tcx>>( |
700 | relation: &mut R, | |
f035d41b XL |
701 | a: ty::GeneratorSubsts<'tcx>, |
702 | b: ty::GeneratorSubsts<'tcx>, | |
dc9dc135 | 703 | ) -> RelateResult<'tcx, ty::GeneratorSubsts<'tcx>> { |
04454e1e | 704 | let substs = relate_substs(relation, a.substs, b.substs)?; |
94b46f34 | 705 | Ok(ty::GeneratorSubsts { substs }) |
ea8adc8c XL |
706 | } |
707 | } | |
708 | ||
532ac7d7 | 709 | impl<'tcx> Relate<'tcx> for SubstsRef<'tcx> { |
dc9dc135 XL |
710 | fn relate<R: TypeRelation<'tcx>>( |
711 | relation: &mut R, | |
f035d41b XL |
712 | a: SubstsRef<'tcx>, |
713 | b: SubstsRef<'tcx>, | |
dc9dc135 | 714 | ) -> RelateResult<'tcx, SubstsRef<'tcx>> { |
04454e1e | 715 | relate_substs(relation, a, b) |
54a0048b SL |
716 | } |
717 | } | |
718 | ||
7cac9316 | 719 | impl<'tcx> Relate<'tcx> for ty::Region<'tcx> { |
dc9dc135 XL |
720 | fn relate<R: TypeRelation<'tcx>>( |
721 | relation: &mut R, | |
f035d41b XL |
722 | a: ty::Region<'tcx>, |
723 | b: ty::Region<'tcx>, | |
dc9dc135 | 724 | ) -> RelateResult<'tcx, ty::Region<'tcx>> { |
f035d41b | 725 | relation.regions(a, b) |
c34b1796 AL |
726 | } |
727 | } | |
728 | ||
5099ac24 | 729 | impl<'tcx> Relate<'tcx> for ty::Const<'tcx> { |
dc9dc135 XL |
730 | fn relate<R: TypeRelation<'tcx>>( |
731 | relation: &mut R, | |
5099ac24 FG |
732 | a: ty::Const<'tcx>, |
733 | b: ty::Const<'tcx>, | |
734 | ) -> RelateResult<'tcx, ty::Const<'tcx>> { | |
f035d41b | 735 | relation.consts(a, b) |
48663c56 XL |
736 | } |
737 | } | |
738 | ||
cdc7bbd5 | 739 | impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder<'tcx, T> { |
dc9dc135 XL |
740 | fn relate<R: TypeRelation<'tcx>>( |
741 | relation: &mut R, | |
cdc7bbd5 XL |
742 | a: ty::Binder<'tcx, T>, |
743 | b: ty::Binder<'tcx, T>, | |
744 | ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> { | |
c34b1796 AL |
745 | relation.binders(a, b) |
746 | } | |
747 | } | |
748 | ||
e74abb32 | 749 | impl<'tcx> Relate<'tcx> for GenericArg<'tcx> { |
dc9dc135 | 750 | fn relate<R: TypeRelation<'tcx>>( |
0531ce1d | 751 | relation: &mut R, |
f035d41b XL |
752 | a: GenericArg<'tcx>, |
753 | b: GenericArg<'tcx>, | |
e74abb32 | 754 | ) -> RelateResult<'tcx, GenericArg<'tcx>> { |
0531ce1d | 755 | match (a.unpack(), b.unpack()) { |
e74abb32 | 756 | (GenericArgKind::Lifetime(a_lt), GenericArgKind::Lifetime(b_lt)) => { |
f035d41b | 757 | Ok(relation.relate(a_lt, b_lt)?.into()) |
0531ce1d | 758 | } |
e74abb32 | 759 | (GenericArgKind::Type(a_ty), GenericArgKind::Type(b_ty)) => { |
f035d41b | 760 | Ok(relation.relate(a_ty, b_ty)?.into()) |
0531ce1d | 761 | } |
e74abb32 | 762 | (GenericArgKind::Const(a_ct), GenericArgKind::Const(b_ct)) => { |
f035d41b | 763 | Ok(relation.relate(a_ct, b_ct)?.into()) |
48663c56 | 764 | } |
e74abb32 | 765 | (GenericArgKind::Lifetime(unpacked), x) => { |
0bf4aa26 XL |
766 | bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x) |
767 | } | |
e74abb32 | 768 | (GenericArgKind::Type(unpacked), x) => { |
0bf4aa26 XL |
769 | bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x) |
770 | } | |
e74abb32 | 771 | (GenericArgKind::Const(unpacked), x) => { |
48663c56 | 772 | bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x) |
532ac7d7 | 773 | } |
0531ce1d XL |
774 | } |
775 | } | |
776 | } | |
777 | ||
3c0e092e XL |
778 | impl<'tcx> Relate<'tcx> for ty::ImplPolarity { |
779 | fn relate<R: TypeRelation<'tcx>>( | |
780 | relation: &mut R, | |
781 | a: ty::ImplPolarity, | |
782 | b: ty::ImplPolarity, | |
783 | ) -> RelateResult<'tcx, ty::ImplPolarity> { | |
784 | if a != b { | |
785 | Err(TypeError::PolarityMismatch(expected_found(relation, a, b))) | |
786 | } else { | |
787 | Ok(a) | |
788 | } | |
789 | } | |
790 | } | |
791 | ||
a1dfa0c6 | 792 | impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> { |
dc9dc135 | 793 | fn relate<R: TypeRelation<'tcx>>( |
a1dfa0c6 | 794 | relation: &mut R, |
f035d41b XL |
795 | a: ty::TraitPredicate<'tcx>, |
796 | b: ty::TraitPredicate<'tcx>, | |
dc9dc135 | 797 | ) -> RelateResult<'tcx, ty::TraitPredicate<'tcx>> { |
94222f64 XL |
798 | Ok(ty::TraitPredicate { |
799 | trait_ref: relation.relate(a.trait_ref, b.trait_ref)?, | |
800 | constness: relation.relate(a.constness, b.constness)?, | |
3c0e092e | 801 | polarity: relation.relate(a.polarity, b.polarity)?, |
94222f64 | 802 | }) |
a1dfa0c6 XL |
803 | } |
804 | } | |
805 | ||
5099ac24 FG |
806 | impl<'tcx> Relate<'tcx> for ty::Term<'tcx> { |
807 | fn relate<R: TypeRelation<'tcx>>( | |
808 | relation: &mut R, | |
809 | a: Self, | |
810 | b: Self, | |
811 | ) -> RelateResult<'tcx, Self> { | |
812 | Ok(match (a, b) { | |
813 | (Term::Ty(a), Term::Ty(b)) => relation.relate(a, b)?.into(), | |
814 | (Term::Const(a), Term::Const(b)) => relation.relate(a, b)?.into(), | |
815 | _ => return Err(TypeError::Mismatch), | |
816 | }) | |
817 | } | |
818 | } | |
819 | ||
a1dfa0c6 | 820 | impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> { |
dc9dc135 | 821 | fn relate<R: TypeRelation<'tcx>>( |
a1dfa0c6 | 822 | relation: &mut R, |
f035d41b XL |
823 | a: ty::ProjectionPredicate<'tcx>, |
824 | b: ty::ProjectionPredicate<'tcx>, | |
dc9dc135 | 825 | ) -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>> { |
a1dfa0c6 | 826 | Ok(ty::ProjectionPredicate { |
f035d41b | 827 | projection_ty: relation.relate(a.projection_ty, b.projection_ty)?, |
5099ac24 | 828 | term: relation.relate(a.term, b.term)?, |
a1dfa0c6 XL |
829 | }) |
830 | } | |
831 | } | |
832 | ||
c34b1796 AL |
833 | /////////////////////////////////////////////////////////////////////////// |
834 | // Error handling | |
835 | ||
a2a8927a | 836 | pub fn expected_found<'tcx, R, T>(relation: &mut R, a: T, b: T) -> ExpectedFound<T> |
dc9dc135 XL |
837 | where |
838 | R: TypeRelation<'tcx>, | |
c34b1796 | 839 | { |
a2a8927a | 840 | ExpectedFound::new(relation.a_is_expected(), a, b) |
c34b1796 | 841 | } |