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