1use std::{fmt, ops::ControlFlow};
4
5use either::Either;
6use intern::{Interned, InternedRef, InternedSliceRef, impl_internable};
7use macros::GenericTypeVisitable;
8use rustc_abi::ReprOptions;
9use rustc_ast_ir::{FloatTy, IntTy, UintTy};
10pub use tls_cache::clear_tls_solver_cache;
11pub use tls_db::{attach_db, attach_db_allow_change, with_attached_db};
12
13use base_db::Crate;
14use hir_def::{
15 AdtId, CallableDefId, EnumId, GenericParamId, HasModule, ItemContainerId, StructId, TraitId,
16 TypeAliasId, UnionId, VariantId,
17 attrs::AttrFlags,
18 expr_store::{ExpressionStore, StoreVisitor},
19 hir::{ClosureKind as HirClosureKind, CoroutineKind as HirCoroutineKind, ExprId, PatId},
20 lang_item::LangItems,
21 signatures::{
22 EnumFlags, EnumSignature, FnFlags, FunctionSignature, ImplFlags, ImplSignature,
23 StructFlags, StructSignature, TraitFlags, TraitSignature, UnionSignature,
24 },
25};
26use rustc_abi::ExternAbi;
27use rustc_hash::FxHashSet;
28use rustc_index::bit_set::DenseBitSet;
29use rustc_type_ir::{
30 AliasTy, BoundVar, CoroutineWitnessTypes, DebruijnIndex, EarlyBinder, FlagComputation, Flags,
31 FnSigKind, GenericArgKind, GenericTypeVisitable, ImplPolarity, InferTy, Interner, TraitRef,
32 TypeFlags, TypeVisitableExt, Upcast, Variance, VisitorResult,
33 elaborate::elaborate,
34 error::TypeError,
35 fast_reject,
36 inherent::{self, Const as _, GenericsOf, IntoKind, SliceLike as _, Span as _, Ty as _},
37 lang_items::{SolverAdtLangItem, SolverProjectionLangItem, SolverTraitLangItem},
38 solve::{AdtDestructorKind, SizedTraitKind},
39 try_visit,
40};
41
42use crate::{
43 InferBodyId, Span,
44 db::{HirDatabase, InternedClosure, InternedCoroutineId},
45 lower::GenericPredicates,
46 method_resolution::TraitImpls,
47 next_solver::{
48 AdtIdWrapper, AliasTermKind, AliasTyKind, AnyImplId, BoundConst, CallableIdWrapper,
49 CanonicalVarKind, ClosureIdWrapper, Consts, CoroutineClosureIdWrapper, CoroutineIdWrapper,
50 Ctor, FnSig, FreeConstAliasId, FreeTermAliasId, FreeTyAliasId, FxIndexMap,
51 GeneralConstIdWrapper, ImplOrTraitAssocConstId, ImplOrTraitAssocTermId,
52 ImplOrTraitAssocTyId, InherentAssocConstId, InherentAssocTermId, InherentAssocTyId,
53 LateParamRegion, OpaqueTyIdWrapper, OpaqueTypeKey, RegionAssumptions, ScalarInt,
54 SimplifiedType, SolverContext, SolverDefIds, TermId, TraitAssocConstId, TraitAssocTermId,
55 TraitAssocTyId, TraitIdWrapper, TypeAliasIdWrapper, UnevaluatedConst, Unnormalized,
56 util::{explicit_item_bounds, explicit_item_self_bounds},
57 },
58};
59
60use super::{
61 Binder, BoundExistentialPredicates, BoundTy, BoundTyKind, Clause, ClauseKind, Clauses, Const,
62 ErrorGuaranteed, ExprConst, ExternalConstraints, GenericArg, GenericArgs, ParamConst, ParamEnv,
63 ParamTy, PredefinedOpaques, Predicate, SolverDefId, Term, Ty, TyKind, Tys, ValTree, ValueConst,
64 abi::Safety,
65 fold::{BoundVarReplacer, BoundVarReplacerDelegate, FnMutDelegate},
66 generics::{Generics, generics},
67 region::{BoundRegion, BoundRegionKind, EarlyParamRegion, Region},
68 util::sizedness_constraint_for_ty,
69};
70
71macro_rules! interned_slice {
72 ($storage:ident, $name:ident, $stored_name:ident, $default_types_field:ident, $ty_db:ty, $ty_static:ty $(,)?) => {
73 const _: () = {
74 #[allow(unused_lifetimes)]
75 fn _ensure_correct_types<'db: 'static>(v: $ty_db) -> $ty_static { v }
76 };
77
78 ::intern::impl_slice_internable!(gc; $storage, (), $ty_static);
79
80 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
81 pub struct $name<'db> {
82 interned: ::intern::InternedSliceRef<'db, $storage>,
83 }
84
85 impl<'db> std::fmt::Debug for $name<'db> {
86 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 self.as_slice().fmt(fmt)
88 }
89 }
90
91 impl<'db> $name<'db> {
92 #[inline]
93 pub fn empty(interner: DbInterner<'db>) -> Self {
94 interner.default_types().empty.$default_types_field
95 }
96
97 #[inline]
98 pub fn new_from_slice(slice: &[$ty_db]) -> Self {
99 let slice = unsafe { ::std::mem::transmute::<&[$ty_db], &[$ty_static]>(slice) };
100 Self { interned: ::intern::InternedSlice::from_header_and_slice((), slice) }
101 }
102
103 #[inline]
104 pub fn new_from_iter<I, T>(_interner: DbInterner<'db>, args: I) -> T::Output
105 where
106 I: IntoIterator<Item = T>,
107 T: ::rustc_type_ir::CollectAndApply<$ty_db, Self>,
108 {
109 ::rustc_type_ir::CollectAndApply::collect_and_apply(args.into_iter(), |g| {
110 Self::new_from_slice(g)
111 })
112 }
113
114 #[inline]
115 pub fn as_slice(self) -> &'db [$ty_db] {
116 let slice = &self.interned.get().slice;
117 unsafe { ::std::mem::transmute::<&[$ty_static], &[$ty_db]>(slice) }
118 }
119
120 #[inline]
121 pub fn iter(self) -> ::std::iter::Copied<::std::slice::Iter<'db, $ty_db>> {
122 self.as_slice().iter().copied()
123 }
124
125 #[inline]
126 pub fn len(self) -> usize {
127 self.as_slice().len()
128 }
129
130 #[inline]
131 pub fn is_empty(self) -> bool {
132 self.as_slice().is_empty()
133 }
134 }
135
136 impl<'db> IntoIterator for $name<'db> {
137 type IntoIter = ::std::iter::Copied<::std::slice::Iter<'db, $ty_db>>;
138 type Item = $ty_db;
139 #[inline]
140 fn into_iter(self) -> Self::IntoIter { self.iter() }
141 }
142
143 impl<'db> ::std::ops::Deref for $name<'db> {
144 type Target = [$ty_db];
145
146 #[inline]
147 fn deref(&self) -> &Self::Target {
148 (*self).as_slice()
149 }
150 }
151
152 impl<'db> rustc_type_ir::inherent::SliceLike for $name<'db> {
153 type Item = $ty_db;
154
155 type IntoIter = ::std::iter::Copied<::std::slice::Iter<'db, $ty_db>>;
156
157 #[inline]
158 fn iter(self) -> Self::IntoIter {
159 self.iter()
160 }
161
162 #[inline]
163 fn as_slice(&self) -> &[Self::Item] {
164 (*self).as_slice()
165 }
166 }
167
168 impl<'db> Default for $name<'db> {
169 #[inline]
170 fn default() -> Self {
171 $name::empty(DbInterner::conjure())
172 }
173 }
174
175
176 impl<'db, V: $crate::next_solver::interner::WorldExposer>
177 rustc_type_ir::GenericTypeVisitable<V> for $name<'db>
178 {
179 #[inline]
180 fn generic_visit_with(&self, visitor: &mut V) {
181 if visitor.on_interned_slice(self.interned).is_continue() {
182 self.as_slice().iter().for_each(|it| it.generic_visit_with(visitor));
183 }
184 }
185 }
186
187 $crate::next_solver::interner::impl_stored_interned_slice!($storage, $name, $stored_name);
188 };
189}
190pub(crate) use interned_slice;
191
192macro_rules! impl_stored_interned_slice {
193 ( $storage:ident, $name:ident, $stored_name:ident $(,)? ) => {
194 #[derive(Clone, PartialEq, Eq, Hash)]
195 pub struct $stored_name {
196 interned: ::intern::InternedSlice<$storage>,
197 }
198
199 impl $stored_name {
200 #[inline]
201 fn new(it: $name<'_>) -> Self {
202 Self { interned: it.interned.to_owned() }
203 }
204
205 #[inline]
207 pub fn as_ref<'a, 'db>(&'a self) -> $name<'db> {
208 let it = $name { interned: self.interned.as_ref() };
209 unsafe { std::mem::transmute::<$name<'a>, $name<'db>>(it) }
210 }
211 }
212
213 unsafe impl salsa::SalsaValue for $stored_name {}
215
216 impl std::fmt::Debug for $stored_name {
217 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
218 self.as_ref().fmt(f)
219 }
220 }
221
222 impl $name<'_> {
223 #[inline]
224 pub fn store(self) -> $stored_name {
225 $stored_name::new(self)
226 }
227 }
228 };
229}
230pub(crate) use impl_stored_interned_slice;
231
232macro_rules! impl_foldable_for_interned_slice {
233 ($name:ident) => {
234 impl<'db> ::rustc_type_ir::TypeVisitable<DbInterner<'db>> for $name<'db> {
235 fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
236 &self,
237 visitor: &mut V,
238 ) -> V::Result {
239 use rustc_ast_ir::visit::VisitorResult;
240 rustc_ast_ir::walk_visitable_list!(visitor, (*self).iter());
241 V::Result::output()
242 }
243 }
244
245 impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for $name<'db> {
246 fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
247 self,
248 folder: &mut F,
249 ) -> Result<Self, F::Error> {
250 Self::new_from_iter(folder.cx(), self.iter().map(|it| it.try_fold_with(folder)))
251 }
252 fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(
253 self,
254 folder: &mut F,
255 ) -> Self {
256 Self::new_from_iter(folder.cx(), self.iter().map(|it| it.fold_with(folder)))
257 }
258 }
259 };
260}
261pub(crate) use impl_foldable_for_interned_slice;
262
263macro_rules! impl_foldable_for_stored_type {
264 ($name:ident) => {
265 impl<'db> ::rustc_type_ir::TypeVisitable<DbInterner<'db>> for $name {
266 fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
267 &self,
268 visitor: &mut V,
269 ) -> V::Result {
270 self.as_ref().visit_with(visitor)
271 }
272 }
273
274 impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for $name {
275 fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
276 self,
277 folder: &mut F,
278 ) -> Result<Self, F::Error> {
279 Ok(self.as_ref().try_fold_with(folder)?.store())
280 }
281 fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(
282 self,
283 folder: &mut F,
284 ) -> Self {
285 self.as_ref().fold_with(folder).store()
286 }
287 }
288 };
289}
290pub(crate) use impl_foldable_for_stored_type;
291
292macro_rules! impl_stored_interned {
293 ( $storage:ident, $name:ident, $stored_name:ident $(,)? ) => {
294 #[derive(Clone, PartialEq, Eq, Hash, ::salsa::SalsaValue)]
295 pub struct $stored_name {
296 interned: ::intern::Interned<$storage>,
297 }
298
299 impl $stored_name {
300 #[inline]
301 fn new(it: $name<'_>) -> Self {
302 Self { interned: it.interned.to_owned() }
303 }
304
305 #[inline]
306 pub fn as_ref<'a, 'db>(&'a self) -> $name<'db> {
307 let it = $name { interned: self.interned.as_ref() };
308 unsafe { std::mem::transmute::<$name<'a>, $name<'db>>(it) }
309 }
310 }
311
312 impl std::fmt::Debug for $stored_name {
313 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
314 self.as_ref().fmt(f)
315 }
316 }
317
318 impl $name<'_> {
319 #[inline]
320 pub fn store(self) -> $stored_name {
321 $stored_name::new(self)
322 }
323 }
324 };
325}
326pub(crate) use impl_stored_interned;
327
328pub trait WorldExposer {
331 fn on_interned<T: intern::Internable>(
332 &mut self,
333 interned: InternedRef<'_, T>,
334 ) -> ControlFlow<()>;
335 fn on_interned_slice<T: intern::SliceInternable>(
336 &mut self,
337 interned: InternedSliceRef<'_, T>,
338 ) -> ControlFlow<()>;
339}
340
341#[derive(Debug, Copy, Clone)]
342pub struct DbInterner<'db> {
343 pub(crate) db: &'db dyn HirDatabase,
344 krate: Option<Crate>,
345 lang_items: Option<&'db LangItems>,
346}
347
348unsafe impl Send for DbInterner<'_> {}
350unsafe impl Sync for DbInterner<'_> {}
351
352impl<'db> DbInterner<'db> {
353 #[doc(hidden)]
355 pub fn conjure() -> DbInterner<'db> {
356 crate::with_attached_db(|db| DbInterner {
358 db: unsafe { std::mem::transmute::<&dyn HirDatabase, &'db dyn HirDatabase>(db) },
359 krate: None,
360 lang_items: None,
361 })
362 }
363
364 pub fn new_no_crate(db: &'db dyn HirDatabase) -> Self {
369 DbInterner { db, krate: None, lang_items: None }
372 }
373
374 pub fn new_with(db: &'db dyn HirDatabase, krate: Crate) -> DbInterner<'db> {
375 tls_cache::reinit_cache(db);
376 DbInterner {
377 db,
378 krate: Some(krate),
379 lang_items: Some(hir_def::lang_item::lang_items(db, krate)),
382 }
383 }
384
385 #[inline]
386 pub fn db(&self) -> &'db dyn HirDatabase {
387 self.db
388 }
389
390 #[inline]
391 #[track_caller]
392 pub fn lang_items(&self) -> &'db LangItems {
393 self.lang_items.expect(
394 "Must have `DbInterner::lang_items`.\n\n\
395 Note: you might have called `DbInterner::new_no_crate()` \
396 where you should've called `DbInterner::new_with()`",
397 )
398 }
399
400 #[inline]
401 pub fn default_types(&self) -> &'db crate::next_solver::DefaultAny<'db> {
402 crate::next_solver::default_types(self.db)
403 }
404
405 #[inline]
406 pub(crate) fn expect_crate(&self) -> Crate {
407 self.krate.expect("should have a crate")
408 }
409}
410
411impl<'db> inherent::Span<DbInterner<'db>> for Span {
412 fn dummy() -> Self {
413 Span::Dummy
414 }
415}
416
417interned_slice!(
418 BoundVarKindsStorage,
419 BoundVarKinds,
420 StoredBoundVarKinds,
421 bound_var_kinds,
422 BoundVariableKind<'db>,
423 BoundVariableKind<'static>,
424);
425
426pub type BoundVariableKind<'db> = rustc_type_ir::BoundVariableKind<DbInterner<'db>>;
427
428interned_slice!(
429 CanonicalVarsStorage,
430 CanonicalVarKinds,
431 StoredCanonicalVars,
432 canonical_vars,
433 CanonicalVarKind<'db>,
434 CanonicalVarKind<'static>
435);
436
437pub struct DepNodeIndex;
438
439#[derive(Debug)]
440pub struct Tracked<T: fmt::Debug + Clone>(T);
441
442#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
443pub struct AllocId;
444
445interned_slice!(VariancesOfStorage, VariancesOf, StoredVariancesOf, variances, Variance, Variance);
446
447bitflags::bitflags! {
448 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
449 struct AdtFlags: u8 {
450 const IS_FUNDAMENTAL = 1 << 0;
451 const IS_PACKED = 1 << 1;
452 const HAS_REPR = 1 << 2;
453 const IS_PHANTOM_DATA = 1 << 3;
454 const IS_MANUALLY_DROP = 1 << 4;
455 const IS_BOX = 1 << 5;
456 }
457}
458
459#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
460enum AdtDefInner {
461 Struct { id: StructId, flags: AdtFlags },
462 Union { id: UnionId, flags: AdtFlags },
463 Enum { id: EnumId, flags: AdtFlags },
464}
465
466#[derive(Clone, Copy, PartialEq, Eq, Hash)]
467pub struct AdtDef(AdtDefInner);
468
469const _: () = assert!(size_of::<AdtDef>() == 12);
470
471impl AdtDef {
472 pub fn new<'db>(def_id: AdtId, interner: DbInterner<'db>) -> Self {
473 let db = interner.db();
474 let inner = match def_id {
475 AdtId::StructId(id) => {
476 let data = StructSignature::of(db, id);
477 let mut flags = AdtFlags::empty();
478 if data.flags.contains(StructFlags::FUNDAMENTAL) {
479 flags.insert(AdtFlags::IS_FUNDAMENTAL);
480 }
481 if data.flags.contains(StructFlags::IS_PHANTOM_DATA) {
482 flags.insert(AdtFlags::IS_PHANTOM_DATA);
483 }
484 if data.flags.contains(StructFlags::IS_MANUALLY_DROP) {
485 flags.insert(AdtFlags::IS_MANUALLY_DROP);
486 }
487 if data.flags.contains(StructFlags::IS_BOX) {
488 flags.insert(AdtFlags::IS_BOX);
489 }
490 if data.flags.contains(StructFlags::HAS_REPR) {
491 flags.insert(AdtFlags::HAS_REPR);
492 if data.repr(db, id).is_some_and(|repr| repr.packed()) {
493 flags.insert(AdtFlags::IS_PACKED);
494 }
495 }
496 AdtDefInner::Struct { id, flags }
497 }
498 AdtId::UnionId(id) => {
499 let data = UnionSignature::of(db, id);
500 let mut flags = AdtFlags::empty();
501 if data.flags.contains(StructFlags::FUNDAMENTAL) {
502 flags.insert(AdtFlags::IS_FUNDAMENTAL);
503 }
504 if data.flags.contains(StructFlags::HAS_REPR) {
505 flags.insert(AdtFlags::HAS_REPR);
506 if data.repr(db, id).is_some_and(|repr| repr.packed()) {
507 flags.insert(AdtFlags::IS_PACKED);
508 }
509 }
510 AdtDefInner::Union { id, flags }
511 }
512 AdtId::EnumId(id) => {
513 let data = EnumSignature::of(db, id);
514 let mut flags = AdtFlags::empty();
515 if data.flags.contains(EnumFlags::FUNDAMENTAL) {
516 flags.insert(AdtFlags::IS_FUNDAMENTAL);
517 }
518 if data.flags.contains(EnumFlags::HAS_REPR) {
519 flags.insert(AdtFlags::HAS_REPR);
520 if data.repr(db, id).is_some_and(|repr| repr.packed()) {
521 flags.insert(AdtFlags::IS_PACKED);
522 }
523 }
524 AdtDefInner::Enum { id, flags }
525 }
526 };
527 AdtDef(inner)
528 }
529
530 #[inline]
531 pub fn def_id(self) -> AdtId {
532 match self.0 {
533 AdtDefInner::Struct { id, .. } => AdtId::StructId(id),
534 AdtDefInner::Union { id, .. } => AdtId::UnionId(id),
535 AdtDefInner::Enum { id, .. } => AdtId::EnumId(id),
536 }
537 }
538
539 #[inline]
540 fn flags(self) -> AdtFlags {
541 match self.0 {
542 AdtDefInner::Struct { flags, .. }
543 | AdtDefInner::Union { flags, .. }
544 | AdtDefInner::Enum { flags, .. } => flags,
545 }
546 }
547
548 #[inline]
549 pub fn is_struct(self) -> bool {
550 matches!(self.0, AdtDefInner::Struct { .. })
551 }
552
553 #[inline]
554 pub fn is_union(self) -> bool {
555 matches!(self.0, AdtDefInner::Union { .. })
556 }
557
558 #[inline]
559 pub fn is_enum(self) -> bool {
560 matches!(self.0, AdtDefInner::Enum { .. })
561 }
562
563 #[inline]
564 pub fn is_box(self) -> bool {
565 matches!(self.0, AdtDefInner::Struct { flags, .. } if flags.contains(AdtFlags::IS_BOX))
566 }
567
568 #[inline]
569 pub fn repr(self, db: &dyn HirDatabase) -> ReprOptions {
570 if self.flags().contains(AdtFlags::HAS_REPR) {
571 AttrFlags::repr_assume_has(db, self.def_id()).unwrap_or_default()
572 } else {
573 ReprOptions::default()
574 }
575 }
576}
577
578impl<'db> inherent::AdtDef<DbInterner<'db>> for AdtDef {
579 fn def_id(self) -> AdtIdWrapper {
580 self.def_id().into()
581 }
582
583 fn is_struct(self) -> bool {
584 self.is_struct()
585 }
586
587 fn is_phantom_data(self) -> bool {
588 matches!(self.0, AdtDefInner::Struct { flags, .. } if flags.contains(AdtFlags::IS_PHANTOM_DATA))
589 }
590
591 fn is_manually_drop(self) -> bool {
592 matches!(self.0, AdtDefInner::Struct { flags, .. } if flags.contains(AdtFlags::IS_MANUALLY_DROP))
593 }
594
595 fn is_packed(self) -> bool {
596 self.flags().contains(AdtFlags::IS_PACKED)
597 }
598
599 fn is_fundamental(self) -> bool {
600 self.flags().contains(AdtFlags::IS_FUNDAMENTAL)
601 }
602
603 fn struct_tail_ty(
604 self,
605 interner: DbInterner<'db>,
606 ) -> Option<EarlyBinder<DbInterner<'db>, Ty<'db>>> {
607 let hir_def::AdtId::StructId(struct_id) = self.def_id() else {
608 return None;
609 };
610 let id: VariantId = struct_id.into();
611 let field_types = interner.db().field_types(id);
612
613 field_types.iter().last().map(|f| f.1.ty())
614 }
615
616 fn all_field_tys(
617 self,
618 interner: DbInterner<'db>,
619 ) -> EarlyBinder<DbInterner<'db>, impl IntoIterator<Item = Ty<'db>>> {
620 let db = interner.db();
621 let field_tys =
622 |id: VariantId| db.field_types(id).iter().map(|(_, ty)| ty.ty().skip_binder());
623 let tys = match self.def_id() {
624 hir_def::AdtId::StructId(id) => Either::Left(field_tys(id.into())),
625 hir_def::AdtId::UnionId(id) => Either::Left(field_tys(id.into())),
626 hir_def::AdtId::EnumId(id) => Either::Right(
627 id.enum_variants(db)
628 .variants
629 .values()
630 .flat_map(move |&(variant_id, _)| field_tys(variant_id.into())),
631 ),
632 };
633
634 EarlyBinder::bind(tys)
635 }
636
637 fn sizedness_constraint(
638 self,
639 interner: DbInterner<'db>,
640 sizedness: SizedTraitKind,
641 ) -> Option<EarlyBinder<DbInterner<'db>, Ty<'db>>> {
642 let tail_ty = self.struct_tail_ty(interner)?;
643 tail_ty
644 .map_bound(|tail_ty| sizedness_constraint_for_ty(interner, sizedness, tail_ty))
645 .transpose()
646 }
647
648 fn destructor(self, interner: DbInterner<'db>) -> Option<AdtDestructorKind> {
649 crate::drop::destructor(interner.db, self.def_id()).map(|_| AdtDestructorKind::NotConst)
650 }
651
652 fn field_representing_type_info(
653 self,
654 _interner: DbInterner<'db>,
655 _args: GenericArgs<'db>,
656 ) -> Option<rustc_type_ir::FieldInfo<DbInterner<'db>>> {
657 None
659 }
660}
661
662impl fmt::Debug for AdtDef {
663 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
664 crate::with_attached_db(|db| match self.0 {
665 AdtDefInner::Struct { id, .. } => {
666 let data = StructSignature::of(db, id);
667 f.write_str(data.name.as_str())
668 }
669 AdtDefInner::Union { id, .. } => {
670 let data = UnionSignature::of(db, id);
671 f.write_str(data.name.as_str())
672 }
673 AdtDefInner::Enum { id, .. } => {
674 let data = EnumSignature::of(db, id);
675 f.write_str(data.name.as_str())
676 }
677 })
678 }
679}
680
681#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
682pub struct Features;
683
684impl<'db> inherent::Features<DbInterner<'db>> for Features {
685 fn generic_const_exprs(self) -> bool {
686 false
687 }
688
689 fn coroutine_clone(self) -> bool {
690 false
691 }
692
693 fn generic_const_args(self) -> bool {
694 false
695 }
696
697 fn feature_bound_holds_in_crate(self, _symbol: Symbol) -> bool {
698 false
699 }
700}
701
702#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, GenericTypeVisitable)]
703pub struct Symbol;
704
705impl<'db> inherent::Symbol<DbInterner<'db>> for Symbol {
706 fn is_kw_underscore_lifetime(self) -> bool {
707 false
708 }
709}
710
711#[derive(Debug, Clone, Eq, PartialEq, Hash)]
712pub struct UnsizingParams(pub(crate) DenseBitSet<u32>);
713
714impl std::ops::Deref for UnsizingParams {
715 type Target = DenseBitSet<u32>;
716
717 fn deref(&self) -> &Self::Target {
718 &self.0
719 }
720}
721
722pub type PatternKind<'db> = rustc_type_ir::PatternKind<DbInterner<'db>>;
723
724#[derive(Clone, Copy, PartialEq, Eq, Hash)]
725pub struct Pattern<'db> {
726 interned: InternedRef<'db, PatternInterned>,
727}
728
729#[derive(PartialEq, Eq, Hash, GenericTypeVisitable)]
730struct PatternInterned(PatternKind<'static>);
731
732impl_internable!(gc; PatternInterned);
733
734const _: () = {
735 const fn is_copy<T: Copy>() {}
736 is_copy::<Pattern<'static>>();
737};
738
739impl<'db> Pattern<'db> {
740 pub fn new(_interner: DbInterner<'db>, kind: PatternKind<'db>) -> Self {
741 let kind = unsafe { std::mem::transmute::<PatternKind<'db>, PatternKind<'static>>(kind) };
742 Self { interned: Interned::new_gc(PatternInterned(kind)) }
743 }
744
745 pub fn inner(&self) -> &PatternKind<'db> {
746 let inner = &self.interned.0;
747 unsafe { std::mem::transmute::<&PatternKind<'static>, &PatternKind<'db>>(inner) }
748 }
749}
750
751impl<'db> std::fmt::Debug for Pattern<'db> {
752 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
753 self.kind().fmt(f)
754 }
755}
756
757impl<'db> Flags for Pattern<'db> {
758 fn flags(&self) -> TypeFlags {
759 match self.inner() {
760 PatternKind::Range { start, end } => {
761 FlagComputation::for_const_kind(&start.kind()).flags
762 | FlagComputation::for_const_kind(&end.kind()).flags
763 }
764 PatternKind::Or(pats) => {
765 let mut flags = pats.as_slice()[0].flags();
766 for pat in pats.as_slice()[1..].iter() {
767 flags |= pat.flags();
768 }
769 flags
770 }
771 PatternKind::NotNull => TypeFlags::empty(),
772 }
773 }
774
775 fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex {
776 match self.inner() {
777 PatternKind::Range { start, end } => {
778 start.outer_exclusive_binder().max(end.outer_exclusive_binder())
779 }
780 PatternKind::Or(pats) => {
781 let mut idx = pats.as_slice()[0].outer_exclusive_binder();
782 for pat in pats.as_slice()[1..].iter() {
783 idx = idx.max(pat.outer_exclusive_binder());
784 }
785 idx
786 }
787 PatternKind::NotNull => rustc_type_ir::INNERMOST,
788 }
789 }
790}
791
792impl<'db> rustc_type_ir::inherent::IntoKind for Pattern<'db> {
793 type Kind = rustc_type_ir::PatternKind<DbInterner<'db>>;
794 fn kind(self) -> Self::Kind {
795 *self.inner()
796 }
797}
798
799impl<'db> rustc_type_ir::TypeVisitable<DbInterner<'db>> for Pattern<'db> {
800 fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
801 &self,
802 visitor: &mut V,
803 ) -> V::Result {
804 self.kind().visit_with(visitor)
805 }
806}
807
808impl<'db, V: WorldExposer> rustc_type_ir::GenericTypeVisitable<V> for Pattern<'db> {
809 fn generic_visit_with(&self, visitor: &mut V) {
810 if visitor.on_interned(self.interned).is_continue() {
811 self.kind().generic_visit_with(visitor);
812 }
813 }
814}
815
816impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for Pattern<'db> {
817 fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
818 self,
819 folder: &mut F,
820 ) -> Result<Self, F::Error> {
821 Ok(Pattern::new(folder.cx(), self.kind().try_fold_with(folder)?))
822 }
823
824 fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
825 Pattern::new(folder.cx(), self.kind().fold_with(folder))
826 }
827}
828
829impl<'db> rustc_type_ir::relate::Relate<DbInterner<'db>> for Pattern<'db> {
830 fn relate<R: rustc_type_ir::relate::TypeRelation<DbInterner<'db>>>(
831 relation: &mut R,
832 a: Self,
833 b: Self,
834 ) -> rustc_type_ir::relate::RelateResult<DbInterner<'db>, Self> {
835 let tcx = relation.cx();
836 match (a.kind(), b.kind()) {
837 (
838 PatternKind::Range { start: start_a, end: end_a },
839 PatternKind::Range { start: start_b, end: end_b },
840 ) => {
841 let start = relation.relate(start_a, start_b)?;
842 let end = relation.relate(end_a, end_b)?;
843 Ok(Pattern::new(tcx, PatternKind::Range { start, end }))
844 }
845 (PatternKind::Or(a), PatternKind::Or(b)) => {
846 if a.len() != b.len() {
847 return Err(TypeError::Mismatch);
848 }
849 let pats = PatList::new_from_iter(
850 relation.cx(),
851 std::iter::zip(a.iter(), b.iter()).map(|(a, b)| relation.relate(a, b)),
852 )?;
853 Ok(Pattern::new(tcx, PatternKind::Or(pats)))
854 }
855 (PatternKind::NotNull, PatternKind::NotNull) => Ok(a),
856 (PatternKind::Range { .. } | PatternKind::Or(_) | PatternKind::NotNull, _) => {
857 Err(TypeError::Mismatch)
858 }
859 }
860 }
861}
862
863interned_slice!(PatListStorage, PatList, StoredPatList, pat_list, Pattern<'db>, Pattern<'static>);
864impl_foldable_for_interned_slice!(PatList);
865
866macro_rules! as_lang_item {
867 (
868 $solver_enum:ident, $self:ident, $def_id:expr, $id_ty:ty;
869
870 $( $variant:ident ),* $(,)?
871 ) => {{
872 let lang_items = $self.lang_items();
873 if let Some(it) = None::<$solver_enum> {
875 match it {
876 $( $solver_enum::$variant => {} )*
877 }
878 }
879 match $def_id {
880 $( def_id if let Some(it) = lang_items.$variant && <$id_ty>::from(it) == def_id => Some($solver_enum::$variant), )*
881 _ => None
882 }
883 }};
884}
885
886macro_rules! is_lang_item {
887 (
888 $solver_enum:ident, $self:ident, $def_id:expr, $expected_variant:ident;
889
890 $( $variant:ident ),* $(,)?
891 ) => {{
892 let lang_items = $self.lang_items();
893 let def_id = $def_id;
894 match $expected_variant {
895 $( $solver_enum::$variant => lang_items.$variant.is_some_and(|it| it == def_id), )*
896 }
897 }};
898}
899
900impl<'db> Interner for DbInterner<'db> {
901 type DefId = SolverDefId<'db>;
902 type LocalDefId = SolverDefId<'db>;
903 type LocalDefIds = SolverDefIds<'db>;
904 type TraitId = TraitIdWrapper;
905 type ForeignId = TypeAliasIdWrapper;
906 type FunctionId = CallableIdWrapper;
907 type ClosureId = ClosureIdWrapper<'db>;
908 type CoroutineClosureId = CoroutineClosureIdWrapper<'db>;
909 type CoroutineId = CoroutineIdWrapper<'db>;
910 type AdtId = AdtIdWrapper;
911 type ImplId = AnyImplId;
912 type UnevaluatedConstId = GeneralConstIdWrapper<'db>;
913 type TraitAssocTyId = TraitAssocTyId;
914 type TraitAssocConstId = TraitAssocConstId;
915 type TraitAssocTermId = TraitAssocTermId;
916 type OpaqueTyId = OpaqueTyIdWrapper<'db>;
917 type LocalOpaqueTyId = OpaqueTyIdWrapper<'db>;
918 type FreeTyAliasId = FreeTyAliasId;
919 type FreeConstAliasId = FreeConstAliasId;
920 type FreeTermAliasId = FreeTermAliasId;
921 type ImplOrTraitAssocTyId = ImplOrTraitAssocTyId;
922 type ImplOrTraitAssocConstId = ImplOrTraitAssocConstId;
923 type ImplOrTraitAssocTermId = ImplOrTraitAssocTermId;
924 type InherentAssocTyId = InherentAssocTyId;
925 type InherentAssocConstId = InherentAssocConstId;
926 type InherentAssocTermId = InherentAssocTermId;
927 type Span = Span;
928
929 type GenericArgs = GenericArgs<'db>;
930 type GenericArgsSlice = &'db [GenericArg<'db>];
931 type GenericArg = GenericArg<'db>;
932
933 type Term = Term<'db>;
934
935 type BoundVarKinds = BoundVarKinds<'db>;
936
937 type PredefinedOpaques = PredefinedOpaques<'db>;
938
939 fn mk_predefined_opaques_in_body(
940 self,
941 data: &[(OpaqueTypeKey<'db>, Self::Ty)],
942 ) -> Self::PredefinedOpaques {
943 PredefinedOpaques::new_from_slice(data)
944 }
945
946 type CanonicalVarKinds = CanonicalVarKinds<'db>;
947
948 fn mk_canonical_var_kinds(
949 self,
950 kinds: &[rustc_type_ir::CanonicalVarKind<Self>],
951 ) -> Self::CanonicalVarKinds {
952 CanonicalVarKinds::new_from_slice(kinds)
953 }
954
955 type ExternalConstraints = ExternalConstraints<'db>;
956
957 fn mk_external_constraints(
958 self,
959 data: rustc_type_ir::solve::ExternalConstraintsData<Self>,
960 ) -> Self::ExternalConstraints {
961 ExternalConstraints::new(self, data)
962 }
963
964 type DepNodeIndex = DepNodeIndex;
965
966 type Tracked<T: fmt::Debug + Clone> = Tracked<T>;
967
968 type Ty = Ty<'db>;
969 type Tys = Tys<'db>;
970 type FnInputTys = &'db [Ty<'db>];
971 type ParamTy = ParamTy;
972 type Symbol = Symbol;
973
974 type ErrorGuaranteed = ErrorGuaranteed;
975 type BoundExistentialPredicates = BoundExistentialPredicates<'db>;
976 type AllocId = AllocId;
977 type Pat = Pattern<'db>;
978 type PatList = PatList<'db>;
979 type Safety = Safety;
980
981 type Const = Const<'db>;
982 type ParamConst = ParamConst;
983 type ValueConst = ValueConst<'db>;
984 type ValTree = ValTree<'db>;
985 type Consts = Consts<'db>;
986 type ScalarInt = ScalarInt;
987 type ExprConst = ExprConst;
988
989 type Region = Region<'db>;
990 type EarlyParamRegion = EarlyParamRegion;
991 type LateParamRegion = LateParamRegion<'db>;
992
993 type RegionAssumptions = RegionAssumptions<'db>;
994
995 type ParamEnv = ParamEnv<'db>;
996 type Predicate = Predicate<'db>;
997 type Clause = Clause<'db>;
998 type Clauses = Clauses<'db>;
999
1000 type GenericsOf = Generics<'db>;
1001
1002 type VariancesOf = VariancesOf<'db>;
1003
1004 type AdtDef = AdtDef;
1005
1006 type Features = Features;
1007
1008 fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs {
1009 GenericArgs::new_from_slice(args)
1010 }
1011
1012 fn mk_args_from_iter<I, T>(self, args: I) -> T::Output
1013 where
1014 I: Iterator<Item = T>,
1015 T: rustc_type_ir::CollectAndApply<Self::GenericArg, Self::GenericArgs>,
1016 {
1017 GenericArgs::new_from_iter(self, args)
1018 }
1019
1020 type UnsizingParams = UnsizingParams;
1021
1022 fn mk_tracked<T: fmt::Debug + Clone>(
1023 self,
1024 data: T,
1025 _dep_node: Self::DepNodeIndex,
1026 ) -> Self::Tracked<T> {
1027 Tracked(data)
1028 }
1029
1030 fn get_tracked<T: fmt::Debug + Clone>(self, tracked: &Self::Tracked<T>) -> T {
1031 tracked.0.clone()
1032 }
1033
1034 fn with_cached_task<T>(self, task: impl FnOnce() -> T) -> (T, Self::DepNodeIndex) {
1035 (task(), DepNodeIndex)
1036 }
1037
1038 fn with_global_cache<R>(
1039 self,
1040 f: impl FnOnce(&mut rustc_type_ir::search_graph::GlobalCache<Self>) -> R,
1041 ) -> R {
1042 tls_cache::borrow_assume_valid(self.db, f)
1044 }
1045
1046 fn canonical_param_env_cache_get_or_insert<R>(
1047 self,
1048 _param_env: Self::ParamEnv,
1049 f: impl FnOnce() -> rustc_type_ir::CanonicalParamEnvCacheEntry<Self>,
1050 from_entry: impl FnOnce(&rustc_type_ir::CanonicalParamEnvCacheEntry<Self>) -> R,
1051 ) -> R {
1052 from_entry(&f())
1053 }
1054
1055 fn assert_evaluation_is_concurrent(&self) {
1056 panic!("evaluation shouldn't be concurrent yet")
1057 }
1058
1059 fn expand_abstract_consts<T: rustc_type_ir::TypeFoldable<Self>>(self, _: T) -> T {
1060 unreachable!("only used by the old trait solver in rustc");
1061 }
1062
1063 fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf {
1064 generics(self, def_id)
1065 }
1066
1067 fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf {
1068 let generic_def = match def_id {
1069 SolverDefId::Ctor(Ctor::Enum(def_id)) | SolverDefId::EnumVariantId(def_id) => {
1070 def_id.loc(self.db).parent.into()
1071 }
1072 SolverDefId::InternedOpaqueTyId(_def_id) => {
1073 return VariancesOf::new_from_iter(
1078 self,
1079 (0..self.generics_of(def_id).count()).map(|_| Variance::Invariant),
1080 );
1081 }
1082 SolverDefId::Ctor(Ctor::Struct(def_id)) => def_id.into(),
1083 SolverDefId::AdtId(def_id) => def_id.into(),
1084 SolverDefId::FunctionId(def_id) => def_id.into(),
1085 SolverDefId::ConstId(_)
1086 | SolverDefId::StaticId(_)
1087 | SolverDefId::TraitId(_)
1088 | SolverDefId::TypeAliasId(_)
1089 | SolverDefId::ImplId(_)
1090 | SolverDefId::BuiltinDeriveImplId(_)
1091 | SolverDefId::InternedClosureId(_)
1092 | SolverDefId::InternedCoroutineId(_)
1093 | SolverDefId::InternedCoroutineClosureId(_)
1094 | SolverDefId::AnonConstId(_) => {
1095 return VariancesOf::empty(self);
1096 }
1097 };
1098 self.db.variances_of(generic_def)
1099 }
1100
1101 fn type_of(self, def_id: Self::DefId) -> EarlyBinder<Self, Self::Ty> {
1102 match def_id {
1103 SolverDefId::TypeAliasId(id) => self.db().ty(id.into()),
1104 SolverDefId::AdtId(id) => self.db().ty(id.into()),
1105 SolverDefId::InternedOpaqueTyId(def_id) => {
1110 self.type_of_opaque_hir_typeck(def_id.into())
1111 }
1112 SolverDefId::FunctionId(id) => self.db.value_ty(id.into()).unwrap(),
1113 SolverDefId::Ctor(id) => {
1114 let id = match id {
1115 Ctor::Struct(id) => id.into(),
1116 Ctor::Enum(id) => id.into(),
1117 };
1118 self.db.value_ty(id).expect("`SolverDefId::Ctor` should have a function-like ctor")
1119 }
1120 _ => panic!("Unexpected def_id `{def_id:?}` provided for `type_of`"),
1121 }
1122 }
1123
1124 fn adt_def(self, def_id: Self::AdtId) -> Self::AdtDef {
1125 AdtDef::new(def_id.0, self)
1126 }
1127
1128 fn alias_term_kind_from_def_id(self, def_id: SolverDefId<'db>) -> AliasTermKind<'db> {
1129 match def_id {
1130 SolverDefId::InternedOpaqueTyId(def_id) => {
1131 AliasTermKind::OpaqueTy { def_id: def_id.into() }
1132 }
1133 SolverDefId::TypeAliasId(type_alias) => match type_alias.loc(self.db).container {
1134 ItemContainerId::ImplId(impl_)
1135 if ImplSignature::of(self.db, impl_).target_trait.is_none() =>
1136 {
1137 AliasTermKind::InherentTy { def_id: type_alias.into() }
1138 }
1139 ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => {
1140 AliasTermKind::ProjectionTy { def_id: type_alias.into() }
1141 }
1142 _ => AliasTermKind::FreeTy { def_id: type_alias.into() },
1143 },
1144 SolverDefId::ConstId(def_id) => {
1147 AliasTermKind::UnevaluatedConst { def_id: GeneralConstIdWrapper(def_id.into()) }
1148 }
1149 SolverDefId::StaticId(def_id) => {
1150 AliasTermKind::UnevaluatedConst { def_id: GeneralConstIdWrapper(def_id.into()) }
1151 }
1152 SolverDefId::AnonConstId(def_id) => {
1153 AliasTermKind::UnevaluatedConst { def_id: GeneralConstIdWrapper(def_id.into()) }
1154 }
1155 _ => unimplemented!("Unexpected alias: {:?}", def_id),
1156 }
1157 }
1158
1159 fn trait_ref_and_own_args_for_alias(
1160 self,
1161 def_id: Self::TraitAssocTermId,
1162 args: Self::GenericArgs,
1163 ) -> (rustc_type_ir::TraitRef<Self>, Self::GenericArgsSlice) {
1164 let trait_def_id = self.projection_parent(def_id).0;
1165 let trait_generics = crate::generics::generics(self.db, trait_def_id.into());
1166 let trait_generics_len = trait_generics.len(true);
1167 let trait_args = GenericArgs::new_from_slice(&args.as_slice()[..trait_generics_len]);
1168 let alias_args = &args.as_slice()[trait_generics_len..];
1169 (TraitRef::new_from_args(self, trait_def_id.into(), trait_args), alias_args)
1170 }
1171
1172 fn check_args_compatible(self, def_id: Self::DefId, args: Self::GenericArgs) -> bool {
1173 let generics = self.generics_of(def_id);
1174 generics.count() == args.len()
1175 && std::iter::zip(generics.iter(), args).all(|((param, _), arg)| {
1176 matches!(
1177 (param, arg.kind()),
1178 (GenericParamId::LifetimeParamId(_), GenericArgKind::Lifetime(_))
1179 | (GenericParamId::TypeParamId(_), GenericArgKind::Type(_))
1180 | (GenericParamId::ConstParamId(_), GenericArgKind::Const(_))
1181 )
1182 })
1183 }
1184
1185 fn debug_assert_args_compatible(self, _def_id: Self::DefId, _args: Self::GenericArgs) {}
1186
1187 fn debug_assert_existential_args_compatible(
1188 self,
1189 _def_id: Self::DefId,
1190 _args: Self::GenericArgs,
1191 ) {
1192 }
1193
1194 fn mk_type_list_from_iter<I, T>(self, args: I) -> T::Output
1195 where
1196 I: Iterator<Item = T>,
1197 T: rustc_type_ir::CollectAndApply<Self::Ty, Self::Tys>,
1198 {
1199 Tys::new_from_iter(self, args)
1200 }
1201
1202 fn projection_parent(self, def_id: Self::TraitAssocTermId) -> Self::TraitId {
1203 let container = match def_id.0 {
1204 TermId::TypeAliasId(def_id) => def_id.loc(self.db).container,
1205 TermId::ConstId(def_id) => def_id.loc(self.db).container,
1206 };
1207 let ItemContainerId::TraitId(trait_) = container else {
1208 panic!("a TraitAssocTermId can only come from a trait")
1209 };
1210 trait_.into()
1211 }
1212
1213 fn impl_or_trait_assoc_term_parent(self, def_id: Self::ImplOrTraitAssocTermId) -> Self::DefId {
1214 let container = match def_id.0 {
1215 TermId::TypeAliasId(def_id) => def_id.loc(self.db).container,
1216 TermId::ConstId(def_id) => def_id.loc(self.db).container,
1217 };
1218 match container {
1219 ItemContainerId::ImplId(impl_) => impl_.into(),
1220 ItemContainerId::TraitId(trait_) => trait_.into(),
1221 ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => {
1222 panic!("only impl or trait can be the parent of ImplOrTraitAssocTermId")
1223 }
1224 }
1225 }
1226
1227 fn inherent_alias_term_parent(self, def_id: Self::InherentAssocTermId) -> Self::ImplId {
1228 let container = match def_id.0 {
1229 TermId::TypeAliasId(def_id) => def_id.loc(self.db).container,
1230 TermId::ConstId(def_id) => def_id.loc(self.db).container,
1231 };
1232 match container {
1233 ItemContainerId::ImplId(impl_) => impl_.into(),
1234 ItemContainerId::ExternBlockId(_)
1235 | ItemContainerId::ModuleId(_)
1236 | ItemContainerId::TraitId(_) => {
1237 panic!("only impl can be the parent of InherentAliasTermId")
1238 }
1239 }
1240 }
1241
1242 fn recursion_limit(self) -> usize {
1243 50
1244 }
1245
1246 fn is_type_const(self, _def_id: Self::DefId) -> bool {
1247 false
1248 }
1249
1250 fn features(self) -> Features {
1251 Features
1252 }
1253
1254 fn fn_sig(
1255 self,
1256 def_id: Self::FunctionId,
1257 ) -> EarlyBinder<Self, rustc_type_ir::Binder<Self, rustc_type_ir::FnSig<Self>>> {
1258 self.db().callable_item_signature(def_id.0)
1259 }
1260
1261 fn coroutine_movability(self, def_id: Self::CoroutineId) -> rustc_ast_ir::Movability {
1262 match def_id.0.loc(self.db).kind {
1263 hir_def::hir::ClosureKind::OldCoroutine(movability) => match movability {
1264 hir_def::hir::Movability::Static => rustc_ast_ir::Movability::Static,
1265 hir_def::hir::Movability::Movable => rustc_ast_ir::Movability::Movable,
1266 },
1267 hir_def::hir::ClosureKind::Coroutine { .. } => rustc_ast_ir::Movability::Static,
1268 kind => panic!("unexpected kind for a coroutine: {kind:?}"),
1269 }
1270 }
1271
1272 fn coroutine_for_closure(self, def_id: Self::CoroutineClosureId) -> Self::CoroutineId {
1273 let InternedClosure { owner, expr: coroutine_closure_expr, kind: coroutine_closure_kind } =
1274 def_id.0.loc(self.db);
1275 let coroutine_closure_kind = match coroutine_closure_kind {
1276 HirClosureKind::CoroutineClosure(it) => it,
1277 _ => {
1278 panic!("invalid kind closure kind {coroutine_closure_kind:?} for coroutine closure")
1279 }
1280 };
1281 let coroutine_expr = ExpressionStore::coroutine_for_closure(coroutine_closure_expr);
1282 let coroutine_kind = hir_def::hir::ClosureKind::Coroutine {
1283 kind: coroutine_closure_kind,
1284 source: hir_def::hir::CoroutineSource::Closure,
1285 };
1286 InternedCoroutineId::new(
1287 self.db,
1288 InternedClosure { owner, expr: coroutine_expr, kind: coroutine_kind },
1289 )
1290 .into()
1291 }
1292
1293 fn generics_require_sized_self(self, def_id: Self::DefId) -> bool {
1294 let sized_trait = self.lang_items().Sized;
1295 let Some(sized_id) = sized_trait else {
1296 return false; };
1298 let sized_def_id = sized_id.into();
1299
1300 let predicates = self.predicates_of(def_id);
1302 elaborate(self, predicates.iter_identity().map(Unnormalized::skip_norm_wip)).any(|pred| {
1303 match pred.kind().skip_binder() {
1304 ClauseKind::Trait(ref trait_pred) => {
1305 trait_pred.def_id() == sized_def_id
1306 && matches!(
1307 trait_pred.self_ty().kind(),
1308 TyKind::Param(ParamTy { index: 0, .. })
1309 )
1310 }
1311 ClauseKind::RegionOutlives(_)
1312 | ClauseKind::TypeOutlives(_)
1313 | ClauseKind::Projection(_)
1314 | ClauseKind::ConstArgHasType(_, _)
1315 | ClauseKind::WellFormed(_)
1316 | ClauseKind::ConstEvaluatable(_)
1317 | ClauseKind::HostEffect(..)
1318 | ClauseKind::UnstableFeature(_) => false,
1319 }
1320 })
1321 }
1322
1323 #[tracing::instrument(skip(self))]
1324 fn item_bounds(
1325 self,
1326 def_id: Self::DefId,
1327 ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1328 explicit_item_bounds(self, def_id).map_bound(|bounds| elaborate(self, bounds))
1329 }
1330
1331 #[tracing::instrument(skip(self))]
1332 fn item_self_bounds(
1333 self,
1334 def_id: Self::DefId,
1335 ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1336 explicit_item_self_bounds(self, def_id)
1337 .map_bound(|bounds| elaborate(self, bounds).filter_only_self())
1338 }
1339
1340 fn item_non_self_bounds(
1341 self,
1342 def_id: Self::DefId,
1343 ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1344 let all_bounds: FxHashSet<_> = self.item_bounds(def_id).skip_binder().into_iter().collect();
1345 let own_bounds: FxHashSet<_> =
1346 self.item_self_bounds(def_id).skip_binder().into_iter().collect();
1347 if all_bounds.len() == own_bounds.len() {
1348 EarlyBinder::bind(Clauses::empty(self))
1349 } else {
1350 EarlyBinder::bind(Clauses::new_from_iter(
1351 self,
1352 all_bounds.difference(&own_bounds).cloned(),
1353 ))
1354 }
1355 }
1356
1357 fn predicates_of(
1358 self,
1359 def_id: Self::DefId,
1360 ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1361 predicates_of(self.db, def_id).all_predicates()
1362 }
1363
1364 fn own_predicates_of(
1365 self,
1366 def_id: Self::DefId,
1367 ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1368 predicates_of(self.db, def_id).own_explicit_predicates()
1369 }
1370
1371 fn explicit_super_predicates_of(
1372 self,
1373 def_id: Self::TraitId,
1374 ) -> EarlyBinder<Self, impl IntoIterator<Item = (Self::Clause, Self::Span)>> {
1375 GenericPredicates::query(self.db, def_id.0.into())
1376 .explicit_non_assoc_types_predicates()
1377 .map_bound(move |predicates| {
1378 predicates.filter(|p| is_clause_at_ty(p, is_ty_self)).map(|p| (p, Span::dummy()))
1379 })
1380 }
1381
1382 fn explicit_implied_predicates_of(
1383 self,
1384 def_id: Self::DefId,
1385 ) -> EarlyBinder<Self, impl IntoIterator<Item = (Self::Clause, Self::Span)>> {
1386 fn is_ty_assoc_of_self(ty: Ty<'_>) -> bool {
1387 if let TyKind::Alias(alias @ AliasTy { kind: AliasTyKind::Projection { .. }, .. }) =
1390 ty.kind()
1391 {
1392 is_ty_assoc_of_self(alias.self_ty())
1393 } else {
1394 is_ty_self(ty)
1395 }
1396 }
1397
1398 let predicates = predicates_of(self.db, def_id);
1399 let non_assoc_types = predicates
1400 .explicit_non_assoc_types_predicates()
1401 .skip_binder()
1402 .filter(|p| is_clause_at_ty(p, is_ty_self));
1403 let assoc_types = predicates
1404 .explicit_assoc_types_predicates()
1405 .skip_binder()
1406 .filter(|p| is_clause_at_ty(p, is_ty_assoc_of_self));
1407 EarlyBinder::bind(non_assoc_types.chain(assoc_types).map(|it| (it, Span::dummy())))
1408 }
1409
1410 fn impl_super_outlives(
1411 self,
1412 impl_id: Self::ImplId,
1413 ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1414 let trait_ref = self.impl_trait_ref(impl_id);
1415 trait_ref.map_bound(|trait_ref| {
1416 let clause: Clause<'_> = trait_ref.upcast(self);
1417 elaborate(self, [clause]).filter(|clause| {
1418 matches!(
1419 clause.kind().skip_binder(),
1420 ClauseKind::TypeOutlives(_) | ClauseKind::RegionOutlives(_)
1421 )
1422 })
1423 })
1424 }
1425
1426 #[expect(unreachable_code)]
1427 fn const_conditions(
1428 self,
1429 _def_id: Self::DefId,
1430 ) -> EarlyBinder<
1431 Self,
1432 impl IntoIterator<Item = rustc_type_ir::Binder<Self, rustc_type_ir::TraitRef<Self>>>,
1433 > {
1434 EarlyBinder::bind([unimplemented!()])
1435 }
1436
1437 fn has_target_features(self, _def_id: Self::FunctionId) -> bool {
1438 false
1439 }
1440
1441 fn require_projection_lang_item(
1442 self,
1443 lang_item: SolverProjectionLangItem,
1444 ) -> Self::TraitAssocTyId {
1445 let lang_items = self.lang_items();
1446 let lang_item = match lang_item {
1447 SolverProjectionLangItem::AsyncFnKindUpvars => lang_items.AsyncFnKindUpvars,
1448 SolverProjectionLangItem::AsyncFnOnceOutput => lang_items.AsyncFnOnceOutput,
1449 SolverProjectionLangItem::CallOnceFuture => lang_items.CallOnceFuture,
1450 SolverProjectionLangItem::CallRefFuture => lang_items.CallRefFuture,
1451 SolverProjectionLangItem::CoroutineReturn => lang_items.CoroutineReturn,
1452 SolverProjectionLangItem::CoroutineYield => lang_items.CoroutineYield,
1453 SolverProjectionLangItem::FutureOutput => lang_items.FutureOutput,
1454 SolverProjectionLangItem::Metadata => lang_items.Metadata,
1455 SolverProjectionLangItem::FieldBase => lang_items.FieldBase,
1456 SolverProjectionLangItem::FieldType => lang_items.FieldType,
1457 };
1458 lang_item.expect("Lang item required but not found.").into()
1459 }
1460
1461 fn require_trait_lang_item(self, lang_item: SolverTraitLangItem) -> TraitIdWrapper {
1462 let lang_items = self.lang_items();
1463 let lang_item = match lang_item {
1464 SolverTraitLangItem::AsyncFn => lang_items.AsyncFn,
1465 SolverTraitLangItem::AsyncFnKindHelper => lang_items.AsyncFnKindHelper,
1466 SolverTraitLangItem::AsyncFnMut => lang_items.AsyncFnMut,
1467 SolverTraitLangItem::AsyncFnOnce => lang_items.AsyncFnOnce,
1468 SolverTraitLangItem::AsyncIterator => lang_items.AsyncIterator,
1469 SolverTraitLangItem::Clone => lang_items.Clone,
1470 SolverTraitLangItem::Copy => lang_items.Copy,
1471 SolverTraitLangItem::Coroutine => lang_items.Coroutine,
1472 SolverTraitLangItem::Destruct => lang_items.Destruct,
1473 SolverTraitLangItem::DiscriminantKind => lang_items.DiscriminantKind,
1474 SolverTraitLangItem::Drop => lang_items.Drop,
1475 SolverTraitLangItem::Fn => lang_items.Fn,
1476 SolverTraitLangItem::FnMut => lang_items.FnMut,
1477 SolverTraitLangItem::FnOnce => lang_items.FnOnce,
1478 SolverTraitLangItem::FnPtrTrait => lang_items.FnPtrTrait,
1479 SolverTraitLangItem::FusedIterator => lang_items.FusedIterator,
1480 SolverTraitLangItem::Future => lang_items.Future,
1481 SolverTraitLangItem::Iterator => lang_items.Iterator,
1482 SolverTraitLangItem::PointeeTrait => lang_items.PointeeTrait,
1483 SolverTraitLangItem::Sized => lang_items.Sized,
1484 SolverTraitLangItem::MetaSized => lang_items.MetaSized,
1485 SolverTraitLangItem::PointeeSized => lang_items.PointeeSized,
1486 SolverTraitLangItem::TransmuteTrait => lang_items.TransmuteTrait,
1487 SolverTraitLangItem::Tuple => lang_items.Tuple,
1488 SolverTraitLangItem::Unpin => lang_items.Unpin,
1489 SolverTraitLangItem::Unsize => lang_items.Unsize,
1490 SolverTraitLangItem::BikeshedGuaranteedNoDrop => lang_items.BikeshedGuaranteedNoDrop,
1491 SolverTraitLangItem::TrivialClone => lang_items.TrivialClone,
1492 SolverTraitLangItem::Field => lang_items.Field,
1493 };
1494 lang_item.expect("Lang item required but not found.").into()
1495 }
1496
1497 fn require_adt_lang_item(self, lang_item: SolverAdtLangItem) -> AdtIdWrapper {
1498 let lang_items = self.lang_items();
1499 let lang_item = match lang_item {
1500 SolverAdtLangItem::Option => lang_items.Option.map(Into::into),
1501 SolverAdtLangItem::Poll => lang_items.Poll.map(Into::into),
1502 SolverAdtLangItem::DynMetadata => lang_items.DynMetadata.map(Into::into),
1503 };
1504 AdtIdWrapper(lang_item.expect("Lang item required but not found."))
1505 }
1506
1507 fn is_projection_lang_item(
1508 self,
1509 def_id: Self::TraitAssocTyId,
1510 lang_item: SolverProjectionLangItem,
1511 ) -> bool {
1512 self.as_projection_lang_item(def_id)
1513 .map_or(false, |l| std::mem::discriminant(&l) == std::mem::discriminant(&lang_item))
1514 }
1515
1516 fn is_trait_lang_item(self, def_id: Self::TraitId, lang_item: SolverTraitLangItem) -> bool {
1517 is_lang_item!(
1518 SolverTraitLangItem, self, def_id.0, lang_item;
1519
1520 Sized,
1521 MetaSized,
1522 PointeeSized,
1523 Unsize,
1524 Copy,
1525 Clone,
1526 DiscriminantKind,
1527 PointeeTrait,
1528 FnPtrTrait,
1529 Drop,
1530 Destruct,
1531 TransmuteTrait,
1532 Fn,
1533 FnMut,
1534 FnOnce,
1535 Future,
1536 Coroutine,
1537 Unpin,
1538 Tuple,
1539 Iterator,
1540 AsyncFn,
1541 AsyncFnMut,
1542 AsyncFnOnce,
1543 TrivialClone,
1544 AsyncFnKindHelper,
1545 AsyncIterator,
1546 BikeshedGuaranteedNoDrop,
1547 FusedIterator,
1548 Field,
1549 )
1550 }
1551
1552 fn is_adt_lang_item(self, def_id: Self::AdtId, lang_item: SolverAdtLangItem) -> bool {
1553 self.as_adt_lang_item(def_id)
1555 .map_or(false, |l| std::mem::discriminant(&l) == std::mem::discriminant(&lang_item))
1556 }
1557
1558 fn as_projection_lang_item(
1559 self,
1560 def_id: Self::TraitAssocTyId,
1561 ) -> Option<SolverProjectionLangItem> {
1562 as_lang_item!(
1563 SolverProjectionLangItem, self, def_id.0, TypeAliasId;
1564
1565 Metadata,
1566 CoroutineReturn,
1567 CoroutineYield,
1568 FutureOutput,
1569 CallRefFuture,
1570 CallOnceFuture,
1571 AsyncFnOnceOutput,
1572 AsyncFnKindUpvars,
1573 FieldBase,
1574 FieldType,
1575 )
1576 }
1577
1578 fn as_trait_lang_item(self, def_id: Self::TraitId) -> Option<SolverTraitLangItem> {
1579 as_lang_item!(
1580 SolverTraitLangItem, self, def_id.0, TraitId;
1581
1582 Sized,
1583 MetaSized,
1584 PointeeSized,
1585 Unsize,
1586 Copy,
1587 Clone,
1588 DiscriminantKind,
1589 PointeeTrait,
1590 FnPtrTrait,
1591 Drop,
1592 Destruct,
1593 TransmuteTrait,
1594 Fn,
1595 FnMut,
1596 FnOnce,
1597 Future,
1598 Coroutine,
1599 Unpin,
1600 Tuple,
1601 Iterator,
1602 AsyncFn,
1603 AsyncFnMut,
1604 AsyncFnOnce,
1605 TrivialClone,
1606 AsyncFnKindHelper,
1607 AsyncIterator,
1608 BikeshedGuaranteedNoDrop,
1609 FusedIterator,
1610 Field,
1611 )
1612 }
1613
1614 fn as_adt_lang_item(self, def_id: Self::AdtId) -> Option<SolverAdtLangItem> {
1615 as_lang_item!(
1616 SolverAdtLangItem, self, def_id.0, AdtId;
1617
1618 Option,
1619 Poll,
1620 DynMetadata,
1621 )
1622 }
1623
1624 fn associated_type_def_ids(
1625 self,
1626 def_id: Self::TraitId,
1627 ) -> impl IntoIterator<Item = Self::DefId> {
1628 def_id.0.trait_items(self.db()).associated_types().map(|id| id.into())
1629 }
1630
1631 fn for_each_relevant_impl<R: VisitorResult>(
1632 self,
1633 trait_def_id: Self::TraitId,
1634 self_ty: Self::Ty,
1635 mut f: impl FnMut(Self::ImplId) -> R,
1636 ) -> R {
1637 let krate = self.krate.expect("trait solving requires setting `DbInterner::krate`");
1638 let trait_block = trait_def_id.0.loc(self.db).container.block(self.db);
1639 let mut consider_impls_for_simplified_type = |simp: SimplifiedType<'_>| {
1640 let type_block = simp.def().and_then(|def_id| {
1641 let module = match def_id {
1642 SolverDefId::AdtId(AdtId::StructId(id)) => id.module(self.db),
1643 SolverDefId::AdtId(AdtId::EnumId(id)) => id.module(self.db),
1644 SolverDefId::AdtId(AdtId::UnionId(id)) => id.module(self.db),
1645 SolverDefId::TraitId(id) => id.module(self.db),
1646 SolverDefId::TypeAliasId(id) => id.module(self.db),
1647 SolverDefId::ConstId(_)
1648 | SolverDefId::FunctionId(_)
1649 | SolverDefId::ImplId(_)
1650 | SolverDefId::BuiltinDeriveImplId(_)
1651 | SolverDefId::StaticId(_)
1652 | SolverDefId::InternedClosureId(_)
1653 | SolverDefId::InternedCoroutineId(_)
1654 | SolverDefId::InternedCoroutineClosureId(_)
1655 | SolverDefId::InternedOpaqueTyId(_)
1656 | SolverDefId::EnumVariantId(_)
1657 | SolverDefId::AnonConstId(_)
1658 | SolverDefId::Ctor(_) => return None,
1659 };
1660 module.block(self.db)
1661 });
1662 TraitImpls::for_each_crate_and_block_trait_and_type(
1663 self.db,
1664 krate,
1665 type_block,
1666 trait_block,
1667 &mut |impls| {
1668 let (regular_impls, builtin_derive_impls) =
1669 impls.for_trait_and_self_ty(trait_def_id.0, &simp);
1670 for &impl_ in regular_impls {
1671 try_visit!(f(impl_.into()));
1672 }
1673 for &impl_ in builtin_derive_impls {
1674 try_visit!(f(impl_.into()));
1675 }
1676 R::output()
1677 },
1678 )
1679 };
1680
1681 match self_ty.kind() {
1682 TyKind::Bool
1683 | TyKind::Char
1684 | TyKind::Int(_)
1685 | TyKind::Uint(_)
1686 | TyKind::Float(_)
1687 | TyKind::Adt(_, _)
1688 | TyKind::Foreign(_)
1689 | TyKind::Str
1690 | TyKind::Array(_, _)
1691 | TyKind::Pat(_, _)
1692 | TyKind::Slice(_)
1693 | TyKind::RawPtr(_, _)
1694 | TyKind::Ref(_, _, _)
1695 | TyKind::FnDef(_, _)
1696 | TyKind::FnPtr(..)
1697 | TyKind::Dynamic(_, _)
1698 | TyKind::Closure(..)
1699 | TyKind::CoroutineClosure(..)
1700 | TyKind::Coroutine(_, _)
1701 | TyKind::Never
1702 | TyKind::Tuple(_)
1703 | TyKind::UnsafeBinder(_) => {
1704 let simp =
1705 fast_reject::simplify_type(self, self_ty, fast_reject::TreatParams::AsRigid)
1706 .unwrap();
1707 try_visit!(consider_impls_for_simplified_type(simp));
1708 }
1709
1710 TyKind::Infer(InferTy::IntVar(_)) => {
1713 use IntTy::*;
1714 use UintTy::*;
1715 let (I8 | I16 | I32 | I64 | I128 | Isize): IntTy;
1717 let (U8 | U16 | U32 | U64 | U128 | Usize): UintTy;
1718 let possible_integers = [
1719 SimplifiedType::Int(I8),
1721 SimplifiedType::Int(I16),
1722 SimplifiedType::Int(I32),
1723 SimplifiedType::Int(I64),
1724 SimplifiedType::Int(I128),
1725 SimplifiedType::Int(Isize),
1726 SimplifiedType::Uint(U8),
1728 SimplifiedType::Uint(U16),
1729 SimplifiedType::Uint(U32),
1730 SimplifiedType::Uint(U64),
1731 SimplifiedType::Uint(U128),
1732 SimplifiedType::Uint(Usize),
1733 ];
1734 for simp in possible_integers {
1735 try_visit!(consider_impls_for_simplified_type(simp));
1736 }
1737 }
1738
1739 TyKind::Infer(InferTy::FloatVar(_)) => {
1740 let (FloatTy::F16 | FloatTy::F32 | FloatTy::F64 | FloatTy::F128);
1742 let possible_floats = [
1743 SimplifiedType::Float(FloatTy::F16),
1744 SimplifiedType::Float(FloatTy::F32),
1745 SimplifiedType::Float(FloatTy::F64),
1746 SimplifiedType::Float(FloatTy::F128),
1747 ];
1748
1749 for simp in possible_floats {
1750 try_visit!(consider_impls_for_simplified_type(simp));
1751 }
1752 }
1753
1754 TyKind::Alias(..) | TyKind::Placeholder(..) | TyKind::Error(_) => (),
1759
1760 TyKind::CoroutineWitness(..) => (),
1764
1765 TyKind::Infer(
1767 InferTy::TyVar(_)
1768 | InferTy::FreshTy(_)
1769 | InferTy::FreshIntTy(_)
1770 | InferTy::FreshFloatTy(_),
1771 )
1772 | TyKind::Param(_)
1773 | TyKind::Bound(_, _) => panic!("unexpected self type: {self_ty:?}"),
1774 }
1775
1776 self.for_each_blanket_impl(trait_def_id, f)
1777 }
1778
1779 fn for_each_blanket_impl<R: VisitorResult>(
1780 self,
1781 trait_def_id: Self::TraitId,
1782 mut f: impl FnMut(Self::ImplId) -> R,
1783 ) -> R {
1784 let Some(krate) = self.krate else {
1785 return R::output();
1786 };
1787 let block = trait_def_id.0.loc(self.db).container.block(self.db);
1788
1789 TraitImpls::for_each_crate_and_block(self.db, krate, block, &mut |impls| {
1790 for &impl_ in impls.blanket_impls(trait_def_id.0) {
1791 try_visit!(f(impl_.into()));
1792 }
1793 R::output()
1794 })
1795 }
1796
1797 fn has_item_definition(self, _def_id: Self::ImplOrTraitAssocTermId) -> bool {
1798 true
1800 }
1801
1802 fn impl_is_default(self, impl_def_id: Self::ImplId) -> bool {
1803 match impl_def_id {
1804 AnyImplId::ImplId(impl_id) => ImplSignature::of(self.db, impl_id).is_default(),
1805 AnyImplId::BuiltinDeriveImplId(_) => false,
1806 }
1807 }
1808
1809 #[tracing::instrument(skip(self), ret)]
1810 fn impl_trait_ref(
1811 self,
1812 impl_id: Self::ImplId,
1813 ) -> EarlyBinder<Self, rustc_type_ir::TraitRef<Self>> {
1814 match impl_id {
1815 AnyImplId::ImplId(impl_id) => {
1816 let db = self.db();
1817 db.impl_trait(impl_id)
1818 .expect("invalid impl passed to trait solver")
1820 }
1821 AnyImplId::BuiltinDeriveImplId(impl_id) => {
1822 crate::builtin_derive::impl_trait(self, impl_id)
1823 }
1824 }
1825 }
1826
1827 fn impl_polarity(self, impl_id: Self::ImplId) -> rustc_type_ir::ImplPolarity {
1828 let AnyImplId::ImplId(impl_id) = impl_id else {
1829 return ImplPolarity::Positive;
1830 };
1831 let impl_data = ImplSignature::of(self.db(), impl_id);
1832 if impl_data.flags.contains(ImplFlags::NEGATIVE) {
1833 ImplPolarity::Negative
1834 } else {
1835 ImplPolarity::Positive
1836 }
1837 }
1838
1839 fn trait_is_auto(self, trait_: Self::TraitId) -> bool {
1840 let trait_data = TraitSignature::of(self.db(), trait_.0);
1841 trait_data.flags.contains(TraitFlags::AUTO)
1842 }
1843
1844 fn trait_is_alias(self, trait_: Self::TraitId) -> bool {
1845 let trait_data = TraitSignature::of(self.db(), trait_.0);
1846 trait_data.flags.contains(TraitFlags::ALIAS)
1847 }
1848
1849 fn trait_is_dyn_compatible(self, trait_: Self::TraitId) -> bool {
1850 crate::dyn_compatibility::dyn_compatibility(self.db(), trait_.0).is_none()
1851 }
1852
1853 fn trait_is_fundamental(self, trait_: Self::TraitId) -> bool {
1854 let trait_data = TraitSignature::of(self.db(), trait_.0);
1855 trait_data.flags.contains(TraitFlags::FUNDAMENTAL)
1856 }
1857
1858 fn is_impl_trait_in_trait(self, _def_id: Self::DefId) -> bool {
1859 false
1861 }
1862
1863 fn delay_bug(self, _msg: impl ToString) -> Self::ErrorGuaranteed {
1864 ErrorGuaranteed
1865 }
1866
1867 fn is_general_coroutine(self, def_id: Self::CoroutineId) -> bool {
1868 matches!(def_id.0.loc(self.db).kind, HirClosureKind::OldCoroutine(_))
1869 }
1870
1871 fn coroutine_is_async(self, def_id: Self::CoroutineId) -> bool {
1872 matches!(
1873 def_id.0.loc(self.db).kind,
1874 HirClosureKind::Coroutine { kind: HirCoroutineKind::Async, .. }
1875 )
1876 }
1877
1878 fn coroutine_is_gen(self, def_id: Self::CoroutineId) -> bool {
1879 matches!(
1880 def_id.0.loc(self.db).kind,
1881 HirClosureKind::Coroutine { kind: HirCoroutineKind::Gen, .. }
1882 )
1883 }
1884
1885 fn coroutine_is_async_gen(self, def_id: Self::CoroutineId) -> bool {
1886 matches!(
1887 def_id.0.loc(self.db).kind,
1888 HirClosureKind::Coroutine { kind: HirCoroutineKind::AsyncGen, .. }
1889 )
1890 }
1891
1892 fn unsizing_params_for_adt(self, id: Self::AdtId) -> Self::UnsizingParams {
1893 let def = AdtDef::new(id.0, self);
1894 let num_params = self.generics_of(id.into()).count();
1895
1896 let maybe_unsizing_param_idx = |arg: GenericArg<'db>| match arg.kind() {
1897 GenericArgKind::Type(ty) => match ty.kind() {
1898 rustc_type_ir::TyKind::Param(p) => Some(p.index),
1899 _ => None,
1900 },
1901 GenericArgKind::Lifetime(_) => None,
1902 GenericArgKind::Const(ct) => match ct.kind() {
1903 rustc_type_ir::ConstKind::Param(p) => Some(p.index),
1904 _ => None,
1905 },
1906 };
1907
1908 let variant = match def.def_id() {
1910 AdtId::StructId(id) => VariantId::from(id),
1911 AdtId::UnionId(id) => id.into(),
1912 AdtId::EnumId(_) => panic!("expected a struct or a union"),
1913 };
1914 let fields = variant.fields(self.db());
1915 let mut prefix_fields = fields.fields().iter();
1916 let Some(tail_field) = prefix_fields.next_back() else {
1917 return UnsizingParams(DenseBitSet::new_empty(num_params));
1918 };
1919
1920 let field_types = self.db().field_types(variant);
1921 let mut unsizing_params = DenseBitSet::new_empty(num_params);
1922 let ty = field_types[tail_field.0].ty();
1923 for arg in ty.instantiate_identity().skip_norm_wip().walk() {
1924 if let Some(i) = maybe_unsizing_param_idx(arg) {
1925 unsizing_params.insert(i);
1926 }
1927 }
1928
1929 for field in prefix_fields {
1932 for arg in field_types[field.0].ty().instantiate_identity().skip_norm_wip().walk() {
1933 if let Some(i) = maybe_unsizing_param_idx(arg) {
1934 unsizing_params.remove(i);
1935 }
1936 }
1937 }
1938
1939 UnsizingParams(unsizing_params)
1940 }
1941
1942 fn anonymize_bound_vars<T: rustc_type_ir::TypeFoldable<Self>>(
1943 self,
1944 value: rustc_type_ir::Binder<Self, T>,
1945 ) -> rustc_type_ir::Binder<Self, T> {
1946 struct Anonymize<'a, 'db> {
1947 interner: DbInterner<'db>,
1948 map: &'a mut FxIndexMap<BoundVar, BoundVariableKind<'db>>,
1949 }
1950 impl<'db> BoundVarReplacerDelegate<'db> for Anonymize<'_, 'db> {
1951 fn replace_region(&mut self, br: BoundRegion<'db>) -> Region<'db> {
1952 let entry = self.map.entry(br.var);
1953 let index = entry.index();
1954 let var = BoundVar::from_usize(index);
1955 let kind = (*entry
1956 .or_insert_with(|| BoundVariableKind::Region(BoundRegionKind::Anon)))
1957 .expect_region();
1958 let br = BoundRegion { var, kind };
1959 Region::new_bound(self.interner, DebruijnIndex::ZERO, br)
1960 }
1961 fn replace_ty(&mut self, bt: BoundTy<'db>) -> Ty<'db> {
1962 let entry = self.map.entry(bt.var);
1963 let index = entry.index();
1964 let var = BoundVar::from_usize(index);
1965 let kind = (*entry.or_insert_with(|| BoundVariableKind::Ty(BoundTyKind::Anon)))
1966 .expect_ty();
1967 Ty::new_bound(self.interner, DebruijnIndex::ZERO, BoundTy { var, kind })
1968 }
1969 fn replace_const(&mut self, bv: BoundConst<'db>) -> Const<'db> {
1970 let entry = self.map.entry(bv.var);
1971 let index = entry.index();
1972 let var = BoundVar::from_usize(index);
1973 let () = (*entry.or_insert_with(|| BoundVariableKind::Const)).expect_const();
1974 Const::new_bound(self.interner, DebruijnIndex::ZERO, BoundConst::new(var))
1975 }
1976 }
1977
1978 let mut map = Default::default();
1979 let delegate = Anonymize { interner: self, map: &mut map };
1980 let inner = self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate);
1981 let bound_vars = BoundVarKinds::new_from_iter(self, map.into_values());
1982 Binder::bind_with_vars(inner, bound_vars)
1983 }
1984
1985 fn opaque_types_defined_by(self, def_id: Self::LocalDefId) -> Self::LocalDefIds {
1986 let Ok(def_id) = InferBodyId::try_from(def_id) else {
1987 return SolverDefIds::default();
1988 };
1989 let mut result = Vec::new();
1990 crate::opaques::opaque_types_defined_by(self.db, def_id, &mut result);
1991 SolverDefIds::new_from_slice(&result)
1992 }
1993
1994 fn opaque_types_and_coroutines_defined_by(self, def_id: Self::LocalDefId) -> Self::LocalDefIds {
1995 let db = self.db;
1996
1997 let Ok(def_id) = InferBodyId::try_from(def_id) else {
1998 return SolverDefIds::default();
1999 };
2000 let mut result = Vec::new();
2001
2002 crate::opaques::opaque_types_defined_by(db, def_id, &mut result);
2003
2004 let (store, root_expr) = def_id.store_and_root_expr(db);
2006 CoroutinesVisitor { db: self.db, owner: def_id, store, coroutines: &mut result }
2008 .on_expr(root_expr);
2009
2010 return SolverDefIds::new_from_slice(&result);
2011
2012 struct CoroutinesVisitor<'a, 'db> {
2013 db: &'db dyn HirDatabase,
2014 owner: InferBodyId<'db>,
2015 store: &'db ExpressionStore,
2016 coroutines: &'a mut Vec<SolverDefId<'db>>,
2017 }
2018
2019 impl<'db> StoreVisitor for CoroutinesVisitor<'_, 'db> {
2020 fn on_expr(&mut self, expr: ExprId) {
2021 if let hir_def::hir::Expr::Closure {
2022 closure_kind:
2023 kind @ (hir_def::hir::ClosureKind::Coroutine { .. }
2024 | hir_def::hir::ClosureKind::OldCoroutine(_)),
2025 ..
2026 } = self.store[expr]
2027 {
2028 let coroutine = InternedCoroutineId::new(
2029 self.db,
2030 InternedClosure { owner: self.owner, expr, kind },
2031 );
2032 self.coroutines.push(coroutine.into());
2033 }
2034
2035 self.store.visit_expr_children(expr, self);
2036 }
2037 fn on_pat(&mut self, pat: PatId) {
2038 self.store.visit_pat_children(pat, self);
2039 }
2040 fn on_anon_const_expr(&mut self, _expr: ExprId) {}
2042 }
2043 }
2044
2045 fn alias_has_const_conditions(self, _def_id: Self::DefId) -> bool {
2046 false
2048 }
2049
2050 fn explicit_implied_const_bounds(
2051 self,
2052 _def_id: Self::DefId,
2053 ) -> EarlyBinder<
2054 Self,
2055 impl IntoIterator<Item = rustc_type_ir::Binder<Self, rustc_type_ir::TraitRef<Self>>>,
2056 > {
2057 EarlyBinder::bind([])
2059 }
2060
2061 fn fn_is_const(self, id: Self::FunctionId) -> bool {
2062 let id = match id.0 {
2063 CallableDefId::FunctionId(id) => id,
2064 _ => return false,
2065 };
2066 FunctionSignature::of(self.db(), id).flags.contains(FnFlags::CONST)
2067 }
2068
2069 fn impl_is_const(self, _def_id: Self::ImplId) -> bool {
2070 false
2071 }
2072
2073 fn opt_alias_variances(
2074 self,
2075 _kind: impl Into<AliasTermKind<'db>>,
2076 ) -> Option<Self::VariancesOf> {
2077 None
2078 }
2079
2080 fn type_of_opaque_hir_typeck(
2081 self,
2082 opaque: Self::LocalOpaqueTyId,
2083 ) -> EarlyBinder<Self, Self::Ty> {
2084 let impl_trait_id = opaque.0.loc(self.db);
2085 let hidden_type = match impl_trait_id {
2088 crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => {
2089 crate::opaques::rpit_hidden_types(self.db, func).get(idx)
2090 }
2091 crate::ImplTraitId::TypeAliasImplTrait(type_alias, idx) => {
2092 crate::opaques::tait_hidden_types(self.db, type_alias).get(idx)
2093 }
2094 };
2095 match hidden_type {
2096 Some(hidden_type) => hidden_type.get(),
2097 None => EarlyBinder::bind(Ty::new_error(self, ErrorGuaranteed)),
2098 }
2099 }
2100
2101 fn coroutine_hidden_types(
2102 self,
2103 _def_id: Self::CoroutineId,
2104 ) -> EarlyBinder<Self, Binder<'db, CoroutineWitnessTypes<Self>>> {
2105 EarlyBinder::bind(Binder::dummy(CoroutineWitnessTypes {
2107 types: Tys::default(),
2108 assumptions: RegionAssumptions::default(),
2109 }))
2110 }
2111
2112 fn is_default_trait(self, def_id: Self::TraitId) -> bool {
2113 self.as_trait_lang_item(def_id).map_or(false, |l| matches!(l, SolverTraitLangItem::Sized))
2114 }
2115
2116 fn trait_is_coinductive(self, trait_: Self::TraitId) -> bool {
2117 TraitSignature::of(self.db(), trait_.0).flags.contains(TraitFlags::COINDUCTIVE)
2118 }
2119
2120 fn trait_is_unsafe(self, trait_: Self::TraitId) -> bool {
2121 TraitSignature::of(self.db(), trait_.0).flags.contains(TraitFlags::UNSAFE)
2122 }
2123
2124 fn impl_self_is_guaranteed_unsized(self, _def_id: Self::ImplId) -> bool {
2125 false
2126 }
2127
2128 fn impl_specializes(
2129 self,
2130 specializing_impl_def_id: Self::ImplId,
2131 parent_impl_def_id: Self::ImplId,
2132 ) -> bool {
2133 let (AnyImplId::ImplId(specializing_impl_def_id), AnyImplId::ImplId(parent_impl_def_id)) =
2134 (specializing_impl_def_id, parent_impl_def_id)
2135 else {
2136 return false;
2138 };
2139 crate::specialization::specializes(self.db, specializing_impl_def_id, parent_impl_def_id)
2140 }
2141
2142 fn next_trait_solver_globally(self) -> bool {
2143 true
2144 }
2145
2146 type Probe = rustc_type_ir::solve::inspect::Probe<DbInterner<'db>>;
2147 fn mk_probe(self, probe: rustc_type_ir::solve::inspect::Probe<Self>) -> Self::Probe {
2148 probe
2149 }
2150 fn evaluate_root_goal_for_proof_tree_raw(
2151 self,
2152 canonical_goal: rustc_type_ir::solve::CanonicalInput<Self>,
2153 ) -> (rustc_type_ir::solve::QueryResult<Self>, Self::Probe) {
2154 rustc_next_trait_solver::solve::evaluate_root_goal_for_proof_tree_raw_provider::<
2155 SolverContext<'db>,
2156 Self,
2157 >(self, canonical_goal)
2158 }
2159
2160 fn is_sizedness_trait(self, def_id: Self::TraitId) -> bool {
2161 matches!(
2162 self.as_trait_lang_item(def_id),
2163 Some(SolverTraitLangItem::Sized | SolverTraitLangItem::MetaSized)
2164 )
2165 }
2166
2167 fn const_of_item(self, def_id: Self::DefId) -> rustc_type_ir::EarlyBinder<Self, Self::Const> {
2168 let id = match def_id {
2169 SolverDefId::StaticId(id) => id.into(),
2170 SolverDefId::ConstId(id) => id.into(),
2171 _ => unreachable!(),
2172 };
2173 EarlyBinder::bind(Const::new_unevaluated(
2174 self,
2175 UnevaluatedConst { def: GeneralConstIdWrapper(id), args: GenericArgs::empty(self) },
2176 ))
2177 }
2178
2179 fn anon_const_kind(self, _def_id: Self::DefId) -> rustc_type_ir::AnonConstKind {
2180 rustc_type_ir::AnonConstKind::GCE
2182 }
2183
2184 fn alias_ty_kind_from_def_id(self, def_id: Self::DefId) -> AliasTyKind<'db> {
2185 match def_id {
2186 SolverDefId::TypeAliasId(type_alias) => match type_alias.loc(self.db).container {
2187 ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => {
2188 AliasTyKind::Free { def_id: type_alias.into() }
2189 }
2190 ItemContainerId::ImplId(_) => AliasTyKind::Inherent { def_id: type_alias.into() },
2191 ItemContainerId::TraitId(_) => {
2192 AliasTyKind::Projection { def_id: type_alias.into() }
2193 }
2194 },
2195 SolverDefId::InternedOpaqueTyId(def_id) => {
2196 AliasTyKind::Opaque { def_id: def_id.into() }
2197 }
2198 _ => unreachable!(),
2199 }
2200 }
2201
2202 fn closure_is_const(self, _def_id: Self::ClosureId) -> bool {
2203 false
2205 }
2206
2207 fn item_name(self, _item_index: Self::DefId) -> Self::Symbol {
2208 Symbol
2209 }
2210}
2211
2212fn is_ty_self(ty: Ty<'_>) -> bool {
2213 match ty.kind() {
2214 TyKind::Param(param) => param.index == 0,
2215 _ => false,
2216 }
2217}
2218fn is_clause_at_ty(p: &Clause<'_>, filter: impl FnOnce(Ty<'_>) -> bool) -> bool {
2219 match p.kind().skip_binder() {
2220 ClauseKind::Trait(it) => filter(it.self_ty()),
2223 ClauseKind::TypeOutlives(it) => filter(it.0),
2224 ClauseKind::Projection(it) => filter(it.self_ty()),
2225 ClauseKind::HostEffect(it) => filter(it.self_ty()),
2226 _ => false,
2227 }
2228}
2229
2230impl<'db> DbInterner<'db> {
2231 pub fn shift_bound_var_indices<T>(self, bound_vars: usize, value: T) -> T
2232 where
2233 T: rustc_type_ir::TypeFoldable<Self>,
2234 {
2235 let shift_bv = |bv: BoundVar| BoundVar::from_usize(bv.as_usize() + bound_vars);
2236 self.replace_escaping_bound_vars_uncached(
2237 value,
2238 FnMutDelegate {
2239 regions: &mut |r: BoundRegion<'db>| {
2240 Region::new_bound(
2241 self,
2242 DebruijnIndex::ZERO,
2243 BoundRegion { var: shift_bv(r.var), kind: r.kind },
2244 )
2245 },
2246 types: &mut |t: BoundTy<'db>| {
2247 Ty::new_bound(
2248 self,
2249 DebruijnIndex::ZERO,
2250 BoundTy { var: shift_bv(t.var), kind: t.kind },
2251 )
2252 },
2253 consts: &mut |c| {
2254 Const::new_bound(self, DebruijnIndex::ZERO, BoundConst::new(shift_bv(c.var)))
2255 },
2256 },
2257 )
2258 }
2259
2260 pub fn replace_escaping_bound_vars_uncached<T: rustc_type_ir::TypeFoldable<DbInterner<'db>>>(
2261 self,
2262 value: T,
2263 delegate: impl BoundVarReplacerDelegate<'db>,
2264 ) -> T {
2265 if !value.has_escaping_bound_vars() {
2266 value
2267 } else {
2268 let mut replacer = BoundVarReplacer::new(self, delegate);
2269 value.fold_with(&mut replacer)
2270 }
2271 }
2272
2273 pub fn replace_bound_vars_uncached<T: rustc_type_ir::TypeFoldable<DbInterner<'db>>>(
2274 self,
2275 value: Binder<'db, T>,
2276 delegate: impl BoundVarReplacerDelegate<'db>,
2277 ) -> T {
2278 self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate)
2279 }
2280
2281 pub fn mk_fn_sig<I>(
2283 self,
2284 inputs: I,
2285 output: Ty<'db>,
2286 c_variadic: bool,
2287 safety: Safety,
2288 abi: ExternAbi,
2289 ) -> FnSig<'db>
2290 where
2291 I: IntoIterator<Item = Ty<'db>>,
2292 {
2293 FnSig {
2294 inputs_and_output: Tys::new_from_iter(
2295 self,
2296 inputs.into_iter().chain(std::iter::once(output)),
2297 ),
2298 fn_sig_kind: FnSigKind::new(abi, safety, c_variadic),
2299 }
2300 }
2301
2302 pub fn mk_fn_sig_safe_rust_abi<I>(self, inputs: I, output: Ty<'db>) -> FnSig<'db>
2304 where
2305 I: IntoIterator<Item = Ty<'db>>,
2306 {
2307 self.mk_fn_sig(inputs, output, false, Safety::Safe, ExternAbi::Rust)
2308 }
2309}
2310
2311fn predicates_of<'db>(
2312 db: &'db dyn HirDatabase,
2313 def_id: SolverDefId<'db>,
2314) -> &'db GenericPredicates {
2315 match def_id {
2316 SolverDefId::BuiltinDeriveImplId(impl_) => crate::builtin_derive::predicates(db, impl_),
2317 SolverDefId::AnonConstId(anon_const) => {
2318 let loc = anon_const.loc(db);
2319 if loc.allow_using_generic_params {
2320 GenericPredicates::query(db, loc.owner.generic_def(db))
2321 } else {
2322 GenericPredicates::empty()
2323 }
2324 }
2325 _ => GenericPredicates::query(db, def_id.try_into().unwrap()),
2326 }
2327}
2328
2329macro_rules! TrivialTypeTraversalImpls {
2330 ($($ty:ty,)+) => {
2331 $(
2332 impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for $ty {
2333 fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
2334 self,
2335 _: &mut F,
2336 ) -> ::std::result::Result<Self, F::Error> {
2337 Ok(self)
2338 }
2339
2340 #[inline]
2341 fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(
2342 self,
2343 _: &mut F,
2344 ) -> Self {
2345 self
2346 }
2347 }
2348
2349 impl<'db> rustc_type_ir::TypeVisitable<DbInterner<'db>> for $ty {
2350 #[inline]
2351 fn visit_with<F: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
2352 &self,
2353 _: &mut F)
2354 -> F::Result
2355 {
2356 <F::Result as rustc_ast_ir::visit::VisitorResult>::output()
2357 }
2358 }
2359
2360 impl<V> rustc_type_ir::GenericTypeVisitable<V> for $ty {
2361 #[inline]
2362 fn generic_visit_with(&self, _visitor: &mut V) {}
2363 }
2364 )+
2365 };
2366}
2367
2368TrivialTypeTraversalImpls! {
2369 SolverDefId<'_>,
2370 TraitIdWrapper,
2371 TypeAliasIdWrapper,
2372 CallableIdWrapper,
2373 ClosureIdWrapper<'_>,
2374 CoroutineIdWrapper<'_>,
2375 CoroutineClosureIdWrapper<'_>,
2376 AdtIdWrapper,
2377 TraitAssocTyId,
2378 TraitAssocConstId,
2379 TraitAssocTermId,
2380 ImplOrTraitAssocTyId,
2381 ImplOrTraitAssocConstId,
2382 ImplOrTraitAssocTermId,
2383 FreeTyAliasId,
2384 FreeConstAliasId,
2385 FreeTermAliasId,
2386 InherentAssocTyId,
2387 InherentAssocConstId,
2388 InherentAssocTermId,
2389 OpaqueTyIdWrapper<'_>,
2390 AnyImplId,
2391 GeneralConstIdWrapper<'_>,
2392 Safety,
2393 Span,
2394 ParamConst,
2395 ParamTy,
2396 EarlyParamRegion,
2397 AdtDef,
2398 ScalarInt,
2399}
2400
2401mod tls_db {
2402 use std::{cell::Cell, ptr::NonNull};
2403
2404 use crate::db::HirDatabase;
2405
2406 struct Attached {
2407 database: Cell<Option<NonNull<dyn HirDatabase>>>,
2408 }
2409
2410 impl Attached {
2411 #[inline]
2412 fn attach<R>(&self, db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
2413 struct DbGuard<'s> {
2414 state: Option<&'s Attached>,
2415 }
2416
2417 impl<'s> DbGuard<'s> {
2418 #[inline]
2419 fn new(attached: &'s Attached, db: &dyn HirDatabase) -> Self {
2420 match attached.database.get() {
2421 Some(current_db) => {
2422 let new_db = NonNull::from(db);
2423 if !std::ptr::addr_eq(current_db.as_ptr(), new_db.as_ptr()) {
2424 panic!(
2425 "Cannot change attached database. This is likely a bug.\n\
2426 If this is not a bug, you can use `attach_db_allow_change()`."
2427 );
2428 }
2429 Self { state: None }
2430 }
2431 None => {
2432 attached.database.set(Some(NonNull::from(db)));
2434 Self { state: Some(attached) }
2435 }
2436 }
2437 }
2438 }
2439
2440 impl Drop for DbGuard<'_> {
2441 #[inline]
2442 fn drop(&mut self) {
2443 if let Some(attached) = self.state {
2445 attached.database.set(None);
2446 }
2447 }
2448 }
2449
2450 let _guard = DbGuard::new(self, db);
2451 super::tls_cache::reinit_cache(db);
2452 op()
2453 }
2454
2455 #[inline]
2456 fn attach_allow_change<R>(&self, db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
2457 struct DbGuard<'s> {
2458 state: &'s Attached,
2459 prev: Option<NonNull<dyn HirDatabase>>,
2460 }
2461
2462 impl<'s> DbGuard<'s> {
2463 #[inline]
2464 fn new(attached: &'s Attached, db: &dyn HirDatabase) -> Self {
2465 let prev = attached.database.replace(Some(NonNull::from(db)));
2466 Self { state: attached, prev }
2467 }
2468 }
2469
2470 impl Drop for DbGuard<'_> {
2471 #[inline]
2472 fn drop(&mut self) {
2473 self.state.database.set(self.prev);
2474 if let Some(prev) = self.prev {
2475 super::tls_cache::reinit_cache(unsafe { prev.as_ref() });
2476 }
2477 }
2478 }
2479
2480 let _guard = DbGuard::new(self, db);
2481 super::tls_cache::reinit_cache(db);
2482 op()
2483 }
2484
2485 #[inline]
2486 fn with<R>(&self, op: impl FnOnce(&dyn HirDatabase) -> R) -> R {
2487 let db = self.database.get().expect("Try to use attached db, but not db is attached");
2488
2489 op(unsafe { db.as_ref() })
2491 }
2492 }
2493
2494 thread_local! {
2495 static GLOBAL_DB: Attached = const { Attached { database: Cell::new(None) } };
2496 }
2497
2498 #[inline]
2499 pub fn attach_db<R>(db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
2500 GLOBAL_DB.with(|global_db| global_db.attach(db, op))
2501 }
2502
2503 #[inline]
2504 pub fn attach_db_allow_change<R>(db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
2505 GLOBAL_DB.with(|global_db| global_db.attach_allow_change(db, op))
2506 }
2507
2508 #[inline]
2509 pub fn with_attached_db<R>(op: impl FnOnce(&dyn HirDatabase) -> R) -> R {
2510 GLOBAL_DB.with(
2511 #[inline]
2512 |a| a.with(op),
2513 )
2514 }
2515}
2516
2517mod tls_cache {
2518 use crate::db::HirDatabase;
2519
2520 use super::DbInterner;
2521 use base_db::Nonce;
2522 use rustc_type_ir::search_graph::GlobalCache;
2523 use salsa::Revision;
2524 use std::cell::RefCell;
2525
2526 struct Cache {
2527 cache: GlobalCache<DbInterner<'static>>,
2528 revision: Revision,
2529 db_nonce: Nonce,
2530 }
2531
2532 impl Cache {
2533 const fn default() -> Cache {
2534 Cache {
2535 cache: GlobalCache::new(),
2536 revision: Revision::max(),
2537 db_nonce: Nonce::invalid(),
2538 }
2539 }
2540 }
2541
2542 thread_local! {
2543 static GLOBAL_CACHE: RefCell<Cache> = const { RefCell::new(Cache::default()) };
2544 }
2545
2546 pub(super) fn reinit_cache(db: &dyn HirDatabase) {
2547 GLOBAL_CACHE.with_borrow_mut(|handle| {
2548 let (db_nonce, revision) = db.nonce_and_revision();
2549 if handle.revision != revision || db_nonce != handle.db_nonce {
2550 *handle = Cache { cache: GlobalCache::default(), revision, db_nonce };
2551 }
2552 })
2553 }
2554
2555 #[inline]
2556 pub(super) fn borrow_assume_valid<'db, T>(
2557 db: &'db dyn HirDatabase,
2558 f: impl FnOnce(&mut GlobalCache<DbInterner<'db>>) -> T,
2559 ) -> T {
2560 if cfg!(debug_assertions) {
2561 let get_state =
2562 || GLOBAL_CACHE.with_borrow(|handle| (handle.db_nonce, handle.revision));
2563 let old_state = get_state();
2564 reinit_cache(db);
2565 let new_state = get_state();
2566 assert_eq!(old_state, new_state, "you assumed the cache is valid!");
2567 }
2568
2569 GLOBAL_CACHE.with_borrow_mut(|handle| {
2570 f(unsafe {
2572 std::mem::transmute::<
2573 &mut GlobalCache<DbInterner<'static>>,
2574 &mut GlobalCache<DbInterner<'db>>,
2575 >(&mut handle.cache)
2576 })
2577 })
2578 }
2579
2580 pub fn clear_tls_solver_cache() {
2585 GLOBAL_CACHE.with_borrow_mut(|handle| *handle = Cache::default());
2586 }
2587}
2588
2589impl WorldExposer for intern::GarbageCollector {
2590 fn on_interned<T: intern::Internable>(
2591 &mut self,
2592 interned: InternedRef<'_, T>,
2593 ) -> ControlFlow<()> {
2594 self.mark_interned_alive(interned)
2595 }
2596
2597 fn on_interned_slice<T: intern::SliceInternable>(
2598 &mut self,
2599 interned: InternedSliceRef<'_, T>,
2600 ) -> ControlFlow<()> {
2601 self.mark_interned_slice_alive(interned)
2602 }
2603}
2604
2605pub unsafe fn collect_ty_garbage() {
2611 let mut gc = intern::GarbageCollector::default();
2612
2613 gc.add_storage::<super::consts::ConstInterned>();
2614 gc.add_storage::<super::consts::ValTreeInterned>();
2615 gc.add_storage::<super::allocation::AllocationInterned>();
2616 gc.add_storage::<PatternInterned>();
2617 gc.add_storage::<super::opaques::ExternalConstraintsInterned>();
2618 gc.add_storage::<super::predicate::PredicateInterned>();
2619 gc.add_storage::<super::region::RegionInterned>();
2620 gc.add_storage::<super::ty::TyInterned>();
2621
2622 gc.add_slice_storage::<super::consts::ConstsStorage>();
2623 gc.add_slice_storage::<super::predicate::ClausesStorage>();
2624 gc.add_slice_storage::<super::generic_arg::GenericArgsStorage>();
2625 gc.add_slice_storage::<BoundVarKindsStorage>();
2626 gc.add_slice_storage::<VariancesOfStorage>();
2627 gc.add_slice_storage::<CanonicalVarsStorage>();
2628 gc.add_slice_storage::<PatListStorage>();
2629 gc.add_slice_storage::<super::opaques::PredefinedOpaquesStorage>();
2630 gc.add_slice_storage::<super::opaques::SolverDefIdsStorage>();
2631 gc.add_slice_storage::<super::predicate::BoundExistentialPredicatesStorage>();
2632 gc.add_slice_storage::<super::region::RegionAssumptionsStorage>();
2633 gc.add_slice_storage::<super::ty::TysStorage>();
2634 gc.add_slice_storage::<crate::mir::ProjectionStorage>();
2635
2636 unsafe { gc.collect() };
2641}
2642
2643macro_rules! impl_gc_visit {
2644 ( $($ty:ty),* $(,)? ) => {
2645 $(
2646 impl ::intern::GcInternedVisit for $ty {
2647 #[inline]
2648 fn visit_with(&self, gc: &mut ::intern::GarbageCollector) {
2649 self.generic_visit_with(gc);
2650 }
2651 }
2652 )*
2653 };
2654}
2655
2656impl_gc_visit!(
2657 super::consts::ConstInterned,
2658 super::consts::ValTreeInterned,
2659 super::allocation::AllocationInterned,
2660 PatternInterned,
2661 super::opaques::ExternalConstraintsInterned,
2662 super::predicate::PredicateInterned,
2663 super::region::RegionInterned,
2664 super::ty::TyInterned,
2665 super::predicate::ClausesCachedTypeInfo,
2666);
2667
2668macro_rules! impl_gc_visit_slice {
2669 ( $($ty:ty),* $(,)? ) => {
2670 $(
2671 impl ::intern::GcInternedSliceVisit for $ty {
2672 #[inline]
2673 fn visit_header(header: &<Self as ::intern::SliceInternable>::Header, gc: &mut ::intern::GarbageCollector) {
2674 header.generic_visit_with(gc);
2675 }
2676
2677 #[inline]
2678 fn visit_slice(slice: &[<Self as ::intern::SliceInternable>::SliceType], gc: &mut ::intern::GarbageCollector) {
2679 slice.generic_visit_with(gc);
2680 }
2681 }
2682 )*
2683 };
2684}
2685
2686impl_gc_visit_slice!(
2687 super::predicate::ClausesStorage,
2688 super::generic_arg::GenericArgsStorage,
2689 BoundVarKindsStorage,
2690 VariancesOfStorage,
2691 CanonicalVarsStorage,
2692 PatListStorage,
2693 super::opaques::PredefinedOpaquesStorage,
2694 super::opaques::SolverDefIdsStorage,
2695 super::predicate::BoundExistentialPredicatesStorage,
2696 super::region::RegionAssumptionsStorage,
2697 super::ty::TysStorage,
2698 super::consts::ConstsStorage,
2699 crate::mir::ProjectionStorage,
2700);