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::{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 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 #[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
468struct 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 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}