1use std::cell::{Cell, RefCell};
4use std::fmt;
5use std::ops::Range;
6use std::sync::Arc;
7
8pub use BoundRegionConversionTime::*;
9use ena::unify as ut;
10use hir_def::GenericParamId;
11use opaque_types::{OpaqueHiddenType, OpaqueTypeStorage};
12use region_constraints::{RegionConstraintCollector, RegionConstraintStorage};
13use rustc_next_trait_solver::solve::SolverDelegateEvalExt;
14use rustc_pattern_analysis::Captures;
15use rustc_type_ir::{
16 ClosureKind, ConstVid, FloatVarValue, FloatVid, GenericArgKind, InferConst, InferTy,
17 IntVarValue, IntVid, OutlivesPredicate, RegionVid, TermKind, TyVid, TypeFoldable, TypeFolder,
18 TypeSuperFoldable, TypeVisitableExt, UniverseIndex,
19 error::{ExpectedFound, TypeError},
20 inherent::{
21 Const as _, GenericArg as _, GenericArgs as _, IntoKind, SliceLike, Term as _, Ty as _,
22 },
23};
24use snapshot::undo_log::InferCtxtUndoLogs;
25use tracing::{debug, instrument};
26use traits::{ObligationCause, PredicateObligations};
27use type_variable::TypeVariableOrigin;
28use unify_key::{ConstVariableOrigin, ConstVariableValue, ConstVidKey};
29
30use crate::next_solver::{
31 ArgOutlivesPredicate, BoundConst, BoundRegion, BoundTy, BoundVarKind, Goal, Predicate,
32 SolverContext,
33 fold::BoundVarReplacerDelegate,
34 infer::{at::ToTrace, select::EvaluationResult, traits::PredicateObligation},
35 obligation_ctxt::ObligationCtxt,
36};
37
38use super::{
39 AliasTerm, Binder, CanonicalQueryInput, CanonicalVarValues, Const, ConstKind, DbInterner,
40 ErrorGuaranteed, GenericArg, GenericArgs, OpaqueTypeKey, ParamEnv, PolyCoercePredicate,
41 PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyRegionOutlivesPredicate,
42 PolySubtypePredicate, Region, SolverDefId, SubtypePredicate, Term, TraitRef, Ty, TyKind,
43 TypingMode,
44};
45
46pub mod at;
47pub mod canonical;
48mod context;
49pub mod opaque_types;
50mod outlives;
51pub mod region_constraints;
52pub mod relate;
53pub mod resolve;
54pub(crate) mod select;
55pub(crate) mod snapshot;
56pub(crate) mod traits;
57mod type_variable;
58mod unify_key;
59
60#[must_use]
68#[derive(Debug)]
69pub struct InferOk<'db, T> {
70 pub value: T,
71 pub obligations: PredicateObligations<'db>,
72}
73pub type InferResult<'db, T> = Result<InferOk<'db, T>, TypeError<DbInterner<'db>>>;
74
75pub(crate) type UnificationTable<'a, 'db, T> = ut::UnificationTable<
76 ut::InPlace<T, &'a mut ut::UnificationStorage<T>, &'a mut InferCtxtUndoLogs<'db>>,
77>;
78
79fn iter_idx_range<T: From<u32> + Into<u32>>(range: Range<T>) -> impl Iterator<Item = T> {
80 (range.start.into()..range.end.into()).map(Into::into)
81}
82
83#[derive(Clone)]
88pub struct InferCtxtInner<'db> {
89 pub(crate) undo_log: InferCtxtUndoLogs<'db>,
90
91 pub(crate) type_variable_storage: type_variable::TypeVariableStorage<'db>,
95
96 pub(crate) const_unification_storage: ut::UnificationTableStorage<ConstVidKey<'db>>,
98
99 pub(crate) int_unification_storage: ut::UnificationTableStorage<IntVid>,
101
102 pub(crate) float_unification_storage: ut::UnificationTableStorage<FloatVid>,
104
105 pub(crate) region_constraint_storage: Option<RegionConstraintStorage<'db>>,
112
113 pub(crate) region_obligations: Vec<TypeOutlivesConstraint<'db>>,
146
147 region_assumptions: Vec<ArgOutlivesPredicate<'db>>,
153
154 pub(crate) opaque_type_storage: OpaqueTypeStorage<'db>,
156}
157
158impl<'db> InferCtxtInner<'db> {
159 fn new() -> InferCtxtInner<'db> {
160 InferCtxtInner {
161 undo_log: InferCtxtUndoLogs::default(),
162
163 type_variable_storage: Default::default(),
164 const_unification_storage: Default::default(),
165 int_unification_storage: Default::default(),
166 float_unification_storage: Default::default(),
167 region_constraint_storage: Some(Default::default()),
168 region_obligations: vec![],
169 region_assumptions: Default::default(),
170 opaque_type_storage: Default::default(),
171 }
172 }
173
174 #[inline]
175 pub fn region_obligations(&self) -> &[TypeOutlivesConstraint<'db>] {
176 &self.region_obligations
177 }
178
179 #[inline]
180 fn try_type_variables_probe_ref(
181 &self,
182 vid: TyVid,
183 ) -> Option<&type_variable::TypeVariableValue<'db>> {
184 self.type_variable_storage.eq_relations_ref().try_probe_value(vid)
187 }
188
189 #[inline]
190 fn type_variables(&mut self) -> type_variable::TypeVariableTable<'_, 'db> {
191 self.type_variable_storage.with_log(&mut self.undo_log)
192 }
193
194 #[inline]
195 pub(crate) fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'db> {
196 self.opaque_type_storage.with_log(&mut self.undo_log)
197 }
198
199 #[inline]
200 pub(crate) fn int_unification_table(&mut self) -> UnificationTable<'_, 'db, IntVid> {
201 tracing::debug!(?self.int_unification_storage);
202 self.int_unification_storage.with_log(&mut self.undo_log)
203 }
204
205 #[inline]
206 pub(crate) fn float_unification_table(&mut self) -> UnificationTable<'_, 'db, FloatVid> {
207 self.float_unification_storage.with_log(&mut self.undo_log)
208 }
209
210 #[inline]
211 fn const_unification_table(&mut self) -> UnificationTable<'_, 'db, ConstVidKey<'db>> {
212 self.const_unification_storage.with_log(&mut self.undo_log)
213 }
214
215 #[inline]
216 pub fn unwrap_region_constraints(&mut self) -> RegionConstraintCollector<'db, '_> {
217 self.region_constraint_storage
218 .as_mut()
219 .expect("region constraints already solved")
220 .with_log(&mut self.undo_log)
221 }
222}
223
224#[derive(Clone)]
225pub struct InferCtxt<'db> {
226 pub interner: DbInterner<'db>,
227
228 typing_mode: TypingMode<'db>,
231
232 pub inner: RefCell<InferCtxtInner<'db>>,
233
234 tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
242
243 universe: Cell<UniverseIndex>,
253}
254
255#[derive(Clone, Debug, PartialEq, Eq)]
257pub enum ValuePairs<'db> {
258 Regions(ExpectedFound<Region<'db>>),
259 Terms(ExpectedFound<Term<'db>>),
260 Aliases(ExpectedFound<AliasTerm<'db>>),
261 TraitRefs(ExpectedFound<TraitRef<'db>>),
262 PolySigs(ExpectedFound<PolyFnSig<'db>>),
263 ExistentialTraitRef(ExpectedFound<PolyExistentialTraitRef<'db>>),
264 ExistentialProjection(ExpectedFound<PolyExistentialProjection<'db>>),
265}
266
267impl<'db> ValuePairs<'db> {
268 pub fn ty(&self) -> Option<(Ty<'db>, Ty<'db>)> {
269 if let ValuePairs::Terms(ExpectedFound { expected, found }) = self
270 && let Some(expected) = expected.as_type()
271 && let Some(found) = found.as_type()
272 {
273 return Some((expected, found));
274 }
275 None
276 }
277}
278
279#[derive(Clone, Debug)]
284pub struct TypeTrace<'db> {
285 pub cause: ObligationCause,
286 pub values: ValuePairs<'db>,
287}
288
289#[derive(Clone, Copy, Debug)]
291pub enum BoundRegionConversionTime {
292 FnCall,
294
295 HigherRankedType,
297
298 AssocTypeProjection(SolverDefId),
300}
301
302#[derive(Copy, Clone, Debug)]
303pub struct FixupError {
304 unresolved: TyOrConstInferVar,
305}
306
307impl fmt::Display for FixupError {
308 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
309 use TyOrConstInferVar::*;
310
311 match self.unresolved {
312 TyInt(_) => write!(
313 f,
314 "cannot determine the type of this integer; \
315 add a suffix to specify the type explicitly"
316 ),
317 TyFloat(_) => write!(
318 f,
319 "cannot determine the type of this number; \
320 add a suffix to specify the type explicitly"
321 ),
322 Ty(_) => write!(f, "unconstrained type"),
323 Const(_) => write!(f, "unconstrained const value"),
324 }
325 }
326}
327
328#[derive(Clone, Debug)]
330pub struct TypeOutlivesConstraint<'db> {
331 pub sub_region: Region<'db>,
332 pub sup_type: Ty<'db>,
333}
334
335pub struct InferCtxtBuilder<'db> {
337 interner: DbInterner<'db>,
338}
339
340pub trait DbInternerInferExt<'db> {
341 fn infer_ctxt(self) -> InferCtxtBuilder<'db>;
342}
343
344impl<'db> DbInternerInferExt<'db> for DbInterner<'db> {
345 fn infer_ctxt(self) -> InferCtxtBuilder<'db> {
346 InferCtxtBuilder { interner: self }
347 }
348}
349
350impl<'db> InferCtxtBuilder<'db> {
351 pub fn build_with_canonical<T>(
359 mut self,
360 input: &CanonicalQueryInput<'db, T>,
361 ) -> (InferCtxt<'db>, T, CanonicalVarValues<'db>)
362 where
363 T: TypeFoldable<DbInterner<'db>>,
364 {
365 let infcx = self.build(input.typing_mode);
366 let (value, args) = infcx.instantiate_canonical(&input.canonical);
367 (infcx, value, args)
368 }
369
370 pub fn build(&mut self, typing_mode: TypingMode<'db>) -> InferCtxt<'db> {
371 let InferCtxtBuilder { interner } = *self;
372 InferCtxt {
373 interner,
374 typing_mode,
375 inner: RefCell::new(InferCtxtInner::new()),
376 tainted_by_errors: Cell::new(None),
377 universe: Cell::new(UniverseIndex::ROOT),
378 }
379 }
380}
381
382impl<'db> InferOk<'db, ()> {
383 pub fn into_obligations(self) -> PredicateObligations<'db> {
384 self.obligations
385 }
386}
387
388impl<'db> InferCtxt<'db> {
389 #[inline(always)]
390 pub fn typing_mode(&self) -> TypingMode<'db> {
391 self.typing_mode
392 }
393
394 #[inline(always)]
395 pub fn typing_mode_unchecked(&self) -> TypingMode<'db> {
396 self.typing_mode
397 }
398
399 pub fn predicate_may_hold(&self, obligation: &PredicateObligation<'db>) -> bool {
402 self.evaluate_obligation(obligation).may_apply()
403 }
404
405 pub fn predicate_may_hold_opaque_types_jank(
408 &self,
409 obligation: &PredicateObligation<'db>,
410 ) -> bool {
411 <&SolverContext<'db>>::from(self).root_goal_may_hold_opaque_types_jank(Goal::new(
412 self.interner,
413 obligation.param_env,
414 obligation.predicate,
415 ))
416 }
417
418 pub(crate) fn insert_type_vars<T>(&self, ty: T) -> T
419 where
420 T: TypeFoldable<DbInterner<'db>>,
421 {
422 struct Folder<'a, 'db> {
423 infcx: &'a InferCtxt<'db>,
424 }
425 impl<'db> TypeFolder<DbInterner<'db>> for Folder<'_, 'db> {
426 fn cx(&self) -> DbInterner<'db> {
427 self.infcx.interner
428 }
429
430 fn fold_ty(&mut self, ty: Ty<'db>) -> Ty<'db> {
431 if !ty.references_error() {
432 return ty;
433 }
434
435 if ty.is_ty_error() { self.infcx.next_ty_var() } else { ty.super_fold_with(self) }
436 }
437
438 fn fold_const(&mut self, ct: Const<'db>) -> Const<'db> {
439 if !ct.references_error() {
440 return ct;
441 }
442
443 if ct.is_ct_error() {
444 self.infcx.next_const_var()
445 } else {
446 ct.super_fold_with(self)
447 }
448 }
449
450 fn fold_region(&mut self, r: Region<'db>) -> Region<'db> {
451 if r.is_error() { self.infcx.next_region_var() } else { r }
452 }
453 }
454
455 ty.fold_with(&mut Folder { infcx: self })
456 }
457
458 #[expect(dead_code, reason = "this is used in rustc")]
486 fn predicate_must_hold_considering_regions(
487 &self,
488 obligation: &PredicateObligation<'db>,
489 ) -> bool {
490 self.evaluate_obligation(obligation).must_apply_considering_regions()
491 }
492
493 #[expect(dead_code, reason = "this is used in rustc")]
499 fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'db>) -> bool {
500 self.evaluate_obligation(obligation).must_apply_modulo_regions()
501 }
502
503 fn evaluate_obligation(&self, obligation: &PredicateObligation<'db>) -> EvaluationResult {
505 self.probe(|snapshot| {
506 let mut ocx = ObligationCtxt::new(self);
507 ocx.register_obligation(obligation.clone());
508 let mut result = EvaluationResult::EvaluatedToOk;
509 for error in ocx.evaluate_obligations_error_on_ambiguity() {
510 if error.is_true_error() {
511 return EvaluationResult::EvaluatedToErr;
512 } else {
513 result = result.max(EvaluationResult::EvaluatedToAmbig);
514 }
515 }
516 if self.opaque_types_added_in_snapshot(snapshot) {
517 result = result.max(EvaluationResult::EvaluatedToOkModuloOpaqueTypes);
518 } else if self.region_constraints_added_in_snapshot(snapshot) {
519 result = result.max(EvaluationResult::EvaluatedToOkModuloRegions);
520 }
521 result
522 })
523 }
524
525 pub fn can_eq<T: ToTrace<'db>>(&self, param_env: ParamEnv<'db>, a: T, b: T) -> bool {
526 self.probe(|_| {
527 let mut ocx = ObligationCtxt::new(self);
528 let Ok(()) = ocx.eq(&ObligationCause::dummy(), param_env, a, b) else {
529 return false;
530 };
531 ocx.try_evaluate_obligations().is_empty()
532 })
533 }
534
535 pub fn goal_may_hold_opaque_types_jank(&self, goal: Goal<'db, Predicate<'db>>) -> bool {
538 <&SolverContext<'db>>::from(self).root_goal_may_hold_opaque_types_jank(goal)
539 }
540
541 pub fn type_is_copy_modulo_regions(&self, param_env: ParamEnv<'db>, ty: Ty<'db>) -> bool {
542 let ty = self.resolve_vars_if_possible(ty);
543
544 let Some(copy_def_id) = self.interner.lang_items().Copy else {
545 return false;
546 };
547
548 traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id)
553 }
554
555 pub fn unresolved_variables(&self) -> Vec<Ty<'db>> {
556 let mut inner = self.inner.borrow_mut();
557 let mut vars: Vec<Ty<'db>> = inner
558 .type_variables()
559 .unresolved_variables()
560 .into_iter()
561 .map(|t| Ty::new_var(self.interner, t))
562 .collect();
563 vars.extend(
564 (0..inner.int_unification_table().len())
565 .map(IntVid::from_usize)
566 .filter(|&vid| inner.int_unification_table().probe_value(vid).is_unknown())
567 .map(|v| Ty::new_int_var(self.interner, v)),
568 );
569 vars.extend(
570 (0..inner.float_unification_table().len())
571 .map(FloatVid::from_usize)
572 .filter(|&vid| inner.float_unification_table().probe_value(vid).is_unknown())
573 .map(|v| Ty::new_float_var(self.interner, v)),
574 );
575 vars
576 }
577
578 #[instrument(skip(self), level = "debug")]
579 pub fn sub_regions(&self, a: Region<'db>, b: Region<'db>) {
580 self.inner.borrow_mut().unwrap_region_constraints().make_subregion(a, b);
581 }
582
583 pub fn coerce_predicate(
599 &self,
600 cause: &ObligationCause,
601 param_env: ParamEnv<'db>,
602 predicate: PolyCoercePredicate<'db>,
603 ) -> Result<InferResult<'db, ()>, (TyVid, TyVid)> {
604 let subtype_predicate = predicate.map_bound(|p| SubtypePredicate {
605 a_is_expected: false, a: p.a,
607 b: p.b,
608 });
609 self.subtype_predicate(cause, param_env, subtype_predicate)
610 }
611
612 pub fn subtype_predicate(
613 &self,
614 cause: &ObligationCause,
615 param_env: ParamEnv<'db>,
616 predicate: PolySubtypePredicate<'db>,
617 ) -> Result<InferResult<'db, ()>, (TyVid, TyVid)> {
618 let r_a = self.shallow_resolve(predicate.skip_binder().a);
632 let r_b = self.shallow_resolve(predicate.skip_binder().b);
633 match (r_a.kind(), r_b.kind()) {
634 (TyKind::Infer(InferTy::TyVar(a_vid)), TyKind::Infer(InferTy::TyVar(b_vid))) => {
635 return Err((a_vid, b_vid));
636 }
637 _ => {}
638 }
639
640 self.enter_forall(predicate, |SubtypePredicate { a_is_expected, a, b }| {
641 if a_is_expected {
642 Ok(self.at(cause, param_env).sub(a, b))
643 } else {
644 Ok(self.at(cause, param_env).sup(b, a))
645 }
646 })
647 }
648
649 pub fn region_outlives_predicate(
650 &self,
651 _cause: &traits::ObligationCause,
652 predicate: PolyRegionOutlivesPredicate<'db>,
653 ) {
654 self.enter_forall(predicate, |OutlivesPredicate(r_a, r_b)| {
655 self.sub_regions(r_b, r_a); })
657 }
658
659 pub fn num_ty_vars(&self) -> usize {
661 self.inner.borrow_mut().type_variables().num_vars()
662 }
663
664 pub fn next_var_for_param(&self, id: GenericParamId) -> GenericArg<'db> {
665 match id {
666 GenericParamId::TypeParamId(_) => self.next_ty_var().into(),
667 GenericParamId::ConstParamId(_) => self.next_const_var().into(),
668 GenericParamId::LifetimeParamId(_) => self.next_region_var().into(),
669 }
670 }
671
672 pub fn next_ty_var(&self) -> Ty<'db> {
673 self.next_ty_var_with_origin(TypeVariableOrigin { param_def_id: None })
674 }
675
676 pub fn next_ty_vid(&self) -> TyVid {
677 self.inner
678 .borrow_mut()
679 .type_variables()
680 .new_var(self.universe(), TypeVariableOrigin { param_def_id: None })
681 }
682
683 pub fn next_ty_var_with_origin(&self, origin: TypeVariableOrigin) -> Ty<'db> {
684 let vid = self.inner.borrow_mut().type_variables().new_var(self.universe(), origin);
685 Ty::new_var(self.interner, vid)
686 }
687
688 pub fn next_ty_var_id_in_universe(&self, universe: UniverseIndex) -> TyVid {
689 let origin = TypeVariableOrigin { param_def_id: None };
690 self.inner.borrow_mut().type_variables().new_var(universe, origin)
691 }
692
693 pub fn next_ty_var_in_universe(&self, universe: UniverseIndex) -> Ty<'db> {
694 let vid = self.next_ty_var_id_in_universe(universe);
695 Ty::new_var(self.interner, vid)
696 }
697
698 pub fn next_const_var(&self) -> Const<'db> {
699 self.next_const_var_with_origin(ConstVariableOrigin {})
700 }
701
702 pub fn next_const_vid(&self) -> ConstVid {
703 self.inner
704 .borrow_mut()
705 .const_unification_table()
706 .new_key(ConstVariableValue::Unknown {
707 origin: ConstVariableOrigin {},
708 universe: self.universe(),
709 })
710 .vid
711 }
712
713 pub fn next_const_var_with_origin(&self, origin: ConstVariableOrigin) -> Const<'db> {
714 let vid = self
715 .inner
716 .borrow_mut()
717 .const_unification_table()
718 .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
719 .vid;
720 Const::new_var(self.interner, vid)
721 }
722
723 pub fn next_const_var_in_universe(&self, universe: UniverseIndex) -> Const<'db> {
724 let origin = ConstVariableOrigin {};
725 let vid = self
726 .inner
727 .borrow_mut()
728 .const_unification_table()
729 .new_key(ConstVariableValue::Unknown { origin, universe })
730 .vid;
731 Const::new_var(self.interner, vid)
732 }
733
734 pub fn next_int_var(&self) -> Ty<'db> {
735 let next_int_var_id =
736 self.inner.borrow_mut().int_unification_table().new_key(IntVarValue::Unknown);
737 Ty::new_int_var(self.interner, next_int_var_id)
738 }
739
740 pub fn next_int_vid(&self) -> IntVid {
741 self.inner.borrow_mut().int_unification_table().new_key(IntVarValue::Unknown)
742 }
743
744 pub fn next_float_var(&self) -> Ty<'db> {
745 Ty::new_float_var(self.interner, self.next_float_vid())
746 }
747
748 pub fn next_float_vid(&self) -> FloatVid {
749 self.inner.borrow_mut().float_unification_table().new_key(FloatVarValue::Unknown)
750 }
751
752 pub fn next_region_var(&self) -> Region<'db> {
756 self.next_region_var_in_universe(self.universe())
757 }
758
759 pub fn next_region_vid(&self) -> RegionVid {
760 self.inner.borrow_mut().unwrap_region_constraints().new_region_var(self.universe())
761 }
762
763 pub fn next_region_var_in_universe(&self, universe: UniverseIndex) -> Region<'db> {
767 let region_var =
768 self.inner.borrow_mut().unwrap_region_constraints().new_region_var(universe);
769 Region::new_var(self.interner, region_var)
770 }
771
772 pub fn next_term_var_of_kind(&self, term: Term<'db>) -> Term<'db> {
773 match term.kind() {
774 TermKind::Ty(_) => self.next_ty_var().into(),
775 TermKind::Const(_) => self.next_const_var().into(),
776 }
777 }
778
779 pub fn universe_of_region(&self, r: Region<'db>) -> UniverseIndex {
785 self.inner.borrow_mut().unwrap_region_constraints().universe(r)
786 }
787
788 pub fn num_region_vars(&self) -> usize {
790 self.inner.borrow_mut().unwrap_region_constraints().num_region_vars()
791 }
792
793 #[instrument(skip(self), level = "debug")]
795 pub fn next_nll_region_var(&self) -> Region<'db> {
796 self.next_region_var()
797 }
798
799 #[instrument(skip(self), level = "debug")]
801 pub fn next_nll_region_var_in_universe(&self, universe: UniverseIndex) -> Region<'db> {
802 self.next_region_var_in_universe(universe)
803 }
804
805 fn var_for_def(&self, id: GenericParamId) -> GenericArg<'db> {
806 match id {
807 GenericParamId::LifetimeParamId(_) => {
808 self.next_region_var().into()
811 }
812 GenericParamId::TypeParamId(_) => {
813 let ty_var_id = self
822 .inner
823 .borrow_mut()
824 .type_variables()
825 .new_var(self.universe(), TypeVariableOrigin { param_def_id: None });
826
827 Ty::new_var(self.interner, ty_var_id).into()
828 }
829 GenericParamId::ConstParamId(_) => {
830 let origin = ConstVariableOrigin {};
831 let const_var_id = self
832 .inner
833 .borrow_mut()
834 .const_unification_table()
835 .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
836 .vid;
837 Const::new_var(self.interner, const_var_id).into()
838 }
839 }
840 }
841
842 pub fn fresh_args_for_item(&self, def_id: SolverDefId) -> GenericArgs<'db> {
845 GenericArgs::for_item(self.interner, def_id, |_index, kind, _| self.var_for_def(kind))
846 }
847
848 pub fn fill_rest_fresh_args(
850 &self,
851 def_id: SolverDefId,
852 first: impl IntoIterator<Item = GenericArg<'db>>,
853 ) -> GenericArgs<'db> {
854 GenericArgs::fill_rest(self.interner, def_id, first, |_index, kind, _| {
855 self.var_for_def(kind)
856 })
857 }
858
859 #[must_use = "this method does not have any side effects"]
865 pub fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
866 self.tainted_by_errors.get()
867 }
868
869 pub fn set_tainted_by_errors(&self, e: ErrorGuaranteed) {
872 debug!("set_tainted_by_errors(ErrorGuaranteed)");
873 self.tainted_by_errors.set(Some(e));
874 }
875
876 #[instrument(level = "debug", skip(self), ret)]
877 pub fn take_opaque_types(&self) -> Vec<(OpaqueTypeKey<'db>, OpaqueHiddenType<'db>)> {
878 self.inner.borrow_mut().opaque_type_storage.take_opaque_types().collect()
879 }
880
881 #[instrument(level = "debug", skip(self), ret)]
882 pub fn clone_opaque_types(&self) -> Vec<(OpaqueTypeKey<'db>, OpaqueHiddenType<'db>)> {
883 self.inner.borrow_mut().opaque_type_storage.iter_opaque_types().collect()
884 }
885
886 pub fn has_opaques_with_sub_unified_hidden_type(&self, ty_vid: TyVid) -> bool {
887 let ty_sub_vid = self.sub_unification_table_root_var(ty_vid);
888 let inner = &mut *self.inner.borrow_mut();
889 let mut type_variables = inner.type_variable_storage.with_log(&mut inner.undo_log);
890 inner.opaque_type_storage.iter_opaque_types().any(|(_, hidden_ty)| {
891 if let TyKind::Infer(InferTy::TyVar(hidden_vid)) = hidden_ty.ty.kind() {
892 let opaque_sub_vid = type_variables.sub_unification_table_root_var(hidden_vid);
893 if opaque_sub_vid == ty_sub_vid {
894 return true;
895 }
896 }
897
898 false
899 })
900 }
901
902 #[inline(always)]
903 pub fn can_define_opaque_ty(&self, id: impl Into<SolverDefId>) -> bool {
904 match self.typing_mode_unchecked() {
905 TypingMode::Analysis { defining_opaque_types_and_generators } => {
906 defining_opaque_types_and_generators.contains(&id.into())
907 }
908 TypingMode::Coherence | TypingMode::PostAnalysis => false,
909 TypingMode::Borrowck { defining_opaque_types: _ } => unimplemented!(),
910 TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => unimplemented!(),
911 }
912 }
913
914 pub fn probe_ty_var(&self, vid: TyVid) -> Result<Ty<'db>, UniverseIndex> {
917 use self::type_variable::TypeVariableValue;
918
919 match self.inner.borrow_mut().type_variables().probe(vid) {
920 TypeVariableValue::Known { value } => Ok(value),
921 TypeVariableValue::Unknown { universe } => Err(universe),
922 }
923 }
924
925 pub fn shallow_resolve(&self, ty: Ty<'db>) -> Ty<'db> {
926 if let TyKind::Infer(v) = ty.kind() {
927 match v {
928 InferTy::TyVar(v) => {
929 let known = self.inner.borrow_mut().type_variables().probe(v).known();
942 known.map_or(ty, |t| self.shallow_resolve(t))
943 }
944
945 InferTy::IntVar(v) => {
946 match self.inner.borrow_mut().int_unification_table().probe_value(v) {
947 IntVarValue::IntType(ty) => Ty::new_int(self.interner, ty),
948 IntVarValue::UintType(ty) => Ty::new_uint(self.interner, ty),
949 IntVarValue::Unknown => ty,
950 }
951 }
952
953 InferTy::FloatVar(v) => {
954 match self.inner.borrow_mut().float_unification_table().probe_value(v) {
955 FloatVarValue::Known(ty) => Ty::new_float(self.interner, ty),
956 FloatVarValue::Unknown => ty,
957 }
958 }
959
960 InferTy::FreshTy(_) | InferTy::FreshIntTy(_) | InferTy::FreshFloatTy(_) => ty,
961 }
962 } else {
963 ty
964 }
965 }
966
967 pub fn shallow_resolve_const(&self, ct: Const<'db>) -> Const<'db> {
968 match ct.kind() {
969 ConstKind::Infer(infer_ct) => match infer_ct {
970 InferConst::Var(vid) => self
971 .inner
972 .borrow_mut()
973 .const_unification_table()
974 .probe_value(vid)
975 .known()
976 .unwrap_or(ct),
977 InferConst::Fresh(_) => ct,
978 },
979 ConstKind::Param(_)
980 | ConstKind::Bound(_, _)
981 | ConstKind::Placeholder(_)
982 | ConstKind::Unevaluated(_)
983 | ConstKind::Value(_)
984 | ConstKind::Error(_)
985 | ConstKind::Expr(_) => ct,
986 }
987 }
988
989 pub fn root_var(&self, var: TyVid) -> TyVid {
990 self.inner.borrow_mut().type_variables().root_var(var)
991 }
992
993 pub fn root_const_var(&self, var: ConstVid) -> ConstVid {
994 self.inner.borrow_mut().const_unification_table().find(var).vid
995 }
996
997 pub fn opportunistic_resolve_int_var(&self, vid: IntVid) -> Ty<'db> {
1000 let mut inner = self.inner.borrow_mut();
1001 let value = inner.int_unification_table().probe_value(vid);
1002 match value {
1003 IntVarValue::IntType(ty) => Ty::new_int(self.interner, ty),
1004 IntVarValue::UintType(ty) => Ty::new_uint(self.interner, ty),
1005 IntVarValue::Unknown => {
1006 Ty::new_int_var(self.interner, inner.int_unification_table().find(vid))
1007 }
1008 }
1009 }
1010
1011 pub fn resolve_int_var(&self, vid: IntVid) -> Option<Ty<'db>> {
1012 let mut inner = self.inner.borrow_mut();
1013 let value = inner.int_unification_table().probe_value(vid);
1014 match value {
1015 IntVarValue::IntType(ty) => Some(Ty::new_int(self.interner, ty)),
1016 IntVarValue::UintType(ty) => Some(Ty::new_uint(self.interner, ty)),
1017 IntVarValue::Unknown => None,
1018 }
1019 }
1020
1021 pub fn opportunistic_resolve_float_var(&self, vid: FloatVid) -> Ty<'db> {
1024 let mut inner = self.inner.borrow_mut();
1025 let value = inner.float_unification_table().probe_value(vid);
1026 match value {
1027 FloatVarValue::Known(ty) => Ty::new_float(self.interner, ty),
1028 FloatVarValue::Unknown => {
1029 Ty::new_float_var(self.interner, inner.float_unification_table().find(vid))
1030 }
1031 }
1032 }
1033
1034 pub fn resolve_float_var(&self, vid: FloatVid) -> Option<Ty<'db>> {
1035 let mut inner = self.inner.borrow_mut();
1036 let value = inner.float_unification_table().probe_value(vid);
1037 match value {
1038 FloatVarValue::Known(ty) => Some(Ty::new_float(self.interner, ty)),
1039 FloatVarValue::Unknown => None,
1040 }
1041 }
1042
1043 pub fn resolve_vars_if_possible<T>(&self, value: T) -> T
1050 where
1051 T: TypeFoldable<DbInterner<'db>>,
1052 {
1053 if let Err(guar) = value.error_reported() {
1054 self.set_tainted_by_errors(guar);
1055 }
1056 if !value.has_non_region_infer() {
1057 return value;
1058 }
1059 let mut r = resolve::OpportunisticVarResolver::new(self);
1060 value.fold_with(&mut r)
1061 }
1062
1063 pub fn probe_const_var(&self, vid: ConstVid) -> Result<Const<'db>, UniverseIndex> {
1064 match self.inner.borrow_mut().const_unification_table().probe_value(vid) {
1065 ConstVariableValue::Known { value } => Ok(value),
1066 ConstVariableValue::Unknown { origin: _, universe } => Err(universe),
1067 }
1068 }
1069
1070 pub fn instantiate_binder_with_fresh_vars<T>(
1078 &self,
1079 _lbrct: BoundRegionConversionTime,
1080 value: Binder<'db, T>,
1081 ) -> T
1082 where
1083 T: TypeFoldable<DbInterner<'db>> + Clone,
1084 {
1085 if let Some(inner) = value.clone().no_bound_vars() {
1086 return inner;
1087 }
1088
1089 let bound_vars = value.clone().bound_vars();
1090 let mut args = Vec::with_capacity(bound_vars.len());
1091
1092 for bound_var_kind in bound_vars {
1093 let arg: GenericArg<'db> = match bound_var_kind {
1094 BoundVarKind::Ty(_) => self.next_ty_var().into(),
1095 BoundVarKind::Region(_) => self.next_region_var().into(),
1096 BoundVarKind::Const => self.next_const_var().into(),
1097 };
1098 args.push(arg);
1099 }
1100
1101 struct ToFreshVars<'db> {
1102 args: Vec<GenericArg<'db>>,
1103 }
1104
1105 impl<'db> BoundVarReplacerDelegate<'db> for ToFreshVars<'db> {
1106 fn replace_region(&mut self, br: BoundRegion) -> Region<'db> {
1107 self.args[br.var.index()].expect_region()
1108 }
1109 fn replace_ty(&mut self, bt: BoundTy) -> Ty<'db> {
1110 self.args[bt.var.index()].expect_ty()
1111 }
1112 fn replace_const(&mut self, bv: BoundConst) -> Const<'db> {
1113 self.args[bv.var.index()].expect_const()
1114 }
1115 }
1116 let delegate = ToFreshVars { args };
1117 self.interner.replace_bound_vars_uncached(value, delegate)
1118 }
1119
1120 pub fn closure_kind(&self, closure_ty: Ty<'db>) -> Option<ClosureKind> {
1124 let unresolved_kind_ty = match closure_ty.kind() {
1125 TyKind::Closure(_, args) => args.as_closure().kind_ty(),
1126 TyKind::CoroutineClosure(_, args) => args.as_coroutine_closure().kind_ty(),
1127 _ => panic!("unexpected type {closure_ty:?}"),
1128 };
1129 let closure_kind_ty = self.shallow_resolve(unresolved_kind_ty);
1130 closure_kind_ty.to_opt_closure_kind()
1131 }
1132
1133 pub fn universe(&self) -> UniverseIndex {
1134 self.universe.get()
1135 }
1136
1137 pub fn create_next_universe(&self) -> UniverseIndex {
1140 let u = self.universe.get().next_universe();
1141 debug!("create_next_universe {u:?}");
1142 self.universe.set(u);
1143 u
1144 }
1145
1146 #[inline]
1149 pub fn is_ty_infer_var_definitely_unchanged<'a>(
1150 &'a self,
1151 ) -> impl Fn(TyOrConstInferVar) -> bool + Captures<'db> + 'a {
1152 let inner = self.inner.try_borrow();
1154
1155 move |infer_var: TyOrConstInferVar| match (infer_var, &inner) {
1156 (TyOrConstInferVar::Ty(ty_var), Ok(inner)) => {
1157 use self::type_variable::TypeVariableValue;
1158
1159 matches!(
1160 inner.try_type_variables_probe_ref(ty_var),
1161 Some(TypeVariableValue::Unknown { .. })
1162 )
1163 }
1164 _ => false,
1165 }
1166 }
1167
1168 #[inline(always)]
1178 pub fn ty_or_const_infer_var_changed(&self, infer_var: TyOrConstInferVar) -> bool {
1179 match infer_var {
1180 TyOrConstInferVar::Ty(v) => {
1181 use self::type_variable::TypeVariableValue;
1182
1183 match self.inner.borrow_mut().type_variables().inlined_probe(v) {
1186 TypeVariableValue::Unknown { .. } => false,
1187 TypeVariableValue::Known { .. } => true,
1188 }
1189 }
1190
1191 TyOrConstInferVar::TyInt(v) => {
1192 self.inner.borrow_mut().int_unification_table().inlined_probe_value(v).is_known()
1196 }
1197
1198 TyOrConstInferVar::TyFloat(v) => {
1199 self.inner.borrow_mut().float_unification_table().probe_value(v).is_known()
1204 }
1205
1206 TyOrConstInferVar::Const(v) => {
1207 match self.inner.borrow_mut().const_unification_table().probe_value(v) {
1212 ConstVariableValue::Unknown { .. } => false,
1213 ConstVariableValue::Known { .. } => true,
1214 }
1215 }
1216 }
1217 }
1218
1219 fn sub_unification_table_root_var(&self, var: rustc_type_ir::TyVid) -> rustc_type_ir::TyVid {
1220 self.inner.borrow_mut().type_variables().sub_unification_table_root_var(var)
1221 }
1222
1223 fn sub_unify_ty_vids_raw(&self, a: rustc_type_ir::TyVid, b: rustc_type_ir::TyVid) {
1224 self.inner.borrow_mut().type_variables().sub_unify(a, b);
1225 }
1226}
1227
1228#[derive(Copy, Clone, Debug)]
1231pub enum TyOrConstInferVar {
1232 Ty(TyVid),
1234 TyInt(IntVid),
1236 TyFloat(FloatVid),
1238
1239 Const(ConstVid),
1241}
1242
1243impl TyOrConstInferVar {
1244 pub fn maybe_from_generic_arg<'db>(arg: GenericArg<'db>) -> Option<Self> {
1248 match arg.kind() {
1249 GenericArgKind::Type(ty) => Self::maybe_from_ty(ty),
1250 GenericArgKind::Const(ct) => Self::maybe_from_const(ct),
1251 GenericArgKind::Lifetime(_) => None,
1252 }
1253 }
1254
1255 fn maybe_from_ty<'db>(ty: Ty<'db>) -> Option<Self> {
1258 match ty.kind() {
1259 TyKind::Infer(InferTy::TyVar(v)) => Some(TyOrConstInferVar::Ty(v)),
1260 TyKind::Infer(InferTy::IntVar(v)) => Some(TyOrConstInferVar::TyInt(v)),
1261 TyKind::Infer(InferTy::FloatVar(v)) => Some(TyOrConstInferVar::TyFloat(v)),
1262 _ => None,
1263 }
1264 }
1265
1266 fn maybe_from_const<'db>(ct: Const<'db>) -> Option<Self> {
1269 match ct.kind() {
1270 ConstKind::Infer(InferConst::Var(v)) => Some(TyOrConstInferVar::Const(v)),
1271 _ => None,
1272 }
1273 }
1274}
1275
1276impl<'db> TypeTrace<'db> {
1277 pub fn types(cause: &ObligationCause, a: Ty<'db>, b: Ty<'db>) -> TypeTrace<'db> {
1278 TypeTrace {
1279 cause: cause.clone(),
1280 values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
1281 }
1282 }
1283
1284 pub fn trait_refs(
1285 cause: &ObligationCause,
1286 a: TraitRef<'db>,
1287 b: TraitRef<'db>,
1288 ) -> TypeTrace<'db> {
1289 TypeTrace { cause: cause.clone(), values: ValuePairs::TraitRefs(ExpectedFound::new(a, b)) }
1290 }
1291
1292 pub fn consts(cause: &ObligationCause, a: Const<'db>, b: Const<'db>) -> TypeTrace<'db> {
1293 TypeTrace {
1294 cause: cause.clone(),
1295 values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
1296 }
1297 }
1298}
1299
1300#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1307pub struct MemberConstraint<'db> {
1308 pub key: OpaqueTypeKey<'db>,
1311
1312 pub hidden_ty: Ty<'db>,
1314
1315 pub member_region: Region<'db>,
1317
1318 pub choice_regions: Arc<Vec<Region<'db>>>,
1320}