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() -> Self {
94 $crate::next_solver::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()
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()
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 }
1059
1060 fn expand_abstract_consts<T: rustc_type_ir::TypeFoldable<Self>>(self, _: T) -> T {
1061 unreachable!("only used by the old trait solver in rustc");
1062 }
1063
1064 fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf {
1065 generics(self, def_id)
1066 }
1067
1068 fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf {
1069 let generic_def = match def_id {
1070 SolverDefId::Ctor(Ctor::Enum(def_id)) | SolverDefId::EnumVariantId(def_id) => {
1071 def_id.loc(self.db).parent.into()
1072 }
1073 SolverDefId::InternedOpaqueTyId(_def_id) => {
1074 return VariancesOf::new_from_iter(
1079 self,
1080 (0..self.generics_of(def_id).count()).map(|_| Variance::Invariant),
1081 );
1082 }
1083 SolverDefId::Ctor(Ctor::Struct(def_id)) => def_id.into(),
1084 SolverDefId::AdtId(def_id) => def_id.into(),
1085 SolverDefId::FunctionId(def_id) => def_id.into(),
1086 SolverDefId::ConstId(_)
1087 | SolverDefId::StaticId(_)
1088 | SolverDefId::TraitId(_)
1089 | SolverDefId::TypeAliasId(_)
1090 | SolverDefId::ImplId(_)
1091 | SolverDefId::BuiltinDeriveImplId(_)
1092 | SolverDefId::InternedClosureId(_)
1093 | SolverDefId::InternedCoroutineId(_)
1094 | SolverDefId::InternedCoroutineClosureId(_)
1095 | SolverDefId::AnonConstId(_) => {
1096 return VariancesOf::empty();
1097 }
1098 };
1099 self.db.variances_of(generic_def)
1100 }
1101
1102 fn type_of(self, def_id: Self::DefId) -> EarlyBinder<Self, Self::Ty> {
1103 match def_id {
1104 SolverDefId::TypeAliasId(id) => self.db().ty(id.into()),
1105 SolverDefId::AdtId(id) => self.db().ty(id.into()),
1106 SolverDefId::InternedOpaqueTyId(def_id) => {
1111 self.type_of_opaque_hir_typeck(def_id.into())
1112 }
1113 SolverDefId::FunctionId(id) => self.db.value_ty(id.into()).unwrap(),
1114 SolverDefId::Ctor(id) => {
1115 let id = match id {
1116 Ctor::Struct(id) => id.into(),
1117 Ctor::Enum(id) => id.into(),
1118 };
1119 self.db.value_ty(id).expect("`SolverDefId::Ctor` should have a function-like ctor")
1120 }
1121 _ => panic!("Unexpected def_id `{def_id:?}` provided for `type_of`"),
1122 }
1123 }
1124
1125 fn adt_def(self, def_id: Self::AdtId) -> Self::AdtDef {
1126 AdtDef::new(def_id.0, self)
1127 }
1128
1129 fn alias_term_kind_from_def_id(self, def_id: SolverDefId<'db>) -> AliasTermKind<'db> {
1130 match def_id {
1131 SolverDefId::InternedOpaqueTyId(def_id) => {
1132 AliasTermKind::OpaqueTy { def_id: def_id.into() }
1133 }
1134 SolverDefId::TypeAliasId(type_alias) => match type_alias.loc(self.db).container {
1135 ItemContainerId::ImplId(impl_)
1136 if ImplSignature::of(self.db, impl_).target_trait.is_none() =>
1137 {
1138 AliasTermKind::InherentTy { def_id: type_alias.into() }
1139 }
1140 ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => {
1141 AliasTermKind::ProjectionTy { def_id: type_alias.into() }
1142 }
1143 _ => AliasTermKind::FreeTy { def_id: type_alias.into() },
1144 },
1145 SolverDefId::ConstId(def_id) => {
1148 AliasTermKind::UnevaluatedConst { def_id: GeneralConstIdWrapper(def_id.into()) }
1149 }
1150 SolverDefId::StaticId(def_id) => {
1151 AliasTermKind::UnevaluatedConst { def_id: GeneralConstIdWrapper(def_id.into()) }
1152 }
1153 SolverDefId::AnonConstId(def_id) => {
1154 AliasTermKind::UnevaluatedConst { def_id: GeneralConstIdWrapper(def_id.into()) }
1155 }
1156 _ => unimplemented!("Unexpected alias: {:?}", def_id),
1157 }
1158 }
1159
1160 fn trait_ref_and_own_args_for_alias(
1161 self,
1162 def_id: Self::TraitAssocTermId,
1163 args: Self::GenericArgs,
1164 ) -> (rustc_type_ir::TraitRef<Self>, Self::GenericArgsSlice) {
1165 let trait_def_id = self.projection_parent(def_id).0;
1166 let trait_generics = crate::generics::generics(self.db, trait_def_id.into());
1167 let trait_generics_len = trait_generics.len(true);
1168 let trait_args = GenericArgs::new_from_slice(&args.as_slice()[..trait_generics_len]);
1169 let alias_args = &args.as_slice()[trait_generics_len..];
1170 (TraitRef::new_from_args(self, trait_def_id.into(), trait_args), alias_args)
1171 }
1172
1173 fn check_args_compatible(self, def_id: Self::DefId, args: Self::GenericArgs) -> bool {
1174 let generics = self.generics_of(def_id);
1175 generics.count() == args.len()
1176 && std::iter::zip(generics.iter(), args).all(|((param, _), arg)| {
1177 matches!(
1178 (param, arg.kind()),
1179 (GenericParamId::LifetimeParamId(_), GenericArgKind::Lifetime(_))
1180 | (GenericParamId::TypeParamId(_), GenericArgKind::Type(_))
1181 | (GenericParamId::ConstParamId(_), GenericArgKind::Const(_))
1182 )
1183 })
1184 }
1185
1186 fn debug_assert_args_compatible(self, _def_id: Self::DefId, _args: Self::GenericArgs) {}
1187
1188 fn debug_assert_existential_args_compatible(
1189 self,
1190 _def_id: Self::DefId,
1191 _args: Self::GenericArgs,
1192 ) {
1193 }
1194
1195 fn mk_type_list_from_iter<I, T>(self, args: I) -> T::Output
1196 where
1197 I: Iterator<Item = T>,
1198 T: rustc_type_ir::CollectAndApply<Self::Ty, Self::Tys>,
1199 {
1200 Tys::new_from_iter(self, args)
1201 }
1202
1203 fn projection_parent(self, def_id: Self::TraitAssocTermId) -> Self::TraitId {
1204 let container = match def_id.0 {
1205 TermId::TypeAliasId(def_id) => def_id.loc(self.db).container,
1206 TermId::ConstId(def_id) => def_id.loc(self.db).container,
1207 };
1208 let ItemContainerId::TraitId(trait_) = container else {
1209 panic!("a TraitAssocTermId can only come from a trait")
1210 };
1211 trait_.into()
1212 }
1213
1214 fn impl_or_trait_assoc_term_parent(self, def_id: Self::ImplOrTraitAssocTermId) -> Self::DefId {
1215 let container = match def_id.0 {
1216 TermId::TypeAliasId(def_id) => def_id.loc(self.db).container,
1217 TermId::ConstId(def_id) => def_id.loc(self.db).container,
1218 };
1219 match container {
1220 ItemContainerId::ImplId(impl_) => impl_.into(),
1221 ItemContainerId::TraitId(trait_) => trait_.into(),
1222 ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => {
1223 panic!("only impl or trait can be the parent of ImplOrTraitAssocTermId")
1224 }
1225 }
1226 }
1227
1228 fn inherent_alias_term_parent(self, def_id: Self::InherentAssocTermId) -> Self::ImplId {
1229 let container = match def_id.0 {
1230 TermId::TypeAliasId(def_id) => def_id.loc(self.db).container,
1231 TermId::ConstId(def_id) => def_id.loc(self.db).container,
1232 };
1233 match container {
1234 ItemContainerId::ImplId(impl_) => impl_.into(),
1235 ItemContainerId::ExternBlockId(_)
1236 | ItemContainerId::ModuleId(_)
1237 | ItemContainerId::TraitId(_) => {
1238 panic!("only impl can be the parent of InherentAliasTermId")
1239 }
1240 }
1241 }
1242
1243 fn recursion_limit(self) -> usize {
1244 50
1245 }
1246
1247 fn is_type_const(self, _def_id: Self::DefId) -> bool {
1248 false
1249 }
1250
1251 fn features(self) -> Features {
1252 Features
1253 }
1254
1255 fn fn_sig(
1256 self,
1257 def_id: Self::FunctionId,
1258 ) -> EarlyBinder<Self, rustc_type_ir::Binder<Self, rustc_type_ir::FnSig<Self>>> {
1259 self.db().callable_item_signature(def_id.0)
1260 }
1261
1262 fn coroutine_movability(self, def_id: Self::CoroutineId) -> rustc_ast_ir::Movability {
1263 match def_id.0.loc(self.db).kind {
1264 hir_def::hir::ClosureKind::OldCoroutine(movability) => match movability {
1265 hir_def::hir::Movability::Static => rustc_ast_ir::Movability::Static,
1266 hir_def::hir::Movability::Movable => rustc_ast_ir::Movability::Movable,
1267 },
1268 hir_def::hir::ClosureKind::Coroutine { .. } => rustc_ast_ir::Movability::Static,
1269 kind => panic!("unexpected kind for a coroutine: {kind:?}"),
1270 }
1271 }
1272
1273 fn coroutine_for_closure(self, def_id: Self::CoroutineClosureId) -> Self::CoroutineId {
1274 let InternedClosure { owner, expr: coroutine_closure_expr, kind: coroutine_closure_kind } =
1275 def_id.0.loc(self.db);
1276 let coroutine_closure_kind = match coroutine_closure_kind {
1277 HirClosureKind::CoroutineClosure(it) => it,
1278 _ => {
1279 panic!("invalid kind closure kind {coroutine_closure_kind:?} for coroutine closure")
1280 }
1281 };
1282 let coroutine_expr = ExpressionStore::coroutine_for_closure(coroutine_closure_expr);
1283 let coroutine_kind = hir_def::hir::ClosureKind::Coroutine {
1284 kind: coroutine_closure_kind,
1285 source: hir_def::hir::CoroutineSource::Closure,
1286 };
1287 InternedCoroutineId::new(
1288 self.db,
1289 InternedClosure { owner, expr: coroutine_expr, kind: coroutine_kind },
1290 )
1291 .into()
1292 }
1293
1294 fn generics_require_sized_self(self, def_id: Self::DefId) -> bool {
1295 let sized_trait = self.lang_items().Sized;
1296 let Some(sized_id) = sized_trait else {
1297 return false; };
1299 let sized_def_id = sized_id.into();
1300
1301 let predicates = self.predicates_of(def_id);
1303 elaborate(self, predicates.iter_identity().map(Unnormalized::skip_norm_wip)).any(|pred| {
1304 match pred.kind().skip_binder() {
1305 ClauseKind::Trait(ref trait_pred) => {
1306 trait_pred.def_id() == sized_def_id
1307 && matches!(
1308 trait_pred.self_ty().kind(),
1309 TyKind::Param(ParamTy { index: 0, .. })
1310 )
1311 }
1312 ClauseKind::RegionOutlives(_)
1313 | ClauseKind::TypeOutlives(_)
1314 | ClauseKind::Projection(_)
1315 | ClauseKind::ConstArgHasType(_, _)
1316 | ClauseKind::WellFormed(_)
1317 | ClauseKind::ConstEvaluatable(_)
1318 | ClauseKind::HostEffect(..)
1319 | ClauseKind::UnstableFeature(_) => false,
1320 }
1321 })
1322 }
1323
1324 #[tracing::instrument(skip(self))]
1325 fn item_bounds(
1326 self,
1327 def_id: Self::DefId,
1328 ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1329 explicit_item_bounds(self, def_id).map_bound(|bounds| elaborate(self, bounds))
1330 }
1331
1332 #[tracing::instrument(skip(self))]
1333 fn item_self_bounds(
1334 self,
1335 def_id: Self::DefId,
1336 ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1337 explicit_item_self_bounds(self, def_id)
1338 .map_bound(|bounds| elaborate(self, bounds).filter_only_self())
1339 }
1340
1341 fn item_non_self_bounds(
1342 self,
1343 def_id: Self::DefId,
1344 ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1345 let all_bounds: FxHashSet<_> = self.item_bounds(def_id).skip_binder().into_iter().collect();
1346 let own_bounds: FxHashSet<_> =
1347 self.item_self_bounds(def_id).skip_binder().into_iter().collect();
1348 if all_bounds.len() == own_bounds.len() {
1349 EarlyBinder::bind(Clauses::empty())
1350 } else {
1351 EarlyBinder::bind(Clauses::new_from_iter(
1352 self,
1353 all_bounds.difference(&own_bounds).cloned(),
1354 ))
1355 }
1356 }
1357
1358 fn predicates_of(
1359 self,
1360 def_id: Self::DefId,
1361 ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1362 predicates_of(self.db, def_id).all_predicates()
1363 }
1364
1365 fn own_predicates_of(
1366 self,
1367 def_id: Self::DefId,
1368 ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1369 predicates_of(self.db, def_id).own_explicit_predicates()
1370 }
1371
1372 fn explicit_super_predicates_of(
1373 self,
1374 def_id: Self::TraitId,
1375 ) -> EarlyBinder<Self, impl IntoIterator<Item = (Self::Clause, Self::Span)>> {
1376 GenericPredicates::query(self.db, def_id.0.into())
1377 .explicit_non_assoc_types_predicates()
1378 .map_bound(move |predicates| {
1379 predicates.filter(|p| is_clause_at_ty(p, is_ty_self)).map(|p| (p, Span::dummy()))
1380 })
1381 }
1382
1383 fn explicit_implied_predicates_of(
1384 self,
1385 def_id: Self::DefId,
1386 ) -> EarlyBinder<Self, impl IntoIterator<Item = (Self::Clause, Self::Span)>> {
1387 fn is_ty_assoc_of_self(ty: Ty<'_>) -> bool {
1388 if let TyKind::Alias(alias @ AliasTy { kind: AliasTyKind::Projection { .. }, .. }) =
1391 ty.kind()
1392 {
1393 is_ty_assoc_of_self(alias.self_ty())
1394 } else {
1395 is_ty_self(ty)
1396 }
1397 }
1398
1399 let predicates = predicates_of(self.db, def_id);
1400 let non_assoc_types = predicates
1401 .explicit_non_assoc_types_predicates()
1402 .skip_binder()
1403 .filter(|p| is_clause_at_ty(p, is_ty_self));
1404 let assoc_types = predicates
1405 .explicit_assoc_types_predicates()
1406 .skip_binder()
1407 .filter(|p| is_clause_at_ty(p, is_ty_assoc_of_self));
1408 EarlyBinder::bind(non_assoc_types.chain(assoc_types).map(|it| (it, Span::dummy())))
1409 }
1410
1411 fn impl_super_outlives(
1412 self,
1413 impl_id: Self::ImplId,
1414 ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1415 let trait_ref = self.impl_trait_ref(impl_id);
1416 trait_ref.map_bound(|trait_ref| {
1417 let clause: Clause<'_> = trait_ref.upcast(self);
1418 elaborate(self, [clause]).filter(|clause| {
1419 matches!(
1420 clause.kind().skip_binder(),
1421 ClauseKind::TypeOutlives(_) | ClauseKind::RegionOutlives(_)
1422 )
1423 })
1424 })
1425 }
1426
1427 #[expect(unreachable_code)]
1428 fn const_conditions(
1429 self,
1430 _def_id: Self::DefId,
1431 ) -> EarlyBinder<
1432 Self,
1433 impl IntoIterator<Item = rustc_type_ir::Binder<Self, rustc_type_ir::TraitRef<Self>>>,
1434 > {
1435 EarlyBinder::bind([unimplemented!()])
1436 }
1437
1438 fn has_target_features(self, _def_id: Self::FunctionId) -> bool {
1439 false
1440 }
1441
1442 fn require_projection_lang_item(
1443 self,
1444 lang_item: SolverProjectionLangItem,
1445 ) -> Self::TraitAssocTyId {
1446 let lang_items = self.lang_items();
1447 let lang_item = match lang_item {
1448 SolverProjectionLangItem::AsyncFnKindUpvars => lang_items.AsyncFnKindUpvars,
1449 SolverProjectionLangItem::AsyncFnOnceOutput => lang_items.AsyncFnOnceOutput,
1450 SolverProjectionLangItem::CallOnceFuture => lang_items.CallOnceFuture,
1451 SolverProjectionLangItem::CallRefFuture => lang_items.CallRefFuture,
1452 SolverProjectionLangItem::CoroutineReturn => lang_items.CoroutineReturn,
1453 SolverProjectionLangItem::CoroutineYield => lang_items.CoroutineYield,
1454 SolverProjectionLangItem::FutureOutput => lang_items.FutureOutput,
1455 SolverProjectionLangItem::Metadata => lang_items.Metadata,
1456 SolverProjectionLangItem::FieldBase => lang_items.FieldBase,
1457 SolverProjectionLangItem::FieldType => lang_items.FieldType,
1458 };
1459 lang_item.expect("Lang item required but not found.").into()
1460 }
1461
1462 fn require_trait_lang_item(self, lang_item: SolverTraitLangItem) -> TraitIdWrapper {
1463 let lang_items = self.lang_items();
1464 let lang_item = match lang_item {
1465 SolverTraitLangItem::AsyncFn => lang_items.AsyncFn,
1466 SolverTraitLangItem::AsyncFnKindHelper => lang_items.AsyncFnKindHelper,
1467 SolverTraitLangItem::AsyncFnMut => lang_items.AsyncFnMut,
1468 SolverTraitLangItem::AsyncFnOnce => lang_items.AsyncFnOnce,
1469 SolverTraitLangItem::AsyncIterator => lang_items.AsyncIterator,
1470 SolverTraitLangItem::Clone => lang_items.Clone,
1471 SolverTraitLangItem::Copy => lang_items.Copy,
1472 SolverTraitLangItem::Coroutine => lang_items.Coroutine,
1473 SolverTraitLangItem::Destruct => lang_items.Destruct,
1474 SolverTraitLangItem::DiscriminantKind => lang_items.DiscriminantKind,
1475 SolverTraitLangItem::Drop => lang_items.Drop,
1476 SolverTraitLangItem::Fn => lang_items.Fn,
1477 SolverTraitLangItem::FnMut => lang_items.FnMut,
1478 SolverTraitLangItem::FnOnce => lang_items.FnOnce,
1479 SolverTraitLangItem::FnPtrTrait => lang_items.FnPtrTrait,
1480 SolverTraitLangItem::FusedIterator => lang_items.FusedIterator,
1481 SolverTraitLangItem::Future => lang_items.Future,
1482 SolverTraitLangItem::Iterator => lang_items.Iterator,
1483 SolverTraitLangItem::PointeeTrait => lang_items.PointeeTrait,
1484 SolverTraitLangItem::Sized => lang_items.Sized,
1485 SolverTraitLangItem::MetaSized => lang_items.MetaSized,
1486 SolverTraitLangItem::PointeeSized => lang_items.PointeeSized,
1487 SolverTraitLangItem::TransmuteTrait => lang_items.TransmuteTrait,
1488 SolverTraitLangItem::Tuple => lang_items.Tuple,
1489 SolverTraitLangItem::Unpin => lang_items.Unpin,
1490 SolverTraitLangItem::Unsize => lang_items.Unsize,
1491 SolverTraitLangItem::BikeshedGuaranteedNoDrop => lang_items.BikeshedGuaranteedNoDrop,
1492 SolverTraitLangItem::TrivialClone => lang_items.TrivialClone,
1493 SolverTraitLangItem::Field => lang_items.Field,
1494 };
1495 lang_item.expect("Lang item required but not found.").into()
1496 }
1497
1498 fn require_adt_lang_item(self, lang_item: SolverAdtLangItem) -> AdtIdWrapper {
1499 let lang_items = self.lang_items();
1500 let lang_item = match lang_item {
1501 SolverAdtLangItem::Option => lang_items.Option.map(Into::into),
1502 SolverAdtLangItem::Poll => lang_items.Poll.map(Into::into),
1503 SolverAdtLangItem::DynMetadata => lang_items.DynMetadata.map(Into::into),
1504 };
1505 AdtIdWrapper(lang_item.expect("Lang item required but not found."))
1506 }
1507
1508 fn is_projection_lang_item(
1509 self,
1510 def_id: Self::TraitAssocTyId,
1511 lang_item: SolverProjectionLangItem,
1512 ) -> bool {
1513 self.as_projection_lang_item(def_id)
1514 .map_or(false, |l| std::mem::discriminant(&l) == std::mem::discriminant(&lang_item))
1515 }
1516
1517 fn is_trait_lang_item(self, def_id: Self::TraitId, lang_item: SolverTraitLangItem) -> bool {
1518 is_lang_item!(
1519 SolverTraitLangItem, self, def_id.0, lang_item;
1520
1521 Sized,
1522 MetaSized,
1523 PointeeSized,
1524 Unsize,
1525 Copy,
1526 Clone,
1527 DiscriminantKind,
1528 PointeeTrait,
1529 FnPtrTrait,
1530 Drop,
1531 Destruct,
1532 TransmuteTrait,
1533 Fn,
1534 FnMut,
1535 FnOnce,
1536 Future,
1537 Coroutine,
1538 Unpin,
1539 Tuple,
1540 Iterator,
1541 AsyncFn,
1542 AsyncFnMut,
1543 AsyncFnOnce,
1544 TrivialClone,
1545 AsyncFnKindHelper,
1546 AsyncIterator,
1547 BikeshedGuaranteedNoDrop,
1548 FusedIterator,
1549 Field,
1550 )
1551 }
1552
1553 fn is_adt_lang_item(self, def_id: Self::AdtId, lang_item: SolverAdtLangItem) -> bool {
1554 self.as_adt_lang_item(def_id)
1556 .map_or(false, |l| std::mem::discriminant(&l) == std::mem::discriminant(&lang_item))
1557 }
1558
1559 fn as_projection_lang_item(
1560 self,
1561 def_id: Self::TraitAssocTyId,
1562 ) -> Option<SolverProjectionLangItem> {
1563 as_lang_item!(
1564 SolverProjectionLangItem, self, def_id.0, TypeAliasId;
1565
1566 Metadata,
1567 CoroutineReturn,
1568 CoroutineYield,
1569 FutureOutput,
1570 CallRefFuture,
1571 CallOnceFuture,
1572 AsyncFnOnceOutput,
1573 AsyncFnKindUpvars,
1574 FieldBase,
1575 FieldType,
1576 )
1577 }
1578
1579 fn as_trait_lang_item(self, def_id: Self::TraitId) -> Option<SolverTraitLangItem> {
1580 as_lang_item!(
1581 SolverTraitLangItem, self, def_id.0, TraitId;
1582
1583 Sized,
1584 MetaSized,
1585 PointeeSized,
1586 Unsize,
1587 Copy,
1588 Clone,
1589 DiscriminantKind,
1590 PointeeTrait,
1591 FnPtrTrait,
1592 Drop,
1593 Destruct,
1594 TransmuteTrait,
1595 Fn,
1596 FnMut,
1597 FnOnce,
1598 Future,
1599 Coroutine,
1600 Unpin,
1601 Tuple,
1602 Iterator,
1603 AsyncFn,
1604 AsyncFnMut,
1605 AsyncFnOnce,
1606 TrivialClone,
1607 AsyncFnKindHelper,
1608 AsyncIterator,
1609 BikeshedGuaranteedNoDrop,
1610 FusedIterator,
1611 Field,
1612 )
1613 }
1614
1615 fn as_adt_lang_item(self, def_id: Self::AdtId) -> Option<SolverAdtLangItem> {
1616 as_lang_item!(
1617 SolverAdtLangItem, self, def_id.0, AdtId;
1618
1619 Option,
1620 Poll,
1621 DynMetadata,
1622 )
1623 }
1624
1625 fn associated_type_def_ids(
1626 self,
1627 def_id: Self::TraitId,
1628 ) -> impl IntoIterator<Item = Self::DefId> {
1629 def_id.0.trait_items(self.db()).associated_types().map(|id| id.into())
1630 }
1631
1632 fn for_each_relevant_impl<R: VisitorResult>(
1633 self,
1634 trait_def_id: Self::TraitId,
1635 self_ty: Self::Ty,
1636 mut f: impl FnMut(Self::ImplId) -> R,
1637 ) -> R {
1638 let krate = self.krate.expect("trait solving requires setting `DbInterner::krate`");
1639 let trait_block = trait_def_id.0.loc(self.db).container.block(self.db);
1640 let mut consider_impls_for_simplified_type = |simp: SimplifiedType<'_>| {
1641 let type_block = simp.def().and_then(|def_id| {
1642 let module = match def_id {
1643 SolverDefId::AdtId(AdtId::StructId(id)) => id.module(self.db),
1644 SolverDefId::AdtId(AdtId::EnumId(id)) => id.module(self.db),
1645 SolverDefId::AdtId(AdtId::UnionId(id)) => id.module(self.db),
1646 SolverDefId::TraitId(id) => id.module(self.db),
1647 SolverDefId::TypeAliasId(id) => id.module(self.db),
1648 SolverDefId::ConstId(_)
1649 | SolverDefId::FunctionId(_)
1650 | SolverDefId::ImplId(_)
1651 | SolverDefId::BuiltinDeriveImplId(_)
1652 | SolverDefId::StaticId(_)
1653 | SolverDefId::InternedClosureId(_)
1654 | SolverDefId::InternedCoroutineId(_)
1655 | SolverDefId::InternedCoroutineClosureId(_)
1656 | SolverDefId::InternedOpaqueTyId(_)
1657 | SolverDefId::EnumVariantId(_)
1658 | SolverDefId::AnonConstId(_)
1659 | SolverDefId::Ctor(_) => return None,
1660 };
1661 module.block(self.db)
1662 });
1663 TraitImpls::for_each_crate_and_block_trait_and_type(
1664 self.db,
1665 krate,
1666 type_block,
1667 trait_block,
1668 &mut |impls| {
1669 let (regular_impls, builtin_derive_impls) =
1670 impls.for_trait_and_self_ty(trait_def_id.0, &simp);
1671 for &impl_ in regular_impls {
1672 try_visit!(f(impl_.into()));
1673 }
1674 for &impl_ in builtin_derive_impls {
1675 try_visit!(f(impl_.into()));
1676 }
1677 R::output()
1678 },
1679 )
1680 };
1681
1682 match self_ty.kind() {
1683 TyKind::Bool
1684 | TyKind::Char
1685 | TyKind::Int(_)
1686 | TyKind::Uint(_)
1687 | TyKind::Float(_)
1688 | TyKind::Adt(_, _)
1689 | TyKind::Foreign(_)
1690 | TyKind::Str
1691 | TyKind::Array(_, _)
1692 | TyKind::Pat(_, _)
1693 | TyKind::Slice(_)
1694 | TyKind::RawPtr(_, _)
1695 | TyKind::Ref(_, _, _)
1696 | TyKind::FnDef(_, _)
1697 | TyKind::FnPtr(..)
1698 | TyKind::Dynamic(_, _)
1699 | TyKind::Closure(..)
1700 | TyKind::CoroutineClosure(..)
1701 | TyKind::Coroutine(_, _)
1702 | TyKind::Never
1703 | TyKind::Tuple(_)
1704 | TyKind::UnsafeBinder(_) => {
1705 let simp =
1706 fast_reject::simplify_type(self, self_ty, fast_reject::TreatParams::AsRigid)
1707 .unwrap();
1708 try_visit!(consider_impls_for_simplified_type(simp));
1709 }
1710
1711 TyKind::Infer(InferTy::IntVar(_)) => {
1714 use IntTy::*;
1715 use UintTy::*;
1716 let (I8 | I16 | I32 | I64 | I128 | Isize): IntTy;
1718 let (U8 | U16 | U32 | U64 | U128 | Usize): UintTy;
1719 let possible_integers = [
1720 SimplifiedType::Int(I8),
1722 SimplifiedType::Int(I16),
1723 SimplifiedType::Int(I32),
1724 SimplifiedType::Int(I64),
1725 SimplifiedType::Int(I128),
1726 SimplifiedType::Int(Isize),
1727 SimplifiedType::Uint(U8),
1729 SimplifiedType::Uint(U16),
1730 SimplifiedType::Uint(U32),
1731 SimplifiedType::Uint(U64),
1732 SimplifiedType::Uint(U128),
1733 SimplifiedType::Uint(Usize),
1734 ];
1735 for simp in possible_integers {
1736 try_visit!(consider_impls_for_simplified_type(simp));
1737 }
1738 }
1739
1740 TyKind::Infer(InferTy::FloatVar(_)) => {
1741 let (FloatTy::F16 | FloatTy::F32 | FloatTy::F64 | FloatTy::F128);
1743 let possible_floats = [
1744 SimplifiedType::Float(FloatTy::F16),
1745 SimplifiedType::Float(FloatTy::F32),
1746 SimplifiedType::Float(FloatTy::F64),
1747 SimplifiedType::Float(FloatTy::F128),
1748 ];
1749
1750 for simp in possible_floats {
1751 try_visit!(consider_impls_for_simplified_type(simp));
1752 }
1753 }
1754
1755 TyKind::Alias(..) | TyKind::Placeholder(..) | TyKind::Error(_) => (),
1760
1761 TyKind::CoroutineWitness(..) => (),
1765
1766 TyKind::Infer(
1768 InferTy::TyVar(_)
1769 | InferTy::FreshTy(_)
1770 | InferTy::FreshIntTy(_)
1771 | InferTy::FreshFloatTy(_),
1772 )
1773 | TyKind::Param(_)
1774 | TyKind::Bound(_, _) => panic!("unexpected self type: {self_ty:?}"),
1775 }
1776
1777 self.for_each_blanket_impl(trait_def_id, f)
1778 }
1779
1780 fn for_each_blanket_impl<R: VisitorResult>(
1781 self,
1782 trait_def_id: Self::TraitId,
1783 mut f: impl FnMut(Self::ImplId) -> R,
1784 ) -> R {
1785 let Some(krate) = self.krate else {
1786 return R::output();
1787 };
1788 let block = trait_def_id.0.loc(self.db).container.block(self.db);
1789
1790 TraitImpls::for_each_crate_and_block(self.db, krate, block, &mut |impls| {
1791 for &impl_ in impls.blanket_impls(trait_def_id.0) {
1792 try_visit!(f(impl_.into()));
1793 }
1794 R::output()
1795 })
1796 }
1797
1798 fn has_item_definition(self, _def_id: Self::ImplOrTraitAssocTermId) -> bool {
1799 true
1801 }
1802
1803 fn impl_is_default(self, impl_def_id: Self::ImplId) -> bool {
1804 match impl_def_id {
1805 AnyImplId::ImplId(impl_id) => ImplSignature::of(self.db, impl_id).is_default(),
1806 AnyImplId::BuiltinDeriveImplId(_) => false,
1807 }
1808 }
1809
1810 #[tracing::instrument(skip(self), ret)]
1811 fn impl_trait_ref(
1812 self,
1813 impl_id: Self::ImplId,
1814 ) -> EarlyBinder<Self, rustc_type_ir::TraitRef<Self>> {
1815 match impl_id {
1816 AnyImplId::ImplId(impl_id) => {
1817 let db = self.db();
1818 db.impl_trait(impl_id)
1819 .expect("invalid impl passed to trait solver")
1821 }
1822 AnyImplId::BuiltinDeriveImplId(impl_id) => {
1823 crate::builtin_derive::impl_trait(self, impl_id)
1824 }
1825 }
1826 }
1827
1828 fn impl_polarity(self, impl_id: Self::ImplId) -> rustc_type_ir::ImplPolarity {
1829 let AnyImplId::ImplId(impl_id) = impl_id else {
1830 return ImplPolarity::Positive;
1831 };
1832 let impl_data = ImplSignature::of(self.db(), impl_id);
1833 if impl_data.flags.contains(ImplFlags::NEGATIVE) {
1834 ImplPolarity::Negative
1835 } else {
1836 ImplPolarity::Positive
1837 }
1838 }
1839
1840 fn trait_is_auto(self, trait_: Self::TraitId) -> bool {
1841 let trait_data = TraitSignature::of(self.db(), trait_.0);
1842 trait_data.flags.contains(TraitFlags::AUTO)
1843 }
1844
1845 fn trait_is_alias(self, trait_: Self::TraitId) -> bool {
1846 let trait_data = TraitSignature::of(self.db(), trait_.0);
1847 trait_data.flags.contains(TraitFlags::ALIAS)
1848 }
1849
1850 fn trait_is_dyn_compatible(self, trait_: Self::TraitId) -> bool {
1851 crate::dyn_compatibility::dyn_compatibility(self.db(), trait_.0).is_none()
1852 }
1853
1854 fn trait_is_fundamental(self, trait_: Self::TraitId) -> bool {
1855 let trait_data = TraitSignature::of(self.db(), trait_.0);
1856 trait_data.flags.contains(TraitFlags::FUNDAMENTAL)
1857 }
1858
1859 fn is_impl_trait_in_trait(self, _def_id: Self::DefId) -> bool {
1860 false
1862 }
1863
1864 fn delay_bug(self, _msg: impl ToString) -> Self::ErrorGuaranteed {
1865 ErrorGuaranteed
1866 }
1867
1868 fn is_general_coroutine(self, def_id: Self::CoroutineId) -> bool {
1869 matches!(def_id.0.loc(self.db).kind, HirClosureKind::OldCoroutine(_))
1870 }
1871
1872 fn coroutine_is_async(self, def_id: Self::CoroutineId) -> bool {
1873 matches!(
1874 def_id.0.loc(self.db).kind,
1875 HirClosureKind::Coroutine { kind: HirCoroutineKind::Async, .. }
1876 )
1877 }
1878
1879 fn coroutine_is_gen(self, def_id: Self::CoroutineId) -> bool {
1880 matches!(
1881 def_id.0.loc(self.db).kind,
1882 HirClosureKind::Coroutine { kind: HirCoroutineKind::Gen, .. }
1883 )
1884 }
1885
1886 fn coroutine_is_async_gen(self, def_id: Self::CoroutineId) -> bool {
1887 matches!(
1888 def_id.0.loc(self.db).kind,
1889 HirClosureKind::Coroutine { kind: HirCoroutineKind::AsyncGen, .. }
1890 )
1891 }
1892
1893 fn unsizing_params_for_adt(self, id: Self::AdtId) -> Self::UnsizingParams {
1894 let def = AdtDef::new(id.0, self);
1895 let num_params = self.generics_of(id.into()).count();
1896
1897 let maybe_unsizing_param_idx = |arg: GenericArg<'db>| match arg.kind() {
1898 GenericArgKind::Type(ty) => match ty.kind() {
1899 rustc_type_ir::TyKind::Param(p) => Some(p.index),
1900 _ => None,
1901 },
1902 GenericArgKind::Lifetime(_) => None,
1903 GenericArgKind::Const(ct) => match ct.kind() {
1904 rustc_type_ir::ConstKind::Param(p) => Some(p.index),
1905 _ => None,
1906 },
1907 };
1908
1909 let variant = match def.def_id() {
1911 AdtId::StructId(id) => VariantId::from(id),
1912 AdtId::UnionId(id) => id.into(),
1913 AdtId::EnumId(_) => panic!("expected a struct or a union"),
1914 };
1915 let fields = variant.fields(self.db());
1916 let mut prefix_fields = fields.fields().iter();
1917 let Some(tail_field) = prefix_fields.next_back() else {
1918 return UnsizingParams(DenseBitSet::new_empty(num_params));
1919 };
1920
1921 let field_types = self.db().field_types(variant);
1922 let mut unsizing_params = DenseBitSet::new_empty(num_params);
1923 let ty = field_types[tail_field.0].ty();
1924 for arg in ty.instantiate_identity().skip_norm_wip().walk() {
1925 if let Some(i) = maybe_unsizing_param_idx(arg) {
1926 unsizing_params.insert(i);
1927 }
1928 }
1929
1930 for field in prefix_fields {
1933 for arg in field_types[field.0].ty().instantiate_identity().skip_norm_wip().walk() {
1934 if let Some(i) = maybe_unsizing_param_idx(arg) {
1935 unsizing_params.remove(i);
1936 }
1937 }
1938 }
1939
1940 UnsizingParams(unsizing_params)
1941 }
1942
1943 fn anonymize_bound_vars<T: rustc_type_ir::TypeFoldable<Self>>(
1944 self,
1945 value: rustc_type_ir::Binder<Self, T>,
1946 ) -> rustc_type_ir::Binder<Self, T> {
1947 struct Anonymize<'a, 'db> {
1948 interner: DbInterner<'db>,
1949 map: &'a mut FxIndexMap<BoundVar, BoundVariableKind<'db>>,
1950 }
1951 impl<'db> BoundVarReplacerDelegate<'db> for Anonymize<'_, 'db> {
1952 fn replace_region(&mut self, br: BoundRegion<'db>) -> Region<'db> {
1953 let entry = self.map.entry(br.var);
1954 let index = entry.index();
1955 let var = BoundVar::from_usize(index);
1956 let kind = (*entry
1957 .or_insert_with(|| BoundVariableKind::Region(BoundRegionKind::Anon)))
1958 .expect_region();
1959 let br = BoundRegion { var, kind };
1960 Region::new_bound(self.interner, DebruijnIndex::ZERO, br)
1961 }
1962 fn replace_ty(&mut self, bt: BoundTy<'db>) -> Ty<'db> {
1963 let entry = self.map.entry(bt.var);
1964 let index = entry.index();
1965 let var = BoundVar::from_usize(index);
1966 let kind = (*entry.or_insert_with(|| BoundVariableKind::Ty(BoundTyKind::Anon)))
1967 .expect_ty();
1968 Ty::new_bound(self.interner, DebruijnIndex::ZERO, BoundTy { var, kind })
1969 }
1970 fn replace_const(&mut self, bv: BoundConst<'db>) -> Const<'db> {
1971 let entry = self.map.entry(bv.var);
1972 let index = entry.index();
1973 let var = BoundVar::from_usize(index);
1974 let () = (*entry.or_insert_with(|| BoundVariableKind::Const)).expect_const();
1975 Const::new_bound(self.interner, DebruijnIndex::ZERO, BoundConst::new(var))
1976 }
1977 }
1978
1979 let mut map = Default::default();
1980 let delegate = Anonymize { interner: self, map: &mut map };
1981 let inner = self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate);
1982 let bound_vars = BoundVarKinds::new_from_iter(self, map.into_values());
1983 Binder::bind_with_vars(inner, bound_vars)
1984 }
1985
1986 fn opaque_types_defined_by(self, def_id: Self::LocalDefId) -> Self::LocalDefIds {
1987 let Ok(def_id) = InferBodyId::try_from(def_id) else {
1988 return SolverDefIds::default();
1989 };
1990 let mut result = Vec::new();
1991 crate::opaques::opaque_types_defined_by(self.db, def_id, &mut result);
1992 SolverDefIds::new_from_slice(&result)
1993 }
1994
1995 fn opaque_types_and_coroutines_defined_by(self, def_id: Self::LocalDefId) -> Self::LocalDefIds {
1996 let db = self.db;
1997
1998 let Ok(def_id) = InferBodyId::try_from(def_id) else {
1999 return SolverDefIds::default();
2000 };
2001 let mut result = Vec::new();
2002
2003 crate::opaques::opaque_types_defined_by(db, def_id, &mut result);
2004
2005 let (store, root_expr) = def_id.store_and_root_expr(db);
2007 CoroutinesVisitor { db: self.db, owner: def_id, store, coroutines: &mut result }
2009 .on_expr(root_expr);
2010
2011 return SolverDefIds::new_from_slice(&result);
2012
2013 struct CoroutinesVisitor<'a, 'db> {
2014 db: &'db dyn HirDatabase,
2015 owner: InferBodyId<'db>,
2016 store: &'db ExpressionStore,
2017 coroutines: &'a mut Vec<SolverDefId<'db>>,
2018 }
2019
2020 impl<'db> StoreVisitor for CoroutinesVisitor<'_, 'db> {
2021 fn on_expr(&mut self, expr: ExprId) {
2022 if let hir_def::hir::Expr::Closure {
2023 closure_kind:
2024 kind @ (hir_def::hir::ClosureKind::Coroutine { .. }
2025 | hir_def::hir::ClosureKind::OldCoroutine(_)),
2026 ..
2027 } = self.store[expr]
2028 {
2029 let coroutine = InternedCoroutineId::new(
2030 self.db,
2031 InternedClosure { owner: self.owner, expr, kind },
2032 );
2033 self.coroutines.push(coroutine.into());
2034 }
2035
2036 self.store.visit_expr_children(expr, self);
2037 }
2038 fn on_pat(&mut self, pat: PatId) {
2039 self.store.visit_pat_children(pat, self);
2040 }
2041 fn on_anon_const_expr(&mut self, _expr: ExprId) {}
2043 }
2044 }
2045
2046 fn alias_has_const_conditions(self, _def_id: Self::DefId) -> bool {
2047 false
2049 }
2050
2051 fn explicit_implied_const_bounds(
2052 self,
2053 _def_id: Self::DefId,
2054 ) -> EarlyBinder<
2055 Self,
2056 impl IntoIterator<Item = rustc_type_ir::Binder<Self, rustc_type_ir::TraitRef<Self>>>,
2057 > {
2058 EarlyBinder::bind([])
2060 }
2061
2062 fn fn_is_const(self, id: Self::FunctionId) -> bool {
2063 let id = match id.0 {
2064 CallableDefId::FunctionId(id) => id,
2065 _ => return false,
2066 };
2067 FunctionSignature::of(self.db(), id).flags.contains(FnFlags::CONST)
2068 }
2069
2070 fn impl_is_const(self, _def_id: Self::ImplId) -> bool {
2071 false
2072 }
2073
2074 fn opt_alias_variances(
2075 self,
2076 _kind: impl Into<AliasTermKind<'db>>,
2077 ) -> Option<Self::VariancesOf> {
2078 None
2079 }
2080
2081 fn type_of_opaque_hir_typeck(
2082 self,
2083 opaque: Self::LocalOpaqueTyId,
2084 ) -> EarlyBinder<Self, Self::Ty> {
2085 let impl_trait_id = opaque.0.loc(self.db);
2086 let hidden_type = match impl_trait_id {
2089 crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => {
2090 crate::opaques::rpit_hidden_types(self.db, func).get(idx)
2091 }
2092 crate::ImplTraitId::TypeAliasImplTrait(type_alias, idx) => {
2093 crate::opaques::tait_hidden_types(self.db, type_alias).get(idx)
2094 }
2095 };
2096 match hidden_type {
2097 Some(hidden_type) => hidden_type.get(),
2098 None => EarlyBinder::bind(Ty::new_error(self, ErrorGuaranteed)),
2099 }
2100 }
2101
2102 fn coroutine_hidden_types(
2103 self,
2104 _def_id: Self::CoroutineId,
2105 ) -> EarlyBinder<Self, Binder<'db, CoroutineWitnessTypes<Self>>> {
2106 EarlyBinder::bind(Binder::dummy(CoroutineWitnessTypes {
2108 types: Tys::default(),
2109 assumptions: RegionAssumptions::default(),
2110 }))
2111 }
2112
2113 fn is_default_trait(self, def_id: Self::TraitId) -> bool {
2114 self.as_trait_lang_item(def_id).map_or(false, |l| matches!(l, SolverTraitLangItem::Sized))
2115 }
2116
2117 fn trait_is_coinductive(self, trait_: Self::TraitId) -> bool {
2118 TraitSignature::of(self.db(), trait_.0).flags.contains(TraitFlags::COINDUCTIVE)
2119 }
2120
2121 fn trait_is_unsafe(self, trait_: Self::TraitId) -> bool {
2122 TraitSignature::of(self.db(), trait_.0).flags.contains(TraitFlags::UNSAFE)
2123 }
2124
2125 fn impl_self_is_guaranteed_unsized(self, _def_id: Self::ImplId) -> bool {
2126 false
2127 }
2128
2129 fn impl_specializes(
2130 self,
2131 specializing_impl_def_id: Self::ImplId,
2132 parent_impl_def_id: Self::ImplId,
2133 ) -> bool {
2134 let (AnyImplId::ImplId(specializing_impl_def_id), AnyImplId::ImplId(parent_impl_def_id)) =
2135 (specializing_impl_def_id, parent_impl_def_id)
2136 else {
2137 return false;
2139 };
2140 crate::specialization::specializes(self.db, specializing_impl_def_id, parent_impl_def_id)
2141 }
2142
2143 fn next_trait_solver_globally(self) -> bool {
2144 true
2145 }
2146
2147 type Probe = rustc_type_ir::solve::inspect::Probe<DbInterner<'db>>;
2148 fn mk_probe(self, probe: rustc_type_ir::solve::inspect::Probe<Self>) -> Self::Probe {
2149 probe
2150 }
2151 fn evaluate_root_goal_for_proof_tree_raw(
2152 self,
2153 canonical_goal: rustc_type_ir::solve::CanonicalInput<Self>,
2154 ) -> (rustc_type_ir::solve::QueryResult<Self>, Self::Probe) {
2155 rustc_next_trait_solver::solve::evaluate_root_goal_for_proof_tree_raw_provider::<
2156 SolverContext<'db>,
2157 Self,
2158 >(self, canonical_goal)
2159 }
2160
2161 fn is_sizedness_trait(self, def_id: Self::TraitId) -> bool {
2162 matches!(
2163 self.as_trait_lang_item(def_id),
2164 Some(SolverTraitLangItem::Sized | SolverTraitLangItem::MetaSized)
2165 )
2166 }
2167
2168 fn const_of_item(self, def_id: Self::DefId) -> rustc_type_ir::EarlyBinder<Self, Self::Const> {
2169 let id = match def_id {
2170 SolverDefId::StaticId(id) => id.into(),
2171 SolverDefId::ConstId(id) => id.into(),
2172 _ => unreachable!(),
2173 };
2174 EarlyBinder::bind(Const::new_unevaluated(
2175 self,
2176 UnevaluatedConst { def: GeneralConstIdWrapper(id), args: GenericArgs::empty() },
2177 ))
2178 }
2179
2180 fn anon_const_kind(self, _def_id: Self::DefId) -> rustc_type_ir::AnonConstKind {
2181 rustc_type_ir::AnonConstKind::GCE
2183 }
2184
2185 fn alias_ty_kind_from_def_id(self, def_id: Self::DefId) -> AliasTyKind<'db> {
2186 match def_id {
2187 SolverDefId::TypeAliasId(type_alias) => match type_alias.loc(self.db).container {
2188 ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => {
2189 AliasTyKind::Free { def_id: type_alias.into() }
2190 }
2191 ItemContainerId::ImplId(_) => AliasTyKind::Inherent { def_id: type_alias.into() },
2192 ItemContainerId::TraitId(_) => {
2193 AliasTyKind::Projection { def_id: type_alias.into() }
2194 }
2195 },
2196 SolverDefId::InternedOpaqueTyId(def_id) => {
2197 AliasTyKind::Opaque { def_id: def_id.into() }
2198 }
2199 _ => unreachable!(),
2200 }
2201 }
2202
2203 fn closure_is_const(self, _def_id: Self::ClosureId) -> bool {
2204 false
2206 }
2207
2208 fn item_name(self, _item_index: Self::DefId) -> Self::Symbol {
2209 Symbol
2210 }
2211}
2212
2213fn is_ty_self(ty: Ty<'_>) -> bool {
2214 match ty.kind() {
2215 TyKind::Param(param) => param.index == 0,
2216 _ => false,
2217 }
2218}
2219fn is_clause_at_ty(p: &Clause<'_>, filter: impl FnOnce(Ty<'_>) -> bool) -> bool {
2220 match p.kind().skip_binder() {
2221 ClauseKind::Trait(it) => filter(it.self_ty()),
2224 ClauseKind::TypeOutlives(it) => filter(it.0),
2225 ClauseKind::Projection(it) => filter(it.self_ty()),
2226 ClauseKind::HostEffect(it) => filter(it.self_ty()),
2227 _ => false,
2228 }
2229}
2230
2231impl<'db> DbInterner<'db> {
2232 pub fn shift_bound_var_indices<T>(self, bound_vars: usize, value: T) -> T
2233 where
2234 T: rustc_type_ir::TypeFoldable<Self>,
2235 {
2236 let shift_bv = |bv: BoundVar| BoundVar::from_usize(bv.as_usize() + bound_vars);
2237 self.replace_escaping_bound_vars_uncached(
2238 value,
2239 FnMutDelegate {
2240 regions: &mut |r: BoundRegion<'db>| {
2241 Region::new_bound(
2242 self,
2243 DebruijnIndex::ZERO,
2244 BoundRegion { var: shift_bv(r.var), kind: r.kind },
2245 )
2246 },
2247 types: &mut |t: BoundTy<'db>| {
2248 Ty::new_bound(
2249 self,
2250 DebruijnIndex::ZERO,
2251 BoundTy { var: shift_bv(t.var), kind: t.kind },
2252 )
2253 },
2254 consts: &mut |c| {
2255 Const::new_bound(self, DebruijnIndex::ZERO, BoundConst::new(shift_bv(c.var)))
2256 },
2257 },
2258 )
2259 }
2260
2261 pub fn replace_escaping_bound_vars_uncached<T: rustc_type_ir::TypeFoldable<DbInterner<'db>>>(
2262 self,
2263 value: T,
2264 delegate: impl BoundVarReplacerDelegate<'db>,
2265 ) -> T {
2266 if !value.has_escaping_bound_vars() {
2267 value
2268 } else {
2269 let mut replacer = BoundVarReplacer::new(self, delegate);
2270 value.fold_with(&mut replacer)
2271 }
2272 }
2273
2274 pub fn replace_bound_vars_uncached<T: rustc_type_ir::TypeFoldable<DbInterner<'db>>>(
2275 self,
2276 value: Binder<'db, T>,
2277 delegate: impl BoundVarReplacerDelegate<'db>,
2278 ) -> T {
2279 self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate)
2280 }
2281
2282 pub fn mk_fn_sig<I>(
2284 self,
2285 inputs: I,
2286 output: Ty<'db>,
2287 c_variadic: bool,
2288 safety: Safety,
2289 abi: ExternAbi,
2290 ) -> FnSig<'db>
2291 where
2292 I: IntoIterator<Item = Ty<'db>>,
2293 {
2294 FnSig {
2295 inputs_and_output: Tys::new_from_iter(
2296 self,
2297 inputs.into_iter().chain(std::iter::once(output)),
2298 ),
2299 fn_sig_kind: FnSigKind::new(abi, safety, c_variadic),
2300 }
2301 }
2302
2303 pub fn mk_fn_sig_safe_rust_abi<I>(self, inputs: I, output: Ty<'db>) -> FnSig<'db>
2305 where
2306 I: IntoIterator<Item = Ty<'db>>,
2307 {
2308 self.mk_fn_sig(inputs, output, false, Safety::Safe, ExternAbi::Rust)
2309 }
2310}
2311
2312fn predicates_of<'db>(
2313 db: &'db dyn HirDatabase,
2314 def_id: SolverDefId<'db>,
2315) -> &'db GenericPredicates {
2316 match def_id {
2317 SolverDefId::BuiltinDeriveImplId(impl_) => crate::builtin_derive::predicates(db, impl_),
2318 SolverDefId::AnonConstId(anon_const) => {
2319 let loc = anon_const.loc(db);
2320 if loc.allow_using_generic_params {
2321 GenericPredicates::query(db, loc.owner.generic_def(db))
2322 } else {
2323 GenericPredicates::empty()
2324 }
2325 }
2326 _ => GenericPredicates::query(db, def_id.try_into().unwrap()),
2327 }
2328}
2329
2330macro_rules! TrivialTypeTraversalImpls {
2331 ($($ty:ty,)+) => {
2332 $(
2333 impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for $ty {
2334 fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
2335 self,
2336 _: &mut F,
2337 ) -> ::std::result::Result<Self, F::Error> {
2338 Ok(self)
2339 }
2340
2341 #[inline]
2342 fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(
2343 self,
2344 _: &mut F,
2345 ) -> Self {
2346 self
2347 }
2348 }
2349
2350 impl<'db> rustc_type_ir::TypeVisitable<DbInterner<'db>> for $ty {
2351 #[inline]
2352 fn visit_with<F: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
2353 &self,
2354 _: &mut F)
2355 -> F::Result
2356 {
2357 <F::Result as rustc_ast_ir::visit::VisitorResult>::output()
2358 }
2359 }
2360
2361 impl<V> rustc_type_ir::GenericTypeVisitable<V> for $ty {
2362 #[inline]
2363 fn generic_visit_with(&self, _visitor: &mut V) {}
2364 }
2365 )+
2366 };
2367}
2368
2369TrivialTypeTraversalImpls! {
2370 SolverDefId<'_>,
2371 TraitIdWrapper,
2372 TypeAliasIdWrapper,
2373 CallableIdWrapper,
2374 ClosureIdWrapper<'_>,
2375 CoroutineIdWrapper<'_>,
2376 CoroutineClosureIdWrapper<'_>,
2377 AdtIdWrapper,
2378 TraitAssocTyId,
2379 TraitAssocConstId,
2380 TraitAssocTermId,
2381 ImplOrTraitAssocTyId,
2382 ImplOrTraitAssocConstId,
2383 ImplOrTraitAssocTermId,
2384 FreeTyAliasId,
2385 FreeConstAliasId,
2386 FreeTermAliasId,
2387 InherentAssocTyId,
2388 InherentAssocConstId,
2389 InherentAssocTermId,
2390 OpaqueTyIdWrapper<'_>,
2391 AnyImplId,
2392 GeneralConstIdWrapper<'_>,
2393 Safety,
2394 Span,
2395 ParamConst,
2396 ParamTy,
2397 EarlyParamRegion,
2398 AdtDef,
2399 ScalarInt,
2400}
2401
2402mod tls_db {
2403 use std::{cell::Cell, ptr::NonNull};
2404
2405 use crate::db::HirDatabase;
2406
2407 struct Attached {
2408 database: Cell<Option<NonNull<dyn HirDatabase>>>,
2409 }
2410
2411 impl Attached {
2412 #[inline]
2413 fn attach<R>(&self, db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
2414 struct DbGuard<'s> {
2415 state: Option<&'s Attached>,
2416 }
2417
2418 impl<'s> DbGuard<'s> {
2419 #[inline]
2420 fn new(attached: &'s Attached, db: &dyn HirDatabase) -> Self {
2421 match attached.database.get() {
2422 Some(current_db) => {
2423 let new_db = NonNull::from(db);
2424 if !std::ptr::addr_eq(current_db.as_ptr(), new_db.as_ptr()) {
2425 panic!(
2426 "Cannot change attached database. This is likely a bug.\n\
2427 If this is not a bug, you can use `attach_db_allow_change()`."
2428 );
2429 }
2430 Self { state: None }
2431 }
2432 None => {
2433 attached.database.set(Some(NonNull::from(db)));
2435 Self { state: Some(attached) }
2436 }
2437 }
2438 }
2439 }
2440
2441 impl Drop for DbGuard<'_> {
2442 #[inline]
2443 fn drop(&mut self) {
2444 if let Some(attached) = self.state {
2446 attached.database.set(None);
2447 }
2448 }
2449 }
2450
2451 let _guard = DbGuard::new(self, db);
2452 super::tls_cache::reinit_cache(db);
2453 op()
2454 }
2455
2456 #[inline]
2457 fn attach_allow_change<R>(&self, db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
2458 struct DbGuard<'s> {
2459 state: &'s Attached,
2460 prev: Option<NonNull<dyn HirDatabase>>,
2461 }
2462
2463 impl<'s> DbGuard<'s> {
2464 #[inline]
2465 fn new(attached: &'s Attached, db: &dyn HirDatabase) -> Self {
2466 let prev = attached.database.replace(Some(NonNull::from(db)));
2467 Self { state: attached, prev }
2468 }
2469 }
2470
2471 impl Drop for DbGuard<'_> {
2472 #[inline]
2473 fn drop(&mut self) {
2474 self.state.database.set(self.prev);
2475 if let Some(prev) = self.prev {
2476 super::tls_cache::reinit_cache(unsafe { prev.as_ref() });
2477 }
2478 }
2479 }
2480
2481 let _guard = DbGuard::new(self, db);
2482 super::tls_cache::reinit_cache(db);
2483 op()
2484 }
2485
2486 #[inline]
2487 fn with<R>(&self, op: impl FnOnce(&dyn HirDatabase) -> R) -> R {
2488 let db = self.database.get().expect("Try to use attached db, but not db is attached");
2489
2490 op(unsafe { db.as_ref() })
2492 }
2493 }
2494
2495 thread_local! {
2496 static GLOBAL_DB: Attached = const { Attached { database: Cell::new(None) } };
2497 }
2498
2499 #[inline]
2500 pub fn attach_db<R>(db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
2501 GLOBAL_DB.with(|global_db| global_db.attach(db, op))
2502 }
2503
2504 #[inline]
2505 pub fn attach_db_allow_change<R>(db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
2506 GLOBAL_DB.with(|global_db| global_db.attach_allow_change(db, op))
2507 }
2508
2509 #[inline]
2510 pub fn with_attached_db<R>(op: impl FnOnce(&dyn HirDatabase) -> R) -> R {
2511 GLOBAL_DB.with(
2512 #[inline]
2513 |a| a.with(op),
2514 )
2515 }
2516}
2517
2518mod tls_cache {
2519 use crate::db::HirDatabase;
2520
2521 use super::DbInterner;
2522 use base_db::Nonce;
2523 use rustc_type_ir::search_graph::GlobalCache;
2524 use salsa::Revision;
2525 use std::cell::RefCell;
2526
2527 struct Cache {
2528 cache: GlobalCache<DbInterner<'static>>,
2529 revision: Revision,
2530 db_nonce: Nonce,
2531 }
2532
2533 impl Cache {
2534 const fn default() -> Cache {
2535 Cache {
2536 cache: GlobalCache::new(),
2537 revision: Revision::max(),
2538 db_nonce: Nonce::invalid(),
2539 }
2540 }
2541 }
2542
2543 thread_local! {
2544 static GLOBAL_CACHE: RefCell<Cache> = const { RefCell::new(Cache::default()) };
2545 }
2546
2547 pub(super) fn reinit_cache(db: &dyn HirDatabase) {
2548 GLOBAL_CACHE.with_borrow_mut(|handle| {
2549 let (db_nonce, revision) = db.nonce_and_revision();
2550 if handle.revision != revision || db_nonce != handle.db_nonce {
2551 *handle = Cache { cache: GlobalCache::default(), revision, db_nonce };
2552 }
2553 })
2554 }
2555
2556 #[inline]
2557 pub(super) fn borrow_assume_valid<'db, T>(
2558 db: &'db dyn HirDatabase,
2559 f: impl FnOnce(&mut GlobalCache<DbInterner<'db>>) -> T,
2560 ) -> T {
2561 if cfg!(debug_assertions) {
2562 let get_state =
2563 || GLOBAL_CACHE.with_borrow(|handle| (handle.db_nonce, handle.revision));
2564 let old_state = get_state();
2565 reinit_cache(db);
2566 let new_state = get_state();
2567 assert_eq!(old_state, new_state, "you assumed the cache is valid!");
2568 }
2569
2570 GLOBAL_CACHE.with_borrow_mut(|handle| {
2571 f(unsafe {
2573 std::mem::transmute::<
2574 &mut GlobalCache<DbInterner<'static>>,
2575 &mut GlobalCache<DbInterner<'db>>,
2576 >(&mut handle.cache)
2577 })
2578 })
2579 }
2580
2581 pub fn clear_tls_solver_cache() {
2586 GLOBAL_CACHE.with_borrow_mut(|handle| *handle = Cache::default());
2587 }
2588}
2589
2590impl WorldExposer for intern::GarbageCollector {
2591 fn on_interned<T: intern::Internable>(
2592 &mut self,
2593 interned: InternedRef<'_, T>,
2594 ) -> ControlFlow<()> {
2595 self.mark_interned_alive(interned)
2596 }
2597
2598 fn on_interned_slice<T: intern::SliceInternable>(
2599 &mut self,
2600 interned: InternedSliceRef<'_, T>,
2601 ) -> ControlFlow<()> {
2602 self.mark_interned_slice_alive(interned)
2603 }
2604}
2605
2606pub unsafe fn collect_ty_garbage() {
2612 let mut gc = intern::GarbageCollector::default();
2613
2614 gc.add_storage::<super::consts::ConstInterned>();
2615 gc.add_storage::<super::consts::ValTreeInterned>();
2616 gc.add_storage::<super::allocation::AllocationInterned>();
2617 gc.add_storage::<PatternInterned>();
2618 gc.add_storage::<super::opaques::ExternalConstraintsInterned>();
2619 gc.add_storage::<super::predicate::PredicateInterned>();
2620 gc.add_storage::<super::region::RegionInterned>();
2621 gc.add_storage::<super::ty::TyInterned>();
2622
2623 gc.add_slice_storage::<super::consts::ConstsStorage>();
2624 gc.add_slice_storage::<super::predicate::ClausesStorage>();
2625 gc.add_slice_storage::<super::generic_arg::GenericArgsStorage>();
2626 gc.add_slice_storage::<BoundVarKindsStorage>();
2627 gc.add_slice_storage::<VariancesOfStorage>();
2628 gc.add_slice_storage::<CanonicalVarsStorage>();
2629 gc.add_slice_storage::<PatListStorage>();
2630 gc.add_slice_storage::<super::opaques::PredefinedOpaquesStorage>();
2631 gc.add_slice_storage::<super::opaques::SolverDefIdsStorage>();
2632 gc.add_slice_storage::<super::predicate::BoundExistentialPredicatesStorage>();
2633 gc.add_slice_storage::<super::region::RegionAssumptionsStorage>();
2634 gc.add_slice_storage::<super::ty::TysStorage>();
2635 gc.add_slice_storage::<crate::mir::ProjectionStorage>();
2636
2637 unsafe { gc.collect() };
2642}
2643
2644macro_rules! impl_gc_visit {
2645 ( $($ty:ty),* $(,)? ) => {
2646 $(
2647 impl ::intern::GcInternedVisit for $ty {
2648 #[inline]
2649 fn visit_with(&self, gc: &mut ::intern::GarbageCollector) {
2650 self.generic_visit_with(gc);
2651 }
2652 }
2653 )*
2654 };
2655}
2656
2657impl_gc_visit!(
2658 super::consts::ConstInterned,
2659 super::consts::ValTreeInterned,
2660 super::allocation::AllocationInterned,
2661 PatternInterned,
2662 super::opaques::ExternalConstraintsInterned,
2663 super::predicate::PredicateInterned,
2664 super::region::RegionInterned,
2665 super::ty::TyInterned,
2666 super::predicate::ClausesCachedTypeInfo,
2667);
2668
2669macro_rules! impl_gc_visit_slice {
2670 ( $($ty:ty),* $(,)? ) => {
2671 $(
2672 impl ::intern::GcInternedSliceVisit for $ty {
2673 #[inline]
2674 fn visit_header(header: &<Self as ::intern::SliceInternable>::Header, gc: &mut ::intern::GarbageCollector) {
2675 header.generic_visit_with(gc);
2676 }
2677
2678 #[inline]
2679 fn visit_slice(slice: &[<Self as ::intern::SliceInternable>::SliceType], gc: &mut ::intern::GarbageCollector) {
2680 slice.generic_visit_with(gc);
2681 }
2682 }
2683 )*
2684 };
2685}
2686
2687impl_gc_visit_slice!(
2688 super::predicate::ClausesStorage,
2689 super::generic_arg::GenericArgsStorage,
2690 BoundVarKindsStorage,
2691 VariancesOfStorage,
2692 CanonicalVarsStorage,
2693 PatListStorage,
2694 super::opaques::PredefinedOpaquesStorage,
2695 super::opaques::SolverDefIdsStorage,
2696 super::predicate::BoundExistentialPredicatesStorage,
2697 super::region::RegionAssumptionsStorage,
2698 super::ty::TysStorage,
2699 super::consts::ConstsStorage,
2700 crate::mir::ProjectionStorage,
2701);