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