]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/ty/relate.rs
New upstream version 1.63.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};
5e7ed085 9use crate::ty::{self, ImplSubject, Term, 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
f035d41b 348#[derive(Copy, Debug, Clone, TypeFoldable)]
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
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 573pub 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 649impl<'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 687impl<'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 698impl<'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 709impl<'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 719impl<'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 729impl<'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 739impl<'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 749impl<'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
778impl<'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 792impl<'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
806impl<'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 820impl<'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 836pub fn expected_found<'tcx, R, T>(relation: &mut R, a: T, b: T) -> ExpectedFound<T>
dc9dc135
XL
837where
838 R: TypeRelation<'tcx>,
c34b1796 839{
a2a8927a 840 ExpectedFound::new(relation.a_is_expected(), a, b)
c34b1796 841}