diff options
-rw-r--r-- | crates/ra_hir/src/db.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir/src/lang_item.rs | 154 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/autoderef.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/coerce.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 47 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir_def/src/db.rs | 16 | ||||
-rw-r--r-- | crates/ra_hir_def/src/lang_item.rs | 120 | ||||
-rw-r--r-- | crates/ra_hir_def/src/lib.rs | 1 |
10 files changed, 179 insertions, 202 deletions
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index c3f698ea0..cae305f98 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -3,27 +3,25 @@ | |||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use ra_db::salsa; | 5 | use ra_db::salsa; |
6 | use ra_syntax::SmolStr; | ||
7 | 6 | ||
8 | use crate::{ | 7 | use crate::{ |
9 | debug::HirDebugDatabase, | 8 | debug::HirDebugDatabase, |
10 | ids, | 9 | ids, |
11 | lang_item::{LangItemTarget, LangItems}, | ||
12 | ty::{ | 10 | ty::{ |
13 | method_resolution::CrateImplBlocks, | 11 | method_resolution::CrateImplBlocks, |
14 | traits::{AssocTyValue, Impl}, | 12 | traits::{AssocTyValue, Impl}, |
15 | CallableDef, FnSig, GenericPredicate, InferenceResult, Namespace, Substs, Ty, TypableDef, | 13 | CallableDef, FnSig, GenericPredicate, InferenceResult, Namespace, Substs, Ty, TypableDef, |
16 | TypeCtor, | 14 | TypeCtor, |
17 | }, | 15 | }, |
18 | Crate, DefWithBody, GenericDef, ImplBlock, Module, StructField, Trait, | 16 | Crate, DefWithBody, GenericDef, ImplBlock, StructField, Trait, |
19 | }; | 17 | }; |
20 | 18 | ||
21 | pub use hir_def::db::{ | 19 | pub use hir_def::db::{ |
22 | BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQuery, DefDatabase2, | 20 | BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQuery, CrateLangItemsQuery, |
23 | DefDatabase2Storage, EnumDataQuery, ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, | 21 | DefDatabase2, DefDatabase2Storage, EnumDataQuery, ExprScopesQuery, FunctionDataQuery, |
24 | ImplDataQuery, InternDatabase, InternDatabaseStorage, RawItemsQuery, | 22 | GenericParamsQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage, LangItemQuery, |
25 | RawItemsWithSourceMapQuery, StaticDataQuery, StructDataQuery, TraitDataQuery, | 23 | ModuleLangItemsQuery, RawItemsQuery, RawItemsWithSourceMapQuery, StaticDataQuery, |
26 | TypeAliasDataQuery, | 24 | StructDataQuery, TraitDataQuery, TypeAliasDataQuery, |
27 | }; | 25 | }; |
28 | pub use hir_expand::db::{ | 26 | pub use hir_expand::db::{ |
29 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, | 27 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, |
@@ -34,15 +32,6 @@ pub use hir_expand::db::{ | |||
34 | #[salsa::query_group(DefDatabaseStorage)] | 32 | #[salsa::query_group(DefDatabaseStorage)] |
35 | #[salsa::requires(AstDatabase)] | 33 | #[salsa::requires(AstDatabase)] |
36 | pub trait DefDatabase: HirDebugDatabase + DefDatabase2 { | 34 | pub trait DefDatabase: HirDebugDatabase + DefDatabase2 { |
37 | #[salsa::invoke(LangItems::module_lang_items_query)] | ||
38 | fn module_lang_items(&self, module: Module) -> Option<Arc<LangItems>>; | ||
39 | |||
40 | #[salsa::invoke(LangItems::crate_lang_items_query)] | ||
41 | fn crate_lang_items(&self, krate: Crate) -> Arc<LangItems>; | ||
42 | |||
43 | #[salsa::invoke(LangItems::lang_item_query)] | ||
44 | fn lang_item(&self, start_crate: Crate, item: SmolStr) -> Option<LangItemTarget>; | ||
45 | |||
46 | #[salsa::invoke(crate::code_model::docs::documentation_query)] | 35 | #[salsa::invoke(crate::code_model::docs::documentation_query)] |
47 | fn documentation(&self, def: crate::DocDef) -> Option<crate::Documentation>; | 36 | fn documentation(&self, def: crate::DocDef) -> Option<crate::Documentation>; |
48 | } | 37 | } |
diff --git a/crates/ra_hir/src/lang_item.rs b/crates/ra_hir/src/lang_item.rs deleted file mode 100644 index 55f0c3a13..000000000 --- a/crates/ra_hir/src/lang_item.rs +++ /dev/null | |||
@@ -1,154 +0,0 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | use std::sync::Arc; | ||
4 | |||
5 | use hir_def::{AdtId, AttrDefId, ModuleDefId}; | ||
6 | use ra_syntax::SmolStr; | ||
7 | use rustc_hash::FxHashMap; | ||
8 | |||
9 | use crate::{ | ||
10 | db::{AstDatabase, DefDatabase, HirDatabase}, | ||
11 | Crate, Enum, Function, ImplBlock, Module, Static, Struct, Trait, | ||
12 | }; | ||
13 | |||
14 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
15 | pub enum LangItemTarget { | ||
16 | Enum(Enum), | ||
17 | Function(Function), | ||
18 | ImplBlock(ImplBlock), | ||
19 | Static(Static), | ||
20 | Struct(Struct), | ||
21 | Trait(Trait), | ||
22 | } | ||
23 | |||
24 | impl LangItemTarget { | ||
25 | pub(crate) fn krate(&self, db: &impl HirDatabase) -> Option<Crate> { | ||
26 | Some(match self { | ||
27 | LangItemTarget::Enum(e) => e.module(db).krate(), | ||
28 | LangItemTarget::Function(f) => f.module(db).krate(), | ||
29 | LangItemTarget::ImplBlock(i) => i.krate(db), | ||
30 | LangItemTarget::Static(s) => s.module(db).krate(), | ||
31 | LangItemTarget::Struct(s) => s.module(db).krate(), | ||
32 | LangItemTarget::Trait(t) => t.module(db).krate(), | ||
33 | }) | ||
34 | } | ||
35 | } | ||
36 | |||
37 | #[derive(Default, Debug, Clone, PartialEq, Eq)] | ||
38 | pub struct LangItems { | ||
39 | items: FxHashMap<SmolStr, LangItemTarget>, | ||
40 | } | ||
41 | |||
42 | impl LangItems { | ||
43 | pub fn target<'a>(&'a self, item: &str) -> Option<&'a LangItemTarget> { | ||
44 | self.items.get(item) | ||
45 | } | ||
46 | |||
47 | /// Salsa query. This will look for lang items in a specific crate. | ||
48 | pub(crate) fn crate_lang_items_query( | ||
49 | db: &(impl DefDatabase + AstDatabase), | ||
50 | krate: Crate, | ||
51 | ) -> Arc<LangItems> { | ||
52 | let mut lang_items = LangItems::default(); | ||
53 | |||
54 | if let Some(module) = krate.root_module(db) { | ||
55 | lang_items.collect_lang_items_recursive(db, module); | ||
56 | } | ||
57 | |||
58 | Arc::new(lang_items) | ||
59 | } | ||
60 | |||
61 | pub(crate) fn module_lang_items_query( | ||
62 | db: &(impl DefDatabase + AstDatabase), | ||
63 | module: Module, | ||
64 | ) -> Option<Arc<LangItems>> { | ||
65 | let mut lang_items = LangItems::default(); | ||
66 | lang_items.collect_lang_items(db, module); | ||
67 | if lang_items.items.is_empty() { | ||
68 | None | ||
69 | } else { | ||
70 | Some(Arc::new(lang_items)) | ||
71 | } | ||
72 | } | ||
73 | |||
74 | /// Salsa query. Look for a lang item, starting from the specified crate and recursively | ||
75 | /// traversing its dependencies. | ||
76 | pub(crate) fn lang_item_query( | ||
77 | db: &impl DefDatabase, | ||
78 | start_crate: Crate, | ||
79 | item: SmolStr, | ||
80 | ) -> Option<LangItemTarget> { | ||
81 | let lang_items = db.crate_lang_items(start_crate); | ||
82 | let start_crate_target = lang_items.items.get(&item); | ||
83 | if let Some(target) = start_crate_target { | ||
84 | Some(*target) | ||
85 | } else { | ||
86 | for dep in start_crate.dependencies(db) { | ||
87 | let dep_crate = dep.krate; | ||
88 | let dep_target = db.lang_item(dep_crate, item.clone()); | ||
89 | if dep_target.is_some() { | ||
90 | return dep_target; | ||
91 | } | ||
92 | } | ||
93 | None | ||
94 | } | ||
95 | } | ||
96 | |||
97 | fn collect_lang_items(&mut self, db: &(impl DefDatabase + AstDatabase), module: Module) { | ||
98 | // Look for impl targets | ||
99 | let def_map = db.crate_def_map(module.id.krate); | ||
100 | let module_data = &def_map[module.id.module_id]; | ||
101 | for &impl_block in module_data.impls.iter() { | ||
102 | self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlock) | ||
103 | } | ||
104 | |||
105 | for def in module_data.scope.declarations() { | ||
106 | match def { | ||
107 | ModuleDefId::TraitId(trait_) => { | ||
108 | self.collect_lang_item(db, trait_, LangItemTarget::Trait) | ||
109 | } | ||
110 | ModuleDefId::AdtId(AdtId::EnumId(e)) => { | ||
111 | self.collect_lang_item(db, e, LangItemTarget::Enum) | ||
112 | } | ||
113 | ModuleDefId::AdtId(AdtId::StructId(s)) => { | ||
114 | self.collect_lang_item(db, s, LangItemTarget::Struct) | ||
115 | } | ||
116 | ModuleDefId::FunctionId(f) => { | ||
117 | self.collect_lang_item(db, f, LangItemTarget::Function) | ||
118 | } | ||
119 | ModuleDefId::StaticId(s) => self.collect_lang_item(db, s, LangItemTarget::Static), | ||
120 | _ => {} | ||
121 | } | ||
122 | } | ||
123 | } | ||
124 | |||
125 | fn collect_lang_items_recursive( | ||
126 | &mut self, | ||
127 | db: &(impl DefDatabase + AstDatabase), | ||
128 | module: Module, | ||
129 | ) { | ||
130 | if let Some(module_lang_items) = db.module_lang_items(module) { | ||
131 | self.items.extend(module_lang_items.items.iter().map(|(k, v)| (k.clone(), *v))) | ||
132 | } | ||
133 | |||
134 | // Look for lang items in the children | ||
135 | for child in module.children(db) { | ||
136 | self.collect_lang_items_recursive(db, child); | ||
137 | } | ||
138 | } | ||
139 | |||
140 | fn collect_lang_item<T, D>( | ||
141 | &mut self, | ||
142 | db: &(impl DefDatabase + AstDatabase), | ||
143 | item: T, | ||
144 | constructor: fn(D) -> LangItemTarget, | ||
145 | ) where | ||
146 | T: Into<AttrDefId> + Copy, | ||
147 | D: From<T>, | ||
148 | { | ||
149 | let attrs = db.attrs(item.into()); | ||
150 | if let Some(lang_item_name) = attrs.find_string_value("lang") { | ||
151 | self.items.entry(lang_item_name).or_insert_with(|| constructor(D::from(item))); | ||
152 | } | ||
153 | } | ||
154 | } | ||
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 152590cd1..22da05a97 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -35,7 +35,6 @@ mod ids; | |||
35 | mod ty; | 35 | mod ty; |
36 | mod impl_block; | 36 | mod impl_block; |
37 | mod expr; | 37 | mod expr; |
38 | mod lang_item; | ||
39 | pub mod diagnostics; | 38 | pub mod diagnostics; |
40 | mod util; | 39 | mod util; |
41 | 40 | ||
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs index b60e4bb31..41c99d227 100644 --- a/crates/ra_hir/src/ty/autoderef.rs +++ b/crates/ra_hir/src/ty/autoderef.rs | |||
@@ -5,12 +5,13 @@ | |||
5 | 5 | ||
6 | use std::iter::successors; | 6 | use std::iter::successors; |
7 | 7 | ||
8 | use hir_def::resolver::Resolver; | 8 | use hir_def::{lang_item::LangItemTarget, resolver::Resolver}; |
9 | use hir_expand::name; | 9 | use hir_expand::name; |
10 | use log::{info, warn}; | 10 | use log::{info, warn}; |
11 | 11 | ||
12 | use crate::{db::HirDatabase, Trait}; | ||
13 | |||
12 | use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; | 14 | use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; |
13 | use crate::db::HirDatabase; | ||
14 | 15 | ||
15 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 16 | const AUTODEREF_RECURSION_LIMIT: usize = 10; |
16 | 17 | ||
@@ -41,7 +42,7 @@ fn deref_by_trait( | |||
41 | ) -> Option<Canonical<Ty>> { | 42 | ) -> Option<Canonical<Ty>> { |
42 | let krate = resolver.krate()?; | 43 | let krate = resolver.krate()?; |
43 | let deref_trait = match db.lang_item(krate.into(), "deref".into())? { | 44 | let deref_trait = match db.lang_item(krate.into(), "deref".into())? { |
44 | crate::lang_item::LangItemTarget::Trait(t) => t, | 45 | LangItemTarget::TraitId(t) => Trait::from(t), |
45 | _ => return None, | 46 | _ => return None, |
46 | }; | 47 | }; |
47 | let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?; | 48 | let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?; |
diff --git a/crates/ra_hir/src/ty/infer/coerce.rs b/crates/ra_hir/src/ty/infer/coerce.rs index 0772b9df5..4ea038d99 100644 --- a/crates/ra_hir/src/ty/infer/coerce.rs +++ b/crates/ra_hir/src/ty/infer/coerce.rs | |||
@@ -4,13 +4,12 @@ | |||
4 | //! | 4 | //! |
5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html | 5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html |
6 | 6 | ||
7 | use hir_def::resolver::Resolver; | 7 | use hir_def::{lang_item::LangItemTarget, resolver::Resolver}; |
8 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
9 | use test_utils::tested_by; | 9 | use test_utils::tested_by; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | db::HirDatabase, | 12 | db::HirDatabase, |
13 | lang_item::LangItemTarget, | ||
14 | ty::{autoderef, Substs, Ty, TypeCtor, TypeWalk}, | 13 | ty::{autoderef, Substs, Ty, TypeCtor, TypeWalk}, |
15 | Adt, Mutability, | 14 | Adt, Mutability, |
16 | }; | 15 | }; |
@@ -50,7 +49,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
50 | ) -> FxHashMap<(TypeCtor, TypeCtor), usize> { | 49 | ) -> FxHashMap<(TypeCtor, TypeCtor), usize> { |
51 | let krate = resolver.krate().unwrap(); | 50 | let krate = resolver.krate().unwrap(); |
52 | let impls = match db.lang_item(krate.into(), "coerce_unsized".into()) { | 51 | let impls = match db.lang_item(krate.into(), "coerce_unsized".into()) { |
53 | Some(LangItemTarget::Trait(trait_)) => db.impls_for_trait(krate.into(), trait_), | 52 | Some(LangItemTarget::TraitId(trait_)) => { |
53 | db.impls_for_trait(krate.into(), trait_.into()) | ||
54 | } | ||
54 | _ => return FxHashMap::default(), | 55 | _ => return FxHashMap::default(), |
55 | }; | 56 | }; |
56 | 57 | ||
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index f61c27218..caa5f5f74 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -5,7 +5,7 @@ | |||
5 | use std::sync::Arc; | 5 | use std::sync::Arc; |
6 | 6 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use hir_def::resolver::Resolver; | 8 | use hir_def::{lang_item::LangItemTarget, resolver::Resolver, AstItemDef}; |
9 | use rustc_hash::FxHashMap; | 9 | use rustc_hash::FxHashMap; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
@@ -91,34 +91,43 @@ fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayV | |||
91 | // Types like slice can have inherent impls in several crates, (core and alloc). | 91 | // Types like slice can have inherent impls in several crates, (core and alloc). |
92 | // The corresponding impls are marked with lang items, so we can use them to find the required crates. | 92 | // The corresponding impls are marked with lang items, so we can use them to find the required crates. |
93 | macro_rules! lang_item_crate { | 93 | macro_rules! lang_item_crate { |
94 | ($db:expr, $cur_crate:expr, $($name:expr),+ $(,)?) => {{ | 94 | ($($name:expr),+ $(,)?) => {{ |
95 | let mut v = ArrayVec::<[Crate; 2]>::new(); | 95 | let mut v = ArrayVec::<[LangItemTarget; 2]>::new(); |
96 | $( | 96 | $( |
97 | v.extend($db.lang_item($cur_crate, $name.into()).and_then(|item| item.krate($db))); | 97 | v.extend(db.lang_item(cur_crate.crate_id, $name.into())); |
98 | )+ | 98 | )+ |
99 | Some(v) | 99 | v |
100 | }}; | 100 | }}; |
101 | } | 101 | } |
102 | 102 | ||
103 | match ty { | 103 | let lang_item_targets = match ty { |
104 | Ty::Apply(a_ty) => match a_ty.ctor { | 104 | Ty::Apply(a_ty) => match a_ty.ctor { |
105 | TypeCtor::Adt(def_id) => Some(std::iter::once(def_id.krate(db)?).collect()), | 105 | TypeCtor::Adt(def_id) => return Some(std::iter::once(def_id.krate(db)?).collect()), |
106 | TypeCtor::Bool => lang_item_crate!(db, cur_crate, "bool"), | 106 | TypeCtor::Bool => lang_item_crate!("bool"), |
107 | TypeCtor::Char => lang_item_crate!(db, cur_crate, "char"), | 107 | TypeCtor::Char => lang_item_crate!("char"), |
108 | TypeCtor::Float(Uncertain::Known(f)) => match f.bitness { | 108 | TypeCtor::Float(Uncertain::Known(f)) => match f.bitness { |
109 | // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) | 109 | // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) |
110 | FloatBitness::X32 => lang_item_crate!(db, cur_crate, "f32", "f32_runtime"), | 110 | FloatBitness::X32 => lang_item_crate!("f32", "f32_runtime"), |
111 | FloatBitness::X64 => lang_item_crate!(db, cur_crate, "f64", "f64_runtime"), | 111 | FloatBitness::X64 => lang_item_crate!("f64", "f64_runtime"), |
112 | }, | 112 | }, |
113 | TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(db, cur_crate, i.ty_to_string()), | 113 | TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(i.ty_to_string()), |
114 | TypeCtor::Str => lang_item_crate!(db, cur_crate, "str_alloc", "str"), | 114 | TypeCtor::Str => lang_item_crate!("str_alloc", "str"), |
115 | TypeCtor::Slice => lang_item_crate!(db, cur_crate, "slice_alloc", "slice"), | 115 | TypeCtor::Slice => lang_item_crate!("slice_alloc", "slice"), |
116 | TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!(db, cur_crate, "const_ptr"), | 116 | TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!("const_ptr"), |
117 | TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!(db, cur_crate, "mut_ptr"), | 117 | TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"), |
118 | _ => None, | 118 | _ => return None, |
119 | }, | 119 | }, |
120 | _ => None, | 120 | _ => return None, |
121 | } | 121 | }; |
122 | let res = lang_item_targets | ||
123 | .into_iter() | ||
124 | .filter_map(|it| match it { | ||
125 | LangItemTarget::ImplBlockId(it) => Some(it), | ||
126 | _ => None, | ||
127 | }) | ||
128 | .map(|it| it.module(db).krate.into()) | ||
129 | .collect(); | ||
130 | Some(res) | ||
122 | } | 131 | } |
123 | 132 | ||
124 | /// Look up the method with the given name, returning the actual autoderefed | 133 | /// Look up the method with the given name, returning the actual autoderefed |
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 88785f305..53818a5e5 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -9,6 +9,7 @@ use chalk_ir::{ | |||
9 | }; | 9 | }; |
10 | use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; | 10 | use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; |
11 | 11 | ||
12 | use hir_def::lang_item::LangItemTarget; | ||
12 | use hir_expand::name; | 13 | use hir_expand::name; |
13 | 14 | ||
14 | use ra_db::salsa::{InternId, InternKey}; | 15 | use ra_db::salsa::{InternId, InternKey}; |
@@ -832,9 +833,9 @@ fn closure_fn_trait_output_assoc_ty_value( | |||
832 | } | 833 | } |
833 | 834 | ||
834 | fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { | 835 | fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { |
835 | let target = db.lang_item(krate, fn_trait.lang_item_name().into())?; | 836 | let target = db.lang_item(krate.crate_id, fn_trait.lang_item_name().into())?; |
836 | match target { | 837 | match target { |
837 | crate::lang_item::LangItemTarget::Trait(t) => Some(t), | 838 | LangItemTarget::TraitId(t) => Some(t.into()), |
838 | _ => None, | 839 | _ => None, |
839 | } | 840 | } |
840 | } | 841 | } |
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 | ||
4 | use hir_expand::{db::AstDatabase, HirFileId}; | 4 | use hir_expand::{db::AstDatabase, HirFileId}; |
5 | use ra_db::{salsa, CrateId, SourceDatabase}; | 5 | use ra_db::{salsa, CrateId, SourceDatabase}; |
6 | use ra_syntax::ast; | 6 | use ra_syntax::{ast, SmolStr}; |
7 | 7 | ||
8 | use crate::{ | 8 | use 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. | ||
5 | use std::sync::Arc; | ||
6 | |||
7 | use ra_syntax::SmolStr; | ||
8 | use rustc_hash::FxHashMap; | ||
9 | |||
10 | use 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)] | ||
16 | pub 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)] | ||
26 | pub struct LangItems { | ||
27 | items: FxHashMap<SmolStr, LangItemTarget>, | ||
28 | } | ||
29 | |||
30 | impl 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; | |||
19 | pub mod generics; | 19 | pub mod generics; |
20 | pub mod resolver; | 20 | pub mod resolver; |
21 | pub mod data; | 21 | pub mod data; |
22 | pub mod lang_item; | ||
22 | 23 | ||
23 | mod trace; | 24 | mod trace; |
24 | 25 | ||