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