aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r--crates/ra_hir_def/src/db.rs16
-rw-r--r--crates/ra_hir_def/src/lang_item.rs120
-rw-r--r--crates/ra_hir_def/src/lib.rs1
3 files changed, 134 insertions, 3 deletions
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index e91e741bb..e87bd525a 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -3,7 +3,7 @@ use std::sync::Arc;
3 3
4use hir_expand::{db::AstDatabase, HirFileId}; 4use hir_expand::{db::AstDatabase, HirFileId};
5use ra_db::{salsa, CrateId, SourceDatabase}; 5use ra_db::{salsa, CrateId, SourceDatabase};
6use ra_syntax::ast; 6use ra_syntax::{ast, SmolStr};
7 7
8use crate::{ 8use crate::{
9 adt::{EnumData, StructData}, 9 adt::{EnumData, StructData},
@@ -11,12 +11,13 @@ use crate::{
11 body::{scope::ExprScopes, Body, BodySourceMap}, 11 body::{scope::ExprScopes, Body, BodySourceMap},
12 data::{ConstData, FunctionData, ImplData, TraitData, TypeAliasData}, 12 data::{ConstData, FunctionData, ImplData, TraitData, TypeAliasData},
13 generics::GenericParams, 13 generics::GenericParams,
14 lang_item::{LangItemTarget, LangItems},
14 nameres::{ 15 nameres::{
15 raw::{ImportSourceMap, RawItems}, 16 raw::{ImportSourceMap, RawItems},
16 CrateDefMap, 17 CrateDefMap,
17 }, 18 },
18 AttrDefId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, ImplId, ItemLoc, StaticId, 19 AttrDefId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, ImplId, ItemLoc, ModuleId,
19 StructOrUnionId, TraitId, TypeAliasId, 20 StaticId, StructOrUnionId, TraitId, TypeAliasId,
20}; 21};
21 22
22#[salsa::query_group(InternDatabaseStorage)] 23#[salsa::query_group(InternDatabaseStorage)]
@@ -91,4 +92,13 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
91 92
92 #[salsa::invoke(Attrs::attrs_query)] 93 #[salsa::invoke(Attrs::attrs_query)]
93 fn attrs(&self, def: AttrDefId) -> Attrs; 94 fn attrs(&self, def: AttrDefId) -> Attrs;
95
96 #[salsa::invoke(LangItems::module_lang_items_query)]
97 fn module_lang_items(&self, module: ModuleId) -> Option<Arc<LangItems>>;
98
99 #[salsa::invoke(LangItems::crate_lang_items_query)]
100 fn crate_lang_items(&self, krate: CrateId) -> Arc<LangItems>;
101
102 #[salsa::invoke(LangItems::lang_item_query)]
103 fn lang_item(&self, start_crate: CrateId, item: SmolStr) -> Option<LangItemTarget>;
94} 104}
diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs
new file mode 100644
index 000000000..4c1a764ea
--- /dev/null
+++ b/crates/ra_hir_def/src/lang_item.rs
@@ -0,0 +1,120 @@
1//! Collects lang items: items marked with `#[lang = "..."]` attribute.
2//!
3//! This attribute to tell the compiler about semi built-in std library
4//! features, such as Fn family of traits.
5use std::sync::Arc;
6
7use ra_syntax::SmolStr;
8use rustc_hash::FxHashMap;
9
10use crate::{
11 db::DefDatabase2, AdtId, AttrDefId, CrateId, EnumId, FunctionId, ImplId, ModuleDefId, ModuleId,
12 StaticId, StructId, TraitId,
13};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16pub enum LangItemTarget {
17 EnumId(EnumId),
18 FunctionId(FunctionId),
19 ImplBlockId(ImplId),
20 StaticId(StaticId),
21 StructId(StructId),
22 TraitId(TraitId),
23}
24
25#[derive(Default, Debug, Clone, PartialEq, Eq)]
26pub struct LangItems {
27 items: FxHashMap<SmolStr, LangItemTarget>,
28}
29
30impl LangItems {
31 pub fn target<'a>(&'a self, item: &str) -> Option<&'a LangItemTarget> {
32 self.items.get(item)
33 }
34
35 /// Salsa query. This will look for lang items in a specific crate.
36 pub(crate) fn crate_lang_items_query(db: &impl DefDatabase2, krate: CrateId) -> Arc<LangItems> {
37 let mut lang_items = LangItems::default();
38
39 let crate_def_map = db.crate_def_map(krate);
40
41 crate_def_map
42 .modules()
43 .filter_map(|module_id| db.module_lang_items(ModuleId { krate, module_id }))
44 .for_each(|it| lang_items.items.extend(it.items.iter().map(|(k, v)| (k.clone(), *v))));
45
46 Arc::new(lang_items)
47 }
48
49 pub(crate) fn module_lang_items_query(
50 db: &impl DefDatabase2,
51 module: ModuleId,
52 ) -> Option<Arc<LangItems>> {
53 let mut lang_items = LangItems::default();
54 lang_items.collect_lang_items(db, module);
55 if lang_items.items.is_empty() {
56 None
57 } else {
58 Some(Arc::new(lang_items))
59 }
60 }
61
62 /// Salsa query. Look for a lang item, starting from the specified crate and recursively
63 /// traversing its dependencies.
64 pub(crate) fn lang_item_query(
65 db: &impl DefDatabase2,
66 start_crate: CrateId,
67 item: SmolStr,
68 ) -> Option<LangItemTarget> {
69 let lang_items = db.crate_lang_items(start_crate);
70 let start_crate_target = lang_items.items.get(&item);
71 if let Some(target) = start_crate_target {
72 return Some(*target);
73 }
74 db.crate_graph()
75 .dependencies(start_crate)
76 .find_map(|dep| db.lang_item(dep.crate_id, item.clone()))
77 }
78
79 fn collect_lang_items(&mut self, db: &impl DefDatabase2, module: ModuleId) {
80 // Look for impl targets
81 let def_map = db.crate_def_map(module.krate);
82 let module_data = &def_map[module.module_id];
83 for &impl_block in module_data.impls.iter() {
84 self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlockId)
85 }
86
87 for def in module_data.scope.declarations() {
88 match def {
89 ModuleDefId::TraitId(trait_) => {
90 self.collect_lang_item(db, trait_, LangItemTarget::TraitId)
91 }
92 ModuleDefId::AdtId(AdtId::EnumId(e)) => {
93 self.collect_lang_item(db, e, LangItemTarget::EnumId)
94 }
95 ModuleDefId::AdtId(AdtId::StructId(s)) => {
96 self.collect_lang_item(db, s, LangItemTarget::StructId)
97 }
98 ModuleDefId::FunctionId(f) => {
99 self.collect_lang_item(db, f, LangItemTarget::FunctionId)
100 }
101 ModuleDefId::StaticId(s) => self.collect_lang_item(db, s, LangItemTarget::StaticId),
102 _ => {}
103 }
104 }
105 }
106
107 fn collect_lang_item<T>(
108 &mut self,
109 db: &impl DefDatabase2,
110 item: T,
111 constructor: fn(T) -> LangItemTarget,
112 ) where
113 T: Into<AttrDefId> + Copy,
114 {
115 let attrs = db.attrs(item.into());
116 if let Some(lang_item_name) = attrs.find_string_value("lang") {
117 self.items.entry(lang_item_name).or_insert_with(|| constructor(item));
118 }
119 }
120}
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 20d4deadb..899510be4 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -19,6 +19,7 @@ pub mod body;
19pub mod generics; 19pub mod generics;
20pub mod resolver; 20pub mod resolver;
21pub mod data; 21pub mod data;
22pub mod lang_item;
22 23
23mod trace; 24mod trace;
24 25