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