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