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