1use std::cell::{Cell, RefCell};
2use std::fmt;
3
4pub use BoundRegionConversionTime::*;
5pub use RegionVariableOrigin::*;
6pub use SubregionOrigin::*;
7pub use at::DefineOpaqueTypes;
8use free_regions::RegionRelations;
9pub use freshen::TypeFreshener;
10use lexical_region_resolve::LexicalRegionResolutions;
11pub use lexical_region_resolve::RegionResolutionError;
12use opaque_types::OpaqueTypeStorage;
13use region_constraints::{
14 GenericKind, RegionConstraintCollector, RegionConstraintStorage, VarInfos, VerifyBound,
15};
16pub use relate::StructurallyRelateAliases;
17pub use relate::combine::PredicateEmittingRelation;
18use rustc_data_structures::captures::Captures;
19use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
20use rustc_data_structures::undo_log::{Rollback, UndoLogs};
21use rustc_data_structures::unify as ut;
22use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed};
23use rustc_hir as hir;
24use rustc_hir::def_id::{DefId, LocalDefId};
25use rustc_macros::extension;
26pub use rustc_macros::{TypeFoldable, TypeVisitable};
27use rustc_middle::bug;
28use rustc_middle::infer::canonical::{CanonicalQueryInput, CanonicalVarValues};
29use rustc_middle::mir::ConstraintCategory;
30use rustc_middle::traits::select;
31pub use rustc_middle::ty::IntVarValue;
32use rustc_middle::ty::error::{ExpectedFound, TypeError};
33use rustc_middle::ty::fold::{
34 BoundVarReplacerDelegate, TypeFoldable, TypeFolder, TypeSuperFoldable, fold_regions,
35};
36use rustc_middle::ty::visit::TypeVisitableExt;
37use rustc_middle::ty::{
38 self, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef,
39 GenericParamDefKind, InferConst, IntVid, PseudoCanonicalInput, Ty, TyCtxt, TyVid,
40 TypeVisitable, TypingEnv, TypingMode,
41};
42use rustc_span::{Span, Symbol};
43use snapshot::undo_log::InferCtxtUndoLogs;
44use tracing::{debug, instrument};
45use type_variable::TypeVariableOrigin;
46
47use crate::infer::region_constraints::UndoLog;
48use crate::infer::unify_key::{ConstVariableOrigin, ConstVariableValue, ConstVidKey};
49use crate::traits::{
50 self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine,
51};
52
53pub mod at;
54pub mod canonical;
55mod context;
56mod free_regions;
57mod freshen;
58mod lexical_region_resolve;
59mod opaque_types;
60pub mod outlives;
61mod projection;
62pub mod region_constraints;
63pub mod relate;
64pub mod resolve;
65pub(crate) mod snapshot;
66mod type_variable;
67mod unify_key;
68
69#[must_use]
77#[derive(Debug)]
78pub struct InferOk<'tcx, T> {
79 pub value: T,
80 pub obligations: PredicateObligations<'tcx>,
81}
82pub type InferResult<'tcx, T> = Result<InferOk<'tcx, T>, TypeError<'tcx>>;
83
84pub(crate) type FixupResult<T> = Result<T, FixupError>; pub(crate) type UnificationTable<'a, 'tcx, T> = ut::UnificationTable<
87 ut::InPlace<T, &'a mut ut::UnificationStorage<T>, &'a mut InferCtxtUndoLogs<'tcx>>,
88>;
89
90#[derive(Clone)]
95pub struct InferCtxtInner<'tcx> {
96 undo_log: InferCtxtUndoLogs<'tcx>,
97
98 projection_cache: traits::ProjectionCacheStorage<'tcx>,
102
103 type_variable_storage: type_variable::TypeVariableStorage<'tcx>,
107
108 const_unification_storage: ut::UnificationTableStorage<ConstVidKey<'tcx>>,
110
111 int_unification_storage: ut::UnificationTableStorage<ty::IntVid>,
113
114 float_unification_storage: ut::UnificationTableStorage<ty::FloatVid>,
116
117 region_constraint_storage: Option<RegionConstraintStorage<'tcx>>,
124
125 region_obligations: Vec<RegionObligation<'tcx>>,
158
159 opaque_type_storage: OpaqueTypeStorage<'tcx>,
161}
162
163impl<'tcx> InferCtxtInner<'tcx> {
164 fn new() -> InferCtxtInner<'tcx> {
165 InferCtxtInner {
166 undo_log: InferCtxtUndoLogs::default(),
167
168 projection_cache: Default::default(),
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 opaque_type_storage: Default::default(),
176 }
177 }
178
179 #[inline]
180 pub fn region_obligations(&self) -> &[RegionObligation<'tcx>] {
181 &self.region_obligations
182 }
183
184 #[inline]
185 pub fn projection_cache(&mut self) -> traits::ProjectionCache<'_, 'tcx> {
186 self.projection_cache.with_log(&mut self.undo_log)
187 }
188
189 #[inline]
190 fn try_type_variables_probe_ref(
191 &self,
192 vid: ty::TyVid,
193 ) -> Option<&type_variable::TypeVariableValue<'tcx>> {
194 self.type_variable_storage.eq_relations_ref().try_probe_value(vid)
197 }
198
199 #[inline]
200 fn type_variables(&mut self) -> type_variable::TypeVariableTable<'_, 'tcx> {
201 self.type_variable_storage.with_log(&mut self.undo_log)
202 }
203
204 #[inline]
205 fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> {
206 self.opaque_type_storage.with_log(&mut self.undo_log)
207 }
208
209 #[inline]
210 fn int_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::IntVid> {
211 self.int_unification_storage.with_log(&mut self.undo_log)
212 }
213
214 #[inline]
215 fn float_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::FloatVid> {
216 self.float_unification_storage.with_log(&mut self.undo_log)
217 }
218
219 #[inline]
220 fn const_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ConstVidKey<'tcx>> {
221 self.const_unification_storage.with_log(&mut self.undo_log)
222 }
223
224 #[inline]
225 pub fn unwrap_region_constraints(&mut self) -> RegionConstraintCollector<'_, 'tcx> {
226 self.region_constraint_storage
227 .as_mut()
228 .expect("region constraints already solved")
229 .with_log(&mut self.undo_log)
230 }
231
232 pub fn iter_opaque_types(
236 &self,
237 ) -> impl Iterator<Item = (ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>)> + '_ {
238 self.opaque_type_storage.opaque_types.iter().map(|(&k, &v)| (k, v))
239 }
240}
241
242pub struct InferCtxt<'tcx> {
243 pub tcx: TyCtxt<'tcx>,
244
245 typing_mode: TypingMode<'tcx>,
248
249 pub considering_regions: bool,
253
254 skip_leak_check: bool,
259
260 pub inner: RefCell<InferCtxtInner<'tcx>>,
261
262 lexical_region_resolutions: RefCell<Option<LexicalRegionResolutions<'tcx>>>,
264
265 pub selection_cache: select::SelectionCache<'tcx, ty::ParamEnv<'tcx>>,
268
269 pub evaluation_cache: select::EvaluationCache<'tcx, ty::ParamEnv<'tcx>>,
272
273 pub reported_trait_errors:
276 RefCell<FxIndexMap<Span, (Vec<ty::Predicate<'tcx>>, ErrorGuaranteed)>>,
277
278 pub reported_signature_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>,
279
280 tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
288
289 universe: Cell<ty::UniverseIndex>,
299
300 next_trait_solver: bool,
301
302 pub obligation_inspector: Cell<Option<ObligationInspector<'tcx>>>,
303}
304
305#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)]
307pub enum ValuePairs<'tcx> {
308 Regions(ExpectedFound<ty::Region<'tcx>>),
309 Terms(ExpectedFound<ty::Term<'tcx>>),
310 Aliases(ExpectedFound<ty::AliasTerm<'tcx>>),
311 TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>),
312 PolySigs(ExpectedFound<ty::PolyFnSig<'tcx>>),
313 ExistentialTraitRef(ExpectedFound<ty::PolyExistentialTraitRef<'tcx>>),
314 ExistentialProjection(ExpectedFound<ty::PolyExistentialProjection<'tcx>>),
315}
316
317impl<'tcx> ValuePairs<'tcx> {
318 pub fn ty(&self) -> Option<(Ty<'tcx>, Ty<'tcx>)> {
319 if let ValuePairs::Terms(ExpectedFound { expected, found }) = self
320 && let Some(expected) = expected.as_type()
321 && let Some(found) = found.as_type()
322 {
323 Some((expected, found))
324 } else {
325 None
326 }
327 }
328}
329
330#[derive(Clone, Debug)]
335pub struct TypeTrace<'tcx> {
336 pub cause: ObligationCause<'tcx>,
337 pub values: ValuePairs<'tcx>,
338}
339
340#[derive(Clone, Debug)]
344pub enum SubregionOrigin<'tcx> {
345 Subtype(Box<TypeTrace<'tcx>>),
347
348 RelateObjectBound(Span),
351
352 RelateParamBound(Span, Ty<'tcx>, Option<Span>),
355
356 RelateRegionParamBound(Span, Option<Ty<'tcx>>),
359
360 Reborrow(Span),
362
363 ReferenceOutlivesReferent(Ty<'tcx>, Span),
365
366 CompareImplItemObligation {
369 span: Span,
370 impl_item_def_id: LocalDefId,
371 trait_item_def_id: DefId,
372 },
373
374 CheckAssociatedTypeBounds {
376 parent: Box<SubregionOrigin<'tcx>>,
377 impl_item_def_id: LocalDefId,
378 trait_item_def_id: DefId,
379 },
380
381 AscribeUserTypeProvePredicate(Span),
382}
383
384#[cfg(target_pointer_width = "64")]
386rustc_data_structures::static_assert_size!(SubregionOrigin<'_>, 32);
387
388impl<'tcx> SubregionOrigin<'tcx> {
389 pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> {
390 match self {
391 Self::Subtype(type_trace) => type_trace.cause.to_constraint_category(),
392 Self::AscribeUserTypeProvePredicate(span) => ConstraintCategory::Predicate(*span),
393 _ => ConstraintCategory::BoringNoLocation,
394 }
395 }
396}
397
398#[derive(Clone, Copy, Debug)]
400pub enum BoundRegionConversionTime {
401 FnCall,
403
404 HigherRankedType,
406
407 AssocTypeProjection(DefId),
409}
410
411#[derive(Copy, Clone, Debug)]
415pub enum RegionVariableOrigin {
416 MiscVariable(Span),
420
421 PatternRegion(Span),
423
424 BorrowRegion(Span),
426
427 Autoref(Span),
429
430 Coercion(Span),
432
433 RegionParameterDefinition(Span, Symbol),
438
439 BoundRegion(Span, ty::BoundRegionKind, BoundRegionConversionTime),
442
443 UpvarRegion(ty::UpvarId, Span),
444
445 Nll(NllRegionVariableOrigin),
448}
449
450#[derive(Copy, Clone, Debug)]
451pub enum NllRegionVariableOrigin {
452 FreeRegion,
456
457 Placeholder(ty::PlaceholderRegion),
460
461 Existential {
462 from_forall: bool,
473 },
474}
475
476#[derive(Copy, Clone, Debug)]
477pub struct FixupError {
478 unresolved: TyOrConstInferVar,
479}
480
481impl fmt::Display for FixupError {
482 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
483 use TyOrConstInferVar::*;
484
485 match self.unresolved {
486 TyInt(_) => write!(
487 f,
488 "cannot determine the type of this integer; \
489 add a suffix to specify the type explicitly"
490 ),
491 TyFloat(_) => write!(
492 f,
493 "cannot determine the type of this number; \
494 add a suffix to specify the type explicitly"
495 ),
496 Ty(_) => write!(f, "unconstrained type"),
497 Const(_) => write!(f, "unconstrained const value"),
498 }
499 }
500}
501
502#[derive(Clone, Debug)]
504pub struct RegionObligation<'tcx> {
505 pub sub_region: ty::Region<'tcx>,
506 pub sup_type: Ty<'tcx>,
507 pub origin: SubregionOrigin<'tcx>,
508}
509
510pub struct InferCtxtBuilder<'tcx> {
512 tcx: TyCtxt<'tcx>,
513 considering_regions: bool,
514 skip_leak_check: bool,
515 next_trait_solver: bool,
518}
519
520#[extension(pub trait TyCtxtInferExt<'tcx>)]
521impl<'tcx> TyCtxt<'tcx> {
522 fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> {
523 InferCtxtBuilder {
524 tcx: self,
525 considering_regions: true,
526 skip_leak_check: false,
527 next_trait_solver: self.next_trait_solver_globally(),
528 }
529 }
530}
531
532impl<'tcx> InferCtxtBuilder<'tcx> {
533 pub fn with_next_trait_solver(mut self, next_trait_solver: bool) -> Self {
534 self.next_trait_solver = next_trait_solver;
535 self
536 }
537
538 pub fn ignoring_regions(mut self) -> Self {
539 self.considering_regions = false;
540 self
541 }
542
543 pub fn skip_leak_check(mut self, skip_leak_check: bool) -> Self {
544 self.skip_leak_check = skip_leak_check;
545 self
546 }
547
548 pub fn build_with_canonical<T>(
556 mut self,
557 span: Span,
558 input: &CanonicalQueryInput<'tcx, T>,
559 ) -> (InferCtxt<'tcx>, T, CanonicalVarValues<'tcx>)
560 where
561 T: TypeFoldable<TyCtxt<'tcx>>,
562 {
563 let infcx = self.build(input.typing_mode);
564 let (value, args) = infcx.instantiate_canonical(span, &input.canonical);
565 (infcx, value, args)
566 }
567
568 pub fn build_with_typing_env(
569 mut self,
570 TypingEnv { typing_mode, param_env }: TypingEnv<'tcx>,
571 ) -> (InferCtxt<'tcx>, ty::ParamEnv<'tcx>) {
572 (self.build(typing_mode), param_env)
573 }
574
575 pub fn build(&mut self, typing_mode: TypingMode<'tcx>) -> InferCtxt<'tcx> {
576 let InferCtxtBuilder { tcx, considering_regions, skip_leak_check, next_trait_solver } =
577 *self;
578 InferCtxt {
579 tcx,
580 typing_mode,
581 considering_regions,
582 skip_leak_check,
583 inner: RefCell::new(InferCtxtInner::new()),
584 lexical_region_resolutions: RefCell::new(None),
585 selection_cache: Default::default(),
586 evaluation_cache: Default::default(),
587 reported_trait_errors: Default::default(),
588 reported_signature_mismatch: Default::default(),
589 tainted_by_errors: Cell::new(None),
590 universe: Cell::new(ty::UniverseIndex::ROOT),
591 next_trait_solver,
592 obligation_inspector: Cell::new(None),
593 }
594 }
595}
596
597impl<'tcx, T> InferOk<'tcx, T> {
598 pub fn into_value_registering_obligations<E: 'tcx>(
600 self,
601 infcx: &InferCtxt<'tcx>,
602 fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
603 ) -> T {
604 let InferOk { value, obligations } = self;
605 fulfill_cx.register_predicate_obligations(infcx, obligations);
606 value
607 }
608}
609
610impl<'tcx> InferOk<'tcx, ()> {
611 pub fn into_obligations(self) -> PredicateObligations<'tcx> {
612 self.obligations
613 }
614}
615
616impl<'tcx> InferCtxt<'tcx> {
617 pub fn dcx(&self) -> DiagCtxtHandle<'_> {
618 self.tcx.dcx().taintable_handle(&self.tainted_by_errors)
619 }
620
621 pub fn next_trait_solver(&self) -> bool {
622 self.next_trait_solver
623 }
624
625 #[inline(always)]
626 pub fn typing_mode(&self) -> TypingMode<'tcx> {
627 self.typing_mode
628 }
629
630 pub fn freshen<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
631 t.fold_with(&mut self.freshener())
632 }
633
634 pub fn type_var_origin(&self, vid: TyVid) -> TypeVariableOrigin {
638 self.inner.borrow_mut().type_variables().var_origin(vid)
639 }
640
641 pub fn const_var_origin(&self, vid: ConstVid) -> Option<ConstVariableOrigin> {
645 match self.inner.borrow_mut().const_unification_table().probe_value(vid) {
646 ConstVariableValue::Known { .. } => None,
647 ConstVariableValue::Unknown { origin, .. } => Some(origin),
648 }
649 }
650
651 pub fn freshener<'b>(&'b self) -> TypeFreshener<'b, 'tcx> {
652 freshen::TypeFreshener::new(self)
653 }
654
655 pub fn unresolved_variables(&self) -> Vec<Ty<'tcx>> {
656 let mut inner = self.inner.borrow_mut();
657 let mut vars: Vec<Ty<'_>> = inner
658 .type_variables()
659 .unresolved_variables()
660 .into_iter()
661 .map(|t| Ty::new_var(self.tcx, t))
662 .collect();
663 vars.extend(
664 (0..inner.int_unification_table().len())
665 .map(|i| ty::IntVid::from_usize(i))
666 .filter(|&vid| inner.int_unification_table().probe_value(vid).is_unknown())
667 .map(|v| Ty::new_int_var(self.tcx, v)),
668 );
669 vars.extend(
670 (0..inner.float_unification_table().len())
671 .map(|i| ty::FloatVid::from_usize(i))
672 .filter(|&vid| inner.float_unification_table().probe_value(vid).is_unknown())
673 .map(|v| Ty::new_float_var(self.tcx, v)),
674 );
675 vars
676 }
677
678 #[instrument(skip(self), level = "debug")]
679 pub fn sub_regions(
680 &self,
681 origin: SubregionOrigin<'tcx>,
682 a: ty::Region<'tcx>,
683 b: ty::Region<'tcx>,
684 ) {
685 self.inner.borrow_mut().unwrap_region_constraints().make_subregion(origin, a, b);
686 }
687
688 pub fn coerce_predicate(
704 &self,
705 cause: &ObligationCause<'tcx>,
706 param_env: ty::ParamEnv<'tcx>,
707 predicate: ty::PolyCoercePredicate<'tcx>,
708 ) -> Result<InferResult<'tcx, ()>, (TyVid, TyVid)> {
709 let subtype_predicate = predicate.map_bound(|p| ty::SubtypePredicate {
710 a_is_expected: false, a: p.a,
712 b: p.b,
713 });
714 self.subtype_predicate(cause, param_env, subtype_predicate)
715 }
716
717 pub fn subtype_predicate(
718 &self,
719 cause: &ObligationCause<'tcx>,
720 param_env: ty::ParamEnv<'tcx>,
721 predicate: ty::PolySubtypePredicate<'tcx>,
722 ) -> Result<InferResult<'tcx, ()>, (TyVid, TyVid)> {
723 let r_a = self.shallow_resolve(predicate.skip_binder().a);
737 let r_b = self.shallow_resolve(predicate.skip_binder().b);
738 match (r_a.kind(), r_b.kind()) {
739 (&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
740 return Err((a_vid, b_vid));
741 }
742 _ => {}
743 }
744
745 self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| {
746 if a_is_expected {
747 Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::Yes, a, b))
748 } else {
749 Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::Yes, b, a))
750 }
751 })
752 }
753
754 pub fn region_outlives_predicate(
755 &self,
756 cause: &traits::ObligationCause<'tcx>,
757 predicate: ty::PolyRegionOutlivesPredicate<'tcx>,
758 ) {
759 self.enter_forall(predicate, |ty::OutlivesPredicate(r_a, r_b)| {
760 let origin = SubregionOrigin::from_obligation_cause(cause, || {
761 RelateRegionParamBound(cause.span, None)
762 });
763 self.sub_regions(origin, r_b, r_a); })
765 }
766
767 pub fn num_ty_vars(&self) -> usize {
769 self.inner.borrow_mut().type_variables().num_vars()
770 }
771
772 pub fn next_ty_var(&self, span: Span) -> Ty<'tcx> {
773 self.next_ty_var_with_origin(TypeVariableOrigin { span, param_def_id: None })
774 }
775
776 pub fn next_ty_var_with_origin(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
777 let vid = self.inner.borrow_mut().type_variables().new_var(self.universe(), origin);
778 Ty::new_var(self.tcx, vid)
779 }
780
781 pub fn next_ty_var_id_in_universe(&self, span: Span, universe: ty::UniverseIndex) -> TyVid {
782 let origin = TypeVariableOrigin { span, param_def_id: None };
783 self.inner.borrow_mut().type_variables().new_var(universe, origin)
784 }
785
786 pub fn next_ty_var_in_universe(&self, span: Span, universe: ty::UniverseIndex) -> Ty<'tcx> {
787 let vid = self.next_ty_var_id_in_universe(span, universe);
788 Ty::new_var(self.tcx, vid)
789 }
790
791 pub fn next_const_var(&self, span: Span) -> ty::Const<'tcx> {
792 self.next_const_var_with_origin(ConstVariableOrigin { span, param_def_id: None })
793 }
794
795 pub fn next_const_var_with_origin(&self, origin: ConstVariableOrigin) -> ty::Const<'tcx> {
796 let vid = self
797 .inner
798 .borrow_mut()
799 .const_unification_table()
800 .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
801 .vid;
802 ty::Const::new_var(self.tcx, vid)
803 }
804
805 pub fn next_const_var_in_universe(
806 &self,
807 span: Span,
808 universe: ty::UniverseIndex,
809 ) -> ty::Const<'tcx> {
810 let origin = ConstVariableOrigin { span, param_def_id: None };
811 let vid = self
812 .inner
813 .borrow_mut()
814 .const_unification_table()
815 .new_key(ConstVariableValue::Unknown { origin, universe })
816 .vid;
817 ty::Const::new_var(self.tcx, vid)
818 }
819
820 pub fn next_int_var(&self) -> Ty<'tcx> {
821 let next_int_var_id =
822 self.inner.borrow_mut().int_unification_table().new_key(ty::IntVarValue::Unknown);
823 Ty::new_int_var(self.tcx, next_int_var_id)
824 }
825
826 pub fn next_float_var(&self) -> Ty<'tcx> {
827 let next_float_var_id =
828 self.inner.borrow_mut().float_unification_table().new_key(ty::FloatVarValue::Unknown);
829 Ty::new_float_var(self.tcx, next_float_var_id)
830 }
831
832 pub fn next_region_var(&self, origin: RegionVariableOrigin) -> ty::Region<'tcx> {
836 self.next_region_var_in_universe(origin, self.universe())
837 }
838
839 pub fn next_region_var_in_universe(
843 &self,
844 origin: RegionVariableOrigin,
845 universe: ty::UniverseIndex,
846 ) -> ty::Region<'tcx> {
847 let region_var =
848 self.inner.borrow_mut().unwrap_region_constraints().new_region_var(universe, origin);
849 ty::Region::new_var(self.tcx, region_var)
850 }
851
852 pub fn universe_of_region(&self, r: ty::Region<'tcx>) -> ty::UniverseIndex {
858 self.inner.borrow_mut().unwrap_region_constraints().universe(r)
859 }
860
861 pub fn num_region_vars(&self) -> usize {
863 self.inner.borrow_mut().unwrap_region_constraints().num_region_vars()
864 }
865
866 #[instrument(skip(self), level = "debug")]
868 pub fn next_nll_region_var(&self, origin: NllRegionVariableOrigin) -> ty::Region<'tcx> {
869 self.next_region_var(RegionVariableOrigin::Nll(origin))
870 }
871
872 #[instrument(skip(self), level = "debug")]
874 pub fn next_nll_region_var_in_universe(
875 &self,
876 origin: NllRegionVariableOrigin,
877 universe: ty::UniverseIndex,
878 ) -> ty::Region<'tcx> {
879 self.next_region_var_in_universe(RegionVariableOrigin::Nll(origin), universe)
880 }
881
882 pub fn var_for_def(&self, span: Span, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
883 match param.kind {
884 GenericParamDefKind::Lifetime => {
885 self.next_region_var(RegionParameterDefinition(span, param.name)).into()
888 }
889 GenericParamDefKind::Type { .. } => {
890 let ty_var_id = self.inner.borrow_mut().type_variables().new_var(
899 self.universe(),
900 TypeVariableOrigin { param_def_id: Some(param.def_id), span },
901 );
902
903 Ty::new_var(self.tcx, ty_var_id).into()
904 }
905 GenericParamDefKind::Const { .. } => {
906 let origin = ConstVariableOrigin { param_def_id: Some(param.def_id), span };
907 let const_var_id = self
908 .inner
909 .borrow_mut()
910 .const_unification_table()
911 .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
912 .vid;
913 ty::Const::new_var(self.tcx, const_var_id).into()
914 }
915 }
916 }
917
918 pub fn fresh_args_for_item(&self, span: Span, def_id: DefId) -> GenericArgsRef<'tcx> {
921 GenericArgs::for_item(self.tcx, def_id, |param, _| self.var_for_def(span, param))
922 }
923
924 #[must_use = "this method does not have any side effects"]
930 pub fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
931 self.tainted_by_errors.get()
932 }
933
934 pub fn set_tainted_by_errors(&self, e: ErrorGuaranteed) {
937 debug!("set_tainted_by_errors(ErrorGuaranteed)");
938 self.tainted_by_errors.set(Some(e));
939 }
940
941 pub fn region_var_origin(&self, vid: ty::RegionVid) -> RegionVariableOrigin {
942 let mut inner = self.inner.borrow_mut();
943 let inner = &mut *inner;
944 inner.unwrap_region_constraints().var_origin(vid)
945 }
946
947 pub fn get_region_var_infos(&self) -> VarInfos {
950 let inner = self.inner.borrow();
951 assert!(!UndoLogs::<UndoLog<'_>>::in_snapshot(&inner.undo_log));
952 let storage = inner.region_constraint_storage.as_ref().expect("regions already resolved");
953 assert!(storage.data.is_empty());
954 storage.var_infos.clone()
958 }
959
960 #[instrument(level = "debug", skip(self), ret)]
961 pub fn take_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> {
962 std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
963 }
964
965 #[instrument(level = "debug", skip(self), ret)]
966 pub fn clone_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> {
967 self.inner.borrow().opaque_type_storage.opaque_types.clone()
968 }
969
970 #[inline(always)]
971 pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
972 debug_assert!(!self.next_trait_solver());
973 match self.typing_mode() {
974 TypingMode::Analysis { defining_opaque_types } => {
975 id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
976 }
977 TypingMode::Coherence
981 | TypingMode::PostBorrowckAnalysis { .. }
982 | TypingMode::PostAnalysis => false,
983 }
984 }
985
986 pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
987 self.resolve_vars_if_possible(t).to_string()
988 }
989
990 pub fn probe_ty_var(&self, vid: TyVid) -> Result<Ty<'tcx>, ty::UniverseIndex> {
993 use self::type_variable::TypeVariableValue;
994
995 match self.inner.borrow_mut().type_variables().probe(vid) {
996 TypeVariableValue::Known { value } => Ok(value),
997 TypeVariableValue::Unknown { universe } => Err(universe),
998 }
999 }
1000
1001 pub fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
1002 if let ty::Infer(v) = *ty.kind() {
1003 match v {
1004 ty::TyVar(v) => {
1005 let known = self.inner.borrow_mut().type_variables().probe(v).known();
1018 known.map_or(ty, |t| self.shallow_resolve(t))
1019 }
1020
1021 ty::IntVar(v) => {
1022 match self.inner.borrow_mut().int_unification_table().probe_value(v) {
1023 ty::IntVarValue::IntType(ty) => Ty::new_int(self.tcx, ty),
1024 ty::IntVarValue::UintType(ty) => Ty::new_uint(self.tcx, ty),
1025 ty::IntVarValue::Unknown => ty,
1026 }
1027 }
1028
1029 ty::FloatVar(v) => {
1030 match self.inner.borrow_mut().float_unification_table().probe_value(v) {
1031 ty::FloatVarValue::Known(ty) => Ty::new_float(self.tcx, ty),
1032 ty::FloatVarValue::Unknown => ty,
1033 }
1034 }
1035
1036 ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => ty,
1037 }
1038 } else {
1039 ty
1040 }
1041 }
1042
1043 pub fn shallow_resolve_const(&self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
1044 match ct.kind() {
1045 ty::ConstKind::Infer(infer_ct) => match infer_ct {
1046 InferConst::Var(vid) => self
1047 .inner
1048 .borrow_mut()
1049 .const_unification_table()
1050 .probe_value(vid)
1051 .known()
1052 .unwrap_or(ct),
1053 InferConst::Fresh(_) => ct,
1054 },
1055 ty::ConstKind::Param(_)
1056 | ty::ConstKind::Bound(_, _)
1057 | ty::ConstKind::Placeholder(_)
1058 | ty::ConstKind::Unevaluated(_)
1059 | ty::ConstKind::Value(_)
1060 | ty::ConstKind::Error(_)
1061 | ty::ConstKind::Expr(_) => ct,
1062 }
1063 }
1064
1065 pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
1066 self.inner.borrow_mut().type_variables().root_var(var)
1067 }
1068
1069 pub fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid {
1070 self.inner.borrow_mut().const_unification_table().find(var).vid
1071 }
1072
1073 pub fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> Ty<'tcx> {
1076 let mut inner = self.inner.borrow_mut();
1077 let value = inner.int_unification_table().probe_value(vid);
1078 match value {
1079 ty::IntVarValue::IntType(ty) => Ty::new_int(self.tcx, ty),
1080 ty::IntVarValue::UintType(ty) => Ty::new_uint(self.tcx, ty),
1081 ty::IntVarValue::Unknown => {
1082 Ty::new_int_var(self.tcx, inner.int_unification_table().find(vid))
1083 }
1084 }
1085 }
1086
1087 pub fn opportunistic_resolve_float_var(&self, vid: ty::FloatVid) -> Ty<'tcx> {
1090 let mut inner = self.inner.borrow_mut();
1091 let value = inner.float_unification_table().probe_value(vid);
1092 match value {
1093 ty::FloatVarValue::Known(ty) => Ty::new_float(self.tcx, ty),
1094 ty::FloatVarValue::Unknown => {
1095 Ty::new_float_var(self.tcx, inner.float_unification_table().find(vid))
1096 }
1097 }
1098 }
1099
1100 pub fn resolve_vars_if_possible<T>(&self, value: T) -> T
1107 where
1108 T: TypeFoldable<TyCtxt<'tcx>>,
1109 {
1110 if let Err(guar) = value.error_reported() {
1111 self.set_tainted_by_errors(guar);
1112 }
1113 if !value.has_non_region_infer() {
1114 return value;
1115 }
1116 let mut r = resolve::OpportunisticVarResolver::new(self);
1117 value.fold_with(&mut r)
1118 }
1119
1120 pub fn resolve_numeric_literals_with_default<T>(&self, value: T) -> T
1121 where
1122 T: TypeFoldable<TyCtxt<'tcx>>,
1123 {
1124 if !value.has_infer() {
1125 return value; }
1127 let mut r = InferenceLiteralEraser { tcx: self.tcx };
1128 value.fold_with(&mut r)
1129 }
1130
1131 pub fn probe_const_var(&self, vid: ty::ConstVid) -> Result<ty::Const<'tcx>, ty::UniverseIndex> {
1132 match self.inner.borrow_mut().const_unification_table().probe_value(vid) {
1133 ConstVariableValue::Known { value } => Ok(value),
1134 ConstVariableValue::Unknown { origin: _, universe } => Err(universe),
1135 }
1136 }
1137
1138 pub fn fully_resolve<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> FixupResult<T> {
1146 match resolve::fully_resolve(self, value) {
1147 Ok(value) => {
1148 if value.has_non_region_infer() {
1149 bug!("`{value:?}` is not fully resolved");
1150 }
1151 if value.has_infer_regions() {
1152 let guar = self.dcx().delayed_bug(format!("`{value:?}` is not fully resolved"));
1153 Ok(fold_regions(self.tcx, value, |re, _| {
1154 if re.is_var() { ty::Region::new_error(self.tcx, guar) } else { re }
1155 }))
1156 } else {
1157 Ok(value)
1158 }
1159 }
1160 Err(e) => Err(e),
1161 }
1162 }
1163
1164 pub fn instantiate_binder_with_fresh_vars<T>(
1172 &self,
1173 span: Span,
1174 lbrct: BoundRegionConversionTime,
1175 value: ty::Binder<'tcx, T>,
1176 ) -> T
1177 where
1178 T: TypeFoldable<TyCtxt<'tcx>> + Copy,
1179 {
1180 if let Some(inner) = value.no_bound_vars() {
1181 return inner;
1182 }
1183
1184 let bound_vars = value.bound_vars();
1185 let mut args = Vec::with_capacity(bound_vars.len());
1186
1187 for bound_var_kind in bound_vars {
1188 let arg: ty::GenericArg<'_> = match bound_var_kind {
1189 ty::BoundVariableKind::Ty(_) => self.next_ty_var(span).into(),
1190 ty::BoundVariableKind::Region(br) => {
1191 self.next_region_var(BoundRegion(span, br, lbrct)).into()
1192 }
1193 ty::BoundVariableKind::Const => self.next_const_var(span).into(),
1194 };
1195 args.push(arg);
1196 }
1197
1198 struct ToFreshVars<'tcx> {
1199 args: Vec<ty::GenericArg<'tcx>>,
1200 }
1201
1202 impl<'tcx> BoundVarReplacerDelegate<'tcx> for ToFreshVars<'tcx> {
1203 fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> {
1204 self.args[br.var.index()].expect_region()
1205 }
1206 fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
1207 self.args[bt.var.index()].expect_ty()
1208 }
1209 fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx> {
1210 self.args[bv.index()].expect_const()
1211 }
1212 }
1213 let delegate = ToFreshVars { args };
1214 self.tcx.replace_bound_vars_uncached(value, delegate)
1215 }
1216
1217 pub(crate) fn verify_generic_bound(
1219 &self,
1220 origin: SubregionOrigin<'tcx>,
1221 kind: GenericKind<'tcx>,
1222 a: ty::Region<'tcx>,
1223 bound: VerifyBound<'tcx>,
1224 ) {
1225 debug!("verify_generic_bound({:?}, {:?} <: {:?})", kind, a, bound);
1226
1227 self.inner
1228 .borrow_mut()
1229 .unwrap_region_constraints()
1230 .verify_generic_bound(origin, kind, a, bound);
1231 }
1232
1233 pub fn closure_kind(&self, closure_ty: Ty<'tcx>) -> Option<ty::ClosureKind> {
1237 let unresolved_kind_ty = match *closure_ty.kind() {
1238 ty::Closure(_, args) => args.as_closure().kind_ty(),
1239 ty::CoroutineClosure(_, args) => args.as_coroutine_closure().kind_ty(),
1240 _ => bug!("unexpected type {closure_ty}"),
1241 };
1242 let closure_kind_ty = self.shallow_resolve(unresolved_kind_ty);
1243 closure_kind_ty.to_opt_closure_kind()
1244 }
1245
1246 pub fn universe(&self) -> ty::UniverseIndex {
1247 self.universe.get()
1248 }
1249
1250 pub fn create_next_universe(&self) -> ty::UniverseIndex {
1253 let u = self.universe.get().next_universe();
1254 debug!("create_next_universe {u:?}");
1255 self.universe.set(u);
1256 u
1257 }
1258
1259 pub fn typing_env(&self, param_env: ty::ParamEnv<'tcx>) -> ty::TypingEnv<'tcx> {
1263 let typing_mode = match self.typing_mode() {
1264 ty::TypingMode::Analysis { defining_opaque_types: _ } => {
1269 TypingMode::non_body_analysis()
1270 }
1271 mode @ (ty::TypingMode::Coherence
1272 | ty::TypingMode::PostBorrowckAnalysis { .. }
1273 | ty::TypingMode::PostAnalysis) => mode,
1274 };
1275 ty::TypingEnv { typing_mode, param_env }
1276 }
1277
1278 pub fn pseudo_canonicalize_query<V>(
1282 &self,
1283 param_env: ty::ParamEnv<'tcx>,
1284 value: V,
1285 ) -> PseudoCanonicalInput<'tcx, V>
1286 where
1287 V: TypeVisitable<TyCtxt<'tcx>>,
1288 {
1289 debug_assert!(!value.has_infer());
1290 debug_assert!(!value.has_placeholders());
1291 debug_assert!(!param_env.has_infer());
1292 debug_assert!(!param_env.has_placeholders());
1293 self.typing_env(param_env).as_query_input(value)
1294 }
1295
1296 #[inline]
1299 pub fn is_ty_infer_var_definitely_unchanged<'a>(
1300 &'a self,
1301 ) -> (impl Fn(TyOrConstInferVar) -> bool + Captures<'tcx> + 'a) {
1302 let inner = self.inner.try_borrow();
1304
1305 move |infer_var: TyOrConstInferVar| match (infer_var, &inner) {
1306 (TyOrConstInferVar::Ty(ty_var), Ok(inner)) => {
1307 use self::type_variable::TypeVariableValue;
1308
1309 matches!(
1310 inner.try_type_variables_probe_ref(ty_var),
1311 Some(TypeVariableValue::Unknown { .. })
1312 )
1313 }
1314 _ => false,
1315 }
1316 }
1317
1318 #[inline(always)]
1328 pub fn ty_or_const_infer_var_changed(&self, infer_var: TyOrConstInferVar) -> bool {
1329 match infer_var {
1330 TyOrConstInferVar::Ty(v) => {
1331 use self::type_variable::TypeVariableValue;
1332
1333 match self.inner.borrow_mut().type_variables().inlined_probe(v) {
1336 TypeVariableValue::Unknown { .. } => false,
1337 TypeVariableValue::Known { .. } => true,
1338 }
1339 }
1340
1341 TyOrConstInferVar::TyInt(v) => {
1342 self.inner.borrow_mut().int_unification_table().inlined_probe_value(v).is_known()
1346 }
1347
1348 TyOrConstInferVar::TyFloat(v) => {
1349 self.inner.borrow_mut().float_unification_table().probe_value(v).is_known()
1354 }
1355
1356 TyOrConstInferVar::Const(v) => {
1357 match self.inner.borrow_mut().const_unification_table().probe_value(v) {
1362 ConstVariableValue::Unknown { .. } => false,
1363 ConstVariableValue::Known { .. } => true,
1364 }
1365 }
1366 }
1367 }
1368
1369 pub fn attach_obligation_inspector(&self, inspector: ObligationInspector<'tcx>) {
1371 debug_assert!(
1372 self.obligation_inspector.get().is_none(),
1373 "shouldn't override a set obligation inspector"
1374 );
1375 self.obligation_inspector.set(Some(inspector));
1376 }
1377}
1378
1379#[derive(Copy, Clone, Debug)]
1382pub enum TyOrConstInferVar {
1383 Ty(TyVid),
1385 TyInt(IntVid),
1387 TyFloat(FloatVid),
1389
1390 Const(ConstVid),
1392}
1393
1394impl<'tcx> TyOrConstInferVar {
1395 pub fn maybe_from_generic_arg(arg: GenericArg<'tcx>) -> Option<Self> {
1399 match arg.unpack() {
1400 GenericArgKind::Type(ty) => Self::maybe_from_ty(ty),
1401 GenericArgKind::Const(ct) => Self::maybe_from_const(ct),
1402 GenericArgKind::Lifetime(_) => None,
1403 }
1404 }
1405
1406 fn maybe_from_ty(ty: Ty<'tcx>) -> Option<Self> {
1409 match *ty.kind() {
1410 ty::Infer(ty::TyVar(v)) => Some(TyOrConstInferVar::Ty(v)),
1411 ty::Infer(ty::IntVar(v)) => Some(TyOrConstInferVar::TyInt(v)),
1412 ty::Infer(ty::FloatVar(v)) => Some(TyOrConstInferVar::TyFloat(v)),
1413 _ => None,
1414 }
1415 }
1416
1417 fn maybe_from_const(ct: ty::Const<'tcx>) -> Option<Self> {
1420 match ct.kind() {
1421 ty::ConstKind::Infer(InferConst::Var(v)) => Some(TyOrConstInferVar::Const(v)),
1422 _ => None,
1423 }
1424 }
1425}
1426
1427struct InferenceLiteralEraser<'tcx> {
1430 tcx: TyCtxt<'tcx>,
1431}
1432
1433impl<'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceLiteralEraser<'tcx> {
1434 fn cx(&self) -> TyCtxt<'tcx> {
1435 self.tcx
1436 }
1437
1438 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
1439 match ty.kind() {
1440 ty::Infer(ty::IntVar(_) | ty::FreshIntTy(_)) => self.tcx.types.i32,
1441 ty::Infer(ty::FloatVar(_) | ty::FreshFloatTy(_)) => self.tcx.types.f64,
1442 _ => ty.super_fold_with(self),
1443 }
1444 }
1445}
1446
1447impl<'tcx> TypeTrace<'tcx> {
1448 pub fn span(&self) -> Span {
1449 self.cause.span
1450 }
1451
1452 pub fn types(cause: &ObligationCause<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> TypeTrace<'tcx> {
1453 TypeTrace {
1454 cause: cause.clone(),
1455 values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
1456 }
1457 }
1458
1459 pub fn trait_refs(
1460 cause: &ObligationCause<'tcx>,
1461 a: ty::TraitRef<'tcx>,
1462 b: ty::TraitRef<'tcx>,
1463 ) -> TypeTrace<'tcx> {
1464 TypeTrace { cause: cause.clone(), values: ValuePairs::TraitRefs(ExpectedFound::new(a, b)) }
1465 }
1466
1467 pub fn consts(
1468 cause: &ObligationCause<'tcx>,
1469 a: ty::Const<'tcx>,
1470 b: ty::Const<'tcx>,
1471 ) -> TypeTrace<'tcx> {
1472 TypeTrace {
1473 cause: cause.clone(),
1474 values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
1475 }
1476 }
1477}
1478
1479impl<'tcx> SubregionOrigin<'tcx> {
1480 pub fn span(&self) -> Span {
1481 match *self {
1482 Subtype(ref a) => a.span(),
1483 RelateObjectBound(a) => a,
1484 RelateParamBound(a, ..) => a,
1485 RelateRegionParamBound(a, _) => a,
1486 Reborrow(a) => a,
1487 ReferenceOutlivesReferent(_, a) => a,
1488 CompareImplItemObligation { span, .. } => span,
1489 AscribeUserTypeProvePredicate(span) => span,
1490 CheckAssociatedTypeBounds { ref parent, .. } => parent.span(),
1491 }
1492 }
1493
1494 pub fn from_obligation_cause<F>(cause: &traits::ObligationCause<'tcx>, default: F) -> Self
1495 where
1496 F: FnOnce() -> Self,
1497 {
1498 match *cause.code() {
1499 traits::ObligationCauseCode::ReferenceOutlivesReferent(ref_type) => {
1500 SubregionOrigin::ReferenceOutlivesReferent(ref_type, cause.span)
1501 }
1502
1503 traits::ObligationCauseCode::CompareImplItem {
1504 impl_item_def_id,
1505 trait_item_def_id,
1506 kind: _,
1507 } => SubregionOrigin::CompareImplItemObligation {
1508 span: cause.span,
1509 impl_item_def_id,
1510 trait_item_def_id,
1511 },
1512
1513 traits::ObligationCauseCode::CheckAssociatedTypeBounds {
1514 impl_item_def_id,
1515 trait_item_def_id,
1516 } => SubregionOrigin::CheckAssociatedTypeBounds {
1517 impl_item_def_id,
1518 trait_item_def_id,
1519 parent: Box::new(default()),
1520 },
1521
1522 traits::ObligationCauseCode::AscribeUserTypeProvePredicate(span) => {
1523 SubregionOrigin::AscribeUserTypeProvePredicate(span)
1524 }
1525
1526 traits::ObligationCauseCode::ObjectTypeBound(ty, _reg) => {
1527 SubregionOrigin::RelateRegionParamBound(cause.span, Some(ty))
1528 }
1529
1530 _ => default(),
1531 }
1532 }
1533}
1534
1535impl RegionVariableOrigin {
1536 pub fn span(&self) -> Span {
1537 match *self {
1538 MiscVariable(a)
1539 | PatternRegion(a)
1540 | BorrowRegion(a)
1541 | Autoref(a)
1542 | Coercion(a)
1543 | RegionParameterDefinition(a, ..)
1544 | BoundRegion(a, ..)
1545 | UpvarRegion(_, a) => a,
1546 Nll(..) => bug!("NLL variable used with `span`"),
1547 }
1548 }
1549}
1550
1551impl<'tcx> InferCtxt<'tcx> {
1552 pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span {
1555 let block = block.innermost_block();
1556 if let Some(expr) = &block.expr {
1557 expr.span
1558 } else if let Some(stmt) = block.stmts.last() {
1559 stmt.span
1561 } else {
1562 block.span
1564 }
1565 }
1566
1567 pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span {
1570 match self.tcx.hir_node(hir_id) {
1571 hir::Node::Block(blk) => self.find_block_span(blk),
1572 hir::Node::Expr(e) => e.span,
1575 _ => rustc_span::DUMMY_SP,
1576 }
1577 }
1578}