Skip to main content

rustc_infer/infer/
context.rs

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