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.get()
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.insert_placeholder_assumptions(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.get_placeholder_assumptions(u)
62 }
63
64 fn get_solver_region_constraint(
65 &self,
66 ) -> rustc_type_ir::region_constraint::RegionConstraint<TyCtxt<'tcx>> {
67 self.get_solver_region_constraint().without_spans()
68 }
69
70 fn overwrite_solver_region_constraint(
71 &self,
72 constraint: rustc_type_ir::region_constraint::RegionConstraint<TyCtxt<'tcx>>,
73 span: Span,
74 ) {
75 self.overwrite_solver_region_constraint(constraint.with_spans(span));
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_region(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex> {
86 match self.inner.borrow_mut().unwrap_region_constraints().try_resolve_region_var(lt) {
87 Err(universe) => Some(universe),
88 Ok(_) => None,
89 }
90 }
91
92 fn universe_of_const(&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 #[inline]
108 fn is_sub_unification_table_root_var(&self, vid: ty::TyVid) -> bool {
109 self.inner
110 .borrow()
111 .type_variable_storage
112 .sub_unification_table_ref()
113 .try_probe_value(vid)
114 .is_some()
115 }
116
117 fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid {
118 self.root_const_var(var)
119 }
120
121 fn shallow_resolve_ty_var(&self, vid: ty::TyVid) -> Ty<'tcx> {
122 self.shallow_resolve_ty_var(vid)
123 }
124
125 fn shallow_resolve_int_var(&self, vid: ty::IntVid) -> Ty<'tcx> {
126 self.shallow_resolve_int_var(vid)
127 }
128
129 fn shallow_resolve_float_var(&self, vid: ty::FloatVid) -> Ty<'tcx> {
130 self.shallow_resolve_float_var(vid)
131 }
132
133 fn shallow_resolve_const_var(&self, vid: ty::ConstVid) -> ty::Const<'tcx> {
134 self.shallow_resolve_const_var(vid)
135 }
136
137 fn shallow_resolve_region_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> {
138 self.inner
139 .borrow_mut()
140 .unwrap_region_constraints()
141 .shallow_resolve_region_var(self.tcx, vid)
142 }
143
144 fn ty_or_const_infer_var_changed(&self, var: TyOrConstInferVar) -> bool {
145 self.ty_or_const_infer_var_changed(var)
146 }
147
148 fn next_region_infer(&self) -> ty::Region<'tcx> {
149 self.next_region_var(RegionVariableOrigin::Misc(DUMMY_SP))
150 }
151
152 fn next_ty_infer(&self) -> Ty<'tcx> {
153 self.next_ty_var(DUMMY_SP)
154 }
155
156 fn next_const_infer(&self) -> ty::Const<'tcx> {
157 self.next_const_var(DUMMY_SP)
158 }
159
160 fn fresh_args_for_item(&self, def_id: DefId) -> ty::GenericArgsRef<'tcx> {
161 self.fresh_args_for_item(DUMMY_SP, def_id)
162 }
163
164 fn instantiate_binder_with_infer<T: TypeFoldable<TyCtxt<'tcx>> + Copy>(
165 &self,
166 value: ty::Binder<'tcx, T>,
167 ) -> T {
168 self.instantiate_binder_with_fresh_vars(
169 DUMMY_SP,
170 BoundRegionConversionTime::HigherRankedType,
171 value,
172 )
173 }
174
175 fn enter_forall_without_assumptions<T: TypeFoldable<TyCtxt<'tcx>>, U>(
176 &self,
177 value: ty::Binder<'tcx, T>,
178 f: impl FnOnce(T) -> U,
179 ) -> U {
180 self.enter_forall(value, f)
181 }
182
183 fn enter_forall_with_empty_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, |value| {
189 let u = self.universe();
190 self.placeholder_assumptions_for_next_solver
191 .borrow_mut()
192 .insert(u, Some(rustc_type_ir::region_constraint::Assumptions::empty()));
193 f(value)
194 })
195 }
196
197 fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
198 self.inner.borrow_mut().type_variables().equate(a, b);
199 }
200
201 fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
202 self.sub_unify_ty_vids_raw(a, b);
203 }
204
205 fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid) {
206 self.inner.borrow_mut().int_unification_table().union(a, b);
207 }
208
209 fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid) {
210 self.inner.borrow_mut().float_unification_table().union(a, b);
211 }
212
213 fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid) {
214 self.inner.borrow_mut().const_unification_table().union(a, b);
215 }
216
217 fn instantiate_ty_var_raw(&self, vid: ty::TyVid, ty: Ty<'tcx>) {
218 let ty = lower_universe(self, self.try_resolve_ty_var(vid).unwrap_err(), ty);
219
220 self.inner.borrow_mut().type_variables().instantiate(vid, ty);
221 }
222
223 fn instantiate_const_var_raw(&self, vid: ty::ConstVid, ct: ty::Const<'tcx>) {
224 let ct = lower_universe(self, self.try_resolve_const_var(vid).unwrap_err(), ct);
225
226 self.inner
227 .borrow_mut()
228 .const_unification_table()
229 .union_value(vid, ConstVariableValue::Known { value: ct });
230 }
231
232 fn instantiate_ty_var<R: PredicateEmittingRelation<Self>>(
233 &self,
234 relation: &mut R,
235 target_is_expected: bool,
236 target_vid: ty::TyVid,
237 instantiation_variance: ty::Variance,
238 source_ty: Ty<'tcx>,
239 ) -> RelateResult<'tcx, ()> {
240 self.instantiate_ty_var(
241 relation,
242 target_is_expected,
243 target_vid,
244 instantiation_variance,
245 source_ty,
246 )
247 }
248
249 fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue) {
250 self.inner.borrow_mut().int_unification_table().union_value(vid, value);
251 }
252
253 fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue) {
254 self.inner.borrow_mut().float_unification_table().union_value(vid, value);
255 }
256
257 fn instantiate_const_var<R: PredicateEmittingRelation<Self>>(
258 &self,
259 relation: &mut R,
260 target_is_expected: bool,
261 target_vid: ty::ConstVid,
262 source_ct: ty::Const<'tcx>,
263 ) -> RelateResult<'tcx, ()> {
264 self.instantiate_const_var(relation, target_is_expected, target_vid, source_ct)
265 }
266
267 fn set_tainted_by_errors(&self, e: ErrorGuaranteed) {
268 self.set_tainted_by_errors(e)
269 }
270
271 fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
272 self.shallow_resolve(ty)
273 }
274 fn shallow_resolve_const(&self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
275 self.shallow_resolve_const(ct)
276 }
277
278 fn deeply_resolve_ignoring_regions<T>(&self, value: T) -> T
279 where
280 T: TypeFoldable<TyCtxt<'tcx>>,
281 {
282 self.deeply_resolve_ignoring_regions(value)
283 }
284
285 fn probe<T>(&self, probe: impl FnOnce() -> T) -> T {
286 self.probe(|_| probe())
287 }
288
289 fn commit_if_ok<T, E>(&self, f: impl FnOnce() -> Result<T, E>) -> Result<T, E> {
290 self.commit_if_ok(|_| f())
291 }
292
293 fn sub_regions(
294 &self,
295 sub: ty::Region<'tcx>,
296 sup: ty::Region<'tcx>,
297 vis: ty::VisibleForLeakCheck,
298 span: Span,
299 ) {
300 self.inner.borrow_mut().unwrap_region_constraints().make_subregion(
301 SubregionOrigin::RelateRegionParamBound(span, None),
302 sub,
303 sup,
304 vis,
305 );
306 }
307
308 fn equate_regions(
309 &self,
310 a: ty::Region<'tcx>,
311 b: ty::Region<'tcx>,
312 vis: ty::VisibleForLeakCheck,
313 span: Span,
314 ) {
315 self.inner.borrow_mut().unwrap_region_constraints().make_eqregion(
316 SubregionOrigin::RelateRegionParamBound(span, None),
317 a,
318 b,
319 vis,
320 );
321 }
322
323 fn register_solver_region_constraint(
324 &self,
325 c: rustc_type_ir::region_constraint::RegionConstraint<TyCtxt<'tcx>>,
326 span: Span,
327 ) {
328 self.register_solver_region_constraint(c.with_spans(span));
329 }
330
331 fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) {
332 self.register_type_outlives_constraint(ty, r, &ObligationCause::dummy_with_span(span));
333 }
334
335 type OpaqueTypeStorageEntries = OpaqueTypeStorageEntries;
336 #[inline]
337 fn opaque_types_storage_num_entries(&self) -> OpaqueTypeStorageEntries {
338 self.inner.borrow_mut().opaque_types().num_entries()
339 }
340 fn clone_opaque_types_lookup_table(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
341 self.inner.borrow_mut().opaque_types().iter_lookup_table().map(|(k, h)| (k, h.ty)).collect()
342 }
343 fn clone_duplicate_opaque_types(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
344 self.inner
345 .borrow_mut()
346 .opaque_types()
347 .iter_duplicate_entries()
348 .map(|(k, h)| (k, h.ty))
349 .collect()
350 }
351 fn clone_opaque_types_added_since(
352 &self,
353 prev_entries: OpaqueTypeStorageEntries,
354 ) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
355 self.inner
356 .borrow_mut()
357 .opaque_types()
358 .opaque_types_added_since(prev_entries)
359 .map(|(k, h)| (k, h.ty))
360 .collect()
361 }
362 fn opaques_with_sub_unified_hidden_type(&self, ty: ty::TyVid) -> Vec<ty::OpaqueAliasTy<'tcx>> {
363 self.opaques_with_sub_unified_hidden_type(ty)
364 }
365
366 fn register_hidden_type_in_storage(
367 &self,
368 opaque_type_key: ty::OpaqueTypeKey<'tcx>,
369 hidden_ty: Ty<'tcx>,
370 span: Span,
371 ) -> Option<Ty<'tcx>> {
372 self.register_hidden_type_in_storage(
373 opaque_type_key,
374 ty::ProvisionalHiddenType { span, ty: hidden_ty },
375 )
376 }
377 fn add_duplicate_opaque_type(
378 &self,
379 opaque_type_key: ty::OpaqueTypeKey<'tcx>,
380 hidden_ty: Ty<'tcx>,
381 span: Span,
382 ) {
383 self.inner
384 .borrow_mut()
385 .opaque_types()
386 .add_duplicate(opaque_type_key, ty::ProvisionalHiddenType { span, ty: hidden_ty })
387 }
388
389 fn reset_opaque_types(&self) {
390 let _ = self.take_opaque_types();
391 }
392}
393
394fn lower_universe<'tcx, T: TypeFoldable<TyCtxt<'tcx>> + Copy>(
395 infcx: &InferCtxt<'tcx>,
396 for_universe: ty::UniverseIndex,
397 value: T,
398) -> T {
399 let value = value.fold_with(&mut LowerUniverseFolder {
400 infcx,
401 for_universe,
402 cache: Default::default(),
403 });
404
405 #[cfg(debug_assertions)]
408 {
409 let value_universe = ty::max_universe(infcx, value);
410 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!(
411 for_universe.can_name(value_universe),
412 "variable in universe {:?} can't name value in universe {:?}",
413 for_universe,
414 value_universe,
415 );
416 }
417
418 value
419}
420
421struct LowerUniverseFolder<'a, 'tcx> {
432 infcx: &'a InferCtxt<'tcx>,
433 for_universe: ty::UniverseIndex,
434 cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
435}
436impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for LowerUniverseFolder<'a, 'tcx> {
437 fn cx(&self) -> TyCtxt<'tcx> {
438 self.infcx.tcx
439 }
440
441 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
442 if !(t.has_free_regions() || t.has_infer()) {
443 return t;
444 }
445
446 if let Some(&answer) = self.cache.get(&t) {
447 return answer;
448 }
449
450 let folded = match t.kind() {
451 ty::Infer(ty::TyVar(vid)) => {
452 let vid = self.infcx.root_var(*vid);
453 let probe = self.infcx.inner.borrow_mut().type_variables().probe(vid);
454 match probe {
455 TypeVariableValue::Known { value: u } => u.super_fold_with(self),
456 TypeVariableValue::Unknown { universe } => {
457 if self.for_universe.can_name(universe) {
458 t
459 } else {
460 let mut inner = self.infcx.inner.borrow_mut();
461 let origin = inner.type_variables().var_origin(vid);
462 let new_var_id =
463 inner.type_variables().new_var(self.for_universe, origin);
464 inner.type_variables().equate(vid, new_var_id);
465 Ty::new_var(self.cx(), new_var_id)
466 }
467 }
468 }
469 }
470 _ => t.super_fold_with(self),
471 };
472
473 self.cache.insert(t, folded);
474 folded
475 }
476
477 fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
478 if !(c.has_free_regions() || c.has_infer()) {
479 return c;
480 }
481
482 match c.kind() {
483 ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
484 let vid = self.infcx.root_const_var(vid);
485 let universe = match self.infcx.try_resolve_const_var(vid) {
486 Ok(value) => return value.fold_with(self),
487 Err(universe) => universe,
488 };
489 if self.for_universe.can_name(universe) {
490 c
491 } else {
492 let origin = self.infcx.const_var_origin(vid).unwrap();
493 let new_var_id = self
494 .infcx
495 .inner
496 .borrow_mut()
497 .const_unification_table()
498 .new_key(ConstVariableValue::Unknown {
499 origin,
500 universe: self.for_universe,
501 })
502 .vid;
503
504 self.infcx.inner.borrow_mut().const_unification_table().union(vid, new_var_id);
505
506 ty::Const::new_var(self.cx(), new_var_id)
507 }
508 }
509 _ => c.super_fold_with(self),
510 }
511 }
512
513 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
514 match r.kind() {
515 ty::ReBound(..) | ty::ReErased => r,
516 _ => {
517 let r_universe = self.infcx.universe_of_region(r);
518 if self.for_universe.can_name(r_universe) {
519 r
520 } else {
521 let new_region = self.infcx.next_region_var_in_universe(
524 RegionVariableOrigin::Misc(DUMMY_SP),
525 self.for_universe,
526 );
527 self.infcx.equate_regions(
528 SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None),
529 r,
530 new_region,
531 ty::VisibleForLeakCheck::Yes,
532 );
533 new_region
534 }
535 }
536 }
537 }
538}