]>
Commit | Line | Data |
---|---|---|
923072b8 FG |
1 | //! There are four type combiners: [Equate], [Sub], [Lub], and [Glb]. |
2 | //! Each implements the trait [TypeRelation] and contains methods for | |
3 | //! combining two instances of various things and yielding a new instance. | |
4 | //! These combiner methods always yield a `Result<T>`. To relate two | |
5 | //! types, you can use `infcx.at(cause, param_env)` which then allows | |
6 | //! you to use the relevant methods of [At](super::at::At). | |
7 | //! | |
8 | //! Combiners mostly do their specific behavior and then hand off the | |
9 | //! bulk of the work to [InferCtxt::super_combine_tys] and | |
10 | //! [InferCtxt::super_combine_consts]. | |
11 | //! | |
12 | //! Combining two types may have side-effects on the inference contexts | |
13 | //! which can be undone by using snapshots. You probably want to use | |
14 | //! either [InferCtxt::commit_if_ok] or [InferCtxt::probe]. | |
15 | //! | |
16 | //! On success, the LUB/GLB operations return the appropriate bound. The | |
17 | //! return value of `Equate` or `Sub` shouldn't really be used. | |
18 | //! | |
19 | //! ## Contravariance | |
20 | //! | |
21 | //! We explicitly track which argument is expected using | |
22 | //! [TypeRelation::a_is_expected], so when dealing with contravariance | |
23 | //! this should be correctly updated. | |
1a4d82fc | 24 | |
c295e0f8 | 25 | use super::equate::Equate; |
1a4d82fc JJ |
26 | use super::glb::Glb; |
27 | use super::lub::Lub; | |
28 | use super::sub::Sub; | |
0531ce1d | 29 | use super::type_variable::TypeVariableValue; |
dfeec247 | 30 | use super::{InferCtxt, MiscVariable, TypeTrace}; |
dfeec247 | 31 | use crate::traits::{Obligation, PredicateObligations}; |
29967ef6 | 32 | use rustc_data_structures::sso::SsoHashMap; |
dfeec247 | 33 | use rustc_hir::def_id::DefId; |
5e7ed085 FG |
34 | use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; |
35 | use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; | |
3dfed10e | 36 | use rustc_middle::traits::ObligationCause; |
a2a8927a | 37 | use rustc_middle::ty::error::{ExpectedFound, TypeError}; |
ba9703b0 XL |
38 | use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; |
39 | use rustc_middle::ty::subst::SubstsRef; | |
064997fb | 40 | use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitable}; |
ba9703b0 | 41 | use rustc_middle::ty::{IntType, UintType}; |
1b1a35ee | 42 | use rustc_span::{Span, DUMMY_SP}; |
1a4d82fc | 43 | |
1a4d82fc | 44 | #[derive(Clone)] |
dc9dc135 XL |
45 | pub struct CombineFields<'infcx, 'tcx> { |
46 | pub infcx: &'infcx InferCtxt<'infcx, 'tcx>, | |
1a4d82fc | 47 | pub trace: TypeTrace<'tcx>, |
e9174d1e | 48 | pub cause: Option<ty::relate::Cause>, |
7cac9316 | 49 | pub param_env: ty::ParamEnv<'tcx>, |
54a0048b | 50 | pub obligations: PredicateObligations<'tcx>, |
5e7ed085 FG |
51 | /// Whether we should define opaque types |
52 | /// or just treat them opaquely. | |
53 | /// Currently only used to prevent predicate | |
54 | /// matching from matching anything against opaque | |
55 | /// types. | |
56 | pub define_opaque_types: bool, | |
1a4d82fc JJ |
57 | } |
58 | ||
e74abb32 | 59 | #[derive(Copy, Clone, Debug)] |
cc61c64b | 60 | pub enum RelationDir { |
dfeec247 XL |
61 | SubtypeOf, |
62 | SupertypeOf, | |
63 | EqTo, | |
cc61c64b XL |
64 | } |
65 | ||
dc9dc135 XL |
66 | impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> { |
67 | pub fn super_combine_tys<R>( | |
68 | &self, | |
69 | relation: &mut R, | |
70 | a: Ty<'tcx>, | |
71 | b: Ty<'tcx>, | |
72 | ) -> RelateResult<'tcx, Ty<'tcx>> | |
73 | where | |
74 | R: TypeRelation<'tcx>, | |
a7813a04 XL |
75 | { |
76 | let a_is_expected = relation.a_is_expected(); | |
1a4d82fc | 77 | |
1b1a35ee | 78 | match (a.kind(), b.kind()) { |
a7813a04 | 79 | // Relate integral variables to other types |
b7449926 | 80 | (&ty::Infer(ty::IntVar(a_id)), &ty::Infer(ty::IntVar(b_id))) => { |
74b04a01 | 81 | self.inner |
a7813a04 | 82 | .borrow_mut() |
f9f354fc | 83 | .int_unification_table() |
a7813a04 XL |
84 | .unify_var_var(a_id, b_id) |
85 | .map_err(|e| int_unification_error(a_is_expected, e))?; | |
86 | Ok(a) | |
87 | } | |
b7449926 | 88 | (&ty::Infer(ty::IntVar(v_id)), &ty::Int(v)) => { |
a7813a04 XL |
89 | self.unify_integral_variable(a_is_expected, v_id, IntType(v)) |
90 | } | |
b7449926 | 91 | (&ty::Int(v), &ty::Infer(ty::IntVar(v_id))) => { |
a7813a04 XL |
92 | self.unify_integral_variable(!a_is_expected, v_id, IntType(v)) |
93 | } | |
b7449926 | 94 | (&ty::Infer(ty::IntVar(v_id)), &ty::Uint(v)) => { |
a7813a04 XL |
95 | self.unify_integral_variable(a_is_expected, v_id, UintType(v)) |
96 | } | |
b7449926 | 97 | (&ty::Uint(v), &ty::Infer(ty::IntVar(v_id))) => { |
a7813a04 XL |
98 | self.unify_integral_variable(!a_is_expected, v_id, UintType(v)) |
99 | } | |
1a4d82fc | 100 | |
a7813a04 | 101 | // Relate floating-point variables to other types |
b7449926 | 102 | (&ty::Infer(ty::FloatVar(a_id)), &ty::Infer(ty::FloatVar(b_id))) => { |
74b04a01 | 103 | self.inner |
a7813a04 | 104 | .borrow_mut() |
f9f354fc | 105 | .float_unification_table() |
a7813a04 XL |
106 | .unify_var_var(a_id, b_id) |
107 | .map_err(|e| float_unification_error(relation.a_is_expected(), e))?; | |
108 | Ok(a) | |
109 | } | |
b7449926 | 110 | (&ty::Infer(ty::FloatVar(v_id)), &ty::Float(v)) => { |
a7813a04 XL |
111 | self.unify_float_variable(a_is_expected, v_id, v) |
112 | } | |
b7449926 | 113 | (&ty::Float(v), &ty::Infer(ty::FloatVar(v_id))) => { |
a7813a04 XL |
114 | self.unify_float_variable(!a_is_expected, v_id, v) |
115 | } | |
1a4d82fc | 116 | |
a7813a04 | 117 | // All other cases of inference are errors |
dfeec247 | 118 | (&ty::Infer(_), _) | (_, &ty::Infer(_)) => { |
f035d41b | 119 | Err(TypeError::Sorts(ty::relate::expected_found(relation, a, b))) |
a7813a04 | 120 | } |
1a4d82fc | 121 | |
dfeec247 | 122 | _ => ty::relate::super_relate_tys(relation, a, b), |
1a4d82fc JJ |
123 | } |
124 | } | |
125 | ||
48663c56 XL |
126 | pub fn super_combine_consts<R>( |
127 | &self, | |
128 | relation: &mut R, | |
5099ac24 FG |
129 | a: ty::Const<'tcx>, |
130 | b: ty::Const<'tcx>, | |
131 | ) -> RelateResult<'tcx, ty::Const<'tcx>> | |
48663c56 | 132 | where |
f9f354fc | 133 | R: ConstEquateRelation<'tcx>, |
48663c56 | 134 | { |
e1599b0c | 135 | debug!("{}.consts({:?}, {:?})", relation.tag(), a, b); |
dfeec247 XL |
136 | if a == b { |
137 | return Ok(a); | |
138 | } | |
e1599b0c | 139 | |
5e7ed085 FG |
140 | let a = self.shallow_resolve(a); |
141 | let b = self.shallow_resolve(b); | |
e1599b0c | 142 | |
48663c56 XL |
143 | let a_is_expected = relation.a_is_expected(); |
144 | ||
923072b8 | 145 | match (a.kind(), b.kind()) { |
dfeec247 XL |
146 | ( |
147 | ty::ConstKind::Infer(InferConst::Var(a_vid)), | |
148 | ty::ConstKind::Infer(InferConst::Var(b_vid)), | |
149 | ) => { | |
74b04a01 | 150 | self.inner |
48663c56 | 151 | .borrow_mut() |
f9f354fc | 152 | .const_unification_table() |
48663c56 XL |
153 | .unify_var_var(a_vid, b_vid) |
154 | .map_err(|e| const_unification_error(a_is_expected, e))?; | |
155 | return Ok(a); | |
156 | } | |
157 | ||
158 | // All other cases of inference with other variables are errors. | |
dfeec247 XL |
159 | (ty::ConstKind::Infer(InferConst::Var(_)), ty::ConstKind::Infer(_)) |
160 | | (ty::ConstKind::Infer(_), ty::ConstKind::Infer(InferConst::Var(_))) => { | |
60c5eb7d | 161 | bug!("tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var)") |
48663c56 XL |
162 | } |
163 | ||
60c5eb7d | 164 | (ty::ConstKind::Infer(InferConst::Var(vid)), _) => { |
1b1a35ee | 165 | return self.unify_const_variable(relation.param_env(), vid, b, a_is_expected); |
48663c56 XL |
166 | } |
167 | ||
60c5eb7d | 168 | (_, ty::ConstKind::Infer(InferConst::Var(vid))) => { |
1b1a35ee | 169 | return self.unify_const_variable(relation.param_env(), vid, a, !a_is_expected); |
48663c56 | 170 | } |
f9f354fc | 171 | (ty::ConstKind::Unevaluated(..), _) if self.tcx.lazy_normalization() => { |
3dfed10e | 172 | // FIXME(#59490): Need to remove the leak check to accommodate |
f9f354fc XL |
173 | // escaping bound variables here. |
174 | if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() { | |
175 | relation.const_equate_obligation(a, b); | |
176 | } | |
177 | return Ok(b); | |
178 | } | |
179 | (_, ty::ConstKind::Unevaluated(..)) if self.tcx.lazy_normalization() => { | |
3dfed10e | 180 | // FIXME(#59490): Need to remove the leak check to accommodate |
f9f354fc XL |
181 | // escaping bound variables here. |
182 | if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() { | |
183 | relation.const_equate_obligation(a, b); | |
184 | } | |
185 | return Ok(a); | |
186 | } | |
48663c56 XL |
187 | _ => {} |
188 | } | |
189 | ||
190 | ty::relate::super_relate_consts(relation, a, b) | |
191 | } | |
192 | ||
1b1a35ee XL |
193 | /// Unifies the const variable `target_vid` with the given constant. |
194 | /// | |
195 | /// This also tests if the given const `ct` contains an inference variable which was previously | |
196 | /// unioned with `target_vid`. If this is the case, inferring `target_vid` to `ct` | |
cdc7bbd5 | 197 | /// would result in an infinite type as we continuously replace an inference variable |
1b1a35ee XL |
198 | /// in `ct` with `ct` itself. |
199 | /// | |
200 | /// This is especially important as unevaluated consts use their parents generics. | |
201 | /// They therefore often contain unused substs, making these errors far more likely. | |
202 | /// | |
203 | /// A good example of this is the following: | |
204 | /// | |
04454e1e | 205 | /// ```compile_fail,E0308 |
94222f64 | 206 | /// #![feature(generic_const_exprs)] |
1b1a35ee XL |
207 | /// |
208 | /// fn bind<const N: usize>(value: [u8; N]) -> [u8; 3 + 4] { | |
209 | /// todo!() | |
210 | /// } | |
211 | /// | |
212 | /// fn main() { | |
213 | /// let mut arr = Default::default(); | |
214 | /// arr = bind(arr); | |
215 | /// } | |
216 | /// ``` | |
217 | /// | |
218 | /// Here `3 + 4` ends up as `ConstKind::Unevaluated` which uses the generics | |
219 | /// of `fn bind` (meaning that its substs contain `N`). | |
220 | /// | |
221 | /// `bind(arr)` now infers that the type of `arr` must be `[u8; N]`. | |
222 | /// The assignment `arr = bind(arr)` now tries to equate `N` with `3 + 4`. | |
223 | /// | |
224 | /// As `3 + 4` contains `N` in its substs, this must not succeed. | |
225 | /// | |
226 | /// See `src/test/ui/const-generics/occurs-check/` for more examples where this is relevant. | |
6a06907d | 227 | #[instrument(level = "debug", skip(self))] |
1b1a35ee | 228 | fn unify_const_variable( |
48663c56 | 229 | &self, |
1b1a35ee XL |
230 | param_env: ty::ParamEnv<'tcx>, |
231 | target_vid: ty::ConstVid<'tcx>, | |
5099ac24 | 232 | ct: ty::Const<'tcx>, |
48663c56 | 233 | vid_is_expected: bool, |
5099ac24 | 234 | ) -> RelateResult<'tcx, ty::Const<'tcx>> { |
1b1a35ee XL |
235 | let (for_universe, span) = { |
236 | let mut inner = self.inner.borrow_mut(); | |
237 | let variable_table = &mut inner.const_unification_table(); | |
238 | let var_value = variable_table.probe_value(target_vid); | |
239 | match var_value.val { | |
240 | ConstVariableValue::Known { value } => { | |
241 | bug!("instantiating {:?} which has a known value {:?}", target_vid, value) | |
242 | } | |
243 | ConstVariableValue::Unknown { universe } => (universe, var_value.origin.span), | |
244 | } | |
245 | }; | |
246 | let value = ConstInferUnifier { infcx: self, span, param_env, for_universe, target_vid } | |
247 | .relate(ct, ct)?; | |
248 | ||
74b04a01 | 249 | self.inner |
48663c56 | 250 | .borrow_mut() |
f9f354fc | 251 | .const_unification_table() |
dfeec247 | 252 | .unify_var_value( |
1b1a35ee | 253 | target_vid, |
dfeec247 XL |
254 | ConstVarValue { |
255 | origin: ConstVariableOrigin { | |
256 | kind: ConstVariableOriginKind::ConstInference, | |
257 | span: DUMMY_SP, | |
258 | }, | |
259 | val: ConstVariableValue::Known { value }, | |
dc9dc135 | 260 | }, |
dfeec247 | 261 | ) |
1b1a35ee XL |
262 | .map(|()| value) |
263 | .map_err(|e| const_unification_error(vid_is_expected, e)) | |
48663c56 XL |
264 | } |
265 | ||
dfeec247 XL |
266 | fn unify_integral_variable( |
267 | &self, | |
268 | vid_is_expected: bool, | |
269 | vid: ty::IntVid, | |
270 | val: ty::IntVarValue, | |
271 | ) -> RelateResult<'tcx, Ty<'tcx>> { | |
74b04a01 | 272 | self.inner |
a7813a04 | 273 | .borrow_mut() |
f9f354fc | 274 | .int_unification_table() |
0531ce1d | 275 | .unify_var_value(vid, Some(val)) |
a7813a04 XL |
276 | .map_err(|e| int_unification_error(vid_is_expected, e))?; |
277 | match val { | |
278 | IntType(v) => Ok(self.tcx.mk_mach_int(v)), | |
279 | UintType(v) => Ok(self.tcx.mk_mach_uint(v)), | |
280 | } | |
1a4d82fc | 281 | } |
1a4d82fc | 282 | |
dfeec247 XL |
283 | fn unify_float_variable( |
284 | &self, | |
285 | vid_is_expected: bool, | |
286 | vid: ty::FloatVid, | |
5869c6ff | 287 | val: ty::FloatTy, |
dfeec247 | 288 | ) -> RelateResult<'tcx, Ty<'tcx>> { |
74b04a01 | 289 | self.inner |
a7813a04 | 290 | .borrow_mut() |
f9f354fc | 291 | .float_unification_table() |
0531ce1d | 292 | .unify_var_value(vid, Some(ty::FloatVarValue(val))) |
a7813a04 XL |
293 | .map_err(|e| float_unification_error(vid_is_expected, e))?; |
294 | Ok(self.tcx.mk_mach_float(val)) | |
295 | } | |
c34b1796 AL |
296 | } |
297 | ||
dc9dc135 XL |
298 | impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { |
299 | pub fn tcx(&self) -> TyCtxt<'tcx> { | |
c34b1796 AL |
300 | self.infcx.tcx |
301 | } | |
302 | ||
dc9dc135 | 303 | pub fn equate<'a>(&'a mut self, a_is_expected: bool) -> Equate<'a, 'infcx, 'tcx> { |
5bcae85e | 304 | Equate::new(self, a_is_expected) |
1a4d82fc JJ |
305 | } |
306 | ||
dc9dc135 | 307 | pub fn sub<'a>(&'a mut self, a_is_expected: bool) -> Sub<'a, 'infcx, 'tcx> { |
5bcae85e | 308 | Sub::new(self, a_is_expected) |
c34b1796 AL |
309 | } |
310 | ||
dc9dc135 | 311 | pub fn lub<'a>(&'a mut self, a_is_expected: bool) -> Lub<'a, 'infcx, 'tcx> { |
5bcae85e | 312 | Lub::new(self, a_is_expected) |
c34b1796 AL |
313 | } |
314 | ||
dc9dc135 | 315 | pub fn glb<'a>(&'a mut self, a_is_expected: bool) -> Glb<'a, 'infcx, 'tcx> { |
5bcae85e | 316 | Glb::new(self, a_is_expected) |
1a4d82fc JJ |
317 | } |
318 | ||
9fa01778 XL |
319 | /// Here, `dir` is either `EqTo`, `SubtypeOf`, or `SupertypeOf`. |
320 | /// The idea is that we should ensure that the type `a_ty` is equal | |
cc61c64b XL |
321 | /// to, a subtype of, or a supertype of (respectively) the type |
322 | /// to which `b_vid` is bound. | |
323 | /// | |
324 | /// Since `b_vid` has not yet been instantiated with a type, we | |
325 | /// will first instantiate `b_vid` with a *generalized* version | |
326 | /// of `a_ty`. Generalization introduces other inference | |
327 | /// variables wherever subtyping could occur. | |
5e7ed085 | 328 | #[instrument(skip(self), level = "debug")] |
dfeec247 XL |
329 | pub fn instantiate( |
330 | &mut self, | |
331 | a_ty: Ty<'tcx>, | |
332 | dir: RelationDir, | |
333 | b_vid: ty::TyVid, | |
334 | a_is_expected: bool, | |
335 | ) -> RelateResult<'tcx, ()> { | |
cc61c64b | 336 | use self::RelationDir::*; |
1a4d82fc | 337 | |
cc61c64b | 338 | // Get the actual variable that b_vid has been inferred to |
f9f354fc | 339 | debug_assert!(self.infcx.inner.borrow_mut().type_variables().probe(b_vid).is_unknown()); |
1a4d82fc | 340 | |
cc61c64b XL |
341 | // Generalize type of `a_ty` appropriately depending on the |
342 | // direction. As an example, assume: | |
343 | // | |
344 | // - `a_ty == &'x ?1`, where `'x` is some free region and `?1` is an | |
345 | // inference variable, | |
346 | // - and `dir` == `SubtypeOf`. | |
347 | // | |
348 | // Then the generalized form `b_ty` would be `&'?2 ?3`, where | |
349 | // `'?2` and `?3` are fresh region/type inference | |
350 | // variables. (Down below, we will relate `a_ty <: b_ty`, | |
351 | // adding constraints like `'x: '?2` and `?1 <: ?3`.) | |
352 | let Generalization { ty: b_ty, needs_wf } = self.generalize(a_ty, b_vid, dir)?; | |
5e7ed085 | 353 | debug!(?b_ty); |
f9f354fc | 354 | self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty); |
cc61c64b XL |
355 | |
356 | if needs_wf { | |
dfeec247 XL |
357 | self.obligations.push(Obligation::new( |
358 | self.trace.cause.clone(), | |
359 | self.param_env, | |
c295e0f8 XL |
360 | ty::Binder::dummy(ty::PredicateKind::WellFormed(b_ty.into())) |
361 | .to_predicate(self.infcx.tcx), | |
dfeec247 | 362 | )); |
1a4d82fc JJ |
363 | } |
364 | ||
cc61c64b XL |
365 | // Finally, relate `b_ty` to `a_ty`, as described in previous comment. |
366 | // | |
367 | // FIXME(#16847): This code is non-ideal because all these subtype | |
368 | // relations wind up attributed to the same spans. We need | |
369 | // to associate causes/spans with each of the relations in | |
370 | // the stack to get this right. | |
371 | match dir { | |
f035d41b XL |
372 | EqTo => self.equate(a_is_expected).relate(a_ty, b_ty), |
373 | SubtypeOf => self.sub(a_is_expected).relate(a_ty, b_ty), | |
17df50a5 XL |
374 | SupertypeOf => self.sub(a_is_expected).relate_with_variance( |
375 | ty::Contravariant, | |
376 | ty::VarianceDiagInfo::default(), | |
377 | a_ty, | |
378 | b_ty, | |
379 | ), | |
cc61c64b XL |
380 | }?; |
381 | ||
1a4d82fc JJ |
382 | Ok(()) |
383 | } | |
384 | ||
cc61c64b XL |
385 | /// Attempts to generalize `ty` for the type variable `for_vid`. |
386 | /// This checks for cycle -- that is, whether the type `ty` | |
387 | /// references `for_vid`. The `dir` is the "direction" for which we | |
388 | /// a performing the generalization (i.e., are we producing a type | |
389 | /// that can be used as a supertype etc). | |
390 | /// | |
391 | /// Preconditions: | |
392 | /// | |
393 | /// - `for_vid` is a "root vid" | |
f2b60f7d | 394 | #[instrument(skip(self), level = "trace", ret)] |
dfeec247 XL |
395 | fn generalize( |
396 | &self, | |
397 | ty: Ty<'tcx>, | |
398 | for_vid: ty::TyVid, | |
399 | dir: RelationDir, | |
400 | ) -> RelateResult<'tcx, Generalization<'tcx>> { | |
cc61c64b XL |
401 | // Determine the ambient variance within which `ty` appears. |
402 | // The surrounding equation is: | |
403 | // | |
404 | // ty [op] ty2 | |
405 | // | |
406 | // where `op` is either `==`, `<:`, or `:>`. This maps quite | |
407 | // naturally. | |
408 | let ambient_variance = match dir { | |
409 | RelationDir::EqTo => ty::Invariant, | |
410 | RelationDir::SubtypeOf => ty::Covariant, | |
411 | RelationDir::SupertypeOf => ty::Contravariant, | |
412 | }; | |
413 | ||
5e7ed085 | 414 | trace!(?ambient_variance); |
0731742a | 415 | |
f9f354fc | 416 | let for_universe = match self.infcx.inner.borrow_mut().type_variables().probe(for_vid) { |
dfeec247 | 417 | v @ TypeVariableValue::Known { .. } => { |
1b1a35ee | 418 | bug!("instantiating {:?} which has a known value {:?}", for_vid, v,) |
dfeec247 | 419 | } |
0731742a XL |
420 | TypeVariableValue::Unknown { universe } => universe, |
421 | }; | |
422 | ||
5e7ed085 FG |
423 | trace!(?for_universe); |
424 | trace!(?self.trace); | |
0731742a | 425 | |
c34b1796 AL |
426 | let mut generalize = Generalizer { |
427 | infcx: self.infcx, | |
3dfed10e | 428 | cause: &self.trace.cause, |
f9f354fc | 429 | for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid), |
0731742a | 430 | for_universe, |
041b39d2 | 431 | ambient_variance, |
cc61c64b | 432 | needs_wf: false, |
ff7c6d11 | 433 | root_ty: ty, |
416331ca | 434 | param_env: self.param_env, |
29967ef6 | 435 | cache: SsoHashMap::new(), |
c34b1796 | 436 | }; |
cc61c64b | 437 | |
f2b60f7d | 438 | let ty = generalize.relate(ty, ty)?; |
cc61c64b XL |
439 | let needs_wf = generalize.needs_wf; |
440 | Ok(Generalization { ty, needs_wf }) | |
1a4d82fc | 441 | } |
f9f354fc XL |
442 | |
443 | pub fn add_const_equate_obligation( | |
444 | &mut self, | |
445 | a_is_expected: bool, | |
5099ac24 FG |
446 | a: ty::Const<'tcx>, |
447 | b: ty::Const<'tcx>, | |
f9f354fc XL |
448 | ) { |
449 | let predicate = if a_is_expected { | |
5869c6ff | 450 | ty::PredicateKind::ConstEquate(a, b) |
f9f354fc | 451 | } else { |
5869c6ff | 452 | ty::PredicateKind::ConstEquate(b, a) |
f9f354fc XL |
453 | }; |
454 | self.obligations.push(Obligation::new( | |
455 | self.trace.cause.clone(), | |
456 | self.param_env, | |
c295e0f8 | 457 | ty::Binder::dummy(predicate).to_predicate(self.tcx()), |
f9f354fc XL |
458 | )); |
459 | } | |
1a4d82fc JJ |
460 | } |
461 | ||
dc9dc135 XL |
462 | struct Generalizer<'cx, 'tcx> { |
463 | infcx: &'cx InferCtxt<'cx, 'tcx>, | |
ff7c6d11 | 464 | |
9fa01778 | 465 | /// The span, used when creating new type variables and things. |
3dfed10e | 466 | cause: &'cx ObligationCause<'tcx>, |
ff7c6d11 XL |
467 | |
468 | /// The vid of the type variable that is in the process of being | |
469 | /// instantiated; if we find this within the type we are folding, | |
470 | /// that means we would have created a cyclic type. | |
cc61c64b | 471 | for_vid_sub_root: ty::TyVid, |
ff7c6d11 | 472 | |
0731742a XL |
473 | /// The universe of the type variable that is in the process of |
474 | /// being instantiated. Any fresh variables that we create in this | |
475 | /// process should be in that same universe. | |
476 | for_universe: ty::UniverseIndex, | |
477 | ||
ff7c6d11 | 478 | /// Track the variance as we descend into the type. |
cc61c64b | 479 | ambient_variance: ty::Variance, |
ff7c6d11 XL |
480 | |
481 | /// See the field `needs_wf` in `Generalization`. | |
482 | needs_wf: bool, | |
483 | ||
484 | /// The root type that we are generalizing. Used when reporting cycles. | |
485 | root_ty: Ty<'tcx>, | |
416331ca XL |
486 | |
487 | param_env: ty::ParamEnv<'tcx>, | |
6c58768f | 488 | |
f2b60f7d | 489 | cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>, |
cc61c64b XL |
490 | } |
491 | ||
492 | /// Result from a generalization operation. This includes | |
493 | /// not only the generalized type, but also a bool flag | |
83c7162d | 494 | /// indicating whether further WF checks are needed. |
f2b60f7d | 495 | #[derive(Debug)] |
cc61c64b XL |
496 | struct Generalization<'tcx> { |
497 | ty: Ty<'tcx>, | |
498 | ||
499 | /// If true, then the generalized type may not be well-formed, | |
500 | /// even if the source type is well-formed, so we should add an | |
501 | /// additional check to enforce that it is. This arises in | |
502 | /// particular around 'bivariant' type parameters that are only | |
503 | /// constrained by a where-clause. As an example, imagine a type: | |
504 | /// | |
9fa01778 | 505 | /// struct Foo<A, B> where A: Iterator<Item = B> { |
cc61c64b XL |
506 | /// data: A |
507 | /// } | |
508 | /// | |
509 | /// here, `A` will be covariant, but `B` is | |
510 | /// unconstrained. However, whatever it is, for `Foo` to be WF, it | |
511 | /// must be equal to `A::Item`. If we have an input `Foo<?A, ?B>`, | |
512 | /// then after generalization we will wind up with a type like | |
513 | /// `Foo<?C, ?D>`. When we enforce that `Foo<?A, ?B> <: Foo<?C, | |
514 | /// ?D>` (or `>:`), we will wind up with the requirement that `?A | |
515 | /// <: ?C`, but no particular relationship between `?B` and `?D` | |
516 | /// (after all, we do not know the variance of the normalized form | |
517 | /// of `A::Item` with respect to `A`). If we do nothing else, this | |
9fa01778 | 518 | /// may mean that `?D` goes unconstrained (as in #41677). So, in |
cc61c64b XL |
519 | /// this scenario where we create a new type variable in a |
520 | /// bivariant context, we set the `needs_wf` flag to true. This | |
521 | /// will force the calling code to check that `WF(Foo<?C, ?D>)` | |
522 | /// holds, which in turn implies that `?C::Item == ?D`. So once | |
523 | /// `?C` is constrained, that should suffice to restrict `?D`. | |
524 | needs_wf: bool, | |
1a4d82fc JJ |
525 | } |
526 | ||
a2a8927a | 527 | impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> { |
dc9dc135 | 528 | fn tcx(&self) -> TyCtxt<'tcx> { |
1a4d82fc JJ |
529 | self.infcx.tcx |
530 | } | |
dfeec247 XL |
531 | fn param_env(&self) -> ty::ParamEnv<'tcx> { |
532 | self.param_env | |
533 | } | |
1a4d82fc | 534 | |
cc61c64b XL |
535 | fn tag(&self) -> &'static str { |
536 | "Generalizer" | |
537 | } | |
538 | ||
539 | fn a_is_expected(&self) -> bool { | |
540 | true | |
541 | } | |
542 | ||
dfeec247 XL |
543 | fn binders<T>( |
544 | &mut self, | |
cdc7bbd5 XL |
545 | a: ty::Binder<'tcx, T>, |
546 | b: ty::Binder<'tcx, T>, | |
547 | ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> | |
dfeec247 XL |
548 | where |
549 | T: Relate<'tcx>, | |
cc61c64b | 550 | { |
fc512014 | 551 | Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?)) |
cc61c64b XL |
552 | } |
553 | ||
dfeec247 XL |
554 | fn relate_item_substs( |
555 | &mut self, | |
556 | item_def_id: DefId, | |
557 | a_subst: SubstsRef<'tcx>, | |
558 | b_subst: SubstsRef<'tcx>, | |
559 | ) -> RelateResult<'tcx, SubstsRef<'tcx>> { | |
cc61c64b XL |
560 | if self.ambient_variance == ty::Variance::Invariant { |
561 | // Avoid fetching the variance if we are in an invariant | |
562 | // context; no need, and it can induce dependency cycles | |
0731742a | 563 | // (e.g., #41849). |
04454e1e | 564 | relate::relate_substs(self, a_subst, b_subst) |
cc61c64b | 565 | } else { |
a2a8927a XL |
566 | let tcx = self.tcx(); |
567 | let opt_variances = tcx.variances_of(item_def_id); | |
04454e1e FG |
568 | relate::relate_substs_with_variances( |
569 | self, | |
570 | item_def_id, | |
571 | &opt_variances, | |
572 | a_subst, | |
573 | b_subst, | |
574 | ) | |
cc61c64b XL |
575 | } |
576 | } | |
577 | ||
dfeec247 XL |
578 | fn relate_with_variance<T: Relate<'tcx>>( |
579 | &mut self, | |
580 | variance: ty::Variance, | |
17df50a5 | 581 | _info: ty::VarianceDiagInfo<'tcx>, |
f035d41b XL |
582 | a: T, |
583 | b: T, | |
dfeec247 | 584 | ) -> RelateResult<'tcx, T> { |
cc61c64b XL |
585 | let old_ambient_variance = self.ambient_variance; |
586 | self.ambient_variance = self.ambient_variance.xform(variance); | |
587 | ||
588 | let result = self.relate(a, b); | |
589 | self.ambient_variance = old_ambient_variance; | |
590 | result | |
591 | } | |
592 | ||
593 | fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { | |
594 | assert_eq!(t, t2); // we are abusing TypeRelation here; both LHS and RHS ought to be == | |
595 | ||
f2b60f7d FG |
596 | if let Some(&result) = self.cache.get(&t) { |
597 | return Ok(result); | |
6c58768f | 598 | } |
0731742a XL |
599 | debug!("generalize: t={:?}", t); |
600 | ||
48663c56 | 601 | // Check to see whether the type we are generalizing references |
cc61c64b XL |
602 | // any other type variable related to `vid` via |
603 | // subtyping. This is basically our "occurs check", preventing | |
604 | // us from creating infinitely sized types. | |
1b1a35ee | 605 | let result = match *t.kind() { |
b7449926 | 606 | ty::Infer(ty::TyVar(vid)) => { |
f9f354fc XL |
607 | let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid); |
608 | let sub_vid = self.infcx.inner.borrow_mut().type_variables().sub_root_var(vid); | |
cc61c64b XL |
609 | if sub_vid == self.for_vid_sub_root { |
610 | // If sub-roots are equal, then `for_vid` and | |
611 | // `vid` are related via subtyping. | |
e74abb32 | 612 | Err(TypeError::CyclicTy(self.root_ty)) |
1a4d82fc | 613 | } else { |
f9f354fc | 614 | let probe = self.infcx.inner.borrow_mut().type_variables().probe(vid); |
74b04a01 | 615 | match probe { |
0531ce1d | 616 | TypeVariableValue::Known { value: u } => { |
0731742a | 617 | debug!("generalize: known value {:?}", u); |
f035d41b | 618 | self.relate(u, u) |
cc61c64b | 619 | } |
83c7162d | 620 | TypeVariableValue::Unknown { universe } => { |
cc61c64b XL |
621 | match self.ambient_variance { |
622 | // Invariant: no need to make a fresh type variable. | |
0731742a XL |
623 | ty::Invariant => { |
624 | if self.for_universe.can_name(universe) { | |
625 | return Ok(t); | |
626 | } | |
627 | } | |
cc61c64b XL |
628 | |
629 | // Bivariant: make a fresh var, but we | |
630 | // may need a WF predicate. See | |
631 | // comment on `needs_wf` field for | |
632 | // more info. | |
633 | ty::Bivariant => self.needs_wf = true, | |
634 | ||
635 | // Co/contravariant: this will be | |
636 | // sufficiently constrained later on. | |
637 | ty::Covariant | ty::Contravariant => (), | |
638 | } | |
639 | ||
74b04a01 | 640 | let origin = |
f9f354fc XL |
641 | *self.infcx.inner.borrow_mut().type_variables().var_origin(vid); |
642 | let new_var_id = self | |
643 | .infcx | |
644 | .inner | |
645 | .borrow_mut() | |
646 | .type_variables() | |
c295e0f8 | 647 | .new_var(self.for_universe, origin); |
532ac7d7 | 648 | let u = self.tcx().mk_ty_var(new_var_id); |
94222f64 XL |
649 | |
650 | // Record that we replaced `vid` with `new_var_id` as part of a generalization | |
651 | // operation. This is needed to detect cyclic types. To see why, see the | |
652 | // docs in the `type_variables` module. | |
653 | self.infcx.inner.borrow_mut().type_variables().sub(vid, new_var_id); | |
dfeec247 | 654 | debug!("generalize: replacing original vid={:?} with new={:?}", vid, u); |
e74abb32 | 655 | Ok(u) |
54a0048b | 656 | } |
1a4d82fc JJ |
657 | } |
658 | } | |
659 | } | |
ba9703b0 | 660 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => { |
cc61c64b XL |
661 | // No matter what mode we are in, |
662 | // integer/floating-point types must be equal to be | |
663 | // relatable. | |
664 | Ok(t) | |
665 | } | |
dfeec247 | 666 | _ => relate::super_relate_tys(self, t, t), |
f2b60f7d | 667 | }?; |
6c58768f | 668 | |
f2b60f7d FG |
669 | self.cache.insert(t, result); |
670 | Ok(result) | |
1a4d82fc JJ |
671 | } |
672 | ||
dfeec247 XL |
673 | fn regions( |
674 | &mut self, | |
675 | r: ty::Region<'tcx>, | |
676 | r2: ty::Region<'tcx>, | |
677 | ) -> RelateResult<'tcx, ty::Region<'tcx>> { | |
cc61c64b XL |
678 | assert_eq!(r, r2); // we are abusing TypeRelation here; both LHS and RHS ought to be == |
679 | ||
0731742a XL |
680 | debug!("generalize: regions r={:?}", r); |
681 | ||
9e0c209e | 682 | match *r { |
3157f602 XL |
683 | // Never make variables for regions bound within the type itself, |
684 | // nor for erased regions. | |
dfeec247 | 685 | ty::ReLateBound(..) | ty::ReErased => { |
cc61c64b XL |
686 | return Ok(r); |
687 | } | |
1a4d82fc | 688 | |
dfeec247 XL |
689 | ty::RePlaceholder(..) |
690 | | ty::ReVar(..) | |
dfeec247 | 691 | | ty::ReStatic |
dfeec247 XL |
692 | | ty::ReEarlyBound(..) |
693 | | ty::ReFree(..) => { | |
0731742a | 694 | // see common code below |
1a4d82fc | 695 | } |
0731742a | 696 | } |
ff7c6d11 | 697 | |
0731742a XL |
698 | // If we are in an invariant context, we can re-use the region |
699 | // as is, unless it happens to be in some universe that we | |
700 | // can't name. (In the case of a region *variable*, we could | |
701 | // use it if we promoted it into our universe, but we don't | |
702 | // bother.) | |
703 | if let ty::Invariant = self.ambient_variance { | |
704 | let r_universe = self.infcx.universe_of_region(r); | |
705 | if self.for_universe.can_name(r_universe) { | |
706 | return Ok(r); | |
ff7c6d11 | 707 | } |
1a4d82fc JJ |
708 | } |
709 | ||
710 | // FIXME: This is non-ideal because we don't give a | |
711 | // very descriptive origin for this region variable. | |
3dfed10e | 712 | Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.cause.span), self.for_universe)) |
1a4d82fc | 713 | } |
48663c56 XL |
714 | |
715 | fn consts( | |
716 | &mut self, | |
5099ac24 FG |
717 | c: ty::Const<'tcx>, |
718 | c2: ty::Const<'tcx>, | |
719 | ) -> RelateResult<'tcx, ty::Const<'tcx>> { | |
48663c56 XL |
720 | assert_eq!(c, c2); // we are abusing TypeRelation here; both LHS and RHS ought to be == |
721 | ||
923072b8 | 722 | match c.kind() { |
60c5eb7d | 723 | ty::ConstKind::Infer(InferConst::Var(vid)) => { |
f9f354fc XL |
724 | let mut inner = self.infcx.inner.borrow_mut(); |
725 | let variable_table = &mut inner.const_unification_table(); | |
e74abb32 XL |
726 | let var_value = variable_table.probe_value(vid); |
727 | match var_value.val { | |
fc512014 XL |
728 | ConstVariableValue::Known { value: u } => { |
729 | drop(inner); | |
730 | self.relate(u, u) | |
731 | } | |
e74abb32 XL |
732 | ConstVariableValue::Unknown { universe } => { |
733 | if self.for_universe.can_name(universe) { | |
734 | Ok(c) | |
735 | } else { | |
736 | let new_var_id = variable_table.new_key(ConstVarValue { | |
737 | origin: var_value.origin, | |
738 | val: ConstVariableValue::Unknown { universe: self.for_universe }, | |
739 | }); | |
5099ac24 | 740 | Ok(self.tcx().mk_const_var(new_var_id, c.ty())) |
e74abb32 | 741 | } |
48663c56 | 742 | } |
48663c56 XL |
743 | } |
744 | } | |
f2b60f7d FG |
745 | ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { |
746 | assert_eq!(promoted, ()); | |
747 | ||
17df50a5 XL |
748 | let substs = self.relate_with_variance( |
749 | ty::Variance::Invariant, | |
750 | ty::VarianceDiagInfo::default(), | |
751 | substs, | |
752 | substs, | |
753 | )?; | |
5099ac24 FG |
754 | Ok(self.tcx().mk_const(ty::ConstS { |
755 | ty: c.ty(), | |
923072b8 | 756 | kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }), |
cdc7bbd5 XL |
757 | })) |
758 | } | |
e74abb32 | 759 | _ => relate::super_relate_consts(self, c, c), |
48663c56 XL |
760 | } |
761 | } | |
1a4d82fc | 762 | } |
c34b1796 | 763 | |
f9f354fc XL |
764 | pub trait ConstEquateRelation<'tcx>: TypeRelation<'tcx> { |
765 | /// Register an obligation that both constants must be equal to each other. | |
766 | /// | |
767 | /// If they aren't equal then the relation doesn't hold. | |
5099ac24 | 768 | fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>); |
f9f354fc XL |
769 | } |
770 | ||
48663c56 XL |
771 | pub fn const_unification_error<'tcx>( |
772 | a_is_expected: bool, | |
5099ac24 | 773 | (a, b): (ty::Const<'tcx>, ty::Const<'tcx>), |
48663c56 | 774 | ) -> TypeError<'tcx> { |
a2a8927a | 775 | TypeError::ConstMismatch(ExpectedFound::new(a_is_expected, a, b)) |
48663c56 XL |
776 | } |
777 | ||
dfeec247 XL |
778 | fn int_unification_error<'tcx>( |
779 | a_is_expected: bool, | |
780 | v: (ty::IntVarValue, ty::IntVarValue), | |
781 | ) -> TypeError<'tcx> { | |
c34b1796 | 782 | let (a, b) = v; |
a2a8927a | 783 | TypeError::IntMismatch(ExpectedFound::new(a_is_expected, a, b)) |
c34b1796 AL |
784 | } |
785 | ||
dfeec247 XL |
786 | fn float_unification_error<'tcx>( |
787 | a_is_expected: bool, | |
788 | v: (ty::FloatVarValue, ty::FloatVarValue), | |
789 | ) -> TypeError<'tcx> { | |
0531ce1d | 790 | let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v; |
a2a8927a | 791 | TypeError::FloatMismatch(ExpectedFound::new(a_is_expected, a, b)) |
c34b1796 | 792 | } |
1b1a35ee XL |
793 | |
794 | struct ConstInferUnifier<'cx, 'tcx> { | |
795 | infcx: &'cx InferCtxt<'cx, 'tcx>, | |
796 | ||
797 | span: Span, | |
798 | ||
799 | param_env: ty::ParamEnv<'tcx>, | |
800 | ||
801 | for_universe: ty::UniverseIndex, | |
802 | ||
803 | /// The vid of the const variable that is in the process of being | |
804 | /// instantiated; if we find this within the const we are folding, | |
805 | /// that means we would have created a cyclic const. | |
806 | target_vid: ty::ConstVid<'tcx>, | |
807 | } | |
808 | ||
809 | // We use `TypeRelation` here to propagate `RelateResult` upwards. | |
810 | // | |
811 | // Both inputs are expected to be the same. | |
a2a8927a | 812 | impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { |
1b1a35ee XL |
813 | fn tcx(&self) -> TyCtxt<'tcx> { |
814 | self.infcx.tcx | |
815 | } | |
816 | ||
817 | fn param_env(&self) -> ty::ParamEnv<'tcx> { | |
818 | self.param_env | |
819 | } | |
820 | ||
821 | fn tag(&self) -> &'static str { | |
822 | "ConstInferUnifier" | |
823 | } | |
824 | ||
825 | fn a_is_expected(&self) -> bool { | |
826 | true | |
827 | } | |
828 | ||
829 | fn relate_with_variance<T: Relate<'tcx>>( | |
830 | &mut self, | |
831 | _variance: ty::Variance, | |
17df50a5 | 832 | _info: ty::VarianceDiagInfo<'tcx>, |
1b1a35ee XL |
833 | a: T, |
834 | b: T, | |
835 | ) -> RelateResult<'tcx, T> { | |
836 | // We don't care about variance here. | |
837 | self.relate(a, b) | |
838 | } | |
839 | ||
840 | fn binders<T>( | |
841 | &mut self, | |
cdc7bbd5 XL |
842 | a: ty::Binder<'tcx, T>, |
843 | b: ty::Binder<'tcx, T>, | |
844 | ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> | |
1b1a35ee XL |
845 | where |
846 | T: Relate<'tcx>, | |
847 | { | |
fc512014 | 848 | Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?)) |
1b1a35ee XL |
849 | } |
850 | ||
f2b60f7d | 851 | #[instrument(level = "debug", skip(self), ret)] |
1b1a35ee XL |
852 | fn tys(&mut self, t: Ty<'tcx>, _t: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { |
853 | debug_assert_eq!(t, _t); | |
1b1a35ee XL |
854 | |
855 | match t.kind() { | |
856 | &ty::Infer(ty::TyVar(vid)) => { | |
857 | let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid); | |
858 | let probe = self.infcx.inner.borrow_mut().type_variables().probe(vid); | |
859 | match probe { | |
860 | TypeVariableValue::Known { value: u } => { | |
861 | debug!("ConstOccursChecker: known value {:?}", u); | |
862 | self.tys(u, u) | |
863 | } | |
864 | TypeVariableValue::Unknown { universe } => { | |
865 | if self.for_universe.can_name(universe) { | |
866 | return Ok(t); | |
867 | } | |
868 | ||
869 | let origin = | |
870 | *self.infcx.inner.borrow_mut().type_variables().var_origin(vid); | |
c295e0f8 XL |
871 | let new_var_id = self |
872 | .infcx | |
873 | .inner | |
874 | .borrow_mut() | |
875 | .type_variables() | |
876 | .new_var(self.for_universe, origin); | |
f2b60f7d | 877 | Ok(self.tcx().mk_ty_var(new_var_id)) |
1b1a35ee XL |
878 | } |
879 | } | |
880 | } | |
fc512014 | 881 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => Ok(t), |
1b1a35ee XL |
882 | _ => relate::super_relate_tys(self, t, t), |
883 | } | |
884 | } | |
885 | ||
886 | fn regions( | |
887 | &mut self, | |
888 | r: ty::Region<'tcx>, | |
889 | _r: ty::Region<'tcx>, | |
890 | ) -> RelateResult<'tcx, ty::Region<'tcx>> { | |
891 | debug_assert_eq!(r, _r); | |
892 | debug!("ConstInferUnifier: r={:?}", r); | |
893 | ||
5099ac24 | 894 | match *r { |
1b1a35ee XL |
895 | // Never make variables for regions bound within the type itself, |
896 | // nor for erased regions. | |
897 | ty::ReLateBound(..) | ty::ReErased => { | |
898 | return Ok(r); | |
899 | } | |
900 | ||
901 | ty::RePlaceholder(..) | |
902 | | ty::ReVar(..) | |
1b1a35ee XL |
903 | | ty::ReStatic |
904 | | ty::ReEarlyBound(..) | |
905 | | ty::ReFree(..) => { | |
906 | // see common code below | |
907 | } | |
908 | } | |
909 | ||
910 | let r_universe = self.infcx.universe_of_region(r); | |
911 | if self.for_universe.can_name(r_universe) { | |
912 | return Ok(r); | |
913 | } else { | |
914 | // FIXME: This is non-ideal because we don't give a | |
915 | // very descriptive origin for this region variable. | |
916 | Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.span), self.for_universe)) | |
917 | } | |
918 | } | |
919 | ||
f2b60f7d | 920 | #[instrument(level = "debug", skip(self))] |
1b1a35ee XL |
921 | fn consts( |
922 | &mut self, | |
5099ac24 FG |
923 | c: ty::Const<'tcx>, |
924 | _c: ty::Const<'tcx>, | |
925 | ) -> RelateResult<'tcx, ty::Const<'tcx>> { | |
1b1a35ee | 926 | debug_assert_eq!(c, _c); |
1b1a35ee | 927 | |
923072b8 | 928 | match c.kind() { |
1b1a35ee | 929 | ty::ConstKind::Infer(InferConst::Var(vid)) => { |
1b1a35ee XL |
930 | // Check if the current unification would end up |
931 | // unifying `target_vid` with a const which contains | |
932 | // an inference variable which is unioned with `target_vid`. | |
933 | // | |
934 | // Not doing so can easily result in stack overflows. | |
3c0e092e XL |
935 | if self |
936 | .infcx | |
937 | .inner | |
938 | .borrow_mut() | |
939 | .const_unification_table() | |
940 | .unioned(self.target_vid, vid) | |
941 | { | |
1b1a35ee XL |
942 | return Err(TypeError::CyclicConst(c)); |
943 | } | |
944 | ||
3c0e092e XL |
945 | let var_value = |
946 | self.infcx.inner.borrow_mut().const_unification_table().probe_value(vid); | |
1b1a35ee XL |
947 | match var_value.val { |
948 | ConstVariableValue::Known { value: u } => self.consts(u, u), | |
949 | ConstVariableValue::Unknown { universe } => { | |
950 | if self.for_universe.can_name(universe) { | |
951 | Ok(c) | |
952 | } else { | |
3c0e092e XL |
953 | let new_var_id = |
954 | self.infcx.inner.borrow_mut().const_unification_table().new_key( | |
955 | ConstVarValue { | |
956 | origin: var_value.origin, | |
957 | val: ConstVariableValue::Unknown { | |
958 | universe: self.for_universe, | |
959 | }, | |
960 | }, | |
961 | ); | |
5099ac24 | 962 | Ok(self.tcx().mk_const_var(new_var_id, c.ty())) |
1b1a35ee XL |
963 | } |
964 | } | |
965 | } | |
966 | } | |
f2b60f7d FG |
967 | ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { |
968 | assert_eq!(promoted, ()); | |
969 | ||
17df50a5 XL |
970 | let substs = self.relate_with_variance( |
971 | ty::Variance::Invariant, | |
972 | ty::VarianceDiagInfo::default(), | |
973 | substs, | |
974 | substs, | |
975 | )?; | |
f2b60f7d | 976 | |
5099ac24 FG |
977 | Ok(self.tcx().mk_const(ty::ConstS { |
978 | ty: c.ty(), | |
923072b8 | 979 | kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }), |
cdc7bbd5 XL |
980 | })) |
981 | } | |
1b1a35ee XL |
982 | _ => relate::super_relate_consts(self, c, c), |
983 | } | |
984 | } | |
985 | } |