1use std::cell::{Cell, RefCell};
4use std::ops::Range;
5use std::sync::Arc;
6
7pub use BoundRegionConversionTime::*;
8use ena::unify as ut;
9use hir_def::{GenericParamId, TraitId};
10use opaque_types::{OpaqueHiddenType, OpaqueTypeStorage};
11use region_constraints::{RegionConstraintCollector, RegionConstraintStorage};
12use rustc_next_trait_solver::solve::{GoalEvaluation, SolverDelegateEvalExt};
13use rustc_type_ir::{
14 ClosureKind, ConstVid, FloatVarValue, FloatVid, GenericArgKind, InferConst, InferTy,
15 IntVarValue, IntVid, OutlivesPredicate, RegionVid, TermKind, TyVid, TypeFoldable, TypeFolder,
16 TypeSuperFoldable, TypeVisitableExt, UniverseIndex,
17 error::{ExpectedFound, TypeError},
18 inherent::{
19 Const as _, GenericArg as _, GenericArgs as _, IntoKind, SliceLike, Term as _, Ty as _,
20 },
21};
22use rustc_type_ir::{
23 Upcast,
24 solve::{NoSolution, inspect},
25};
26use snapshot::undo_log::InferCtxtUndoLogs;
27use tracing::{debug, instrument};
28use traits::{ObligationCause, PredicateObligations};
29use unify_key::{ConstVariableValue, ConstVidKey};
30
31pub use crate::next_solver::infer::traits::ObligationInspector;
32use crate::{
33 Span,
34 next_solver::{
35 ArgOutlivesPredicate, BoundConst, BoundRegion, BoundTy, BoundVariableKind, Goal, Predicate,
36 SolverContext,
37 fold::BoundVarReplacerDelegate,
38 infer::{at::ToTrace, select::EvaluationResult, traits::PredicateObligation},
39 obligation_ctxt::ObligationCtxt,
40 },
41};
42
43use super::{
44 AliasTerm, Binder, CanonicalQueryInput, CanonicalVarValues, Const, ConstKind, DbInterner,
45 ErrorGuaranteed, GenericArg, GenericArgs, OpaqueTypeKey, ParamEnv, PolyCoercePredicate,
46 PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyRegionOutlivesPredicate,
47 PolySubtypePredicate, Region, SolverDefId, SubtypePredicate, Term, TraitRef, Ty, TyKind,
48 TypingMode,
49};
50
51pub mod at;
52pub mod canonical;
53mod context;
54pub mod errors;
55pub mod opaque_types;
56mod outlives;
57pub mod region_constraints;
58pub mod relate;
59pub mod resolve;
60pub mod select;
61pub(crate) mod snapshot;
62pub mod traits;
63mod type_variable;
64mod unify_key;
65
66#[must_use]
74#[derive(Debug)]
75pub struct InferOk<'db, T> {
76 pub value: T,
77 pub obligations: PredicateObligations<'db>,
78}
79pub type InferResult<'db, T> = Result<InferOk<'db, T>, TypeError<DbInterner<'db>>>;
80
81pub(crate) type UnificationTable<'a, 'db, T> = ut::UnificationTable<
82 ut::InPlace<T, &'a mut ut::UnificationStorage<T>, &'a mut InferCtxtUndoLogs<'db>>,
83>;
84
85fn iter_idx_range<T: From<u32> + Into<u32>>(range: Range<T>) -> impl Iterator<Item = T> {
86 (range.start.into()..range.end.into()).map(Into::into)
87}
88
89#[derive(Clone)]
94pub struct InferCtxtInner<'db> {
95 pub(crate) undo_log: InferCtxtUndoLogs<'db>,
96
97 pub(crate) type_variable_storage: type_variable::TypeVariableStorage<'db>,
101
102 pub(crate) const_unification_storage: ut::UnificationTableStorage<ConstVidKey<'db>>,
104
105 pub(crate) int_unification_storage: ut::UnificationTableStorage<IntVid>,
107
108 pub(crate) float_unification_storage: ut::UnificationTableStorage<FloatVid>,
110
111 pub(crate) region_constraint_storage: Option<RegionConstraintStorage<'db>>,
118
119 pub(crate) region_obligations: Vec<TypeOutlivesConstraint<'db>>,
152
153 region_assumptions: Vec<ArgOutlivesPredicate<'db>>,
159
160 pub(crate) opaque_type_storage: OpaqueTypeStorage<'db>,
162}
163
164impl<'db> InferCtxtInner<'db> {
165 fn new() -> InferCtxtInner<'db> {
166 InferCtxtInner {
167 undo_log: InferCtxtUndoLogs::default(),
168
169 type_variable_storage: Default::default(),
170 const_unification_storage: Default::default(),
171 int_unification_storage: Default::default(),
172 float_unification_storage: Default::default(),
173 region_constraint_storage: Some(Default::default()),
174 region_obligations: vec![],
175 region_assumptions: Default::default(),
176 opaque_type_storage: Default::default(),
177 }
178 }
179
180 #[inline]
181 pub fn region_obligations(&self) -> &[TypeOutlivesConstraint<'db>] {
182 &self.region_obligations
183 }
184
185 #[inline]
186 fn try_type_variables_probe_ref(
187 &self,
188 vid: TyVid,
189 ) -> Option<&type_variable::TypeVariableValue<'db>> {
190 self.type_variable_storage.eq_relations_ref().try_probe_value(vid)
193 }
194
195 #[inline]
196 fn type_variables(&mut self) -> type_variable::TypeVariableTable<'_, 'db> {
197 self.type_variable_storage.with_log(&mut self.undo_log)
198 }
199
200 #[inline]
201 pub(crate) fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'db> {
202 self.opaque_type_storage.with_log(&mut self.undo_log)
203 }
204
205 #[inline]
206 pub(crate) fn int_unification_table(&mut self) -> UnificationTable<'_, 'db, IntVid> {
207 tracing::debug!(?self.int_unification_storage);
208 self.int_unification_storage.with_log(&mut self.undo_log)
209 }
210
211 #[inline]
212 pub(crate) fn float_unification_table(&mut self) -> UnificationTable<'_, 'db, FloatVid> {
213 self.float_unification_storage.with_log(&mut self.undo_log)
214 }
215
216 #[inline]
217 fn const_unification_table(&mut self) -> UnificationTable<'_, 'db, ConstVidKey<'db>> {
218 self.const_unification_storage.with_log(&mut self.undo_log)
219 }
220
221 #[inline]
222 pub fn unwrap_region_constraints(&mut self) -> RegionConstraintCollector<'db, '_> {
223 self.region_constraint_storage
224 .as_mut()
225 .expect("region constraints already solved")
226 .with_log(&mut self.undo_log)
227 }
228}
229
230#[derive(Clone)]
231pub struct InferCtxt<'db> {
232 pub interner: DbInterner<'db>,
233
234 typing_mode: TypingMode<'db>,
237
238 pub inner: RefCell<InferCtxtInner<'db>>,
239
240 tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
248
249 universe: Cell<UniverseIndex>,
259
260 obligation_inspector: Cell<Option<ObligationInspector<'db>>>,
261}
262
263#[derive(Clone, Debug, PartialEq, Eq)]
265pub enum ValuePairs<'db> {
266 Regions(ExpectedFound<Region<'db>>),
267 Terms(ExpectedFound<Term<'db>>),
268 Aliases(ExpectedFound<AliasTerm<'db>>),
269 TraitRefs(ExpectedFound<TraitRef<'db>>),
270 PolySigs(ExpectedFound<PolyFnSig<'db>>),
271 ExistentialTraitRef(ExpectedFound<PolyExistentialTraitRef<'db>>),
272 ExistentialProjection(ExpectedFound<PolyExistentialProjection<'db>>),
273}
274
275impl<'db> ValuePairs<'db> {
276 pub fn ty(&self) -> Option<(Ty<'db>, Ty<'db>)> {
277 if let ValuePairs::Terms(ExpectedFound { expected, found }) = self
278 && let Some(expected) = expected.as_type()
279 && let Some(found) = found.as_type()
280 {
281 return Some((expected, found));
282 }
283 None
284 }
285}
286
287#[derive(Clone, Debug)]
292pub struct TypeTrace<'db> {
293 pub cause: ObligationCause,
294 pub values: ValuePairs<'db>,
295}
296
297#[derive(Clone, Copy, Debug)]
299pub enum BoundRegionConversionTime<'db> {
300 FnCall,
302
303 HigherRankedType,
305
306 AssocTypeProjection(SolverDefId<'db>),
308}
309
310#[derive(Clone, Debug)]
312pub struct TypeOutlivesConstraint<'db> {
313 pub sub_region: Region<'db>,
314 pub sup_type: Ty<'db>,
315}
316
317pub struct InferCtxtBuilder<'db> {
319 interner: DbInterner<'db>,
320}
321
322pub trait DbInternerInferExt<'db> {
323 fn infer_ctxt(self) -> InferCtxtBuilder<'db>;
324}
325
326impl<'db> DbInternerInferExt<'db> for DbInterner<'db> {
327 fn infer_ctxt(self) -> InferCtxtBuilder<'db> {
328 InferCtxtBuilder { interner: self }
329 }
330}
331
332impl<'db> InferCtxtBuilder<'db> {
333 pub fn build_with_canonical<T>(
341 mut self,
342 span: Span,
343 input: &CanonicalQueryInput<'db, T>,
344 ) -> (InferCtxt<'db>, T, CanonicalVarValues<'db>)
345 where
346 T: TypeFoldable<DbInterner<'db>>,
347 {
348 let infcx = self.build(input.typing_mode.0);
349 let (value, args) = infcx.instantiate_canonical(span, &input.canonical);
350 (infcx, value, args)
351 }
352
353 pub fn build(&mut self, typing_mode: TypingMode<'db>) -> InferCtxt<'db> {
354 self.interner.expect_crate();
358 let InferCtxtBuilder { interner } = *self;
359 InferCtxt {
360 interner,
361 typing_mode,
362 inner: RefCell::new(InferCtxtInner::new()),
363 tainted_by_errors: Cell::new(None),
364 universe: Cell::new(UniverseIndex::ROOT),
365 obligation_inspector: Cell::new(None),
366 }
367 }
368}
369
370impl<'db> InferOk<'db, ()> {
371 pub fn into_obligations(self) -> PredicateObligations<'db> {
372 self.obligations
373 }
374}
375
376impl<'db> InferCtxt<'db> {
377 #[inline(always)]
378 pub fn typing_mode_raw(&self) -> TypingMode<'db> {
379 self.typing_mode
380 }
381
382 #[inline(always)]
383 pub fn typing_mode_unchecked(&self) -> TypingMode<'db> {
384 self.typing_mode
385 }
386
387 pub fn predicate_may_hold(&self, obligation: &PredicateObligation<'db>) -> bool {
390 self.evaluate_obligation(obligation).may_apply()
391 }
392
393 pub fn predicate_may_hold_opaque_types_jank(
396 &self,
397 obligation: &PredicateObligation<'db>,
398 ) -> bool {
399 <&SolverContext<'db>>::from(self).root_goal_may_hold_opaque_types_jank(Goal::new(
400 self.interner,
401 obligation.param_env,
402 obligation.predicate,
403 ))
404 }
405
406 pub(crate) fn insert_type_vars<T>(&self, ty: T) -> T
407 where
408 T: TypeFoldable<DbInterner<'db>>,
409 {
410 struct Folder<'a, 'db> {
411 infcx: &'a InferCtxt<'db>,
412 }
413 impl<'db> TypeFolder<DbInterner<'db>> for Folder<'_, 'db> {
414 fn cx(&self) -> DbInterner<'db> {
415 self.infcx.interner
416 }
417
418 fn fold_ty(&mut self, ty: Ty<'db>) -> Ty<'db> {
419 if !ty.references_error() {
420 return ty;
421 }
422
423 if ty.is_ty_error() {
424 self.infcx.next_ty_var(Span::Dummy)
425 } else {
426 ty.super_fold_with(self)
427 }
428 }
429
430 fn fold_const(&mut self, ct: Const<'db>) -> Const<'db> {
431 if !ct.references_error() {
432 return ct;
433 }
434
435 if ct.is_ct_error() {
436 self.infcx.next_const_var(Span::Dummy)
437 } else {
438 ct.super_fold_with(self)
439 }
440 }
441
442 fn fold_region(&mut self, r: Region<'db>) -> Region<'db> {
443 if r.is_error() { self.infcx.next_region_var(Span::Dummy) } else { r }
444 }
445 }
446
447 ty.fold_with(&mut Folder { infcx: self })
448 }
449
450 pub fn predicate_must_hold_considering_regions(
478 &self,
479 obligation: &PredicateObligation<'db>,
480 ) -> bool {
481 self.evaluate_obligation(obligation).must_apply_considering_regions()
482 }
483
484 pub fn predicate_must_hold_modulo_regions(
490 &self,
491 obligation: &PredicateObligation<'db>,
492 ) -> bool {
493 self.evaluate_obligation(obligation).must_apply_modulo_regions()
494 }
495
496 #[instrument(level = "debug", skip(self, params), ret)]
525 pub fn type_implements_trait(
526 &self,
527 trait_def_id: TraitId,
528 params: impl IntoIterator<Item: Into<GenericArg<'db>>>,
529 param_env: ParamEnv<'db>,
530 ) -> EvaluationResult {
531 let trait_ref = TraitRef::new(self.interner, trait_def_id.into(), params);
532
533 let obligation = traits::Obligation {
534 cause: traits::ObligationCause::dummy(),
535 param_env,
536 recursion_depth: 0,
537 predicate: trait_ref.upcast(self.interner),
538 };
539 self.evaluate_obligation(&obligation)
540 }
541
542 fn evaluate_obligation(&self, obligation: &PredicateObligation<'db>) -> EvaluationResult {
544 self.probe(|snapshot| {
545 let mut ocx = ObligationCtxt::new(self);
546 ocx.register_obligation(obligation.clone());
547 let mut result = EvaluationResult::EvaluatedToOk;
548 for error in ocx.evaluate_obligations_error_on_ambiguity() {
549 if error.is_true_error() {
550 return EvaluationResult::EvaluatedToErr;
551 } else {
552 result = result.max(EvaluationResult::EvaluatedToAmbig);
553 }
554 }
555 if self.opaque_types_added_in_snapshot(snapshot) {
556 result = result.max(EvaluationResult::EvaluatedToOkModuloOpaqueTypes);
557 } else if self.region_constraints_added_in_snapshot(snapshot) {
558 result = result.max(EvaluationResult::EvaluatedToOkModuloRegions);
559 }
560 result
561 })
562 }
563
564 pub fn can_eq<T: ToTrace<'db>>(&self, param_env: ParamEnv<'db>, a: T, b: T) -> bool {
565 self.probe(|_| {
566 let mut ocx = ObligationCtxt::new(self);
567 let Ok(()) = ocx.eq(&ObligationCause::dummy(), param_env, a, b) else {
568 return false;
569 };
570 ocx.try_evaluate_obligations().is_empty()
571 })
572 }
573
574 pub fn goal_may_hold_opaque_types_jank(&self, goal: Goal<'db, Predicate<'db>>) -> bool {
577 <&SolverContext<'db>>::from(self).root_goal_may_hold_opaque_types_jank(goal)
578 }
579
580 pub fn type_is_copy_modulo_regions(&self, param_env: ParamEnv<'db>, ty: Ty<'db>) -> bool {
581 let ty = self.resolve_vars_if_possible(ty);
582
583 let Some(copy_def_id) = self.interner.lang_items().Copy else {
584 return false;
585 };
586
587 traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id)
592 }
593
594 pub fn type_is_sized_modulo_regions(&self, param_env: ParamEnv<'db>, ty: Ty<'db>) -> bool {
595 let Some(sized_def_id) = self.interner.lang_items().Sized else {
596 return true;
597 };
598 traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, sized_def_id)
599 }
600
601 pub fn type_is_use_cloned_modulo_regions(&self, param_env: ParamEnv<'db>, ty: Ty<'db>) -> bool {
602 let ty = self.resolve_vars_if_possible(ty);
603
604 let Some(use_cloned_def_id) = self.interner.lang_items().UseCloned else {
605 return false;
606 };
607
608 traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, use_cloned_def_id)
609 }
610
611 pub fn unresolved_variables(&self) -> Vec<Ty<'db>> {
612 let mut inner = self.inner.borrow_mut();
613 let mut vars: Vec<Ty<'db>> = inner
614 .type_variables()
615 .unresolved_variables()
616 .into_iter()
617 .map(|t| Ty::new_var(self.interner, t))
618 .collect();
619 vars.extend(
620 (0..inner.int_unification_table().len())
621 .map(IntVid::from_usize)
622 .filter(|&vid| inner.int_unification_table().probe_value(vid).is_unknown())
623 .map(|v| Ty::new_int_var(self.interner, v)),
624 );
625 vars.extend(
626 (0..inner.float_unification_table().len())
627 .map(FloatVid::from_usize)
628 .filter(|&vid| inner.float_unification_table().probe_value(vid).is_unknown())
629 .map(|v| Ty::new_float_var(self.interner, v)),
630 );
631 vars
632 }
633
634 #[instrument(skip(self), level = "debug")]
635 pub fn sub_regions(&self, a: Region<'db>, b: Region<'db>) {
636 self.inner.borrow_mut().unwrap_region_constraints().make_subregion(a, b);
637 }
638
639 pub fn coerce_predicate(
655 &self,
656 cause: &ObligationCause,
657 param_env: ParamEnv<'db>,
658 predicate: PolyCoercePredicate<'db>,
659 ) -> Result<InferResult<'db, ()>, (TyVid, TyVid)> {
660 let subtype_predicate = predicate.map_bound(|p| SubtypePredicate {
661 a_is_expected: false, a: p.a,
663 b: p.b,
664 });
665 self.subtype_predicate(cause, param_env, subtype_predicate)
666 }
667
668 pub fn subtype_predicate(
669 &self,
670 cause: &ObligationCause,
671 param_env: ParamEnv<'db>,
672 predicate: PolySubtypePredicate<'db>,
673 ) -> Result<InferResult<'db, ()>, (TyVid, TyVid)> {
674 let r_a = self.shallow_resolve(predicate.skip_binder().a);
688 let r_b = self.shallow_resolve(predicate.skip_binder().b);
689 match (r_a.kind(), r_b.kind()) {
690 (TyKind::Infer(InferTy::TyVar(a_vid)), TyKind::Infer(InferTy::TyVar(b_vid))) => {
691 return Err((a_vid, b_vid));
692 }
693 _ => {}
694 }
695
696 self.enter_forall(predicate, |SubtypePredicate { a_is_expected, a, b }| {
697 if a_is_expected {
698 Ok(self.at(cause, param_env).sub(a, b))
699 } else {
700 Ok(self.at(cause, param_env).sup(b, a))
701 }
702 })
703 }
704
705 pub fn region_outlives_predicate(
706 &self,
707 _cause: &traits::ObligationCause,
708 predicate: PolyRegionOutlivesPredicate<'db>,
709 ) {
710 self.enter_forall(predicate, |OutlivesPredicate(r_a, r_b)| {
711 self.sub_regions(r_b, r_a); })
713 }
714
715 pub fn num_ty_vars(&self) -> usize {
717 self.inner.borrow_mut().type_variables().num_vars()
718 }
719
720 pub fn next_ty_var(&self, span: Span) -> Ty<'db> {
721 let vid = self.next_ty_vid(span);
722 Ty::new_var(self.interner, vid)
723 }
724
725 pub fn next_ty_vid(&self, span: Span) -> TyVid {
726 self.next_ty_var_id_in_universe(self.universe(), span)
727 }
728
729 pub fn next_ty_var_id_in_universe(&self, universe: UniverseIndex, span: Span) -> TyVid {
730 self.inner.borrow_mut().type_variables().new_var(universe, span)
731 }
732
733 pub fn next_ty_var_in_universe(&self, universe: UniverseIndex, span: Span) -> Ty<'db> {
734 let vid = self.next_ty_var_id_in_universe(universe, span);
735 Ty::new_var(self.interner, vid)
736 }
737
738 pub fn next_const_var(&self, span: Span) -> Const<'db> {
739 let vid = self.next_const_vid(span);
740 Const::new_var(self.interner, vid)
741 }
742
743 pub fn next_const_vid(&self, span: Span) -> ConstVid {
744 self.next_const_vid_in_universe(self.universe(), span)
745 }
746
747 pub fn next_const_vid_in_universe(&self, universe: UniverseIndex, span: Span) -> ConstVid {
748 self.inner
749 .borrow_mut()
750 .const_unification_table()
751 .new_key(ConstVariableValue::Unknown { span, universe })
752 .vid
753 }
754
755 pub fn next_const_var_in_universe(&self, universe: UniverseIndex, span: Span) -> Const<'db> {
756 let vid = self.next_const_vid_in_universe(universe, span);
757 Const::new_var(self.interner, vid)
758 }
759
760 pub fn next_int_var(&self) -> Ty<'db> {
761 let vid = self.next_int_vid();
762 Ty::new_int_var(self.interner, vid)
763 }
764
765 pub fn next_int_vid(&self) -> IntVid {
766 self.inner.borrow_mut().int_unification_table().new_key(IntVarValue::Unknown)
767 }
768
769 pub fn next_float_var(&self) -> Ty<'db> {
770 Ty::new_float_var(self.interner, self.next_float_vid())
771 }
772
773 pub fn next_float_vid(&self) -> FloatVid {
774 self.inner.borrow_mut().float_unification_table().new_key(FloatVarValue::Unknown)
775 }
776
777 pub fn next_region_var(&self, span: Span) -> Region<'db> {
781 self.next_region_var_in_universe(self.universe(), span)
782 }
783
784 pub fn next_region_vid(&self, span: Span) -> RegionVid {
785 self.inner.borrow_mut().unwrap_region_constraints().new_region_var(self.universe(), span)
786 }
787
788 pub fn next_region_var_in_universe(&self, universe: UniverseIndex, span: Span) -> Region<'db> {
792 let region_var =
793 self.inner.borrow_mut().unwrap_region_constraints().new_region_var(universe, span);
794 Region::new_var(self.interner, region_var)
795 }
796
797 pub fn next_term_var_of_kind(&self, term: Term<'db>, span: Span) -> Term<'db> {
798 match term.kind() {
799 TermKind::Ty(_) => self.next_ty_var(span).into(),
800 TermKind::Const(_) => self.next_const_var(span).into(),
801 }
802 }
803
804 pub fn universe_of_region(&self, r: Region<'db>) -> UniverseIndex {
810 self.inner.borrow_mut().unwrap_region_constraints().universe(r)
811 }
812
813 pub fn num_region_vars(&self) -> usize {
815 self.inner.borrow_mut().unwrap_region_constraints().num_region_vars()
816 }
817
818 pub fn var_for_def(&self, id: GenericParamId, span: Span) -> GenericArg<'db> {
819 match id {
820 GenericParamId::LifetimeParamId(_) => {
821 self.next_region_var(span).into()
824 }
825 GenericParamId::TypeParamId(_) => {
826 self.next_ty_var(span).into()
835 }
836 GenericParamId::ConstParamId(_) => self.next_const_var(span).into(),
837 }
838 }
839
840 pub fn fresh_args_for_item(&self, span: Span, def_id: SolverDefId<'db>) -> GenericArgs<'db> {
843 GenericArgs::for_item(self.interner, def_id, |_index, kind, _, _| {
844 self.var_for_def(kind, span)
845 })
846 }
847
848 pub fn fill_rest_fresh_args(
850 &self,
851 span: Span,
852 def_id: SolverDefId<'db>,
853 first: impl IntoIterator<Item = GenericArg<'db>>,
854 ) -> GenericArgs<'db> {
855 GenericArgs::fill_rest(self.interner, def_id, first, |_index, kind, _| {
856 self.var_for_def(kind, span)
857 })
858 }
859
860 #[must_use = "this method does not have any side effects"]
866 pub fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
867 self.tainted_by_errors.get()
868 }
869
870 pub fn set_tainted_by_errors(&self, e: ErrorGuaranteed) {
873 debug!("set_tainted_by_errors(ErrorGuaranteed)");
874 self.tainted_by_errors.set(Some(e));
875 }
876
877 #[instrument(level = "debug", skip(self))]
878 pub fn take_opaque_types(
879 &self,
880 ) -> impl IntoIterator<Item = (OpaqueTypeKey<'db>, OpaqueHiddenType<'db>)> + use<'db> {
881 self.inner.borrow_mut().opaque_type_storage.take_opaque_types()
882 }
883
884 #[instrument(level = "debug", skip(self), ret)]
885 pub fn clone_opaque_types(&self) -> Vec<(OpaqueTypeKey<'db>, OpaqueHiddenType<'db>)> {
886 self.inner.borrow_mut().opaque_type_storage.iter_opaque_types().collect()
887 }
888
889 pub fn has_opaques_with_sub_unified_hidden_type(&self, ty_vid: TyVid) -> bool {
890 let ty_sub_vid = self.sub_unification_table_root_var(ty_vid);
891 let inner = &mut *self.inner.borrow_mut();
892 let mut type_variables = inner.type_variable_storage.with_log(&mut inner.undo_log);
893 inner.opaque_type_storage.iter_opaque_types().any(|(_, hidden_ty)| {
894 if let TyKind::Infer(InferTy::TyVar(hidden_vid)) = hidden_ty.ty.kind() {
895 let opaque_sub_vid = type_variables.sub_unification_table_root_var(hidden_vid);
896 if opaque_sub_vid == ty_sub_vid {
897 return true;
898 }
899 }
900
901 false
902 })
903 }
904
905 #[inline(always)]
906 pub fn can_define_opaque_ty(&self, id: impl Into<SolverDefId<'db>>) -> bool {
907 match self.typing_mode_raw().assert_not_erased() {
908 TypingMode::Analysis { defining_opaque_types_and_generators } => {
909 defining_opaque_types_and_generators.contains(&id.into())
910 }
911 TypingMode::Coherence | TypingMode::PostAnalysis => false,
912 TypingMode::Borrowck { defining_opaque_types: _ } => unimplemented!(),
913 TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => unimplemented!(),
914 }
915 }
916
917 pub fn probe_ty_var(&self, vid: TyVid) -> Result<Ty<'db>, UniverseIndex> {
920 use self::type_variable::TypeVariableValue;
921
922 match self.inner.borrow_mut().type_variables().probe(vid) {
923 TypeVariableValue::Known { value, .. } => Ok(value),
924 TypeVariableValue::Unknown { universe, .. } => Err(universe),
925 }
926 }
927
928 pub fn shallow_resolve(&self, ty: Ty<'db>) -> Ty<'db> {
929 if let TyKind::Infer(v) = ty.kind() {
930 match v {
931 InferTy::TyVar(v) => {
932 let known = self.inner.borrow_mut().type_variables().probe(v).known();
945 known.map_or(ty, |t| self.shallow_resolve(t))
946 }
947
948 InferTy::IntVar(v) => {
949 match self.inner.borrow_mut().int_unification_table().probe_value(v) {
950 IntVarValue::IntType(ty) => Ty::new_int(self.interner, ty),
951 IntVarValue::UintType(ty) => Ty::new_uint(self.interner, ty),
952 IntVarValue::Unknown => ty,
953 }
954 }
955
956 InferTy::FloatVar(v) => {
957 match self.inner.borrow_mut().float_unification_table().probe_value(v) {
958 FloatVarValue::Known(ty) => Ty::new_float(self.interner, ty),
959 FloatVarValue::Unknown => ty,
960 }
961 }
962
963 InferTy::FreshTy(_) | InferTy::FreshIntTy(_) | InferTy::FreshFloatTy(_) => ty,
964 }
965 } else {
966 ty
967 }
968 }
969
970 pub fn shallow_resolve_const(&self, ct: Const<'db>) -> Const<'db> {
971 match ct.kind() {
972 ConstKind::Infer(infer_ct) => match infer_ct {
973 InferConst::Var(vid) => self
974 .inner
975 .borrow_mut()
976 .const_unification_table()
977 .probe_value(vid)
978 .known()
979 .unwrap_or(ct),
980 InferConst::Fresh(_) => ct,
981 },
982 ConstKind::Param(_)
983 | ConstKind::Bound(_, _)
984 | ConstKind::Placeholder(_)
985 | ConstKind::Unevaluated(_)
986 | ConstKind::Value(_)
987 | ConstKind::Error(_)
988 | ConstKind::Expr(_) => ct,
989 }
990 }
991
992 pub fn shallow_resolve_term(&self, term: Term<'db>) -> Term<'db> {
993 match term.kind() {
994 TermKind::Ty(ty) => self.shallow_resolve(ty).into(),
995 TermKind::Const(ct) => self.shallow_resolve_const(ct).into(),
996 }
997 }
998
999 pub fn root_var(&self, var: TyVid) -> TyVid {
1000 self.inner.borrow_mut().type_variables().root_var(var)
1001 }
1002
1003 pub fn root_const_var(&self, var: ConstVid) -> ConstVid {
1004 self.inner.borrow_mut().const_unification_table().find(var).vid
1005 }
1006
1007 pub fn opportunistic_resolve_int_var(&self, vid: IntVid) -> Ty<'db> {
1010 let mut inner = self.inner.borrow_mut();
1011 let value = inner.int_unification_table().probe_value(vid);
1012 match value {
1013 IntVarValue::IntType(ty) => Ty::new_int(self.interner, ty),
1014 IntVarValue::UintType(ty) => Ty::new_uint(self.interner, ty),
1015 IntVarValue::Unknown => {
1016 Ty::new_int_var(self.interner, inner.int_unification_table().find(vid))
1017 }
1018 }
1019 }
1020
1021 pub fn resolve_int_var(&self, vid: IntVid) -> Option<Ty<'db>> {
1022 let mut inner = self.inner.borrow_mut();
1023 let value = inner.int_unification_table().probe_value(vid);
1024 match value {
1025 IntVarValue::IntType(ty) => Some(Ty::new_int(self.interner, ty)),
1026 IntVarValue::UintType(ty) => Some(Ty::new_uint(self.interner, ty)),
1027 IntVarValue::Unknown => None,
1028 }
1029 }
1030
1031 pub fn opportunistic_resolve_float_var(&self, vid: FloatVid) -> Ty<'db> {
1034 let mut inner = self.inner.borrow_mut();
1035 let value = inner.float_unification_table().probe_value(vid);
1036 match value {
1037 FloatVarValue::Known(ty) => Ty::new_float(self.interner, ty),
1038 FloatVarValue::Unknown => {
1039 Ty::new_float_var(self.interner, inner.float_unification_table().find(vid))
1040 }
1041 }
1042 }
1043
1044 pub fn resolve_float_var(&self, vid: FloatVid) -> Option<Ty<'db>> {
1045 let mut inner = self.inner.borrow_mut();
1046 let value = inner.float_unification_table().probe_value(vid);
1047 match value {
1048 FloatVarValue::Known(ty) => Some(Ty::new_float(self.interner, ty)),
1049 FloatVarValue::Unknown => None,
1050 }
1051 }
1052
1053 pub fn resolve_vars_if_possible<T>(&self, value: T) -> T
1060 where
1061 T: TypeFoldable<DbInterner<'db>>,
1062 {
1063 if let Err(guar) = value.error_reported() {
1064 self.set_tainted_by_errors(guar);
1065 }
1066 if !value.has_non_region_infer() {
1067 return value;
1068 }
1069 let mut r = resolve::OpportunisticVarResolver::new(self);
1070 value.fold_with(&mut r)
1071 }
1072
1073 pub fn probe_const_var(&self, vid: ConstVid) -> Result<Const<'db>, UniverseIndex> {
1074 match self.inner.borrow_mut().const_unification_table().probe_value(vid) {
1075 ConstVariableValue::Known { value } => Ok(value),
1076 ConstVariableValue::Unknown { span: _, universe } => Err(universe),
1077 }
1078 }
1079
1080 pub fn type_var_span(&self, vid: TyVid) -> Span {
1084 self.inner.borrow_mut().type_variables().var_span(vid)
1085 }
1086
1087 pub fn const_var_span(&self, vid: ConstVid) -> Option<Span> {
1089 match self.inner.borrow_mut().const_unification_table().probe_value(vid) {
1090 ConstVariableValue::Known { .. } => None,
1091 ConstVariableValue::Unknown { span, .. } => Some(span),
1092 }
1093 }
1094
1095 pub fn instantiate_binder_with_fresh_vars<T>(
1103 &self,
1104 span: Span,
1105 _lbrct: BoundRegionConversionTime<'db>,
1106 value: Binder<'db, T>,
1107 ) -> T
1108 where
1109 T: TypeFoldable<DbInterner<'db>> + Clone,
1110 {
1111 if let Some(inner) = value.clone().no_bound_vars() {
1112 return inner;
1113 }
1114
1115 let bound_vars = value.clone().bound_vars();
1116 let mut args = Vec::with_capacity(bound_vars.len());
1117
1118 for bound_var_kind in bound_vars {
1119 let arg: GenericArg<'db> = match bound_var_kind {
1120 BoundVariableKind::Ty(_) => self.next_ty_var(span).into(),
1121 BoundVariableKind::Region(_) => self.next_region_var(span).into(),
1122 BoundVariableKind::Const => self.next_const_var(span).into(),
1123 };
1124 args.push(arg);
1125 }
1126
1127 struct ToFreshVars<'db> {
1128 args: Vec<GenericArg<'db>>,
1129 }
1130
1131 impl<'db> BoundVarReplacerDelegate<'db> for ToFreshVars<'db> {
1132 fn replace_region(&mut self, br: BoundRegion<'db>) -> Region<'db> {
1133 self.args[br.var.index()].expect_region()
1134 }
1135 fn replace_ty(&mut self, bt: BoundTy<'db>) -> Ty<'db> {
1136 self.args[bt.var.index()].expect_ty()
1137 }
1138 fn replace_const(&mut self, bv: BoundConst<'db>) -> Const<'db> {
1139 self.args[bv.var.index()].expect_const()
1140 }
1141 }
1142 let delegate = ToFreshVars { args };
1143 self.interner.replace_bound_vars_uncached(value, delegate)
1144 }
1145
1146 pub fn closure_kind(&self, closure_ty: Ty<'db>) -> Option<ClosureKind> {
1150 let unresolved_kind_ty = match closure_ty.kind() {
1151 TyKind::Closure(_, args) => args.as_closure().kind_ty(),
1152 TyKind::CoroutineClosure(_, args) => args.as_coroutine_closure().kind_ty(),
1153 _ => panic!("unexpected type {closure_ty:?}"),
1154 };
1155 let closure_kind_ty = self.shallow_resolve(unresolved_kind_ty);
1156 closure_kind_ty.to_opt_closure_kind()
1157 }
1158
1159 pub fn universe(&self) -> UniverseIndex {
1160 self.universe.get()
1161 }
1162
1163 pub fn create_next_universe(&self) -> UniverseIndex {
1166 let u = self.universe.get().next_universe();
1167 debug!("create_next_universe {u:?}");
1168 self.universe.set(u);
1169 u
1170 }
1171
1172 #[inline]
1175 pub fn is_ty_infer_var_definitely_unchanged<'a>(
1176 &'a self,
1177 ) -> impl Fn(TyOrConstInferVar) -> bool + use<'a, 'db> {
1178 let inner = self.inner.try_borrow();
1180
1181 move |infer_var: TyOrConstInferVar| match (infer_var, &inner) {
1182 (TyOrConstInferVar::Ty(ty_var), Ok(inner)) => {
1183 use self::type_variable::TypeVariableValue;
1184
1185 matches!(
1186 inner.try_type_variables_probe_ref(ty_var),
1187 Some(TypeVariableValue::Unknown { .. })
1188 )
1189 }
1190 _ => false,
1191 }
1192 }
1193
1194 #[inline(always)]
1204 pub fn ty_or_const_infer_var_changed(&self, infer_var: TyOrConstInferVar) -> bool {
1205 match infer_var {
1206 TyOrConstInferVar::Ty(v) => {
1207 use self::type_variable::TypeVariableValue;
1208
1209 match self.inner.borrow_mut().type_variables().inlined_probe(v) {
1212 TypeVariableValue::Unknown { .. } => false,
1213 TypeVariableValue::Known { .. } => true,
1214 }
1215 }
1216
1217 TyOrConstInferVar::TyInt(v) => {
1218 self.inner.borrow_mut().int_unification_table().inlined_probe_value(v).is_known()
1222 }
1223
1224 TyOrConstInferVar::TyFloat(v) => {
1225 self.inner.borrow_mut().float_unification_table().probe_value(v).is_known()
1230 }
1231
1232 TyOrConstInferVar::Const(v) => {
1233 match self.inner.borrow_mut().const_unification_table().probe_value(v) {
1238 ConstVariableValue::Unknown { .. } => false,
1239 ConstVariableValue::Known { .. } => true,
1240 }
1241 }
1242 }
1243 }
1244
1245 fn sub_unification_table_root_var(&self, var: rustc_type_ir::TyVid) -> rustc_type_ir::TyVid {
1246 self.inner.borrow_mut().type_variables().sub_unification_table_root_var(var)
1247 }
1248
1249 fn sub_unify_ty_vids_raw(&self, a: rustc_type_ir::TyVid, b: rustc_type_ir::TyVid) {
1250 self.inner.borrow_mut().type_variables().sub_unify(a, b);
1251 }
1252
1253 pub fn attach_obligation_inspector(&self, inspector: ObligationInspector<'db>) {
1255 debug_assert!(
1256 self.obligation_inspector.get().is_none(),
1257 "shouldn't override a set obligation inspector"
1258 );
1259 self.obligation_inspector.set(Some(inspector));
1260 }
1261
1262 pub fn inspect_evaluated_obligation(
1263 &self,
1264 obligation: &PredicateObligation<'db>,
1265 result: &Result<GoalEvaluation<DbInterner<'db>>, NoSolution>,
1266 get_proof_tree: impl FnOnce() -> Option<inspect::GoalEvaluation<DbInterner<'db>>>,
1267 ) {
1268 if let Some(inspector) = self.obligation_inspector.get() {
1269 let result = match result {
1270 Ok(GoalEvaluation { certainty, .. }) => Ok(*certainty),
1271 Err(_) => Err(NoSolution),
1272 };
1273 (inspector)(self, obligation, result, get_proof_tree());
1274 }
1275 }
1276}
1277
1278#[derive(Copy, Clone, Debug)]
1281pub enum TyOrConstInferVar {
1282 Ty(TyVid),
1284 TyInt(IntVid),
1286 TyFloat(FloatVid),
1288
1289 Const(ConstVid),
1291}
1292
1293impl TyOrConstInferVar {
1294 pub fn maybe_from_generic_arg<'db>(arg: GenericArg<'db>) -> Option<Self> {
1298 match arg.kind() {
1299 GenericArgKind::Type(ty) => Self::maybe_from_ty(ty),
1300 GenericArgKind::Const(ct) => Self::maybe_from_const(ct),
1301 GenericArgKind::Lifetime(_) => None,
1302 }
1303 }
1304
1305 fn maybe_from_ty<'db>(ty: Ty<'db>) -> Option<Self> {
1308 match ty.kind() {
1309 TyKind::Infer(InferTy::TyVar(v)) => Some(TyOrConstInferVar::Ty(v)),
1310 TyKind::Infer(InferTy::IntVar(v)) => Some(TyOrConstInferVar::TyInt(v)),
1311 TyKind::Infer(InferTy::FloatVar(v)) => Some(TyOrConstInferVar::TyFloat(v)),
1312 _ => None,
1313 }
1314 }
1315
1316 fn maybe_from_const<'db>(ct: Const<'db>) -> Option<Self> {
1319 match ct.kind() {
1320 ConstKind::Infer(InferConst::Var(v)) => Some(TyOrConstInferVar::Const(v)),
1321 _ => None,
1322 }
1323 }
1324}
1325
1326impl<'db> TypeTrace<'db> {
1327 pub fn types(cause: &ObligationCause, a: Ty<'db>, b: Ty<'db>) -> TypeTrace<'db> {
1328 TypeTrace {
1329 cause: *cause,
1330 values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
1331 }
1332 }
1333
1334 pub fn trait_refs(
1335 cause: &ObligationCause,
1336 a: TraitRef<'db>,
1337 b: TraitRef<'db>,
1338 ) -> TypeTrace<'db> {
1339 TypeTrace { cause: *cause, values: ValuePairs::TraitRefs(ExpectedFound::new(a, b)) }
1340 }
1341
1342 pub fn consts(cause: &ObligationCause, a: Const<'db>, b: Const<'db>) -> TypeTrace<'db> {
1343 TypeTrace {
1344 cause: *cause,
1345 values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
1346 }
1347 }
1348}
1349
1350#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1357pub struct MemberConstraint<'db> {
1358 pub key: OpaqueTypeKey<'db>,
1361
1362 pub hidden_ty: Ty<'db>,
1364
1365 pub member_region: Region<'db>,
1367
1368 pub choice_regions: Arc<Vec<Region<'db>>>,
1370}