Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/next_solver/interner.rs')
| -rw-r--r-- | crates/hir-ty/src/next_solver/interner.rs | 341 |
1 files changed, 209 insertions, 132 deletions
diff --git a/crates/hir-ty/src/next_solver/interner.rs b/crates/hir-ty/src/next_solver/interner.rs index a3c984f6c9..2e52dcea6c 100644 --- a/crates/hir-ty/src/next_solver/interner.rs +++ b/crates/hir-ty/src/next_solver/interner.rs @@ -8,9 +8,10 @@ pub use tls_db::{attach_db, attach_db_allow_change, with_attached_db}; use base_db::Crate; use hir_def::{ - AdtId, AttrDefId, BlockId, CallableDefId, DefWithBodyId, EnumVariantId, HasModule, - ItemContainerId, StructId, UnionId, VariantId, - lang_item::LangItem, + AdtId, CallableDefId, DefWithBodyId, EnumVariantId, HasModule, ItemContainerId, StructId, + UnionId, VariantId, + attrs::AttrFlags, + lang_item::LangItems, signatures::{FieldData, FnFlags, ImplFlags, StructFlags, TraitFlags}, }; use la_arena::Idx; @@ -270,8 +271,8 @@ pub use crate::_interned_vec_db as interned_vec_db; #[derive(Debug, Copy, Clone)] pub struct DbInterner<'db> { pub(crate) db: &'db dyn HirDatabase, - pub(crate) krate: Option<Crate>, - pub(crate) block: Option<BlockId>, + krate: Option<Crate>, + lang_items: Option<&'db LangItems>, } // FIXME: very wrong, see https://github.com/rust-lang/rust/pull/144808 @@ -284,22 +285,42 @@ impl<'db> DbInterner<'db> { crate::with_attached_db(|db| DbInterner { db: unsafe { std::mem::transmute::<&dyn HirDatabase, &'db dyn HirDatabase>(db) }, krate: None, - block: None, + lang_items: None, }) } - pub fn new_with( - db: &'db dyn HirDatabase, - krate: Option<Crate>, - block: Option<BlockId>, - ) -> DbInterner<'db> { - DbInterner { db, krate, block } + /// Creates a new interner without an active crate. Good only for interning things, not for trait solving etc.. + /// As a rule of thumb, when you create an `InferCtxt`, you need to provide the crate (and the block). + /// + /// Elaboration is a special kind: it needs lang items (for `Sized`), therefore it needs `new_with()`. + pub fn new_no_crate(db: &'db dyn HirDatabase) -> Self { + DbInterner { db, krate: None, lang_items: None } + } + + pub fn new_with(db: &'db dyn HirDatabase, krate: Crate) -> DbInterner<'db> { + DbInterner { + db, + krate: Some(krate), + // As an approximation, when we call `new_with` we're trait solving, therefore we need the lang items. + // This is also convenient since here we have a starting crate but not in `new_no_crate`. + lang_items: Some(hir_def::lang_item::lang_items(db, krate)), + } } #[inline] pub fn db(&self) -> &'db dyn HirDatabase { self.db } + + #[inline] + #[track_caller] + pub fn lang_items(&self) -> &'db LangItems { + self.lang_items.expect( + "Must have `DbInterner::lang_items`.\n\n\ + Note: you might have called `DbInterner::new_no_crate()` \ + where you should've called `DbInterner::new_with()`", + ) + } } // This is intentionally left as `()` @@ -479,28 +500,28 @@ impl AdtDef { let variants = vec![(VariantIdx(0), VariantDef::Struct(struct_id))]; - let mut repr = ReprOptions::default(); - repr.align = data.repr.and_then(|r| r.align); - repr.pack = data.repr.and_then(|r| r.pack); - repr.int = data.repr.and_then(|r| r.int); - + let data_repr = data.repr(db, struct_id); let mut repr_flags = ReprFlags::empty(); if flags.is_box { repr_flags.insert(ReprFlags::IS_LINEAR); } - if data.repr.is_some_and(|r| r.c()) { + if data_repr.is_some_and(|r| r.c()) { repr_flags.insert(ReprFlags::IS_C); } - if data.repr.is_some_and(|r| r.simd()) { + if data_repr.is_some_and(|r| r.simd()) { repr_flags.insert(ReprFlags::IS_SIMD); } - repr.flags = repr_flags; + let repr = ReprOptions { + align: data_repr.and_then(|r| r.align), + pack: data_repr.and_then(|r| r.pack), + int: data_repr.and_then(|r| r.int), + flags: repr_flags, + ..ReprOptions::default() + }; (flags, variants, repr) } AdtId::UnionId(union_id) => { - let data = db.union_signature(union_id); - let flags = AdtFlags { is_enum: false, is_union: true, @@ -513,22 +534,24 @@ impl AdtDef { let variants = vec![(VariantIdx(0), VariantDef::Union(union_id))]; - let mut repr = ReprOptions::default(); - repr.align = data.repr.and_then(|r| r.align); - repr.pack = data.repr.and_then(|r| r.pack); - repr.int = data.repr.and_then(|r| r.int); - + let data_repr = AttrFlags::repr(db, union_id.into()); let mut repr_flags = ReprFlags::empty(); if flags.is_box { repr_flags.insert(ReprFlags::IS_LINEAR); } - if data.repr.is_some_and(|r| r.c()) { + if data_repr.is_some_and(|r| r.c()) { repr_flags.insert(ReprFlags::IS_C); } - if data.repr.is_some_and(|r| r.simd()) { + if data_repr.is_some_and(|r| r.simd()) { repr_flags.insert(ReprFlags::IS_SIMD); } - repr.flags = repr_flags; + let repr = ReprOptions { + align: data_repr.and_then(|r| r.align), + pack: data_repr.and_then(|r| r.pack), + int: data_repr.and_then(|r| r.int), + flags: repr_flags, + ..ReprOptions::default() + }; (flags, variants, repr) } @@ -552,24 +575,26 @@ impl AdtDef { .map(|(idx, v)| (idx, VariantDef::Enum(v.0))) .collect(); - let data = db.enum_signature(enum_id); - - let mut repr = ReprOptions::default(); - repr.align = data.repr.and_then(|r| r.align); - repr.pack = data.repr.and_then(|r| r.pack); - repr.int = data.repr.and_then(|r| r.int); + let data_repr = AttrFlags::repr(db, enum_id.into()); let mut repr_flags = ReprFlags::empty(); if flags.is_box { repr_flags.insert(ReprFlags::IS_LINEAR); } - if data.repr.is_some_and(|r| r.c()) { + if data_repr.is_some_and(|r| r.c()) { repr_flags.insert(ReprFlags::IS_C); } - if data.repr.is_some_and(|r| r.simd()) { + if data_repr.is_some_and(|r| r.simd()) { repr_flags.insert(ReprFlags::IS_SIMD); } - repr.flags = repr_flags; + + let repr = ReprOptions { + align: data_repr.and_then(|r| r.align), + pack: data_repr.and_then(|r| r.pack), + int: data_repr.and_then(|r| r.int), + flags: repr_flags, + ..ReprOptions::default() + }; (flags, variants, repr) } @@ -849,7 +874,7 @@ interned_vec_db!(PatList, Pattern); macro_rules! as_lang_item { ( - $solver_enum:ident, $var:ident; + $solver_enum:ident, $self:ident, $def_id:expr; ignore = { $( $ignore:ident ),* $(,)? @@ -857,6 +882,7 @@ macro_rules! as_lang_item { $( $variant:ident ),* $(,)? ) => {{ + let lang_items = $self.lang_items(); // Ensure exhaustiveness. if let Some(it) = None::<$solver_enum> { match it { @@ -864,13 +890,32 @@ macro_rules! as_lang_item { $( $solver_enum::$ignore => {} )* } } - match $var { - $( LangItem::$variant => Some($solver_enum::$variant), )* + match $def_id { + $( def_id if lang_items.$variant.is_some_and(|it| it == def_id) => Some($solver_enum::$variant), )* _ => None } }}; } +macro_rules! is_lang_item { + ( + $solver_enum:ident, $self:ident, $def_id:expr, $expected_variant:ident; + + ignore = { + $( $ignore:ident ),* $(,)? + } + + $( $variant:ident ),* $(,)? + ) => {{ + let lang_items = $self.lang_items(); + let def_id = $def_id; + match $expected_variant { + $( $solver_enum::$variant => lang_items.$variant.is_some_and(|it| it == def_id), )* + $( $solver_enum::$ignore => false, )* + } + }}; +} + impl<'db> Interner for DbInterner<'db> { type DefId = SolverDefId; type LocalDefId = SolverDefId; @@ -1253,8 +1298,7 @@ impl<'db> Interner for DbInterner<'db> { } fn generics_require_sized_self(self, def_id: Self::DefId) -> bool { - let sized_trait = - LangItem::Sized.resolve_trait(self.db(), self.krate.expect("Must have self.krate")); + let sized_trait = self.lang_items().Sized; let Some(sized_id) = sized_trait else { return false; /* No Sized trait, can't require it! */ }; @@ -1428,84 +1472,69 @@ impl<'db> Interner for DbInterner<'db> { } fn require_lang_item(self, lang_item: SolverLangItem) -> Self::DefId { + let lang_items = self.lang_items(); let lang_item = match lang_item { SolverLangItem::AsyncFnKindUpvars => unimplemented!(), - SolverLangItem::AsyncFnOnceOutput => LangItem::AsyncFnOnceOutput, - SolverLangItem::CallOnceFuture => LangItem::CallOnceFuture, - SolverLangItem::CallRefFuture => LangItem::CallRefFuture, - SolverLangItem::CoroutineReturn => LangItem::CoroutineReturn, - SolverLangItem::CoroutineYield => LangItem::CoroutineYield, - SolverLangItem::DynMetadata => LangItem::DynMetadata, - SolverLangItem::FutureOutput => LangItem::FutureOutput, - SolverLangItem::Metadata => LangItem::Metadata, + SolverLangItem::AsyncFnOnceOutput => lang_items.AsyncFnOnceOutput, + SolverLangItem::CallOnceFuture => lang_items.CallOnceFuture, + SolverLangItem::CallRefFuture => lang_items.CallRefFuture, + SolverLangItem::CoroutineReturn => lang_items.CoroutineReturn, + SolverLangItem::CoroutineYield => lang_items.CoroutineYield, + SolverLangItem::FutureOutput => lang_items.FutureOutput, + SolverLangItem::Metadata => lang_items.Metadata, + SolverLangItem::DynMetadata => { + return lang_items.DynMetadata.expect("Lang item required but not found.").into(); + } }; - let target = hir_def::lang_item::lang_item( - self.db(), - self.krate.expect("Must have self.krate"), - lang_item, - ) - .unwrap_or_else(|| panic!("Lang item {lang_item:?} required but not found.")); - match target { - hir_def::lang_item::LangItemTarget::EnumId(enum_id) => enum_id.into(), - hir_def::lang_item::LangItemTarget::Function(function_id) => function_id.into(), - hir_def::lang_item::LangItemTarget::ImplDef(impl_id) => impl_id.into(), - hir_def::lang_item::LangItemTarget::Static(static_id) => static_id.into(), - hir_def::lang_item::LangItemTarget::Struct(struct_id) => struct_id.into(), - hir_def::lang_item::LangItemTarget::Union(union_id) => union_id.into(), - hir_def::lang_item::LangItemTarget::TypeAlias(type_alias_id) => type_alias_id.into(), - hir_def::lang_item::LangItemTarget::Trait(trait_id) => trait_id.into(), - hir_def::lang_item::LangItemTarget::EnumVariant(_) => unimplemented!(), - } + lang_item.expect("Lang item required but not found.").into() } fn require_trait_lang_item(self, lang_item: SolverTraitLangItem) -> TraitIdWrapper { + let lang_items = self.lang_items(); let lang_item = match lang_item { - SolverTraitLangItem::AsyncFn => LangItem::AsyncFn, + SolverTraitLangItem::AsyncFn => lang_items.AsyncFn, SolverTraitLangItem::AsyncFnKindHelper => unimplemented!(), - SolverTraitLangItem::AsyncFnMut => LangItem::AsyncFnMut, - SolverTraitLangItem::AsyncFnOnce => LangItem::AsyncFnOnce, - SolverTraitLangItem::AsyncFnOnceOutput => LangItem::AsyncFnOnceOutput, + SolverTraitLangItem::AsyncFnMut => lang_items.AsyncFnMut, + SolverTraitLangItem::AsyncFnOnce => lang_items.AsyncFnOnce, + SolverTraitLangItem::AsyncFnOnceOutput => unimplemented!( + "This is incorrectly marked as `SolverTraitLangItem`, and is not used by the solver." + ), SolverTraitLangItem::AsyncIterator => unimplemented!(), - SolverTraitLangItem::Clone => LangItem::Clone, - SolverTraitLangItem::Copy => LangItem::Copy, - SolverTraitLangItem::Coroutine => LangItem::Coroutine, - SolverTraitLangItem::Destruct => LangItem::Destruct, - SolverTraitLangItem::DiscriminantKind => LangItem::DiscriminantKind, - SolverTraitLangItem::Drop => LangItem::Drop, - SolverTraitLangItem::Fn => LangItem::Fn, - SolverTraitLangItem::FnMut => LangItem::FnMut, - SolverTraitLangItem::FnOnce => LangItem::FnOnce, - SolverTraitLangItem::FnPtrTrait => LangItem::FnPtrTrait, + SolverTraitLangItem::Clone => lang_items.Clone, + SolverTraitLangItem::Copy => lang_items.Copy, + SolverTraitLangItem::Coroutine => lang_items.Coroutine, + SolverTraitLangItem::Destruct => lang_items.Destruct, + SolverTraitLangItem::DiscriminantKind => lang_items.DiscriminantKind, + SolverTraitLangItem::Drop => lang_items.Drop, + SolverTraitLangItem::Fn => lang_items.Fn, + SolverTraitLangItem::FnMut => lang_items.FnMut, + SolverTraitLangItem::FnOnce => lang_items.FnOnce, + SolverTraitLangItem::FnPtrTrait => lang_items.FnPtrTrait, SolverTraitLangItem::FusedIterator => unimplemented!(), - SolverTraitLangItem::Future => LangItem::Future, - SolverTraitLangItem::Iterator => LangItem::Iterator, - SolverTraitLangItem::PointeeTrait => LangItem::PointeeTrait, - SolverTraitLangItem::Sized => LangItem::Sized, - SolverTraitLangItem::MetaSized => LangItem::MetaSized, - SolverTraitLangItem::PointeeSized => LangItem::PointeeSized, - SolverTraitLangItem::TransmuteTrait => LangItem::TransmuteTrait, - SolverTraitLangItem::Tuple => LangItem::Tuple, - SolverTraitLangItem::Unpin => LangItem::Unpin, - SolverTraitLangItem::Unsize => LangItem::Unsize, + SolverTraitLangItem::Future => lang_items.Future, + SolverTraitLangItem::Iterator => lang_items.Iterator, + SolverTraitLangItem::PointeeTrait => lang_items.PointeeTrait, + SolverTraitLangItem::Sized => lang_items.Sized, + SolverTraitLangItem::MetaSized => lang_items.MetaSized, + SolverTraitLangItem::PointeeSized => lang_items.PointeeSized, + SolverTraitLangItem::TransmuteTrait => lang_items.TransmuteTrait, + SolverTraitLangItem::Tuple => lang_items.Tuple, + SolverTraitLangItem::Unpin => lang_items.Unpin, + SolverTraitLangItem::Unsize => lang_items.Unsize, SolverTraitLangItem::BikeshedGuaranteedNoDrop => { unimplemented!() } }; - lang_item - .resolve_trait(self.db(), self.krate.expect("Must have self.krate")) - .unwrap_or_else(|| panic!("Lang item {lang_item:?} required but not found.")) - .into() + lang_item.expect("Lang item required but not found.").into() } fn require_adt_lang_item(self, lang_item: SolverAdtLangItem) -> AdtIdWrapper { + let lang_items = self.lang_items(); let lang_item = match lang_item { - SolverAdtLangItem::Option => LangItem::Option, - SolverAdtLangItem::Poll => LangItem::Poll, + SolverAdtLangItem::Option => lang_items.Option, + SolverAdtLangItem::Poll => lang_items.Poll, }; - lang_item - .resolve_adt(self.db(), self.krate.expect("Must have self.krate")) - .unwrap_or_else(|| panic!("Lang item {lang_item:?} required but not found.")) - .into() + AdtIdWrapper(lang_item.expect("Lang item required but not found.").into()) } fn is_lang_item(self, def_id: Self::DefId, lang_item: SolverLangItem) -> bool { @@ -1514,8 +1543,41 @@ impl<'db> Interner for DbInterner<'db> { } fn is_trait_lang_item(self, def_id: Self::TraitId, lang_item: SolverTraitLangItem) -> bool { - self.as_trait_lang_item(def_id) - .map_or(false, |l| std::mem::discriminant(&l) == std::mem::discriminant(&lang_item)) + is_lang_item!( + SolverTraitLangItem, self, def_id.0, lang_item; + + ignore = { + AsyncFnKindHelper, + AsyncIterator, + BikeshedGuaranteedNoDrop, + FusedIterator, + AsyncFnOnceOutput, // This is incorrectly marked as `SolverTraitLangItem`, and is not used by the solver. + } + + Sized, + MetaSized, + PointeeSized, + Unsize, + Copy, + Clone, + DiscriminantKind, + PointeeTrait, + FnPtrTrait, + Drop, + Destruct, + TransmuteTrait, + Fn, + FnMut, + FnOnce, + Future, + Coroutine, + Unpin, + Tuple, + Iterator, + AsyncFn, + AsyncFnMut, + AsyncFnOnce, + ) } fn is_adt_lang_item(self, def_id: Self::AdtId, lang_item: SolverAdtLangItem) -> bool { @@ -1525,42 +1587,57 @@ impl<'db> Interner for DbInterner<'db> { } fn as_lang_item(self, def_id: Self::DefId) -> Option<SolverLangItem> { - let def_id: AttrDefId = match def_id { - SolverDefId::TraitId(id) => id.into(), - SolverDefId::TypeAliasId(id) => id.into(), - SolverDefId::AdtId(id) => id.into(), - _ => panic!("Unexpected SolverDefId in as_lang_item"), - }; - let lang_item = self.db().lang_attr(def_id)?; - as_lang_item!( - SolverLangItem, lang_item; + match def_id { + SolverDefId::TypeAliasId(id) => { + as_lang_item!( + SolverLangItem, self, id; - ignore = { - AsyncFnKindUpvars, + ignore = { + AsyncFnKindUpvars, + DynMetadata, + } + + Metadata, + CoroutineReturn, + CoroutineYield, + FutureOutput, + CallRefFuture, + CallOnceFuture, + AsyncFnOnceOutput, + ) } + SolverDefId::AdtId(AdtId::StructId(id)) => { + as_lang_item!( + SolverLangItem, self, id; + + ignore = { + AsyncFnKindUpvars, + Metadata, + CoroutineReturn, + CoroutineYield, + FutureOutput, + CallRefFuture, + CallOnceFuture, + AsyncFnOnceOutput, + } - Metadata, - DynMetadata, - CoroutineReturn, - CoroutineYield, - FutureOutput, - CallRefFuture, - CallOnceFuture, - AsyncFnOnceOutput, - ) + DynMetadata, + ) + } + _ => panic!("Unexpected SolverDefId in as_lang_item"), + } } fn as_trait_lang_item(self, def_id: Self::TraitId) -> Option<SolverTraitLangItem> { - let def_id: AttrDefId = def_id.0.into(); - let lang_item = self.db().lang_attr(def_id)?; as_lang_item!( - SolverTraitLangItem, lang_item; + SolverTraitLangItem, self, def_id.0; ignore = { AsyncFnKindHelper, AsyncIterator, BikeshedGuaranteedNoDrop, FusedIterator, + AsyncFnOnceOutput, // This is incorrectly marked as `SolverTraitLangItem`, and is not used by the solver. } Sized, @@ -1586,15 +1663,15 @@ impl<'db> Interner for DbInterner<'db> { AsyncFn, AsyncFnMut, AsyncFnOnce, - AsyncFnOnceOutput, ) } fn as_adt_lang_item(self, def_id: Self::AdtId) -> Option<SolverAdtLangItem> { - let def_id: AttrDefId = def_id.0.into(); - let lang_item = self.db().lang_attr(def_id)?; + let AdtId::EnumId(def_id) = def_id.0 else { + panic!("Unexpected SolverDefId in as_adt_lang_item"); + }; as_lang_item!( - SolverAdtLangItem, lang_item; + SolverAdtLangItem, self, def_id; ignore = {} |