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