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