1use std::cell::{Cell, RefCell};
4use std::fmt;
5use std::sync::Arc;
6
7pub use BoundRegionConversionTime::*;
8pub use at::DefineOpaqueTypes;
9use ena::undo_log::UndoLogs;
10use ena::unify as ut;
11use hir_def::GenericParamId;
12use intern::Symbol;
13use opaque_types::{OpaqueHiddenType, OpaqueTypeStorage};
14use region_constraints::{
15 GenericKind, RegionConstraintCollector, RegionConstraintStorage, UndoLog, VarInfos, VerifyBound,
16};
17pub use relate::StructurallyRelateAliases;
18pub use relate::combine::PredicateEmittingRelation;
19use rustc_hash::{FxHashMap, FxHashSet};
20use rustc_pattern_analysis::Captures;
21use rustc_type_ir::error::{ExpectedFound, TypeError};
22use rustc_type_ir::inherent::{
23 Const as _, GenericArg as _, GenericArgs as _, IntoKind, ParamEnv as _, SliceLike, Term as _,
24 Ty as _,
25};
26use rustc_type_ir::{
27 BoundVar, ClosureKind, ConstVid, FloatTy, FloatVarValue, FloatVid, GenericArgKind, InferConst,
28 InferTy, IntTy, IntVarValue, IntVid, OutlivesPredicate, RegionVid, TyVid, UniverseIndex,
29};
30use rustc_type_ir::{TermKind, TypeVisitableExt};
31use rustc_type_ir::{TypeFoldable, TypeFolder, TypeSuperFoldable};
32use snapshot::undo_log::InferCtxtUndoLogs;
33use tracing::{debug, instrument};
34use traits::{ObligationCause, PredicateObligations};
35use type_variable::TypeVariableOrigin;
36use unify_key::{ConstVariableOrigin, ConstVariableValue, ConstVidKey};
37
38use crate::next_solver::fold::BoundVarReplacerDelegate;
39use crate::next_solver::infer::opaque_types::table::OpaqueTypeStorageEntries;
40use crate::next_solver::{BoundRegion, BoundTy, BoundVarKind};
41
42use super::generics::GenericParamDef;
43use super::{
44 AliasTerm, Binder, BoundRegionKind, CanonicalQueryInput, CanonicalVarValues, Const, ConstKind,
45 DbInterner, ErrorGuaranteed, FxIndexMap, GenericArg, GenericArgs, OpaqueTypeKey, ParamEnv,
46 PlaceholderRegion, PolyCoercePredicate, PolyExistentialProjection, PolyExistentialTraitRef,
47 PolyFnSig, PolyRegionOutlivesPredicate, PolySubtypePredicate, Predicate, Region, SolverDefId,
48 SubtypePredicate, Term, TraitPredicate, TraitRef, Ty, TyKind, TypingMode,
49};
50
51pub mod at;
52pub mod canonical;
53mod context;
54mod opaque_types;
55pub mod region_constraints;
56pub mod relate;
57pub mod resolve;
58pub(crate) mod snapshot;
59pub(crate) mod traits;
60mod type_variable;
61mod unify_key;
62
63#[must_use]
71#[derive(Debug)]
72pub struct InferOk<'db, T> {
73 pub value: T,
74 pub obligations: PredicateObligations<'db>,
75}
76pub type InferResult<'db, T> = Result<InferOk<'db, T>, TypeError<DbInterner<'db>>>;
77
78pub(crate) type FixupResult<T> = Result<T, FixupError>; pub(crate) type UnificationTable<'a, 'db, T> = ut::UnificationTable<
81 ut::InPlace<T, &'a mut ut::UnificationStorage<T>, &'a mut InferCtxtUndoLogs<'db>>,
82>;
83
84#[derive(Clone)]
89pub struct InferCtxtInner<'db> {
90 pub(crate) undo_log: InferCtxtUndoLogs<'db>,
91
92 pub(crate) type_variable_storage: type_variable::TypeVariableStorage<'db>,
96
97 pub(crate) const_unification_storage: ut::UnificationTableStorage<ConstVidKey<'db>>,
99
100 pub(crate) int_unification_storage: ut::UnificationTableStorage<IntVid>,
102
103 pub(crate) float_unification_storage: ut::UnificationTableStorage<FloatVid>,
105
106 pub(crate) region_constraint_storage: Option<RegionConstraintStorage<'db>>,
113
114 pub(crate) region_obligations: Vec<RegionObligation<'db>>,
147
148 pub(crate) opaque_type_storage: OpaqueTypeStorage<'db>,
150}
151
152impl<'db> InferCtxtInner<'db> {
153 fn new() -> InferCtxtInner<'db> {
154 InferCtxtInner {
155 undo_log: InferCtxtUndoLogs::default(),
156
157 type_variable_storage: Default::default(),
158 const_unification_storage: Default::default(),
159 int_unification_storage: Default::default(),
160 float_unification_storage: Default::default(),
161 region_constraint_storage: Some(Default::default()),
162 region_obligations: vec![],
163 opaque_type_storage: Default::default(),
164 }
165 }
166
167 #[inline]
168 pub fn region_obligations(&self) -> &[RegionObligation<'db>] {
169 &self.region_obligations
170 }
171
172 #[inline]
173 fn try_type_variables_probe_ref(
174 &self,
175 vid: TyVid,
176 ) -> Option<&type_variable::TypeVariableValue<'db>> {
177 self.type_variable_storage.eq_relations_ref().try_probe_value(vid)
180 }
181
182 #[inline]
183 fn type_variables(&mut self) -> type_variable::TypeVariableTable<'_, 'db> {
184 self.type_variable_storage.with_log(&mut self.undo_log)
185 }
186
187 #[inline]
188 pub(crate) fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'db> {
189 self.opaque_type_storage.with_log(&mut self.undo_log)
190 }
191
192 #[inline]
193 fn int_unification_table(&mut self) -> UnificationTable<'_, 'db, IntVid> {
194 self.int_unification_storage.with_log(&mut self.undo_log)
195 }
196
197 #[inline]
198 fn float_unification_table(&mut self) -> UnificationTable<'_, 'db, FloatVid> {
199 self.float_unification_storage.with_log(&mut self.undo_log)
200 }
201
202 #[inline]
203 fn const_unification_table(&mut self) -> UnificationTable<'_, 'db, ConstVidKey<'db>> {
204 self.const_unification_storage.with_log(&mut self.undo_log)
205 }
206
207 #[inline]
208 pub fn unwrap_region_constraints(&mut self) -> RegionConstraintCollector<'db, '_> {
209 self.region_constraint_storage
210 .as_mut()
211 .expect("region constraints already solved")
212 .with_log(&mut self.undo_log)
213 }
214}
215
216pub struct InferCtxt<'db> {
217 pub interner: DbInterner<'db>,
218
219 typing_mode: TypingMode<'db>,
222
223 pub inner: RefCell<InferCtxtInner<'db>>,
224
225 tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
233
234 universe: Cell<UniverseIndex>,
244}
245
246#[derive(Clone, Debug, PartialEq, Eq)]
248pub enum ValuePairs<'db> {
249 Regions(ExpectedFound<Region<'db>>),
250 Terms(ExpectedFound<Term<'db>>),
251 Aliases(ExpectedFound<AliasTerm<'db>>),
252 TraitRefs(ExpectedFound<TraitRef<'db>>),
253 PolySigs(ExpectedFound<PolyFnSig<'db>>),
254 ExistentialTraitRef(ExpectedFound<PolyExistentialTraitRef<'db>>),
255 ExistentialProjection(ExpectedFound<PolyExistentialProjection<'db>>),
256}
257
258impl<'db> ValuePairs<'db> {
259 pub fn ty(&self) -> Option<(Ty<'db>, Ty<'db>)> {
260 if let ValuePairs::Terms(ExpectedFound { expected, found }) = self
261 && let Some(expected) = expected.as_type()
262 && let Some(found) = found.as_type()
263 {
264 return Some((expected, found));
265 }
266 None
267 }
268}
269
270#[derive(Clone, Debug)]
275pub struct TypeTrace<'db> {
276 pub cause: ObligationCause,
277 pub values: ValuePairs<'db>,
278}
279
280#[derive(Clone, Copy, Debug)]
282pub enum BoundRegionConversionTime {
283 FnCall,
285
286 HigherRankedType,
288
289 AssocTypeProjection(SolverDefId),
291}
292
293#[derive(Copy, Clone, Debug)]
294pub struct FixupError {
295 unresolved: TyOrConstInferVar,
296}
297
298impl fmt::Display for FixupError {
299 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
300 use TyOrConstInferVar::*;
301
302 match self.unresolved {
303 TyInt(_) => write!(
304 f,
305 "cannot determine the type of this integer; \
306 add a suffix to specify the type explicitly"
307 ),
308 TyFloat(_) => write!(
309 f,
310 "cannot determine the type of this number; \
311 add a suffix to specify the type explicitly"
312 ),
313 Ty(_) => write!(f, "unconstrained type"),
314 Const(_) => write!(f, "unconstrained const value"),
315 }
316 }
317}
318
319#[derive(Clone, Debug)]
321pub struct RegionObligation<'db> {
322 pub sub_region: Region<'db>,
323 pub sup_type: Ty<'db>,
324}
325
326pub struct InferCtxtBuilder<'db> {
328 interner: DbInterner<'db>,
329}
330
331pub trait DbInternerInferExt<'db> {
332 fn infer_ctxt(self) -> InferCtxtBuilder<'db>;
333}
334
335impl<'db> DbInternerInferExt<'db> for DbInterner<'db> {
336 fn infer_ctxt(self) -> InferCtxtBuilder<'db> {
337 InferCtxtBuilder { interner: self }
338 }
339}
340
341impl<'db> InferCtxtBuilder<'db> {
342 pub fn build_with_canonical<T>(
350 mut self,
351 input: &CanonicalQueryInput<'db, T>,
352 ) -> (InferCtxt<'db>, T, CanonicalVarValues<'db>)
353 where
354 T: TypeFoldable<DbInterner<'db>>,
355 {
356 let infcx = self.build(input.typing_mode);
357 let (value, args) = infcx.instantiate_canonical(&input.canonical);
358 (infcx, value, args)
359 }
360
361 pub fn build(&mut self, typing_mode: TypingMode<'db>) -> InferCtxt<'db> {
362 let InferCtxtBuilder { interner } = *self;
363 InferCtxt {
364 interner,
365 typing_mode,
366 inner: RefCell::new(InferCtxtInner::new()),
367 tainted_by_errors: Cell::new(None),
368 universe: Cell::new(UniverseIndex::ROOT),
369 }
370 }
371}
372
373impl<'db> InferOk<'db, ()> {
374 pub fn into_obligations(self) -> PredicateObligations<'db> {
375 self.obligations
376 }
377}
378
379impl<'db> InferCtxt<'db> {
380 #[inline(always)]
381 pub fn typing_mode(&self) -> TypingMode<'db> {
382 self.typing_mode
383 }
384
385 #[inline(always)]
386 pub fn typing_mode_unchecked(&self) -> TypingMode<'db> {
387 self.typing_mode
388 }
389
390 pub fn unresolved_variables(&self) -> Vec<Ty<'db>> {
391 let mut inner = self.inner.borrow_mut();
392 let mut vars: Vec<Ty<'db>> = inner
393 .type_variables()
394 .unresolved_variables()
395 .into_iter()
396 .map(|t| Ty::new_var(self.interner, t))
397 .collect();
398 vars.extend(
399 (0..inner.int_unification_table().len())
400 .map(IntVid::from_usize)
401 .filter(|&vid| inner.int_unification_table().probe_value(vid).is_unknown())
402 .map(|v| Ty::new_int_var(self.interner, v)),
403 );
404 vars.extend(
405 (0..inner.float_unification_table().len())
406 .map(FloatVid::from_usize)
407 .filter(|&vid| inner.float_unification_table().probe_value(vid).is_unknown())
408 .map(|v| Ty::new_float_var(self.interner, v)),
409 );
410 vars
411 }
412
413 #[instrument(skip(self), level = "debug")]
414 pub fn sub_regions(&self, a: Region<'db>, b: Region<'db>) {
415 self.inner.borrow_mut().unwrap_region_constraints().make_subregion(a, b);
416 }
417
418 pub fn coerce_predicate(
434 &self,
435 cause: &ObligationCause,
436 param_env: ParamEnv<'db>,
437 predicate: PolyCoercePredicate<'db>,
438 ) -> Result<InferResult<'db, ()>, (TyVid, TyVid)> {
439 let subtype_predicate = predicate.map_bound(|p| SubtypePredicate {
440 a_is_expected: false, a: p.a,
442 b: p.b,
443 });
444 self.subtype_predicate(cause, param_env, subtype_predicate)
445 }
446
447 pub fn subtype_predicate(
448 &self,
449 cause: &ObligationCause,
450 param_env: ParamEnv<'db>,
451 predicate: PolySubtypePredicate<'db>,
452 ) -> Result<InferResult<'db, ()>, (TyVid, TyVid)> {
453 let r_a = self.shallow_resolve(predicate.skip_binder().a);
467 let r_b = self.shallow_resolve(predicate.skip_binder().b);
468 match (r_a.kind(), r_b.kind()) {
469 (TyKind::Infer(InferTy::TyVar(a_vid)), TyKind::Infer(InferTy::TyVar(b_vid))) => {
470 return Err((a_vid, b_vid));
471 }
472 _ => {}
473 }
474
475 self.enter_forall(predicate, |SubtypePredicate { a_is_expected, a, b }| {
476 if a_is_expected {
477 Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::Yes, a, b))
478 } else {
479 Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::Yes, b, a))
480 }
481 })
482 }
483
484 pub fn region_outlives_predicate(
485 &self,
486 cause: &traits::ObligationCause,
487 predicate: PolyRegionOutlivesPredicate<'db>,
488 ) {
489 self.enter_forall(predicate, |OutlivesPredicate(r_a, r_b)| {
490 self.sub_regions(r_b, r_a); })
492 }
493
494 pub fn num_ty_vars(&self) -> usize {
496 self.inner.borrow_mut().type_variables().num_vars()
497 }
498
499 pub fn next_ty_var(&self) -> Ty<'db> {
500 self.next_ty_var_with_origin(TypeVariableOrigin { param_def_id: None })
501 }
502
503 pub fn next_ty_var_with_origin(&self, origin: TypeVariableOrigin) -> Ty<'db> {
504 let vid = self.inner.borrow_mut().type_variables().new_var(self.universe(), origin);
505 Ty::new_var(self.interner, vid)
506 }
507
508 pub fn next_ty_var_id_in_universe(&self, universe: UniverseIndex) -> TyVid {
509 let origin = TypeVariableOrigin { param_def_id: None };
510 self.inner.borrow_mut().type_variables().new_var(universe, origin)
511 }
512
513 pub fn next_ty_var_in_universe(&self, universe: UniverseIndex) -> Ty<'db> {
514 let vid = self.next_ty_var_id_in_universe(universe);
515 Ty::new_var(self.interner, vid)
516 }
517
518 pub fn next_const_var(&self) -> Const<'db> {
519 self.next_const_var_with_origin(ConstVariableOrigin { param_def_id: None })
520 }
521
522 pub fn next_const_var_with_origin(&self, origin: ConstVariableOrigin) -> Const<'db> {
523 let vid = self
524 .inner
525 .borrow_mut()
526 .const_unification_table()
527 .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
528 .vid;
529 Const::new_var(self.interner, vid)
530 }
531
532 pub fn next_const_var_in_universe(&self, universe: UniverseIndex) -> Const<'db> {
533 let origin = ConstVariableOrigin { param_def_id: None };
534 let vid = self
535 .inner
536 .borrow_mut()
537 .const_unification_table()
538 .new_key(ConstVariableValue::Unknown { origin, universe })
539 .vid;
540 Const::new_var(self.interner, vid)
541 }
542
543 pub fn next_int_var(&self) -> Ty<'db> {
544 let next_int_var_id =
545 self.inner.borrow_mut().int_unification_table().new_key(IntVarValue::Unknown);
546 Ty::new_int_var(self.interner, next_int_var_id)
547 }
548
549 pub fn next_float_var(&self) -> Ty<'db> {
550 let next_float_var_id =
551 self.inner.borrow_mut().float_unification_table().new_key(FloatVarValue::Unknown);
552 Ty::new_float_var(self.interner, next_float_var_id)
553 }
554
555 pub fn next_region_var(&self) -> Region<'db> {
559 self.next_region_var_in_universe(self.universe())
560 }
561
562 pub fn next_region_var_in_universe(&self, universe: UniverseIndex) -> Region<'db> {
566 let region_var =
567 self.inner.borrow_mut().unwrap_region_constraints().new_region_var(universe);
568 Region::new_var(self.interner, region_var)
569 }
570
571 pub fn next_term_var_of_kind(&self, term: Term<'db>) -> Term<'db> {
572 match term.kind() {
573 TermKind::Ty(_) => self.next_ty_var().into(),
574 TermKind::Const(_) => self.next_const_var().into(),
575 }
576 }
577
578 pub fn universe_of_region(&self, r: Region<'db>) -> UniverseIndex {
584 self.inner.borrow_mut().unwrap_region_constraints().universe(r)
585 }
586
587 pub fn num_region_vars(&self) -> usize {
589 self.inner.borrow_mut().unwrap_region_constraints().num_region_vars()
590 }
591
592 #[instrument(skip(self), level = "debug")]
594 pub fn next_nll_region_var(&self) -> Region<'db> {
595 self.next_region_var()
596 }
597
598 #[instrument(skip(self), level = "debug")]
600 pub fn next_nll_region_var_in_universe(&self, universe: UniverseIndex) -> Region<'db> {
601 self.next_region_var_in_universe(universe)
602 }
603
604 fn var_for_def(&self, id: GenericParamId, name: &Symbol) -> GenericArg<'db> {
605 match id {
606 GenericParamId::LifetimeParamId(_) => {
607 self.next_region_var().into()
610 }
611 GenericParamId::TypeParamId(_) => {
612 let ty_var_id = self
621 .inner
622 .borrow_mut()
623 .type_variables()
624 .new_var(self.universe(), TypeVariableOrigin { param_def_id: None });
625
626 Ty::new_var(self.interner, ty_var_id).into()
627 }
628 GenericParamId::ConstParamId(_) => {
629 let origin = ConstVariableOrigin { param_def_id: None };
630 let const_var_id = self
631 .inner
632 .borrow_mut()
633 .const_unification_table()
634 .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
635 .vid;
636 Const::new_var(self.interner, const_var_id).into()
637 }
638 }
639 }
640
641 pub fn fresh_args_for_item(&self, def_id: SolverDefId) -> GenericArgs<'db> {
644 GenericArgs::for_item(self.interner, def_id, |name, index, kind, _| {
645 self.var_for_def(kind, name)
646 })
647 }
648
649 #[must_use = "this method does not have any side effects"]
655 pub fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
656 self.tainted_by_errors.get()
657 }
658
659 pub fn set_tainted_by_errors(&self, e: ErrorGuaranteed) {
662 debug!("set_tainted_by_errors(ErrorGuaranteed)");
663 self.tainted_by_errors.set(Some(e));
664 }
665
666 #[instrument(level = "debug", skip(self), ret)]
667 pub fn take_opaque_types(&self) -> Vec<(OpaqueTypeKey<'db>, OpaqueHiddenType<'db>)> {
668 self.inner.borrow_mut().opaque_type_storage.take_opaque_types().collect()
669 }
670
671 #[instrument(level = "debug", skip(self), ret)]
672 pub fn clone_opaque_types(&self) -> Vec<(OpaqueTypeKey<'db>, OpaqueHiddenType<'db>)> {
673 self.inner.borrow_mut().opaque_type_storage.iter_opaque_types().collect()
674 }
675
676 #[inline(always)]
677 pub fn can_define_opaque_ty(&self, id: impl Into<SolverDefId>) -> bool {
678 match self.typing_mode_unchecked() {
679 TypingMode::Analysis { defining_opaque_types_and_generators } => {
680 defining_opaque_types_and_generators.contains(&id.into())
681 }
682 TypingMode::Coherence | TypingMode::PostAnalysis => false,
683 TypingMode::Borrowck { defining_opaque_types } => unimplemented!(),
684 TypingMode::PostBorrowckAnalysis { defined_opaque_types } => unimplemented!(),
685 }
686 }
687
688 pub fn probe_ty_var(&self, vid: TyVid) -> Result<Ty<'db>, UniverseIndex> {
691 use self::type_variable::TypeVariableValue;
692
693 match self.inner.borrow_mut().type_variables().probe(vid) {
694 TypeVariableValue::Known { value } => Ok(value),
695 TypeVariableValue::Unknown { universe } => Err(universe),
696 }
697 }
698
699 pub fn shallow_resolve(&self, ty: Ty<'db>) -> Ty<'db> {
700 if let TyKind::Infer(v) = ty.kind() {
701 match v {
702 InferTy::TyVar(v) => {
703 let known = self.inner.borrow_mut().type_variables().probe(v).known();
716 known.map_or(ty, |t| self.shallow_resolve(t))
717 }
718
719 InferTy::IntVar(v) => {
720 match self.inner.borrow_mut().int_unification_table().probe_value(v) {
721 IntVarValue::IntType(ty) => Ty::new_int(self.interner, ty),
722 IntVarValue::UintType(ty) => Ty::new_uint(self.interner, ty),
723 IntVarValue::Unknown => ty,
724 }
725 }
726
727 InferTy::FloatVar(v) => {
728 match self.inner.borrow_mut().float_unification_table().probe_value(v) {
729 FloatVarValue::Known(ty) => Ty::new_float(self.interner, ty),
730 FloatVarValue::Unknown => ty,
731 }
732 }
733
734 InferTy::FreshTy(_) | InferTy::FreshIntTy(_) | InferTy::FreshFloatTy(_) => ty,
735 }
736 } else {
737 ty
738 }
739 }
740
741 pub fn shallow_resolve_const(&self, ct: Const<'db>) -> Const<'db> {
742 match ct.kind() {
743 ConstKind::Infer(infer_ct) => match infer_ct {
744 InferConst::Var(vid) => self
745 .inner
746 .borrow_mut()
747 .const_unification_table()
748 .probe_value(vid)
749 .known()
750 .unwrap_or(ct),
751 InferConst::Fresh(_) => ct,
752 },
753 ConstKind::Param(_)
754 | ConstKind::Bound(_, _)
755 | ConstKind::Placeholder(_)
756 | ConstKind::Unevaluated(_)
757 | ConstKind::Value(_)
758 | ConstKind::Error(_)
759 | ConstKind::Expr(_) => ct,
760 }
761 }
762
763 pub fn root_var(&self, var: TyVid) -> TyVid {
764 self.inner.borrow_mut().type_variables().root_var(var)
765 }
766
767 pub fn root_const_var(&self, var: ConstVid) -> ConstVid {
768 self.inner.borrow_mut().const_unification_table().find(var).vid
769 }
770
771 pub fn opportunistic_resolve_int_var(&self, vid: IntVid) -> Ty<'db> {
774 let mut inner = self.inner.borrow_mut();
775 let value = inner.int_unification_table().probe_value(vid);
776 match value {
777 IntVarValue::IntType(ty) => Ty::new_int(self.interner, ty),
778 IntVarValue::UintType(ty) => Ty::new_uint(self.interner, ty),
779 IntVarValue::Unknown => {
780 Ty::new_int_var(self.interner, inner.int_unification_table().find(vid))
781 }
782 }
783 }
784
785 pub fn opportunistic_resolve_float_var(&self, vid: FloatVid) -> Ty<'db> {
788 let mut inner = self.inner.borrow_mut();
789 let value = inner.float_unification_table().probe_value(vid);
790 match value {
791 FloatVarValue::Known(ty) => Ty::new_float(self.interner, ty),
792 FloatVarValue::Unknown => {
793 Ty::new_float_var(self.interner, inner.float_unification_table().find(vid))
794 }
795 }
796 }
797
798 pub fn resolve_vars_if_possible<T>(&self, value: T) -> T
805 where
806 T: TypeFoldable<DbInterner<'db>>,
807 {
808 if let Err(guar) = value.error_reported() {
809 self.set_tainted_by_errors(guar);
810 }
811 if !value.has_non_region_infer() {
812 return value;
813 }
814 let mut r = resolve::OpportunisticVarResolver::new(self);
815 value.fold_with(&mut r)
816 }
817
818 pub fn probe_const_var(&self, vid: ConstVid) -> Result<Const<'db>, UniverseIndex> {
819 match self.inner.borrow_mut().const_unification_table().probe_value(vid) {
820 ConstVariableValue::Known { value } => Ok(value),
821 ConstVariableValue::Unknown { origin: _, universe } => Err(universe),
822 }
823 }
824
825 pub fn instantiate_binder_with_fresh_vars<T>(
833 &self,
834 lbrct: BoundRegionConversionTime,
835 value: Binder<'db, T>,
836 ) -> T
837 where
838 T: TypeFoldable<DbInterner<'db>> + Clone,
839 {
840 if let Some(inner) = value.clone().no_bound_vars() {
841 return inner;
842 }
843
844 let bound_vars = value.clone().bound_vars();
845 let mut args = Vec::with_capacity(bound_vars.len());
846
847 for bound_var_kind in bound_vars {
848 let arg: GenericArg<'db> = match bound_var_kind {
849 BoundVarKind::Ty(_) => self.next_ty_var().into(),
850 BoundVarKind::Region(br) => self.next_region_var().into(),
851 BoundVarKind::Const => self.next_const_var().into(),
852 };
853 args.push(arg);
854 }
855
856 struct ToFreshVars<'db> {
857 args: Vec<GenericArg<'db>>,
858 }
859
860 impl<'db> BoundVarReplacerDelegate<'db> for ToFreshVars<'db> {
861 fn replace_region(&mut self, br: BoundRegion) -> Region<'db> {
862 self.args[br.var.index()].expect_region()
863 }
864 fn replace_ty(&mut self, bt: BoundTy) -> Ty<'db> {
865 self.args[bt.var.index()].expect_ty()
866 }
867 fn replace_const(&mut self, bv: BoundVar) -> Const<'db> {
868 self.args[bv.index()].expect_const()
869 }
870 }
871 let delegate = ToFreshVars { args };
872 self.interner.replace_bound_vars_uncached(value, delegate)
873 }
874
875 pub fn closure_kind(&self, closure_ty: Ty<'db>) -> Option<ClosureKind> {
879 let unresolved_kind_ty = match closure_ty.kind() {
880 TyKind::Closure(_, args) => args.as_closure().kind_ty(),
881 TyKind::CoroutineClosure(_, args) => args.as_coroutine_closure().kind_ty(),
882 _ => panic!("unexpected type {closure_ty:?}"),
883 };
884 let closure_kind_ty = self.shallow_resolve(unresolved_kind_ty);
885 closure_kind_ty.to_opt_closure_kind()
886 }
887
888 pub fn universe(&self) -> UniverseIndex {
889 self.universe.get()
890 }
891
892 pub fn create_next_universe(&self) -> UniverseIndex {
895 let u = self.universe.get().next_universe();
896 debug!("create_next_universe {u:?}");
897 self.universe.set(u);
898 u
899 }
900
901 #[inline]
904 pub fn is_ty_infer_var_definitely_unchanged<'a>(
905 &'a self,
906 ) -> (impl Fn(TyOrConstInferVar) -> bool + Captures<'db> + 'a) {
907 let inner = self.inner.try_borrow();
909
910 move |infer_var: TyOrConstInferVar| match (infer_var, &inner) {
911 (TyOrConstInferVar::Ty(ty_var), Ok(inner)) => {
912 use self::type_variable::TypeVariableValue;
913
914 matches!(
915 inner.try_type_variables_probe_ref(ty_var),
916 Some(TypeVariableValue::Unknown { .. })
917 )
918 }
919 _ => false,
920 }
921 }
922
923 #[inline(always)]
933 pub fn ty_or_const_infer_var_changed(&self, infer_var: TyOrConstInferVar) -> bool {
934 match infer_var {
935 TyOrConstInferVar::Ty(v) => {
936 use self::type_variable::TypeVariableValue;
937
938 match self.inner.borrow_mut().type_variables().inlined_probe(v) {
941 TypeVariableValue::Unknown { .. } => false,
942 TypeVariableValue::Known { .. } => true,
943 }
944 }
945
946 TyOrConstInferVar::TyInt(v) => {
947 self.inner.borrow_mut().int_unification_table().inlined_probe_value(v).is_known()
951 }
952
953 TyOrConstInferVar::TyFloat(v) => {
954 self.inner.borrow_mut().float_unification_table().probe_value(v).is_known()
959 }
960
961 TyOrConstInferVar::Const(v) => {
962 match self.inner.borrow_mut().const_unification_table().probe_value(v) {
967 ConstVariableValue::Unknown { .. } => false,
968 ConstVariableValue::Known { .. } => true,
969 }
970 }
971 }
972 }
973}
974
975#[derive(Copy, Clone, Debug)]
978pub enum TyOrConstInferVar {
979 Ty(TyVid),
981 TyInt(IntVid),
983 TyFloat(FloatVid),
985
986 Const(ConstVid),
988}
989
990impl TyOrConstInferVar {
991 pub fn maybe_from_generic_arg<'db>(arg: GenericArg<'db>) -> Option<Self> {
995 match arg.kind() {
996 GenericArgKind::Type(ty) => Self::maybe_from_ty(ty),
997 GenericArgKind::Const(ct) => Self::maybe_from_const(ct),
998 GenericArgKind::Lifetime(_) => None,
999 }
1000 }
1001
1002 fn maybe_from_ty<'db>(ty: Ty<'db>) -> Option<Self> {
1005 match ty.kind() {
1006 TyKind::Infer(InferTy::TyVar(v)) => Some(TyOrConstInferVar::Ty(v)),
1007 TyKind::Infer(InferTy::IntVar(v)) => Some(TyOrConstInferVar::TyInt(v)),
1008 TyKind::Infer(InferTy::FloatVar(v)) => Some(TyOrConstInferVar::TyFloat(v)),
1009 _ => None,
1010 }
1011 }
1012
1013 fn maybe_from_const<'db>(ct: Const<'db>) -> Option<Self> {
1016 match ct.kind() {
1017 ConstKind::Infer(InferConst::Var(v)) => Some(TyOrConstInferVar::Const(v)),
1018 _ => None,
1019 }
1020 }
1021}
1022
1023impl<'db> TypeTrace<'db> {
1024 pub fn types(cause: &ObligationCause, a: Ty<'db>, b: Ty<'db>) -> TypeTrace<'db> {
1025 TypeTrace {
1026 cause: cause.clone(),
1027 values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
1028 }
1029 }
1030
1031 pub fn trait_refs(
1032 cause: &ObligationCause,
1033 a: TraitRef<'db>,
1034 b: TraitRef<'db>,
1035 ) -> TypeTrace<'db> {
1036 TypeTrace { cause: cause.clone(), values: ValuePairs::TraitRefs(ExpectedFound::new(a, b)) }
1037 }
1038
1039 pub fn consts(cause: &ObligationCause, a: Const<'db>, b: Const<'db>) -> TypeTrace<'db> {
1040 TypeTrace {
1041 cause: cause.clone(),
1042 values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
1043 }
1044 }
1045}
1046
1047#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1054pub struct MemberConstraint<'db> {
1055 pub key: OpaqueTypeKey<'db>,
1058
1059 pub hidden_ty: Ty<'db>,
1061
1062 pub member_region: Region<'db>,
1064
1065 pub choice_regions: Arc<Vec<Region<'db>>>,
1067}