]> git.proxmox.com Git - rustc.git/blame - src/librustc_middle/ty/relate.rs
New upstream version 1.46.0~beta.2+dfsg1
[rustc.git] / src / librustc_middle / 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::mir::interpret::{get_slice_bytes, ConstValue};
dfeec247 8use crate::ty::error::{ExpectedFound, TypeError};
e74abb32 9use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
9fa01778 10use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
dfeec247
XL
11use rustc_hir as ast;
12use rustc_hir::def_id::DefId;
f9f354fc 13use rustc_span::DUMMY_SP;
83c7162d 14use rustc_target::spec::abi;
dfeec247 15use std::iter;
c34b1796 16
e9174d1e 17pub type RelateResult<'tcx, T> = Result<T, TypeError<'tcx>>;
c34b1796 18
62682a34
SL
19#[derive(Clone, Debug)]
20pub enum Cause {
c1a9b12d 21 ExistentialRegionBound, // relating an existential region bound
62682a34
SL
22}
23
dc9dc135
XL
24pub trait TypeRelation<'tcx>: Sized {
25 fn tcx(&self) -> TyCtxt<'tcx>;
c34b1796 26
416331ca
XL
27 fn param_env(&self) -> ty::ParamEnv<'tcx>;
28
c34b1796
AL
29 /// Returns a static string we can use for printouts.
30 fn tag(&self) -> &'static str;
31
9fa01778 32 /// Returns `true` if the value `a` is the "expected" type in the
c34b1796
AL
33 /// relation. Just affects error messages.
34 fn a_is_expected(&self) -> bool;
35
dfeec247
XL
36 fn with_cause<F, R>(&mut self, _cause: Cause, f: F) -> R
37 where
38 F: FnOnce(&mut Self) -> R,
62682a34
SL
39 {
40 f(self)
41 }
42
c34b1796 43 /// Generic relation routine suitable for most anything.
f035d41b 44 fn relate<T: Relate<'tcx>>(&mut self, a: T, b: T) -> RelateResult<'tcx, T> {
c34b1796
AL
45 Relate::relate(self, a, b)
46 }
47
cc61c64b
XL
48 /// Relate the two substitutions for the given item. The default
49 /// is to look up the variance for the item and proceed
50 /// accordingly.
dfeec247
XL
51 fn relate_item_substs(
52 &mut self,
53 item_def_id: DefId,
54 a_subst: SubstsRef<'tcx>,
55 b_subst: SubstsRef<'tcx>,
56 ) -> RelateResult<'tcx, SubstsRef<'tcx>> {
57 debug!(
58 "relate_item_substs(item_def_id={:?}, a_subst={:?}, b_subst={:?})",
59 item_def_id, a_subst, b_subst
60 );
cc61c64b 61
7cac9316 62 let opt_variances = self.tcx().variances_of(item_def_id);
48663c56 63 relate_substs(self, Some(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,
f035d41b
XL
70 a: T,
71 b: T,
dfeec247 72 ) -> RelateResult<'tcx, T>;
c34b1796 73
74b04a01 74 // Overridable relations. You shouldn't typically call these
c34b1796
AL
75 // directly, instead call `relate()`, which in turn calls
76 // these. This is both more uniform but also allows us to add
77 // additional hooks for other types in the future if needed
78 // without making older code, which called `relate`, obsolete.
79
48663c56 80 fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>>;
c34b1796 81
48663c56
XL
82 fn regions(
83 &mut self,
84 a: ty::Region<'tcx>,
dfeec247 85 b: ty::Region<'tcx>,
48663c56
XL
86 ) -> RelateResult<'tcx, ty::Region<'tcx>>;
87
88 fn consts(
89 &mut self,
90 a: &'tcx ty::Const<'tcx>,
dfeec247 91 b: &'tcx ty::Const<'tcx>,
48663c56 92 ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>>;
c34b1796 93
dfeec247
XL
94 fn binders<T>(
95 &mut self,
f035d41b
XL
96 a: ty::Binder<T>,
97 b: ty::Binder<T>,
dfeec247
XL
98 ) -> RelateResult<'tcx, ty::Binder<T>>
99 where
100 T: Relate<'tcx>;
c34b1796
AL
101}
102
f035d41b 103pub trait Relate<'tcx>: TypeFoldable<'tcx> + Copy {
dc9dc135
XL
104 fn relate<R: TypeRelation<'tcx>>(
105 relation: &mut R,
f035d41b
XL
106 a: Self,
107 b: Self,
dc9dc135 108 ) -> RelateResult<'tcx, Self>;
c34b1796
AL
109}
110
111///////////////////////////////////////////////////////////////////////////
112// Relate impls
113
a7813a04 114impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> {
dc9dc135
XL
115 fn relate<R: TypeRelation<'tcx>>(
116 relation: &mut R,
f035d41b
XL
117 a: ty::TypeAndMut<'tcx>,
118 b: ty::TypeAndMut<'tcx>,
dc9dc135 119 ) -> RelateResult<'tcx, ty::TypeAndMut<'tcx>> {
dfeec247 120 debug!("{}.mts({:?}, {:?})", relation.tag(), a, b);
c34b1796 121 if a.mutbl != b.mutbl {
c1a9b12d 122 Err(TypeError::Mutability)
c34b1796
AL
123 } else {
124 let mutbl = a.mutbl;
125 let variance = match mutbl {
dfeec247
XL
126 ast::Mutability::Not => ty::Covariant,
127 ast::Mutability::Mut => ty::Invariant,
c34b1796 128 };
f035d41b 129 let ty = relation.relate_with_variance(variance, a.ty, b.ty)?;
48663c56 130 Ok(ty::TypeAndMut { ty, mutbl })
c34b1796
AL
131 }
132 }
133}
134
dc9dc135
XL
135pub fn relate_substs<R: TypeRelation<'tcx>>(
136 relation: &mut R,
137 variances: Option<&[ty::Variance]>,
138 a_subst: SubstsRef<'tcx>,
139 b_subst: SubstsRef<'tcx>,
140) -> RelateResult<'tcx, SubstsRef<'tcx>> {
9e0c209e 141 let tcx = relation.tcx();
c34b1796 142
8bb4bdeb 143 let params = a_subst.iter().zip(b_subst).enumerate().map(|(i, (a, b))| {
9e0c209e 144 let variance = variances.map_or(ty::Invariant, |v| v[i]);
f035d41b 145 relation.relate_with_variance(variance, a, b)
9e0c209e 146 });
c34b1796 147
c30ab7b3 148 Ok(tcx.mk_substs(params)?)
c34b1796
AL
149}
150
a7813a04 151impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
dc9dc135
XL
152 fn relate<R: TypeRelation<'tcx>>(
153 relation: &mut R,
f035d41b
XL
154 a: ty::FnSig<'tcx>,
155 b: ty::FnSig<'tcx>,
dc9dc135 156 ) -> RelateResult<'tcx, ty::FnSig<'tcx>> {
94b46f34
XL
157 let tcx = relation.tcx();
158
532ac7d7 159 if a.c_variadic != b.c_variadic {
dfeec247
XL
160 return Err(TypeError::VariadicMismatch(expected_found(
161 relation,
f035d41b
XL
162 a.c_variadic,
163 b.c_variadic,
dfeec247 164 )));
c34b1796 165 }
f035d41b
XL
166 let unsafety = relation.relate(a.unsafety, b.unsafety)?;
167 let abi = relation.relate(a.abi, b.abi)?;
c34b1796 168
476ff2be
SL
169 if a.inputs().len() != b.inputs().len() {
170 return Err(TypeError::ArgCount);
171 }
c34b1796 172
dfeec247
XL
173 let inputs_and_output = a
174 .inputs()
175 .iter()
176 .cloned()
476ff2be
SL
177 .zip(b.inputs().iter().cloned())
178 .map(|x| (x, false))
179 .chain(iter::once(((a.output(), b.output()), true)))
180 .map(|((a, b), is_output)| {
181 if is_output {
f035d41b 182 relation.relate(a, b)
476ff2be 183 } else {
f035d41b 184 relation.relate_with_variance(ty::Contravariant, a, b)
476ff2be 185 }
94b46f34 186 });
476ff2be 187 Ok(ty::FnSig {
94b46f34 188 inputs_and_output: tcx.mk_type_list(inputs_and_output)?,
532ac7d7 189 c_variadic: a.c_variadic,
041b39d2
XL
190 unsafety,
191 abi,
476ff2be 192 })
c34b1796 193 }
c34b1796
AL
194}
195
a7813a04 196impl<'tcx> Relate<'tcx> for ast::Unsafety {
dc9dc135
XL
197 fn relate<R: TypeRelation<'tcx>>(
198 relation: &mut R,
f035d41b
XL
199 a: ast::Unsafety,
200 b: ast::Unsafety,
dc9dc135 201 ) -> RelateResult<'tcx, ast::Unsafety> {
c34b1796 202 if a != b {
c1a9b12d 203 Err(TypeError::UnsafetyMismatch(expected_found(relation, a, b)))
c34b1796 204 } else {
f035d41b 205 Ok(a)
c34b1796
AL
206 }
207 }
208}
209
a7813a04 210impl<'tcx> Relate<'tcx> for abi::Abi {
dc9dc135
XL
211 fn relate<R: TypeRelation<'tcx>>(
212 relation: &mut R,
f035d41b
XL
213 a: abi::Abi,
214 b: abi::Abi,
dc9dc135 215 ) -> RelateResult<'tcx, abi::Abi> {
f035d41b 216 if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(expected_found(relation, a, b))) }
c34b1796
AL
217 }
218}
219
a7813a04 220impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> {
dc9dc135
XL
221 fn relate<R: TypeRelation<'tcx>>(
222 relation: &mut R,
f035d41b
XL
223 a: ty::ProjectionTy<'tcx>,
224 b: ty::ProjectionTy<'tcx>,
dc9dc135 225 ) -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> {
041b39d2 226 if a.item_def_id != b.item_def_id {
dfeec247
XL
227 Err(TypeError::ProjectionMismatched(expected_found(
228 relation,
f035d41b
XL
229 a.item_def_id,
230 b.item_def_id,
dfeec247 231 )))
c34b1796 232 } else {
f035d41b 233 let substs = relation.relate(a.substs, b.substs)?;
dfeec247 234 Ok(ty::ProjectionTy { item_def_id: a.item_def_id, substs: &substs })
c34b1796
AL
235 }
236 }
237}
238
9e0c209e 239impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
dc9dc135
XL
240 fn relate<R: TypeRelation<'tcx>>(
241 relation: &mut R,
f035d41b
XL
242 a: ty::ExistentialProjection<'tcx>,
243 b: ty::ExistentialProjection<'tcx>,
dc9dc135 244 ) -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> {
041b39d2 245 if a.item_def_id != b.item_def_id {
dfeec247
XL
246 Err(TypeError::ProjectionMismatched(expected_found(
247 relation,
f035d41b
XL
248 a.item_def_id,
249 b.item_def_id,
dfeec247 250 )))
9e0c209e 251 } else {
f035d41b
XL
252 let ty = relation.relate_with_variance(ty::Invariant, a.ty, b.ty)?;
253 let substs = relation.relate_with_variance(ty::Invariant, a.substs, b.substs)?;
dfeec247 254 Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, ty })
9e0c209e 255 }
c34b1796
AL
256 }
257}
258
a7813a04 259impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
dc9dc135
XL
260 fn relate<R: TypeRelation<'tcx>>(
261 relation: &mut R,
f035d41b
XL
262 a: ty::TraitRef<'tcx>,
263 b: ty::TraitRef<'tcx>,
dc9dc135 264 ) -> RelateResult<'tcx, ty::TraitRef<'tcx>> {
60c5eb7d 265 // Different traits cannot be related.
c34b1796 266 if a.def_id != b.def_id {
f035d41b 267 Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
c34b1796 268 } else {
041b39d2 269 let substs = relate_substs(relation, None, a.substs, b.substs)?;
74b04a01 270 Ok(ty::TraitRef { def_id: a.def_id, substs })
c34b1796
AL
271 }
272 }
273}
274
9e0c209e 275impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
dc9dc135
XL
276 fn relate<R: TypeRelation<'tcx>>(
277 relation: &mut R,
f035d41b
XL
278 a: ty::ExistentialTraitRef<'tcx>,
279 b: ty::ExistentialTraitRef<'tcx>,
dc9dc135 280 ) -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>> {
60c5eb7d 281 // Different traits cannot be related.
9e0c209e 282 if a.def_id != b.def_id {
f035d41b 283 Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
9e0c209e 284 } else {
041b39d2 285 let substs = relate_substs(relation, None, a.substs, b.substs)?;
74b04a01 286 Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs })
9e0c209e
SL
287 }
288 }
289}
290
f035d41b 291#[derive(Copy, Debug, Clone, TypeFoldable)]
b7449926 292struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
2c00a5a8 293
2c00a5a8 294impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
dc9dc135
XL
295 fn relate<R: TypeRelation<'tcx>>(
296 relation: &mut R,
f035d41b
XL
297 a: GeneratorWitness<'tcx>,
298 b: GeneratorWitness<'tcx>,
dc9dc135 299 ) -> RelateResult<'tcx, GeneratorWitness<'tcx>> {
0bf4aa26 300 assert_eq!(a.0.len(), b.0.len());
2c00a5a8 301 let tcx = relation.tcx();
f035d41b 302 let types = tcx.mk_type_list(a.0.iter().zip(b.0).map(|(a, b)| relation.relate(a, b)))?;
2c00a5a8
XL
303 Ok(GeneratorWitness(types))
304 }
305}
306
a7813a04 307impl<'tcx> Relate<'tcx> for Ty<'tcx> {
f035d41b 308 #[inline]
dc9dc135
XL
309 fn relate<R: TypeRelation<'tcx>>(
310 relation: &mut R,
f035d41b
XL
311 a: Ty<'tcx>,
312 b: Ty<'tcx>,
dc9dc135 313 ) -> RelateResult<'tcx, Ty<'tcx>> {
c34b1796
AL
314 relation.tys(a, b)
315 }
316}
317
318/// The main "type relation" routine. Note that this does not handle
319/// inference artifacts, so you should filter those out before calling
320/// it.
dc9dc135
XL
321pub fn super_relate_tys<R: TypeRelation<'tcx>>(
322 relation: &mut R,
323 a: Ty<'tcx>,
324 b: Ty<'tcx>,
325) -> RelateResult<'tcx, Ty<'tcx>> {
c34b1796 326 let tcx = relation.tcx();
532ac7d7 327 debug!("super_relate_tys: a={:?} b={:?}", a, b);
e74abb32 328 match (&a.kind, &b.kind) {
dfeec247 329 (&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
c34b1796 330 // The caller should handle these cases!
54a0048b 331 bug!("var types encountered in super_relate_tys")
c34b1796
AL
332 }
333
a1dfa0c6
XL
334 (ty::Bound(..), _) | (_, ty::Bound(..)) => {
335 bug!("bound types encountered in super_relate_tys")
336 }
337
f035d41b 338 (&ty::Error(_), _) | (_, &ty::Error(_)) => Ok(tcx.ty_error()),
c34b1796 339
dfeec247
XL
340 (&ty::Never, _)
341 | (&ty::Char, _)
342 | (&ty::Bool, _)
343 | (&ty::Int(_), _)
344 | (&ty::Uint(_), _)
345 | (&ty::Float(_), _)
346 | (&ty::Str, _)
c34b1796
AL
347 if a == b =>
348 {
349 Ok(a)
350 }
351
dfeec247 352 (&ty::Param(ref a_p), &ty::Param(ref b_p)) if a_p.index == b_p.index => Ok(a),
c34b1796 353
dfeec247 354 (ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a),
a1dfa0c6 355
dfeec247 356 (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs)) if a_def == b_def => {
cc61c64b 357 let substs = relation.relate_item_substs(a_def.did, a_substs, b_substs)?;
9e0c209e 358 Ok(tcx.mk_adt(a_def, substs))
c34b1796
AL
359 }
360
dfeec247 361 (&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(tcx.mk_foreign(a_id)),
abe05a73 362
f035d41b 363 (&ty::Dynamic(a_obj, a_region), &ty::Dynamic(b_obj, b_region)) => {
dfeec247
XL
364 let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| {
365 relation.relate_with_variance(ty::Contravariant, a_region, b_region)
366 })?;
476ff2be 367 Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound))
c34b1796
AL
368 }
369
dfeec247 370 (&ty::Generator(a_id, a_substs, movability), &ty::Generator(b_id, b_substs, _))
ea8adc8c
XL
371 if a_id == b_id =>
372 {
b7449926 373 // All Generator types with the same id represent
ea8adc8c
XL
374 // the (anonymous) type of the same generator expression. So
375 // all of their regions should be equated.
f035d41b 376 let substs = relation.relate(a_substs, b_substs)?;
94b46f34 377 Ok(tcx.mk_generator(a_id, substs, movability))
ea8adc8c
XL
378 }
379
dfeec247 380 (&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => {
2c00a5a8
XL
381 // Wrap our types with a temporary GeneratorWitness struct
382 // inside the binder so we can related them
83c7162d
XL
383 let a_types = a_types.map_bound(GeneratorWitness);
384 let b_types = b_types.map_bound(GeneratorWitness);
2c00a5a8 385 // Then remove the GeneratorWitness for the result
f035d41b 386 let types = relation.relate(a_types, b_types)?.map_bound(|witness| witness.0);
2c00a5a8
XL
387 Ok(tcx.mk_generator_witness(types))
388 }
389
dfeec247 390 (&ty::Closure(a_id, a_substs), &ty::Closure(b_id, b_substs)) if a_id == b_id => {
b7449926 391 // All Closure types with the same id represent
c34b1796
AL
392 // the (anonymous) type of the same closure expression. So
393 // all of their regions should be equated.
f035d41b 394 let substs = relation.relate(a_substs, b_substs)?;
e74abb32 395 Ok(tcx.mk_closure(a_id, &substs))
c34b1796
AL
396 }
397
f035d41b 398 (&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => {
54a0048b 399 let mt = relation.relate(a_mt, b_mt)?;
c1a9b12d 400 Ok(tcx.mk_ptr(mt))
c34b1796
AL
401 }
402
dfeec247 403 (&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => {
f035d41b 404 let r = relation.relate_with_variance(ty::Contravariant, a_r, b_r)?;
94b46f34
XL
405 let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl };
406 let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl };
f035d41b 407 let mt = relation.relate(a_mt, b_mt)?;
9e0c209e 408 Ok(tcx.mk_ref(r, mt))
c34b1796
AL
409 }
410
dfeec247 411 (&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => {
f035d41b
XL
412 let t = relation.relate(a_t, b_t)?;
413 match relation.relate(sz_a, sz_b) {
dc9dc135 414 Ok(sz) => Ok(tcx.mk_ty(ty::Array(t, sz))),
f9f354fc
XL
415 // FIXME(#72219) Implement improved diagnostics for mismatched array
416 // length?
417 Err(err) if relation.tcx().lazy_normalization() => Err(err),
dc9dc135
XL
418 Err(err) => {
419 // Check whether the lengths are both concrete/known values,
420 // but are unequal, for better diagnostics.
416331ca
XL
421 let sz_a = sz_a.try_eval_usize(tcx, relation.param_env());
422 let sz_b = sz_b.try_eval_usize(tcx, relation.param_env());
423 match (sz_a, sz_b) {
dfeec247 424 (Some(sz_a_val), Some(sz_b_val)) => Err(TypeError::FixedArraySize(
f035d41b 425 expected_found(relation, sz_a_val, sz_b_val),
dfeec247 426 )),
ba9703b0 427 _ => Err(err),
ea8adc8c 428 }
ea8adc8c 429 }
c34b1796
AL
430 }
431 }
432
dfeec247 433 (&ty::Slice(a_t), &ty::Slice(b_t)) => {
f035d41b 434 let t = relation.relate(a_t, b_t)?;
c1a9b12d 435 Ok(tcx.mk_slice(t))
c34b1796
AL
436 }
437
dfeec247 438 (&ty::Tuple(as_), &ty::Tuple(bs)) => {
c34b1796 439 if as_.len() == bs.len() {
dfeec247 440 Ok(tcx.mk_tup(
f035d41b 441 as_.iter().zip(bs).map(|(a, b)| relation.relate(a.expect_ty(), b.expect_ty())),
dfeec247 442 )?)
9346a6ac 443 } else if !(as_.is_empty() || bs.is_empty()) {
f035d41b 444 Err(TypeError::TupleSize(expected_found(relation, as_.len(), bs.len())))
c34b1796 445 } else {
f035d41b 446 Err(TypeError::Sorts(expected_found(relation, a, b)))
c34b1796
AL
447 }
448 }
449
b7449926 450 (&ty::FnDef(a_def_id, a_substs), &ty::FnDef(b_def_id, b_substs))
54a0048b
SL
451 if a_def_id == b_def_id =>
452 {
041b39d2
XL
453 let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?;
454 Ok(tcx.mk_fn_def(a_def_id, substs))
54a0048b
SL
455 }
456
dfeec247 457 (&ty::FnPtr(a_fty), &ty::FnPtr(b_fty)) => {
f035d41b 458 let fty = relation.relate(a_fty, b_fty)?;
54a0048b 459 Ok(tcx.mk_fn_ptr(fty))
c34b1796
AL
460 }
461
a1dfa0c6 462 // these two are already handled downstream in case of lazy normalization
f035d41b 463 (&ty::Projection(a_data), &ty::Projection(b_data)) => {
54a0048b 464 let projection_ty = relation.relate(a_data, b_data)?;
041b39d2 465 Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs))
c34b1796
AL
466 }
467
b7449926 468 (&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
5bcae85e
SL
469 if a_def_id == b_def_id =>
470 {
471 let substs = relate_substs(relation, None, a_substs, b_substs)?;
b7449926 472 Ok(tcx.mk_opaque(a_def_id, substs))
5bcae85e
SL
473 }
474
f035d41b 475 _ => Err(TypeError::Sorts(expected_found(relation, a, b))),
c34b1796
AL
476 }
477}
478
48663c56
XL
479/// The main "const relation" routine. Note that this does not handle
480/// inference artifacts, so you should filter those out before calling
481/// it.
dc9dc135 482pub fn super_relate_consts<R: TypeRelation<'tcx>>(
48663c56
XL
483 relation: &mut R,
484 a: &'tcx ty::Const<'tcx>,
dc9dc135
XL
485 b: &'tcx ty::Const<'tcx>,
486) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
f9f354fc 487 debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
48663c56
XL
488 let tcx = relation.tcx();
489
f9f354fc 490 let eagerly_eval = |x: &'tcx ty::Const<'tcx>| x.eval(tcx, relation.param_env()).val;
dc9dc135 491
ba9703b0
XL
492 // FIXME(eddyb) doesn't look like everything below checks that `a.ty == b.ty`.
493 // We could probably always assert it early, as `const` generic parameters
494 // are not allowed to depend on other generic parameters, i.e. are concrete.
495 // (although there could be normalization differences)
496
e74abb32
XL
497 // Currently, the values that can be unified are primitive types,
498 // and those that derive both `PartialEq` and `Eq`, corresponding
ba9703b0 499 // to structural-match types.
e74abb32 500 let new_const_val = match (eagerly_eval(a), eagerly_eval(b)) {
60c5eb7d 501 (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
48663c56
XL
502 // The caller should handle these cases!
503 bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b)
504 }
ba9703b0 505
f035d41b 506 (ty::ConstKind::Error(d), _) | (_, ty::ConstKind::Error(d)) => Ok(ty::ConstKind::Error(d)),
ba9703b0 507
60c5eb7d 508 (ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) if a_p.index == b_p.index => {
e74abb32 509 return Ok(a);
48663c56 510 }
60c5eb7d 511 (ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) if p1 == p2 => {
e74abb32
XL
512 return Ok(a);
513 }
60c5eb7d
XL
514 (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => {
515 let new_val = match (a_val, b_val) {
516 (ConstValue::Scalar(a_val), ConstValue::Scalar(b_val)) if a.ty == b.ty => {
517 if a_val == b_val {
518 Ok(ConstValue::Scalar(a_val))
519 } else if let ty::FnPtr(_) = a.ty.kind {
f9f354fc
XL
520 let a_instance = tcx.global_alloc(a_val.assert_ptr().alloc_id).unwrap_fn();
521 let b_instance = tcx.global_alloc(b_val.assert_ptr().alloc_id).unwrap_fn();
60c5eb7d
XL
522 if a_instance == b_instance {
523 Ok(ConstValue::Scalar(a_val))
524 } else {
f035d41b 525 Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
60c5eb7d
XL
526 }
527 } else {
f035d41b 528 Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
60c5eb7d 529 }
e74abb32 530 }
416331ca 531
f9f354fc 532 (ConstValue::Slice { .. }, ConstValue::Slice { .. }) => {
60c5eb7d
XL
533 let a_bytes = get_slice_bytes(&tcx, a_val);
534 let b_bytes = get_slice_bytes(&tcx, b_val);
535 if a_bytes == b_bytes {
536 Ok(a_val)
537 } else {
f035d41b 538 Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
60c5eb7d
XL
539 }
540 }
541
f9f354fc
XL
542 (ConstValue::ByRef { .. }, ConstValue::ByRef { .. }) => {
543 match a.ty.kind {
544 ty::Array(..) | ty::Adt(..) | ty::Tuple(..) => {
545 let a_destructured = tcx.destructure_const(relation.param_env().and(a));
546 let b_destructured = tcx.destructure_const(relation.param_env().and(b));
547
548 // Both the variant and each field have to be equal.
549 if a_destructured.variant == b_destructured.variant {
550 for (a_field, b_field) in
551 a_destructured.fields.iter().zip(b_destructured.fields.iter())
552 {
553 relation.consts(a_field, b_field)?;
554 }
555
556 Ok(a_val)
557 } else {
f035d41b 558 Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
f9f354fc
XL
559 }
560 }
561 // FIXME(const_generics): There are probably some `TyKind`s
562 // which should be handled here.
563 _ => {
564 tcx.sess.delay_span_bug(
565 DUMMY_SP,
566 &format!("unexpected consts: a: {:?}, b: {:?}", a, b),
567 );
f035d41b 568 Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
f9f354fc
XL
569 }
570 }
571 }
572
f035d41b 573 _ => Err(TypeError::ConstMismatch(expected_found(relation, a, b))),
60c5eb7d 574 };
416331ca 575
60c5eb7d 576 new_val.map(ty::ConstKind::Value)
dfeec247 577 }
48663c56
XL
578
579 // FIXME(const_generics): this is wrong, as it is a projection
dfeec247
XL
580 (
581 ty::ConstKind::Unevaluated(a_def_id, a_substs, a_promoted),
582 ty::ConstKind::Unevaluated(b_def_id, b_substs, b_promoted),
583 ) if a_def_id == b_def_id && a_promoted == b_promoted => {
e74abb32 584 let substs =
f035d41b
XL
585 relation.relate_with_variance(ty::Variance::Invariant, a_substs, b_substs)?;
586 Ok(ty::ConstKind::Unevaluated(a_def_id, substs, a_promoted))
e74abb32 587 }
f035d41b 588 _ => Err(TypeError::ConstMismatch(expected_found(relation, a, b))),
e74abb32 589 };
dfeec247 590 new_const_val.map(|val| tcx.mk_const(ty::Const { val, ty: a.ty }))
48663c56
XL
591}
592
b7449926 593impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
dc9dc135
XL
594 fn relate<R: TypeRelation<'tcx>>(
595 relation: &mut R,
f035d41b
XL
596 a: Self,
597 b: Self,
dc9dc135 598 ) -> RelateResult<'tcx, Self> {
f9f354fc
XL
599 let tcx = relation.tcx();
600
601 // FIXME: this is wasteful, but want to do a perf run to see how slow it is.
602 // We need to perform this deduplication as we sometimes generate duplicate projections
603 // in `a`.
604 let mut a_v: Vec<_> = a.into_iter().collect();
605 let mut b_v: Vec<_> = b.into_iter().collect();
606 a_v.sort_by(|a, b| a.stable_cmp(tcx, b));
607 a_v.dedup();
608 b_v.sort_by(|a, b| a.stable_cmp(tcx, b));
609 b_v.dedup();
610 if a_v.len() != b_v.len() {
476ff2be
SL
611 return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)));
612 }
613
f9f354fc 614 let v = a_v.into_iter().zip(b_v.into_iter()).map(|(ep_a, ep_b)| {
9fa01778 615 use crate::ty::ExistentialPredicate::*;
f9f354fc 616 match (ep_a, ep_b) {
f035d41b
XL
617 (Trait(a), Trait(b)) => Ok(Trait(relation.relate(a, b)?)),
618 (Projection(a), Projection(b)) => Ok(Projection(relation.relate(a, b)?)),
619 (AutoTrait(a), AutoTrait(b)) if a == b => Ok(AutoTrait(a)),
dfeec247 620 _ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))),
476ff2be
SL
621 }
622 });
623 Ok(tcx.mk_existential_predicates(v)?)
624 }
625}
626
a7813a04 627impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> {
dc9dc135
XL
628 fn relate<R: TypeRelation<'tcx>>(
629 relation: &mut R,
f035d41b
XL
630 a: ty::ClosureSubsts<'tcx>,
631 b: ty::ClosureSubsts<'tcx>,
dc9dc135 632 ) -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>> {
476ff2be 633 let substs = relate_substs(relation, None, a.substs, b.substs)?;
94b46f34 634 Ok(ty::ClosureSubsts { substs })
c1a9b12d
SL
635 }
636}
637
94b46f34 638impl<'tcx> Relate<'tcx> for ty::GeneratorSubsts<'tcx> {
dc9dc135
XL
639 fn relate<R: TypeRelation<'tcx>>(
640 relation: &mut R,
f035d41b
XL
641 a: ty::GeneratorSubsts<'tcx>,
642 b: ty::GeneratorSubsts<'tcx>,
dc9dc135 643 ) -> RelateResult<'tcx, ty::GeneratorSubsts<'tcx>> {
94b46f34
XL
644 let substs = relate_substs(relation, None, a.substs, b.substs)?;
645 Ok(ty::GeneratorSubsts { substs })
ea8adc8c
XL
646 }
647}
648
532ac7d7 649impl<'tcx> Relate<'tcx> for SubstsRef<'tcx> {
dc9dc135
XL
650 fn relate<R: TypeRelation<'tcx>>(
651 relation: &mut R,
f035d41b
XL
652 a: SubstsRef<'tcx>,
653 b: SubstsRef<'tcx>,
dc9dc135 654 ) -> RelateResult<'tcx, SubstsRef<'tcx>> {
54a0048b
SL
655 relate_substs(relation, None, a, b)
656 }
657}
658
7cac9316 659impl<'tcx> Relate<'tcx> for ty::Region<'tcx> {
dc9dc135
XL
660 fn relate<R: TypeRelation<'tcx>>(
661 relation: &mut R,
f035d41b
XL
662 a: ty::Region<'tcx>,
663 b: ty::Region<'tcx>,
dc9dc135 664 ) -> RelateResult<'tcx, ty::Region<'tcx>> {
f035d41b 665 relation.regions(a, b)
c34b1796
AL
666 }
667}
668
48663c56 669impl<'tcx> Relate<'tcx> for &'tcx ty::Const<'tcx> {
dc9dc135
XL
670 fn relate<R: TypeRelation<'tcx>>(
671 relation: &mut R,
f035d41b
XL
672 a: &'tcx ty::Const<'tcx>,
673 b: &'tcx ty::Const<'tcx>,
dc9dc135 674 ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
f035d41b 675 relation.consts(a, b)
48663c56
XL
676 }
677}
678
a7813a04 679impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder<T> {
dc9dc135
XL
680 fn relate<R: TypeRelation<'tcx>>(
681 relation: &mut R,
f035d41b
XL
682 a: ty::Binder<T>,
683 b: ty::Binder<T>,
dc9dc135 684 ) -> RelateResult<'tcx, ty::Binder<T>> {
c34b1796
AL
685 relation.binders(a, b)
686 }
687}
688
e74abb32 689impl<'tcx> Relate<'tcx> for GenericArg<'tcx> {
dc9dc135 690 fn relate<R: TypeRelation<'tcx>>(
0531ce1d 691 relation: &mut R,
f035d41b
XL
692 a: GenericArg<'tcx>,
693 b: GenericArg<'tcx>,
e74abb32 694 ) -> RelateResult<'tcx, GenericArg<'tcx>> {
0531ce1d 695 match (a.unpack(), b.unpack()) {
e74abb32 696 (GenericArgKind::Lifetime(a_lt), GenericArgKind::Lifetime(b_lt)) => {
f035d41b 697 Ok(relation.relate(a_lt, b_lt)?.into())
0531ce1d 698 }
e74abb32 699 (GenericArgKind::Type(a_ty), GenericArgKind::Type(b_ty)) => {
f035d41b 700 Ok(relation.relate(a_ty, b_ty)?.into())
0531ce1d 701 }
e74abb32 702 (GenericArgKind::Const(a_ct), GenericArgKind::Const(b_ct)) => {
f035d41b 703 Ok(relation.relate(a_ct, b_ct)?.into())
48663c56 704 }
e74abb32 705 (GenericArgKind::Lifetime(unpacked), x) => {
0bf4aa26
XL
706 bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
707 }
e74abb32 708 (GenericArgKind::Type(unpacked), x) => {
0bf4aa26
XL
709 bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
710 }
e74abb32 711 (GenericArgKind::Const(unpacked), x) => {
48663c56 712 bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
532ac7d7 713 }
0531ce1d
XL
714 }
715 }
716}
717
a1dfa0c6 718impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> {
dc9dc135 719 fn relate<R: TypeRelation<'tcx>>(
a1dfa0c6 720 relation: &mut R,
f035d41b
XL
721 a: ty::TraitPredicate<'tcx>,
722 b: ty::TraitPredicate<'tcx>,
dc9dc135 723 ) -> RelateResult<'tcx, ty::TraitPredicate<'tcx>> {
f035d41b 724 Ok(ty::TraitPredicate { trait_ref: relation.relate(a.trait_ref, b.trait_ref)? })
a1dfa0c6
XL
725 }
726}
727
728impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> {
dc9dc135 729 fn relate<R: TypeRelation<'tcx>>(
a1dfa0c6 730 relation: &mut R,
f035d41b
XL
731 a: ty::ProjectionPredicate<'tcx>,
732 b: ty::ProjectionPredicate<'tcx>,
dc9dc135 733 ) -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>> {
a1dfa0c6 734 Ok(ty::ProjectionPredicate {
f035d41b
XL
735 projection_ty: relation.relate(a.projection_ty, b.projection_ty)?,
736 ty: relation.relate(a.ty, b.ty)?,
a1dfa0c6
XL
737 })
738 }
739}
740
c34b1796
AL
741///////////////////////////////////////////////////////////////////////////
742// Error handling
743
f035d41b 744pub fn expected_found<R, T>(relation: &mut R, a: T, b: T) -> ExpectedFound<T>
dc9dc135
XL
745where
746 R: TypeRelation<'tcx>,
c34b1796
AL
747{
748 expected_found_bool(relation.a_is_expected(), a, b)
749}
750
f035d41b 751pub fn expected_found_bool<T>(a_is_expected: bool, a: T, b: T) -> ExpectedFound<T> {
c34b1796 752 if a_is_expected {
dfeec247 753 ExpectedFound { expected: a, found: b }
c34b1796 754 } else {
dfeec247 755 ExpectedFound { expected: b, found: a }
c34b1796
AL
756 }
757}