Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/lang_item.rs')
| -rw-r--r-- | crates/hir-def/src/lang_item.rs | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs index fd693477a4..eba4d87ec9 100644 --- a/crates/hir-def/src/lang_item.rs +++ b/crates/hir-def/src/lang_item.rs @@ -2,6 +2,7 @@ //! //! This attribute to tell the compiler about semi built-in std library //! features, such as Fn family of traits. +use hir_expand::name::Name; use intern::{Symbol, sym}; use stdx::impl_from; @@ -10,7 +11,7 @@ use crate::{ StaticId, StructId, TraitId, TypeAliasId, UnionId, attrs::AttrFlags, db::DefDatabase, - nameres::{assoc::TraitItems, crate_def_map, crate_local_def_map}, + nameres::{DefMap, assoc::TraitItems, crate_def_map, crate_local_def_map}, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -39,8 +40,12 @@ pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangIt let crate_def_map = crate_def_map(db, krate); + if !crate_def_map.is_unstable_feature_enabled(&sym::lang_items) { + return None; + } + for (_, module_data) in crate_def_map.modules() { - for impl_def in module_data.scope.impls() { + for impl_def in module_data.scope.inherent_impls() { lang_items.collect_lang_item(db, impl_def); for &(_, assoc) in impl_def.impl_items(db).items.iter() { match assoc { @@ -93,6 +98,10 @@ pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangIt } } + if matches!(krate.data(db).origin, base_db::CrateOrigin::Lang(base_db::LangCrateOrigin::Core)) { + lang_items.fill_non_lang_core_traits(db, crate_def_map); + } + if lang_items.is_empty() { None } else { Some(Box::new(lang_items)) } } @@ -135,6 +144,31 @@ impl LangItems { } } +fn resolve_core_trait( + db: &dyn DefDatabase, + core_def_map: &DefMap, + modules: &[Symbol], + name: Symbol, +) -> Option<TraitId> { + let mut current = &core_def_map[core_def_map.root]; + for module in modules { + let Some((ModuleDefId::ModuleId(cur), _)) = + current.scope.type_(&Name::new_symbol_root(module.clone())) + else { + return None; + }; + if cur.krate(db) != core_def_map.krate() || cur.block(db) != core_def_map.block_id() { + return None; + } + current = &core_def_map[cur]; + } + let Some((ModuleDefId::TraitId(trait_), _)) = current.scope.type_(&Name::new_symbol_root(name)) + else { + return None; + }; + Some(trait_) +} + #[salsa::tracked(returns(as_deref))] pub(crate) fn crate_notable_traits(db: &dyn DefDatabase, krate: Crate) -> Option<Box<[TraitId]>> { let mut traits = Vec::new(); @@ -158,6 +192,10 @@ macro_rules! language_item_table { ( $LangItems:ident => $( $(#[$attr:meta])* $lang_item:ident, $module:ident :: $name:ident, $target:ident; )* + + @non_lang_core_traits: + + $( core::$($non_lang_module:ident)::*, $non_lang_trait:ident; )* ) => { #[allow(non_snake_case)] // FIXME: Should we remove this? #[derive(Debug, Default, Clone, PartialEq, Eq, Hash)] @@ -166,6 +204,9 @@ macro_rules! language_item_table { $(#[$attr])* pub $lang_item: Option<$target>, )* + $( + pub $non_lang_trait: Option<TraitId>, + )* } impl LangItems { @@ -176,6 +217,7 @@ macro_rules! language_item_table { /// Merges `self` with `other`, with preference to `self` items. fn merge_prefer_self(&mut self, other: &Self) { $( self.$lang_item = self.$lang_item.or(other.$lang_item); )* + $( self.$non_lang_trait = self.$non_lang_trait.or(other.$non_lang_trait); )* } fn assign_lang_item(&mut self, name: Symbol, target: LangItemTarget) { @@ -190,6 +232,10 @@ macro_rules! language_item_table { _ => {} } } + + fn fill_non_lang_core_traits(&mut self, db: &dyn DefDatabase, core_def_map: &DefMap) { + $( self.$non_lang_trait = resolve_core_trait(db, core_def_map, &[ $(sym::$non_lang_module),* ], sym::$non_lang_trait); )* + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -426,4 +472,11 @@ language_item_table! { LangItems => String, sym::String, StructId; CStr, sym::CStr, StructId; Ordering, sym::Ordering, EnumId; + + @non_lang_core_traits: + core::default, Default; + core::fmt, Debug; + core::hash, Hash; + core::cmp, Ord; + core::cmp, Eq; } |