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