1use 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 #[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
434struct 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 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}