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