Skip to main content

rustc_infer/infer/
context.rs

1//! Definition of `InferCtxtLike` from the librarified type layer.
2use rustc_data_structures::sso::SsoHashMap;
3use rustc_hir::def_id::DefId;
4use rustc_middle::traits::ObligationCause;
5use rustc_middle::ty::relate::RelateResult;
6use rustc_middle::ty::relate::combine::PredicateEmittingRelation;
7use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
8use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
9use rustc_type_ir::{TypeSuperFoldable, TypeVisitableExt};
10
11use super::type_variable::TypeVariableValue;
12use super::{
13    BoundRegionConversionTime, ConstVariableValue, InferCtxt, OpaqueTypeStorageEntries,
14    RegionVariableOrigin, SubregionOrigin,
15};
16
17impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
18    type Interner = TyCtxt<'tcx>;
19
20    fn cx(&self) -> TyCtxt<'tcx> {
21        self.tcx
22    }
23
24    fn next_trait_solver(&self) -> bool {
25        self.next_trait_solver
26    }
27
28    fn disable_trait_solver_fast_paths(&self) -> bool {
29        self.disable_trait_solver_fast_paths()
30    }
31
32    fn typing_mode_raw(&self) -> ty::TypingMode<'tcx> {
33        self.typing_mode_raw()
34    }
35
36    fn universe(&self) -> ty::UniverseIndex {
37        self.universe()
38    }
39
40    fn create_next_universe(&self) -> ty::UniverseIndex {
41        self.create_next_universe()
42    }
43
44    fn insert_placeholder_assumptions(
45        &self,
46        u: ty::UniverseIndex,
47        assumptions: Option<rustc_type_ir::region_constraint::Assumptions<TyCtxt<'tcx>>>,
48    ) {
49        self.placeholder_assumptions_for_next_solver.borrow_mut().insert(u, assumptions);
50    }
51
52    fn get_placeholder_assumptions(
53        &self,
54        u: ty::UniverseIndex,
55    ) -> Option<rustc_type_ir::region_constraint::Assumptions<TyCtxt<'tcx>>> {
56        self.placeholder_assumptions_for_next_solver.borrow().get(&u).unwrap().as_ref().cloned()
57    }
58
59    fn get_solver_region_constraint(
60        &self,
61    ) -> rustc_type_ir::region_constraint::RegionConstraint<TyCtxt<'tcx>> {
62        self.inner.borrow().solver_region_constraint_storage.get_constraint()
63    }
64
65    fn overwrite_solver_region_constraint(
66        &self,
67        constraint: rustc_type_ir::region_constraint::RegionConstraint<TyCtxt<'tcx>>,
68    ) {
69        let mut inner = self.inner.borrow_mut();
70        use rustc_data_structures::undo_log::UndoLogs;
71
72        use crate::infer::UndoLog;
73        let old_constraint = inner.solver_region_constraint_storage.get_constraint();
74        inner.undo_log.push(UndoLog::OverwriteSolverRegionConstraint { old_constraint });
75        inner.solver_region_constraint_storage.overwrite_solver_region_constraint(constraint);
76    }
77
78    fn universe_of_ty(&self, vid: ty::TyVid) -> Option<ty::UniverseIndex> {
79        match self.try_resolve_ty_var(vid) {
80            Err(universe) => Some(universe),
81            Ok(_) => None,
82        }
83    }
84
85    fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex> {
86        match self.inner.borrow_mut().unwrap_region_constraints().probe_value(lt) {
87            Err(universe) => Some(universe),
88            Ok(_) => None,
89        }
90    }
91
92    fn universe_of_ct(&self, ct: ty::ConstVid) -> Option<ty::UniverseIndex> {
93        match self.try_resolve_const_var(ct) {
94            Err(universe) => Some(universe),
95            Ok(_) => None,
96        }
97    }
98
99    fn root_ty_var(&self, var: ty::TyVid) -> ty::TyVid {
100        self.root_var(var)
101    }
102
103    fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid {
104        self.sub_unification_table_root_var(var)
105    }
106
107    fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid {
108        self.root_const_var(var)
109    }
110
111    fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> Ty<'tcx> {
112        match self.try_resolve_ty_var(vid) {
113            Ok(ty) => ty,
114            Err(_) => Ty::new_var(self.tcx, self.root_var(vid)),
115        }
116    }
117
118    fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> Ty<'tcx> {
119        self.opportunistic_resolve_int_var(vid)
120    }
121
122    fn opportunistic_resolve_float_var(&self, vid: ty::FloatVid) -> Ty<'tcx> {
123        self.opportunistic_resolve_float_var(vid)
124    }
125
126    fn opportunistic_resolve_ct_var(&self, vid: ty::ConstVid) -> ty::Const<'tcx> {
127        match self.try_resolve_const_var(vid) {
128            Ok(ct) => ct,
129            Err(_) => ty::Const::new_var(self.tcx, self.root_const_var(vid)),
130        }
131    }
132
133    fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> {
134        self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
135    }
136
137    fn is_changed_arg(&self, arg: ty::GenericArg<'tcx>) -> bool {
138        match arg.kind() {
139            ty::GenericArgKind::Lifetime(_) => {
140                // Lifetimes should not change affect trait selection.
141                false
142            }
143            ty::GenericArgKind::Type(ty) => {
144                if let ty::Infer(infer_ty) = *ty.kind() {
145                    match infer_ty {
146                        ty::InferTy::TyVar(vid) => {
147                            !self.try_resolve_ty_var(vid).is_err_and(|_| self.root_var(vid) == vid)
148                        }
149                        ty::InferTy::IntVar(vid) => {
150                            let mut inner = self.inner.borrow_mut();
151                            !#[allow(non_exhaustive_omitted_patterns)] match inner.int_unification_table().probe_value(vid)
    {
    ty::IntVarValue::Unknown if inner.int_unification_table().find(vid) == vid
        => true,
    _ => false,
}matches!(
152                                inner.int_unification_table().probe_value(vid),
153                                ty::IntVarValue::Unknown
154                                    if inner.int_unification_table().find(vid) == vid
155                            )
156                        }
157                        ty::InferTy::FloatVar(vid) => {
158                            let mut inner = self.inner.borrow_mut();
159                            !#[allow(non_exhaustive_omitted_patterns)] match inner.float_unification_table().probe_value(vid)
    {
    ty::FloatVarValue::Unknown if
        inner.float_unification_table().find(vid) == vid => true,
    _ => false,
}matches!(
160                                inner.float_unification_table().probe_value(vid),
161                                ty::FloatVarValue::Unknown
162                                    if inner.float_unification_table().find(vid) == vid
163                            )
164                        }
165                        ty::InferTy::FreshTy(_)
166                        | ty::InferTy::FreshIntTy(_)
167                        | ty::InferTy::FreshFloatTy(_) => true,
168                    }
169                } else {
170                    true
171                }
172            }
173            ty::GenericArgKind::Const(ct) => {
174                if let ty::ConstKind::Infer(infer_ct) = ct.kind() {
175                    match infer_ct {
176                        ty::InferConst::Var(vid) => !self
177                            .try_resolve_const_var(vid)
178                            .is_err_and(|_| self.root_const_var(vid) == vid),
179                        ty::InferConst::Fresh(_) => true,
180                    }
181                } else {
182                    true
183                }
184            }
185        }
186    }
187
188    fn next_region_infer(&self) -> ty::Region<'tcx> {
189        self.next_region_var(RegionVariableOrigin::Misc(DUMMY_SP))
190    }
191
192    fn next_ty_infer(&self) -> Ty<'tcx> {
193        self.next_ty_var(DUMMY_SP)
194    }
195
196    fn next_const_infer(&self) -> ty::Const<'tcx> {
197        self.next_const_var(DUMMY_SP)
198    }
199
200    fn fresh_args_for_item(&self, def_id: DefId) -> ty::GenericArgsRef<'tcx> {
201        self.fresh_args_for_item(DUMMY_SP, def_id)
202    }
203
204    fn instantiate_binder_with_infer<T: TypeFoldable<TyCtxt<'tcx>> + Copy>(
205        &self,
206        value: ty::Binder<'tcx, T>,
207    ) -> T {
208        self.instantiate_binder_with_fresh_vars(
209            DUMMY_SP,
210            BoundRegionConversionTime::HigherRankedType,
211            value,
212        )
213    }
214
215    fn enter_forall_without_assumptions<T: TypeFoldable<TyCtxt<'tcx>>, U>(
216        &self,
217        value: ty::Binder<'tcx, T>,
218        f: impl FnOnce(T) -> U,
219    ) -> U {
220        self.enter_forall(value, f)
221    }
222
223    fn enter_forall_with_empty_assumptions<T: TypeFoldable<TyCtxt<'tcx>>, U>(
224        &self,
225        value: ty::Binder<'tcx, T>,
226        f: impl FnOnce(T) -> U,
227    ) -> U {
228        self.enter_forall(value, |value| {
229            let u = self.universe();
230            self.placeholder_assumptions_for_next_solver
231                .borrow_mut()
232                .insert(u, Some(rustc_type_ir::region_constraint::Assumptions::empty()));
233            f(value)
234        })
235    }
236
237    fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
238        self.inner.borrow_mut().type_variables().equate(a, b);
239    }
240
241    fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
242        self.sub_unify_ty_vids_raw(a, b);
243    }
244
245    fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid) {
246        self.inner.borrow_mut().int_unification_table().union(a, b);
247    }
248
249    fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid) {
250        self.inner.borrow_mut().float_unification_table().union(a, b);
251    }
252
253    fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid) {
254        self.inner.borrow_mut().const_unification_table().union(a, b);
255    }
256
257    fn instantiate_ty_var_raw(&self, vid: ty::TyVid, ty: Ty<'tcx>) {
258        let ty = lower_universe(self, self.try_resolve_ty_var(vid).unwrap_err(), ty);
259
260        self.inner.borrow_mut().type_variables().instantiate(vid, ty);
261    }
262
263    fn instantiate_const_var_raw(&self, vid: ty::ConstVid, ct: ty::Const<'tcx>) {
264        let ct = lower_universe(self, self.try_resolve_const_var(vid).unwrap_err(), ct);
265
266        self.inner
267            .borrow_mut()
268            .const_unification_table()
269            .union_value(vid, ConstVariableValue::Known { value: ct });
270    }
271
272    fn instantiate_ty_var<R: PredicateEmittingRelation<Self>>(
273        &self,
274        relation: &mut R,
275        target_is_expected: bool,
276        target_vid: ty::TyVid,
277        instantiation_variance: ty::Variance,
278        source_ty: Ty<'tcx>,
279    ) -> RelateResult<'tcx, ()> {
280        self.instantiate_ty_var(
281            relation,
282            target_is_expected,
283            target_vid,
284            instantiation_variance,
285            source_ty,
286        )
287    }
288
289    fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue) {
290        self.inner.borrow_mut().int_unification_table().union_value(vid, value);
291    }
292
293    fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue) {
294        self.inner.borrow_mut().float_unification_table().union_value(vid, value);
295    }
296
297    fn instantiate_const_var<R: PredicateEmittingRelation<Self>>(
298        &self,
299        relation: &mut R,
300        target_is_expected: bool,
301        target_vid: ty::ConstVid,
302        source_ct: ty::Const<'tcx>,
303    ) -> RelateResult<'tcx, ()> {
304        self.instantiate_const_var(relation, target_is_expected, target_vid, source_ct)
305    }
306
307    fn set_tainted_by_errors(&self, e: ErrorGuaranteed) {
308        self.set_tainted_by_errors(e)
309    }
310
311    fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
312        self.shallow_resolve(ty)
313    }
314    fn shallow_resolve_const(&self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
315        self.shallow_resolve_const(ct)
316    }
317
318    fn resolve_vars_if_possible<T>(&self, value: T) -> T
319    where
320        T: TypeFoldable<TyCtxt<'tcx>>,
321    {
322        self.resolve_vars_if_possible(value)
323    }
324
325    fn probe<T>(&self, probe: impl FnOnce() -> T) -> T {
326        self.probe(|_| probe())
327    }
328
329    fn sub_regions(
330        &self,
331        sub: ty::Region<'tcx>,
332        sup: ty::Region<'tcx>,
333        vis: ty::VisibleForLeakCheck,
334        span: Span,
335    ) {
336        self.inner.borrow_mut().unwrap_region_constraints().make_subregion(
337            SubregionOrigin::RelateRegionParamBound(span, None),
338            sub,
339            sup,
340            vis,
341        );
342    }
343
344    fn equate_regions(
345        &self,
346        a: ty::Region<'tcx>,
347        b: ty::Region<'tcx>,
348        vis: ty::VisibleForLeakCheck,
349        span: Span,
350    ) {
351        self.inner.borrow_mut().unwrap_region_constraints().make_eqregion(
352            SubregionOrigin::RelateRegionParamBound(span, None),
353            a,
354            b,
355            vis,
356        );
357    }
358
359    fn register_solver_region_constraint(
360        &self,
361        c: rustc_type_ir::region_constraint::RegionConstraint<TyCtxt<'tcx>>,
362    ) {
363        let mut inner = self.inner.borrow_mut();
364        use rustc_data_structures::undo_log::UndoLogs;
365
366        use crate::infer::UndoLog;
367        inner.undo_log.push(UndoLog::PushSolverRegionConstraint);
368        inner.solver_region_constraint_storage.push(c);
369    }
370
371    fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) {
372        self.register_type_outlives_constraint(ty, r, &ObligationCause::dummy_with_span(span));
373    }
374
375    type OpaqueTypeStorageEntries = OpaqueTypeStorageEntries;
376    fn opaque_types_storage_num_entries(&self) -> OpaqueTypeStorageEntries {
377        self.inner.borrow_mut().opaque_types().num_entries()
378    }
379    fn clone_opaque_types_lookup_table(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
380        self.inner.borrow_mut().opaque_types().iter_lookup_table().map(|(k, h)| (k, h.ty)).collect()
381    }
382    fn clone_duplicate_opaque_types(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
383        self.inner
384            .borrow_mut()
385            .opaque_types()
386            .iter_duplicate_entries()
387            .map(|(k, h)| (k, h.ty))
388            .collect()
389    }
390    fn clone_opaque_types_added_since(
391        &self,
392        prev_entries: OpaqueTypeStorageEntries,
393    ) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
394        self.inner
395            .borrow_mut()
396            .opaque_types()
397            .opaque_types_added_since(prev_entries)
398            .map(|(k, h)| (k, h.ty))
399            .collect()
400    }
401    fn opaques_with_sub_unified_hidden_type(&self, ty: ty::TyVid) -> Vec<ty::OpaqueAliasTy<'tcx>> {
402        self.opaques_with_sub_unified_hidden_type(ty)
403    }
404
405    fn register_hidden_type_in_storage(
406        &self,
407        opaque_type_key: ty::OpaqueTypeKey<'tcx>,
408        hidden_ty: Ty<'tcx>,
409        span: Span,
410    ) -> Option<Ty<'tcx>> {
411        self.register_hidden_type_in_storage(
412            opaque_type_key,
413            ty::ProvisionalHiddenType { span, ty: hidden_ty },
414        )
415    }
416    fn add_duplicate_opaque_type(
417        &self,
418        opaque_type_key: ty::OpaqueTypeKey<'tcx>,
419        hidden_ty: Ty<'tcx>,
420        span: Span,
421    ) {
422        self.inner
423            .borrow_mut()
424            .opaque_types()
425            .add_duplicate(opaque_type_key, ty::ProvisionalHiddenType { span, ty: hidden_ty })
426    }
427
428    fn reset_opaque_types(&self) {
429        let _ = self.take_opaque_types();
430    }
431}
432
433fn lower_universe<'tcx, T: TypeFoldable<TyCtxt<'tcx>> + Copy>(
434    infcx: &InferCtxt<'tcx>,
435    for_universe: ty::UniverseIndex,
436    value: T,
437) -> T {
438    let value = value.fold_with(&mut LowerUniverseFolder {
439        infcx,
440        for_universe,
441        cache: Default::default(),
442    });
443
444    // This assertion is needed because we don't lower the universes of placeholders
445    // in the folder.
446    #[cfg(debug_assertions)]
447    {
448        let value_universe = ty::max_universe(infcx, value);
449        if !for_universe.can_name(value_universe) {
    {
        ::core::panicking::panic_fmt(format_args!("variable in universe {0:?} can\'t name value in universe {1:?}",
                for_universe, value_universe));
    }
};assert!(
450            for_universe.can_name(value_universe),
451            "variable in universe {:?} can't name value in universe {:?}",
452            for_universe,
453            value_universe,
454        );
455    }
456
457    value
458}
459
460/// Canonicalizing inputs puts all inference variables and placeholders
461/// into the root universe.
462///
463/// This means when instantiating the query response we need to pull
464/// down the universe of returned `var_values` to the universe of
465/// the inference variable in `orig_values`.
466///
467/// This folder is similar to the `Generalizer`, except that it simply
468/// structurally folds non-rigid aliases as these should have already
469/// been generalized in the query so we shouldn't try to do it again.
470struct LowerUniverseFolder<'a, 'tcx> {
471    infcx: &'a InferCtxt<'tcx>,
472    for_universe: ty::UniverseIndex,
473    cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
474}
475impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for LowerUniverseFolder<'a, 'tcx> {
476    fn cx(&self) -> TyCtxt<'tcx> {
477        self.infcx.tcx
478    }
479
480    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
481        if !(t.has_free_regions() || t.has_infer()) {
482            return t;
483        }
484
485        if let Some(&answer) = self.cache.get(&t) {
486            return answer;
487        }
488
489        let folded = match t.kind() {
490            ty::Infer(ty::TyVar(vid)) => {
491                let vid = self.infcx.root_var(*vid);
492                let probe = self.infcx.inner.borrow_mut().type_variables().probe(vid);
493                match probe {
494                    TypeVariableValue::Known { value: u } => u.super_fold_with(self),
495                    TypeVariableValue::Unknown { universe } => {
496                        if self.for_universe.can_name(universe) {
497                            t
498                        } else {
499                            let mut inner = self.infcx.inner.borrow_mut();
500                            let origin = inner.type_variables().var_origin(vid);
501                            let new_var_id =
502                                inner.type_variables().new_var(self.for_universe, origin);
503                            inner.type_variables().equate(vid, new_var_id);
504                            Ty::new_var(self.cx(), new_var_id)
505                        }
506                    }
507                }
508            }
509            _ => t.super_fold_with(self),
510        };
511
512        self.cache.insert(t, folded);
513        folded
514    }
515
516    fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
517        if !(c.has_free_regions() || c.has_infer()) {
518            return c;
519        }
520
521        match c.kind() {
522            ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
523                let vid = self.infcx.root_const_var(vid);
524                let universe = self.infcx.try_resolve_const_var(vid).unwrap_err();
525                if self.for_universe.can_name(universe) {
526                    c
527                } else {
528                    let origin = self.infcx.const_var_origin(vid).unwrap();
529                    let new_var_id = self
530                        .infcx
531                        .inner
532                        .borrow_mut()
533                        .const_unification_table()
534                        .new_key(ConstVariableValue::Unknown {
535                            origin,
536                            universe: self.for_universe,
537                        })
538                        .vid;
539
540                    self.infcx.inner.borrow_mut().const_unification_table().union(vid, new_var_id);
541
542                    ty::Const::new_var(self.cx(), new_var_id)
543                }
544            }
545            _ => c.super_fold_with(self),
546        }
547    }
548
549    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
550        match r.kind() {
551            ty::ReBound(..) | ty::ReErased => r,
552            _ => {
553                let r_universe = self.infcx.universe_of_region(r);
554                if self.for_universe.can_name(r_universe) {
555                    r
556                } else {
557                    // FIXME: unfortunately we lose the relating span here unless we take another
558                    // argument.
559                    let new_region = self.infcx.next_region_var_in_universe(
560                        RegionVariableOrigin::Misc(DUMMY_SP),
561                        self.for_universe,
562                    );
563                    self.infcx.equate_regions(
564                        SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None),
565                        r,
566                        new_region,
567                        ty::VisibleForLeakCheck::Yes,
568                    );
569                    new_region
570                }
571            }
572        }
573    }
574}