]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/ty/relate.rs
New upstream version 1.65.0+dfsg1
[rustc.git] / compiler / rustc_middle / src / ty / relate.rs
CommitLineData
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 7use crate::ty::error::{ExpectedFound, TypeError};
a2a8927a 8use crate::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
f2b60f7d 9use crate::ty::{self, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable};
dfeec247
XL
10use rustc_hir as ast;
11use rustc_hir::def_id::DefId;
f9f354fc 12use rustc_span::DUMMY_SP;
83c7162d 13use rustc_target::spec::abi;
dfeec247 14use std::iter;
c34b1796 15
e9174d1e 16pub type RelateResult<'tcx, T> = Result<T, TypeError<'tcx>>;
c34b1796 17
62682a34
SL
18#[derive(Clone, Debug)]
19pub enum Cause {
c1a9b12d 20 ExistentialRegionBound, // relating an existential region bound
62682a34
SL
21}
22
dc9dc135
XL
23pub 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 104pub 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
115pub 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 138pub 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
148pub 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 173impl<'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
229impl<'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 243impl<'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 257impl<'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 267impl<'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 286impl<'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 316impl<'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 332impl<'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 349struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
2c00a5a8 350
2c00a5a8 351impl<'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
364impl<'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 388impl<'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 402pub 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 575pub 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 660impl<'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 698impl<'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 709impl<'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 720impl<'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 730impl<'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 740impl<'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 750impl<'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 760impl<'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
789impl<'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 803impl<'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 817impl<'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 831impl<'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 847pub fn expected_found<'tcx, R, T>(relation: &mut R, a: T, b: T) -> ExpectedFound<T>
dc9dc135
XL
848where
849 R: TypeRelation<'tcx>,
c34b1796 850{
a2a8927a 851 ExpectedFound::new(relation.a_is_expected(), a, b)
c34b1796 852}