rustc_infer/infer/relate/generalize.rs
1use std::mem;
2
3use rustc_data_structures::sso::SsoHashMap;
4use rustc_data_structures::stack::ensure_sufficient_stack;
5use rustc_hir::def_id::DefId;
6use rustc_middle::bug;
7use rustc_middle::ty::error::TypeError;
8use rustc_middle::ty::{
9 self, AliasRelationDirection, InferConst, MaxUniverse, Term, Ty, TyCtxt, TypeVisitable,
10 TypeVisitableExt, TypingMode,
11};
12use rustc_span::Span;
13use tracing::{debug, instrument, warn};
14
15use super::{
16 PredicateEmittingRelation, Relate, RelateResult, StructurallyRelateAliases, TypeRelation,
17};
18use crate::infer::type_variable::TypeVariableValue;
19use crate::infer::unify_key::ConstVariableValue;
20use crate::infer::{InferCtxt, RegionVariableOrigin, relate};
21
22#[derive(Copy, Clone, Eq, PartialEq, Debug)]
23enum TermVid {
24 Ty(ty::TyVid),
25 Const(ty::ConstVid),
26}
27
28impl From<ty::TyVid> for TermVid {
29 fn from(value: ty::TyVid) -> Self {
30 TermVid::Ty(value)
31 }
32}
33
34impl From<ty::ConstVid> for TermVid {
35 fn from(value: ty::ConstVid) -> Self {
36 TermVid::Const(value)
37 }
38}
39
40impl<'tcx> InferCtxt<'tcx> {
41 /// The idea is that we should ensure that the type variable `target_vid`
42 /// is equal to, a subtype of, or a supertype of `source_ty`.
43 ///
44 /// For this, we will instantiate `target_vid` with a *generalized* version
45 /// of `source_ty`. Generalization introduces other inference variables wherever
46 /// subtyping could occur. This also does the occurs checks, detecting whether
47 /// instantiating `target_vid` would result in a cyclic type. We eagerly error
48 /// in this case.
49 ///
50 /// This is *not* expected to be used anywhere except for an implementation of
51 /// `TypeRelation`. Do not use this, and instead please use `At::eq`, for all
52 /// other usecases (i.e. setting the value of a type var).
53 #[instrument(level = "debug", skip(self, relation))]
54 pub fn instantiate_ty_var<R: PredicateEmittingRelation<InferCtxt<'tcx>>>(
55 &self,
56 relation: &mut R,
57 target_is_expected: bool,
58 target_vid: ty::TyVid,
59 instantiation_variance: ty::Variance,
60 source_ty: Ty<'tcx>,
61 ) -> RelateResult<'tcx, ()> {
62 debug_assert!(self.inner.borrow_mut().type_variables().probe(target_vid).is_unknown());
63
64 // Generalize `source_ty` depending on the current variance. As an example, assume
65 // `?target <: &'x ?1`, where `'x` is some free region and `?1` is an inference
66 // variable.
67 //
68 // Then the `generalized_ty` would be `&'?2 ?3`, where `'?2` and `?3` are fresh
69 // region/type inference variables.
70 //
71 // We then relate `generalized_ty <: source_ty`, adding constraints like `'x: '?2` and
72 // `?1 <: ?3`.
73 let Generalization { value_may_be_infer: generalized_ty, has_unconstrained_ty_var } = self
74 .generalize(
75 relation.span(),
76 relation.structurally_relate_aliases(),
77 target_vid,
78 instantiation_variance,
79 source_ty,
80 )?;
81
82 // Constrain `b_vid` to the generalized type `generalized_ty`.
83 if let &ty::Infer(ty::TyVar(generalized_vid)) = generalized_ty.kind() {
84 self.inner.borrow_mut().type_variables().equate(target_vid, generalized_vid);
85 } else {
86 self.inner.borrow_mut().type_variables().instantiate(target_vid, generalized_ty);
87 }
88
89 // See the comment on `Generalization::has_unconstrained_ty_var`.
90 if has_unconstrained_ty_var {
91 relation.register_predicates([ty::ClauseKind::WellFormed(generalized_ty.into())]);
92 }
93
94 // Finally, relate `generalized_ty` to `source_ty`, as described in previous comment.
95 //
96 // FIXME(#16847): This code is non-ideal because all these subtype
97 // relations wind up attributed to the same spans. We need
98 // to associate causes/spans with each of the relations in
99 // the stack to get this right.
100 if generalized_ty.is_ty_var() {
101 // This happens for cases like `<?0 as Trait>::Assoc == ?0`.
102 // We can't instantiate `?0` here as that would result in a
103 // cyclic type. We instead delay the unification in case
104 // the alias can be normalized to something which does not
105 // mention `?0`.
106 if self.next_trait_solver() {
107 let (lhs, rhs, direction) = match instantiation_variance {
108 ty::Invariant => {
109 (generalized_ty.into(), source_ty.into(), AliasRelationDirection::Equate)
110 }
111 ty::Covariant => {
112 (generalized_ty.into(), source_ty.into(), AliasRelationDirection::Subtype)
113 }
114 ty::Contravariant => {
115 (source_ty.into(), generalized_ty.into(), AliasRelationDirection::Subtype)
116 }
117 ty::Bivariant => unreachable!("bivariant generalization"),
118 };
119
120 relation.register_predicates([ty::PredicateKind::AliasRelate(lhs, rhs, direction)]);
121 } else {
122 match source_ty.kind() {
123 &ty::Alias(ty::Projection, data) => {
124 // FIXME: This does not handle subtyping correctly, we could
125 // instead create a new inference variable `?normalized_source`, emitting
126 // `Projection(normalized_source, ?ty_normalized)` and
127 // `?normalized_source <: generalized_ty`.
128 relation.register_predicates([ty::ProjectionPredicate {
129 projection_term: data.into(),
130 term: generalized_ty.into(),
131 }]);
132 }
133 // The old solver only accepts projection predicates for associated types.
134 ty::Alias(ty::Inherent | ty::Free | ty::Opaque, _) => {
135 return Err(TypeError::CyclicTy(source_ty));
136 }
137 _ => bug!("generalized `{source_ty:?} to infer, not an alias"),
138 }
139 }
140 } else {
141 // NOTE: The `instantiation_variance` is not the same variance as
142 // used by the relation. When instantiating `b`, `target_is_expected`
143 // is flipped and the `instantiation_variance` is also flipped. To
144 // constrain the `generalized_ty` while using the original relation,
145 // we therefore only have to flip the arguments.
146 //
147 // ```ignore (not code)
148 // ?a rel B
149 // instantiate_ty_var(?a, B) # expected and variance not flipped
150 // B' rel B
151 // ```
152 // or
153 // ```ignore (not code)
154 // A rel ?b
155 // instantiate_ty_var(?b, A) # expected and variance flipped
156 // A rel A'
157 // ```
158 if target_is_expected {
159 relation.relate(generalized_ty, source_ty)?;
160 } else {
161 debug!("flip relation");
162 relation.relate(source_ty, generalized_ty)?;
163 }
164 }
165
166 Ok(())
167 }
168
169 /// Instantiates the const variable `target_vid` with the given constant.
170 ///
171 /// This also tests if the given const `ct` contains an inference variable which was previously
172 /// unioned with `target_vid`. If this is the case, inferring `target_vid` to `ct`
173 /// would result in an infinite type as we continuously replace an inference variable
174 /// in `ct` with `ct` itself.
175 ///
176 /// This is especially important as unevaluated consts use their parents generics.
177 /// They therefore often contain unused args, making these errors far more likely.
178 ///
179 /// A good example of this is the following:
180 ///
181 /// ```compile_fail,E0308
182 /// #![feature(generic_const_exprs)]
183 ///
184 /// fn bind<const N: usize>(value: [u8; N]) -> [u8; 3 + 4] {
185 /// todo!()
186 /// }
187 ///
188 /// fn main() {
189 /// let mut arr = Default::default();
190 /// arr = bind(arr);
191 /// }
192 /// ```
193 ///
194 /// Here `3 + 4` ends up as `ConstKind::Unevaluated` which uses the generics
195 /// of `fn bind` (meaning that its args contain `N`).
196 ///
197 /// `bind(arr)` now infers that the type of `arr` must be `[u8; N]`.
198 /// The assignment `arr = bind(arr)` now tries to equate `N` with `3 + 4`.
199 ///
200 /// As `3 + 4` contains `N` in its args, this must not succeed.
201 ///
202 /// See `tests/ui/const-generics/occurs-check/` for more examples where this is relevant.
203 #[instrument(level = "debug", skip(self, relation))]
204 pub(crate) fn instantiate_const_var<R: PredicateEmittingRelation<InferCtxt<'tcx>>>(
205 &self,
206 relation: &mut R,
207 target_is_expected: bool,
208 target_vid: ty::ConstVid,
209 source_ct: ty::Const<'tcx>,
210 ) -> RelateResult<'tcx, ()> {
211 // FIXME(generic_const_exprs): Occurs check failures for unevaluated
212 // constants and generic expressions are not yet handled correctly.
213 let Generalization { value_may_be_infer: generalized_ct, has_unconstrained_ty_var } = self
214 .generalize(
215 relation.span(),
216 relation.structurally_relate_aliases(),
217 target_vid,
218 ty::Invariant,
219 source_ct,
220 )?;
221
222 debug_assert!(!generalized_ct.is_ct_infer());
223 if has_unconstrained_ty_var {
224 bug!("unconstrained ty var when generalizing `{source_ct:?}`");
225 }
226
227 self.inner
228 .borrow_mut()
229 .const_unification_table()
230 .union_value(target_vid, ConstVariableValue::Known { value: generalized_ct });
231
232 // Make sure that the order is correct when relating the
233 // generalized const and the source.
234 if target_is_expected {
235 relation.relate_with_variance(
236 ty::Invariant,
237 ty::VarianceDiagInfo::default(),
238 generalized_ct,
239 source_ct,
240 )?;
241 } else {
242 relation.relate_with_variance(
243 ty::Invariant,
244 ty::VarianceDiagInfo::default(),
245 source_ct,
246 generalized_ct,
247 )?;
248 }
249
250 Ok(())
251 }
252
253 /// Attempts to generalize `source_term` for the type variable `target_vid`.
254 /// This checks for cycles -- that is, whether `source_term` references `target_vid`.
255 fn generalize<T: Into<Term<'tcx>> + Relate<TyCtxt<'tcx>>>(
256 &self,
257 span: Span,
258 structurally_relate_aliases: StructurallyRelateAliases,
259 target_vid: impl Into<TermVid>,
260 ambient_variance: ty::Variance,
261 source_term: T,
262 ) -> RelateResult<'tcx, Generalization<T>> {
263 assert!(!source_term.has_escaping_bound_vars());
264 let (for_universe, root_vid) = match target_vid.into() {
265 TermVid::Ty(ty_vid) => {
266 (self.probe_ty_var(ty_vid).unwrap_err(), TermVid::Ty(self.root_var(ty_vid)))
267 }
268 TermVid::Const(ct_vid) => (
269 self.probe_const_var(ct_vid).unwrap_err(),
270 TermVid::Const(self.inner.borrow_mut().const_unification_table().find(ct_vid).vid),
271 ),
272 };
273
274 let mut generalizer = Generalizer {
275 infcx: self,
276 span,
277 structurally_relate_aliases,
278 root_vid,
279 for_universe,
280 root_term: source_term.into(),
281 ambient_variance,
282 in_alias: false,
283 cache: Default::default(),
284 has_unconstrained_ty_var: false,
285 };
286
287 let value_may_be_infer = generalizer.relate(source_term, source_term)?;
288 let has_unconstrained_ty_var = generalizer.has_unconstrained_ty_var;
289 Ok(Generalization { value_may_be_infer, has_unconstrained_ty_var })
290 }
291}
292
293/// The "generalizer" is used when handling inference variables.
294///
295/// The basic strategy for handling a constraint like `?A <: B` is to
296/// apply a "generalization strategy" to the term `B` -- this replaces
297/// all the lifetimes in the term `B` with fresh inference variables.
298/// (You can read more about the strategy in this [blog post].)
299///
300/// As an example, if we had `?A <: &'x u32`, we would generalize `&'x
301/// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the
302/// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which
303/// establishes `'0: 'x` as a constraint.
304///
305/// [blog post]: https://is.gd/0hKvIr
306struct Generalizer<'me, 'tcx> {
307 infcx: &'me InferCtxt<'tcx>,
308
309 span: Span,
310
311 /// Whether aliases should be related structurally. If not, we have to
312 /// be careful when generalizing aliases.
313 structurally_relate_aliases: StructurallyRelateAliases,
314
315 /// The vid of the type variable that is in the process of being
316 /// instantiated. If we find this within the value we are folding,
317 /// that means we would have created a cyclic value.
318 root_vid: TermVid,
319
320 /// The universe of the type variable that is in the process of being
321 /// instantiated. If we find anything that this universe cannot name,
322 /// we reject the relation.
323 for_universe: ty::UniverseIndex,
324
325 /// The root term (const or type) we're generalizing. Used for cycle errors.
326 root_term: Term<'tcx>,
327
328 /// After we generalize this type, we are going to relate it to
329 /// some other type. What will be the variance at this point?
330 ambient_variance: ty::Variance,
331
332 /// This is set once we're generalizing the arguments of an alias.
333 ///
334 /// This is necessary to correctly handle
335 /// `<T as Bar<<?0 as Foo>::Assoc>::Assoc == ?0`. This equality can
336 /// hold by either normalizing the outer or the inner associated type.
337 in_alias: bool,
338
339 cache: SsoHashMap<(Ty<'tcx>, ty::Variance, bool), Ty<'tcx>>,
340
341 /// See the field `has_unconstrained_ty_var` in `Generalization`.
342 has_unconstrained_ty_var: bool,
343}
344
345impl<'tcx> Generalizer<'_, 'tcx> {
346 /// Create an error that corresponds to the term kind in `root_term`
347 fn cyclic_term_error(&self) -> TypeError<'tcx> {
348 match self.root_term.kind() {
349 ty::TermKind::Ty(ty) => TypeError::CyclicTy(ty),
350 ty::TermKind::Const(ct) => TypeError::CyclicConst(ct),
351 }
352 }
353
354 /// Create a new type variable in the universe of the target when
355 /// generalizing an alias. This has to set `has_unconstrained_ty_var`
356 /// if we're currently in a bivariant context.
357 fn next_ty_var_for_alias(&mut self) -> Ty<'tcx> {
358 self.has_unconstrained_ty_var |= self.ambient_variance == ty::Bivariant;
359 self.infcx.next_ty_var_in_universe(self.span, self.for_universe)
360 }
361
362 /// An occurs check failure inside of an alias does not mean
363 /// that the types definitely don't unify. We may be able
364 /// to normalize the alias after all.
365 ///
366 /// We handle this by lazily equating the alias and generalizing
367 /// it to an inference variable. In the new solver, we always
368 /// generalize to an infer var unless the alias contains escaping
369 /// bound variables.
370 ///
371 /// Correctly handling aliases with escaping bound variables is
372 /// difficult and currently incomplete in two opposite ways:
373 /// - if we get an occurs check failure in the alias, replace it with a new infer var.
374 /// This causes us to later emit an alias-relate goal and is incomplete in case the
375 /// alias normalizes to type containing one of the bound variables.
376 /// - if the alias contains an inference variable not nameable by `for_universe`, we
377 /// continue generalizing the alias. This ends up pulling down the universe of the
378 /// inference variable and is incomplete in case the alias would normalize to a type
379 /// which does not mention that inference variable.
380 fn generalize_alias_ty(
381 &mut self,
382 alias: ty::AliasTy<'tcx>,
383 ) -> Result<Ty<'tcx>, TypeError<'tcx>> {
384 // We do not eagerly replace aliases with inference variables if they have
385 // escaping bound vars, see the method comment for details. However, when we
386 // are inside of an alias with escaping bound vars replacing nested aliases
387 // with inference variables can cause incorrect ambiguity.
388 //
389 // cc trait-system-refactor-initiative#110
390 if self.infcx.next_trait_solver() && !alias.has_escaping_bound_vars() && !self.in_alias {
391 return Ok(self.next_ty_var_for_alias());
392 }
393
394 let is_nested_alias = mem::replace(&mut self.in_alias, true);
395 let result = match self.relate(alias, alias) {
396 Ok(alias) => Ok(alias.to_ty(self.cx())),
397 Err(e) => {
398 if is_nested_alias {
399 return Err(e);
400 } else {
401 let mut visitor = MaxUniverse::new();
402 alias.visit_with(&mut visitor);
403 let infer_replacement_is_complete =
404 self.for_universe.can_name(visitor.max_universe())
405 && !alias.has_escaping_bound_vars();
406 if !infer_replacement_is_complete {
407 warn!("may incompletely handle alias type: {alias:?}");
408 }
409
410 debug!("generalization failure in alias");
411 Ok(self.next_ty_var_for_alias())
412 }
413 }
414 };
415 self.in_alias = is_nested_alias;
416 result
417 }
418}
419
420impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
421 fn cx(&self) -> TyCtxt<'tcx> {
422 self.infcx.tcx
423 }
424
425 fn relate_item_args(
426 &mut self,
427 item_def_id: DefId,
428 a_arg: ty::GenericArgsRef<'tcx>,
429 b_arg: ty::GenericArgsRef<'tcx>,
430 ) -> RelateResult<'tcx, ty::GenericArgsRef<'tcx>> {
431 if self.ambient_variance == ty::Invariant {
432 // Avoid fetching the variance if we are in an invariant
433 // context; no need, and it can induce dependency cycles
434 // (e.g., #41849).
435 relate::relate_args_invariantly(self, a_arg, b_arg)
436 } else {
437 let tcx = self.cx();
438 let opt_variances = tcx.variances_of(item_def_id);
439 relate::relate_args_with_variances(
440 self,
441 item_def_id,
442 opt_variances,
443 a_arg,
444 b_arg,
445 false,
446 )
447 }
448 }
449
450 #[instrument(level = "debug", skip(self, variance, b), ret)]
451 fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
452 &mut self,
453 variance: ty::Variance,
454 _info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
455 a: T,
456 b: T,
457 ) -> RelateResult<'tcx, T> {
458 let old_ambient_variance = self.ambient_variance;
459 self.ambient_variance = self.ambient_variance.xform(variance);
460 debug!(?self.ambient_variance, "new ambient variance");
461 // Recursive calls to `relate` can overflow the stack. For example a deeper version of
462 // `ui/associated-consts/issue-93775.rs`.
463 let r = ensure_sufficient_stack(|| self.relate(a, b));
464 self.ambient_variance = old_ambient_variance;
465 r
466 }
467
468 #[instrument(level = "debug", skip(self, t2), ret)]
469 fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
470 assert_eq!(t, t2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
471
472 if let Some(&result) = self.cache.get(&(t, self.ambient_variance, self.in_alias)) {
473 return Ok(result);
474 }
475
476 // Check to see whether the type we are generalizing references
477 // any other type variable related to `vid` via
478 // subtyping. This is basically our "occurs check", preventing
479 // us from creating infinitely sized types.
480 let g = match *t.kind() {
481 ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
482 bug!("unexpected infer type: {t}")
483 }
484
485 ty::Infer(ty::TyVar(vid)) => {
486 let mut inner = self.infcx.inner.borrow_mut();
487 let vid = inner.type_variables().root_var(vid);
488 if TermVid::Ty(vid) == self.root_vid {
489 // If sub-roots are equal, then `root_vid` and
490 // `vid` are related via subtyping.
491 Err(self.cyclic_term_error())
492 } else {
493 let probe = inner.type_variables().probe(vid);
494 match probe {
495 TypeVariableValue::Known { value: u } => {
496 drop(inner);
497 self.relate(u, u)
498 }
499 TypeVariableValue::Unknown { universe } => {
500 match self.ambient_variance {
501 // Invariant: no need to make a fresh type variable
502 // if we can name the universe.
503 ty::Invariant => {
504 if self.for_universe.can_name(universe) {
505 return Ok(t);
506 }
507 }
508
509 // Bivariant: make a fresh var, but remember that
510 // it is unconstrained. See the comment in
511 // `Generalization`.
512 ty::Bivariant => self.has_unconstrained_ty_var = true,
513
514 // Co/contravariant: this will be
515 // sufficiently constrained later on.
516 ty::Covariant | ty::Contravariant => (),
517 }
518
519 let origin = inner.type_variables().var_origin(vid);
520 let new_var_id =
521 inner.type_variables().new_var(self.for_universe, origin);
522 // If we're in the new solver and create a new inference
523 // variable inside of an alias we eagerly constrain that
524 // inference variable to prevent unexpected ambiguity errors.
525 //
526 // This is incomplete as it pulls down the universe of the
527 // original inference variable, even though the alias could
528 // normalize to a type which does not refer to that type at
529 // all. I don't expect this to cause unexpected errors in
530 // practice.
531 //
532 // We only need to do so for type and const variables, as
533 // region variables do not impact normalization, and will get
534 // correctly constrained by `AliasRelate` later on.
535 //
536 // cc trait-system-refactor-initiative#108
537 if self.infcx.next_trait_solver()
538 && !matches!(self.infcx.typing_mode(), TypingMode::Coherence)
539 && self.in_alias
540 {
541 inner.type_variables().equate(vid, new_var_id);
542 }
543
544 debug!("replacing original vid={:?} with new={:?}", vid, new_var_id);
545 Ok(Ty::new_var(self.cx(), new_var_id))
546 }
547 }
548 }
549 }
550
551 ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
552 // No matter what mode we are in,
553 // integer/floating-point types must be equal to be
554 // relatable.
555 Ok(t)
556 }
557
558 ty::Placeholder(placeholder) => {
559 if self.for_universe.can_name(placeholder.universe) {
560 Ok(t)
561 } else {
562 debug!(
563 "root universe {:?} cannot name placeholder in universe {:?}",
564 self.for_universe, placeholder.universe
565 );
566 Err(TypeError::Mismatch)
567 }
568 }
569
570 ty::Alias(_, data) => match self.structurally_relate_aliases {
571 StructurallyRelateAliases::No => self.generalize_alias_ty(data),
572 StructurallyRelateAliases::Yes => relate::structurally_relate_tys(self, t, t),
573 },
574
575 _ => relate::structurally_relate_tys(self, t, t),
576 }?;
577
578 self.cache.insert((t, self.ambient_variance, self.in_alias), g);
579 Ok(g)
580 }
581
582 #[instrument(level = "debug", skip(self, r2), ret)]
583 fn regions(
584 &mut self,
585 r: ty::Region<'tcx>,
586 r2: ty::Region<'tcx>,
587 ) -> RelateResult<'tcx, ty::Region<'tcx>> {
588 assert_eq!(r, r2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
589
590 match r.kind() {
591 // Never make variables for regions bound within the type itself,
592 // nor for erased regions.
593 ty::ReBound(..) | ty::ReErased => {
594 return Ok(r);
595 }
596
597 // It doesn't really matter for correctness if we generalize ReError,
598 // since we're already on a doomed compilation path.
599 ty::ReError(_) => {
600 return Ok(r);
601 }
602
603 ty::RePlaceholder(..)
604 | ty::ReVar(..)
605 | ty::ReStatic
606 | ty::ReEarlyParam(..)
607 | ty::ReLateParam(..) => {
608 // see common code below
609 }
610 }
611
612 // If we are in an invariant context, we can re-use the region
613 // as is, unless it happens to be in some universe that we
614 // can't name.
615 if let ty::Invariant = self.ambient_variance {
616 let r_universe = self.infcx.universe_of_region(r);
617 if self.for_universe.can_name(r_universe) {
618 return Ok(r);
619 }
620 }
621
622 Ok(self
623 .infcx
624 .next_region_var_in_universe(RegionVariableOrigin::Misc(self.span), self.for_universe))
625 }
626
627 #[instrument(level = "debug", skip(self, c2), ret)]
628 fn consts(
629 &mut self,
630 c: ty::Const<'tcx>,
631 c2: ty::Const<'tcx>,
632 ) -> RelateResult<'tcx, ty::Const<'tcx>> {
633 assert_eq!(c, c2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
634
635 match c.kind() {
636 ty::ConstKind::Infer(InferConst::Var(vid)) => {
637 // If root const vids are equal, then `root_vid` and
638 // `vid` are related and we'd be inferring an infinitely
639 // deep const.
640 if TermVid::Const(
641 self.infcx.inner.borrow_mut().const_unification_table().find(vid).vid,
642 ) == self.root_vid
643 {
644 return Err(self.cyclic_term_error());
645 }
646
647 let mut inner = self.infcx.inner.borrow_mut();
648 let variable_table = &mut inner.const_unification_table();
649 match variable_table.probe_value(vid) {
650 ConstVariableValue::Known { value: u } => {
651 drop(inner);
652 self.relate(u, u)
653 }
654 ConstVariableValue::Unknown { origin, universe } => {
655 if self.for_universe.can_name(universe) {
656 Ok(c)
657 } else {
658 let new_var_id = variable_table
659 .new_key(ConstVariableValue::Unknown {
660 origin,
661 universe: self.for_universe,
662 })
663 .vid;
664
665 // See the comment for type inference variables
666 // for more details.
667 if self.infcx.next_trait_solver()
668 && !matches!(self.infcx.typing_mode(), TypingMode::Coherence)
669 && self.in_alias
670 {
671 variable_table.union(vid, new_var_id);
672 }
673 Ok(ty::Const::new_var(self.cx(), new_var_id))
674 }
675 }
676 }
677 }
678 // FIXME: Unevaluated constants are also not rigid, so the current
679 // approach of always relating them structurally is incomplete.
680 //
681 // FIXME: remove this branch once `structurally_relate_consts` is fully
682 // structural.
683 ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => {
684 let args = self.relate_with_variance(
685 ty::Invariant,
686 ty::VarianceDiagInfo::default(),
687 args,
688 args,
689 )?;
690 Ok(ty::Const::new_unevaluated(self.cx(), ty::UnevaluatedConst { def, args }))
691 }
692 ty::ConstKind::Placeholder(placeholder) => {
693 if self.for_universe.can_name(placeholder.universe) {
694 Ok(c)
695 } else {
696 debug!(
697 "root universe {:?} cannot name placeholder in universe {:?}",
698 self.for_universe, placeholder.universe
699 );
700 Err(TypeError::Mismatch)
701 }
702 }
703 _ => relate::structurally_relate_consts(self, c, c),
704 }
705 }
706
707 #[instrument(level = "debug", skip(self), ret)]
708 fn binders<T>(
709 &mut self,
710 a: ty::Binder<'tcx, T>,
711 _: ty::Binder<'tcx, T>,
712 ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
713 where
714 T: Relate<TyCtxt<'tcx>>,
715 {
716 let result = self.relate(a.skip_binder(), a.skip_binder())?;
717 Ok(a.rebind(result))
718 }
719}
720
721/// Result from a generalization operation. This includes
722/// not only the generalized type, but also a bool flag
723/// indicating whether further WF checks are needed.
724#[derive(Debug)]
725struct Generalization<T> {
726 /// When generalizing `<?0 as Trait>::Assoc` or
727 /// `<T as Bar<<?0 as Foo>::Assoc>>::Assoc`
728 /// for `?0` generalization returns an inference
729 /// variable.
730 ///
731 /// This has to be handled wotj care as it can
732 /// otherwise very easily result in infinite
733 /// recursion.
734 pub value_may_be_infer: T,
735
736 /// In general, we do not check whether all types which occur during
737 /// type checking are well-formed. We only check wf of user-provided types
738 /// and when actually using a type, e.g. for method calls.
739 ///
740 /// This means that when subtyping, we may end up with unconstrained
741 /// inference variables if a generalized type has bivariant parameters.
742 /// A parameter may only be bivariant if it is constrained by a projection
743 /// bound in a where-clause. As an example, imagine a type:
744 ///
745 /// struct Foo<A, B> where A: Iterator<Item = B> {
746 /// data: A
747 /// }
748 ///
749 /// here, `A` will be covariant, but `B` is unconstrained.
750 ///
751 /// However, whatever it is, for `Foo` to be WF, it must be equal to `A::Item`.
752 /// If we have an input `Foo<?A, ?B>`, then after generalization we will wind
753 /// up with a type like `Foo<?C, ?D>`. When we enforce `Foo<?A, ?B> <: Foo<?C, ?D>`,
754 /// we will wind up with the requirement that `?A <: ?C`, but no particular
755 /// relationship between `?B` and `?D` (after all, these types may be completely
756 /// different). If we do nothing else, this may mean that `?D` goes unconstrained
757 /// (as in #41677). To avoid this we emit a `WellFormed` obligation in these cases.
758 pub has_unconstrained_ty_var: bool,
759}