From e85ee60c42db57368e24ad9ac24840c2494d383c Mon Sep 17 00:00:00 2001 From: Marco Groppo Date: Mon, 15 Apr 2019 00:03:54 +0200 Subject: Initial support for lang items. --- crates/ra_hir/src/db.rs | 4 + crates/ra_hir/src/lang_item.rs | 102 ++++++++++++++++++++++ crates/ra_hir/src/lib.rs | 1 + crates/ra_hir/src/nameres.rs | 4 + crates/ra_hir/src/resolve.rs | 2 +- crates/ra_hir/src/ty/infer.rs | 54 ++++++------ crates/ra_hir/src/ty/method_resolution.rs | 38 +++++++- crates/ra_ide_api/src/completion/complete_path.rs | 23 ++--- crates/ra_syntax/src/ast/extensions.rs | 14 +++ crates/ra_syntax/src/ast/generated.rs | 1 + crates/ra_syntax/src/grammar.ron | 2 +- 11 files changed, 204 insertions(+), 41 deletions(-) create mode 100644 crates/ra_hir/src/lang_item.rs (limited to 'crates') diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 18627bbc2..b27efcbe3 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -16,6 +16,7 @@ use crate::{ generics::{GenericParams, GenericDef}, type_ref::TypeRef, traits::TraitData, Trait, ty::TraitRef, + lang_item::LangItems, ids }; @@ -100,6 +101,9 @@ pub trait DefDatabase: SourceDatabase { #[salsa::invoke(crate::ConstSignature::static_signature_query)] fn static_signature(&self, konst: Static) -> Arc; + + #[salsa::invoke(crate::lang_item::LangItems::lang_items_query)] + fn lang_items(&self, krate: Crate) -> Arc; } #[salsa::query_group(HirDatabaseStorage)] diff --git a/crates/ra_hir/src/lang_item.rs b/crates/ra_hir/src/lang_item.rs new file mode 100644 index 000000000..adcc682a2 --- /dev/null +++ b/crates/ra_hir/src/lang_item.rs @@ -0,0 +1,102 @@ +use std::sync::Arc; +use rustc_hash::FxHashMap; + +use ra_syntax::{SmolStr, ast::AttrsOwner}; + +use crate::{ + Crate, DefDatabase, Enum, Function, HirDatabase, ImplBlock, Module, Static, Struct, Trait +}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum LangItemTarget { + Enum(Enum), + Function(Function), + Impl(ImplBlock), + Static(Static), + Struct(Struct), + Trait(Trait), +} + +impl LangItemTarget { + pub(crate) fn krate(&self, db: &impl HirDatabase) -> Option { + match self { + LangItemTarget::Enum(e) => e.module(db).krate(db), + LangItemTarget::Function(f) => f.module(db).krate(db), + LangItemTarget::Impl(i) => i.module().krate(db), + LangItemTarget::Static(s) => s.module(db).krate(db), + LangItemTarget::Struct(s) => s.module(db).krate(db), + LangItemTarget::Trait(t) => t.module(db).krate(db), + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct LangItems { + items: FxHashMap, +} + +impl LangItems { + pub fn target<'a>(&'a self, item: &str) -> Option<&'a LangItemTarget> { + self.items.get(item) + } + + /// Salsa query. This will query a specific crate for lang items. + pub(crate) fn lang_items_query(db: &impl DefDatabase, krate: Crate) -> Arc { + let mut lang_items = LangItems { items: FxHashMap::default() }; + + if let Some(module) = krate.root_module(db) { + lang_items.collect_lang_items_recursive(db, &module); + } + + Arc::new(lang_items) + } + + fn collect_lang_items_recursive(&mut self, db: &impl DefDatabase, module: &Module) { + // Look for impl targets + let (impl_blocks, source_map) = db.impls_in_module_with_source_map(module.clone()); + let source = module.definition_source(db).1; + for (impl_id, _) in impl_blocks.impls.iter() { + let impl_block = source_map.get(&source, impl_id); + let lang_item_name = impl_block + .attrs() + .filter_map(|a| a.as_key_value()) + .filter(|(key, _)| key == "lang") + .map(|(_, val)| val) + .nth(0); + if let Some(lang_item_name) = lang_item_name { + let imp = ImplBlock::from_id(*module, impl_id); + self.items.entry(lang_item_name).or_insert(LangItemTarget::Impl(imp)); + } + } + + // FIXME we should look for the other lang item targets (traits, structs, ...) + + // Look for lang items in the children + for child in module.children(db) { + self.collect_lang_items_recursive(db, &child); + } + } +} + +/// Look for a lang item, starting from the specified crate and recursively traversing its +/// dependencies. +pub(crate) fn lang_item_lookup( + db: &impl DefDatabase, + start_krate: Crate, + item: &str, +) -> Option { + let lang_items = db.lang_items(start_krate); + let start_krate_target = lang_items.items.get(item); + if start_krate_target.is_some() { + start_krate_target.map(|t| *t) + } else { + for dep in start_krate.dependencies(db) { + let dep_krate = dep.krate; + let dep_target = lang_item_lookup(db, dep_krate, item); + if dep_target.is_some() { + return dep_target; + } + } + None + } +} diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 9292de1b5..4411715de 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -36,6 +36,7 @@ mod type_ref; mod ty; mod impl_block; mod expr; +mod lang_item; mod generics; mod docs; mod resolve; diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 0eddfab12..39152360c 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs @@ -202,6 +202,10 @@ impl CrateDefMap { Arc::new(def_map) } + pub(crate) fn krate(&self) -> Crate { + self.krate + } + pub(crate) fn root(&self) -> CrateModuleId { self.root } diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 685f4b8b1..61925e832 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs @@ -190,7 +190,7 @@ impl Resolver { .flatten() } - fn module(&self) -> Option<(&CrateDefMap, CrateModuleId)> { + pub(crate) fn module(&self) -> Option<(&CrateDefMap, CrateModuleId)> { self.scopes.iter().rev().find_map(|scope| match scope { Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)), diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 7ca1ff595..2275ac151 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -462,6 +462,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let remaining_index = remaining_index.unwrap_or(path.segments.len()); let mut actual_def_ty: Option = None; + let krate = resolver.module().map(|t| t.0.krate()); // resolve intermediate segments for (i, segment) in path.segments[remaining_index..].iter().enumerate() { let ty = match resolved { @@ -500,38 +501,41 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { // Attempt to find an impl_item for the type which has a name matching // the current segment log::debug!("looking for path segment: {:?}", segment); + actual_def_ty = Some(ty.clone()); - let item: crate::ModuleDef = ty.iterate_impl_items(self.db, |item| { - let matching_def: Option = match item { - crate::ImplItem::Method(func) => { - let sig = func.signature(self.db); - if segment.name == *sig.name() { - Some(func.into()) - } else { - None + let item: crate::ModuleDef = krate.and_then(|k| { + ty.iterate_impl_items(self.db, k, |item| { + let matching_def: Option = match item { + crate::ImplItem::Method(func) => { + let sig = func.signature(self.db); + if segment.name == *sig.name() { + Some(func.into()) + } else { + None + } } - } - crate::ImplItem::Const(konst) => { - let sig = konst.signature(self.db); - if segment.name == *sig.name() { - Some(konst.into()) - } else { - None + crate::ImplItem::Const(konst) => { + let sig = konst.signature(self.db); + if segment.name == *sig.name() { + Some(konst.into()) + } else { + None + } } - } - // FIXME: Resolve associated types - crate::ImplItem::TypeAlias(_) => None, - }; - match matching_def { - Some(_) => { - self.write_assoc_resolution(id, item); - return matching_def; + // FIXME: Resolve associated types + crate::ImplItem::TypeAlias(_) => None, + }; + match matching_def { + Some(_) => { + self.write_assoc_resolution(id, item); + return matching_def; + } + None => None, } - None => None, - } + }) })?; resolved = Resolution::Def(item.into()); diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 667b66095..ba516313c 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -14,6 +14,8 @@ use crate::{ resolve::Resolver, traits::TraitItem, generics::HasGenericParams, + lang_item::lang_item_lookup, + ty::primitive::{UncertainIntTy, UncertainFloatTy} }; use super::{TraitRef, Substs}; @@ -110,10 +112,33 @@ impl CrateImplBlocks { } } -fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option { +/// Rudimentary check whether an impl exists for a given type and trait; this +/// will actually be done by chalk. +pub(crate) fn implements(db: &impl HirDatabase, trait_ref: TraitRef) -> bool { + // FIXME use all trait impls in the whole crate graph + let krate = trait_ref.trait_.module(db).krate(db); + let krate = match krate { + Some(krate) => krate, + None => return false, + }; + let crate_impl_blocks = db.impls_in_crate(krate); + let mut impl_blocks = crate_impl_blocks.lookup_impl_blocks_for_trait(&trait_ref.trait_); + impl_blocks.any(|impl_block| &impl_block.target_ty(db) == trait_ref.self_ty()) +} + +fn def_crate(db: &impl HirDatabase, cur_krate: Crate, ty: &Ty) -> Option { match ty { Ty::Apply(a_ty) => match a_ty.ctor { TypeCtor::Adt(def_id) => def_id.krate(db), + TypeCtor::Bool => lang_item_lookup(db, cur_krate, "bool")?.krate(db), + TypeCtor::Char => lang_item_lookup(db, cur_krate, "char")?.krate(db), + TypeCtor::Float(UncertainFloatTy::Known(f)) => { + lang_item_lookup(db, cur_krate, f.ty_to_string())?.krate(db) + } + TypeCtor::Int(UncertainIntTy::Known(i)) => { + lang_item_lookup(db, cur_krate, i.ty_to_string())?.krate(db) + } + TypeCtor::Str => lang_item_lookup(db, cur_krate, "str")?.krate(db), _ => None, }, _ => None, @@ -150,8 +175,11 @@ impl Ty { // find in the end takes &self, we still do the autoderef step (just as // rustc does an autoderef and then autoref again). + let krate = resolver.module().map(|t| t.0.krate())?; for derefed_ty in self.autoderef(db) { - if let Some(result) = derefed_ty.iterate_inherent_methods(db, name, &mut callback) { + if let Some(result) = + derefed_ty.iterate_inherent_methods(db, name, krate, &mut callback) + { return Some(result); } if let Some(result) = @@ -208,9 +236,10 @@ impl Ty { &self, db: &impl HirDatabase, name: Option<&Name>, + krate: Crate, mut callback: impl FnMut(&Ty, Function) -> Option, ) -> Option { - let krate = match def_crate(db, self) { + let krate = match def_crate(db, krate, self) { Some(krate) => krate, None => return None, }; @@ -239,9 +268,10 @@ impl Ty { pub fn iterate_impl_items( self, db: &impl HirDatabase, + krate: Crate, mut callback: impl FnMut(ImplItem) -> Option, ) -> Option { - let krate = def_crate(db, &self)?; + let krate = def_crate(db, krate, &self)?; let impls = db.impls_in_crate(krate); for impl_block in impls.lookup_impl_blocks(&self) { diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index bc03a7095..c49147b9e 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -38,18 +38,21 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { } hir::ModuleDef::Struct(s) => { let ty = s.ty(ctx.db); - ty.iterate_impl_items(ctx.db, |item| { - match item { - hir::ImplItem::Method(func) => { - let sig = func.signature(ctx.db); - if !sig.has_self_param() { - acc.add_function(ctx, func); + let krate = ctx.module.and_then(|m| m.krate(ctx.db)); + krate.map_or((), |krate| { + ty.iterate_impl_items(ctx.db, krate, |item| { + match item { + hir::ImplItem::Method(func) => { + let sig = func.signature(ctx.db); + if !sig.has_self_param() { + acc.add_function(ctx, func); + } } + hir::ImplItem::Const(ct) => acc.add_const(ctx, ct), + hir::ImplItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), } - hir::ImplItem::Const(ct) => acc.add_const(ctx, ct), - hir::ImplItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), - } - None::<()> + None::<()> + }); }); } _ => return, diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs index ca33b43e7..5c4c0ffc1 100644 --- a/crates/ra_syntax/src/ast/extensions.rs +++ b/crates/ra_syntax/src/ast/extensions.rs @@ -65,6 +65,20 @@ impl ast::Attr { None } } + + pub fn as_key_value(&self) -> Option<(SmolStr, SmolStr)> { + let tt = self.value()?; + let tt_node = tt.syntax(); + let attr = tt_node.children_with_tokens().nth(1)?; + if attr.kind() == IDENT { + let key = attr.as_token()?.text().clone(); + let val_node = tt_node.children_with_tokens().find(|t| t.kind() == STRING)?; + let val = val_node.as_token()?.text().trim_start_matches("\"").trim_end_matches("\""); + Some((key, SmolStr::new(val))) + } else { + None + } + } } #[derive(Debug, Clone, Copy, PartialEq, Eq)] diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 774d9bcc8..29a7ce166 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -1325,6 +1325,7 @@ impl ToOwned for ImplBlock { impl ast::TypeParamsOwner for ImplBlock {} +impl ast::AttrsOwner for ImplBlock {} impl ImplBlock { pub fn item_list(&self) -> Option<&ItemList> { super::child_opt(self) diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index b41241287..41fe35f08 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -341,7 +341,7 @@ Grammar( ], options: ["TypeRef"] ), - "ImplBlock": (options: ["ItemList"], traits: ["TypeParamsOwner"]), + "ImplBlock": (options: ["ItemList"], traits: ["TypeParamsOwner", "AttrsOwner"]), "ParenType": (options: ["TypeRef"]), "TupleType": ( collections: [["fields", "TypeRef"]] ), -- cgit v1.2.3 From 8ebb20edce85b74eab0ed78ba5c4969ec733ad12 Mon Sep 17 00:00:00 2001 From: Marco Groppo Date: Wed, 17 Apr 2019 23:40:00 +0200 Subject: New krate() method in Resolver. Renamed Impl to ImplBlock. --- crates/ra_hir/src/lang_item.rs | 6 +-- crates/ra_hir/src/resolve.rs | 10 ++++- crates/ra_hir/src/ty/infer.rs | 54 +++++++++++------------ crates/ra_hir/src/ty/method_resolution.rs | 28 +++--------- crates/ra_ide_api/src/completion/complete_path.rs | 4 +- 5 files changed, 46 insertions(+), 56 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir/src/lang_item.rs b/crates/ra_hir/src/lang_item.rs index adcc682a2..a25d419e7 100644 --- a/crates/ra_hir/src/lang_item.rs +++ b/crates/ra_hir/src/lang_item.rs @@ -11,7 +11,7 @@ use crate::{ pub enum LangItemTarget { Enum(Enum), Function(Function), - Impl(ImplBlock), + ImplBlock(ImplBlock), Static(Static), Struct(Struct), Trait(Trait), @@ -22,7 +22,7 @@ impl LangItemTarget { match self { LangItemTarget::Enum(e) => e.module(db).krate(db), LangItemTarget::Function(f) => f.module(db).krate(db), - LangItemTarget::Impl(i) => i.module().krate(db), + LangItemTarget::ImplBlock(i) => i.module().krate(db), LangItemTarget::Static(s) => s.module(db).krate(db), LangItemTarget::Struct(s) => s.module(db).krate(db), LangItemTarget::Trait(t) => t.module(db).krate(db), @@ -65,7 +65,7 @@ impl LangItems { .nth(0); if let Some(lang_item_name) = lang_item_name { let imp = ImplBlock::from_id(*module, impl_id); - self.items.entry(lang_item_name).or_insert(LangItemTarget::Impl(imp)); + self.items.entry(lang_item_name).or_insert(LangItemTarget::ImplBlock(imp)); } } diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 61925e832..f2c85eb66 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs @@ -5,13 +5,15 @@ use rustc_hash::FxHashMap; use crate::{ ModuleDef, + code_model_api::Crate, db::HirDatabase, name::{Name, KnownName}, nameres::{PerNs, CrateDefMap, CrateModuleId}, generics::GenericParams, expr::{scope::{ExprScopes, ScopeId}, PatId}, impl_block::ImplBlock, - path::Path, Trait + path::Path, + Trait }; #[derive(Debug, Clone, Default)] @@ -190,13 +192,17 @@ impl Resolver { .flatten() } - pub(crate) fn module(&self) -> Option<(&CrateDefMap, CrateModuleId)> { + fn module(&self) -> Option<(&CrateDefMap, CrateModuleId)> { self.scopes.iter().rev().find_map(|scope| match scope { Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)), _ => None, }) } + + pub(crate) fn krate(&self) -> Option { + self.module().map(|t| t.0.krate()) + } } impl Resolver { diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 2275ac151..c7772a7f6 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -462,7 +462,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let remaining_index = remaining_index.unwrap_or(path.segments.len()); let mut actual_def_ty: Option = None; - let krate = resolver.module().map(|t| t.0.krate()); + let krate = resolver.krate()?; // resolve intermediate segments for (i, segment) in path.segments[remaining_index..].iter().enumerate() { let ty = match resolved { @@ -504,38 +504,36 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { actual_def_ty = Some(ty.clone()); - let item: crate::ModuleDef = krate.and_then(|k| { - ty.iterate_impl_items(self.db, k, |item| { - let matching_def: Option = match item { - crate::ImplItem::Method(func) => { - let sig = func.signature(self.db); - if segment.name == *sig.name() { - Some(func.into()) - } else { - None - } + let item: crate::ModuleDef = ty.iterate_impl_items(self.db, krate, |item| { + let matching_def: Option = match item { + crate::ImplItem::Method(func) => { + let sig = func.signature(self.db); + if segment.name == *sig.name() { + Some(func.into()) + } else { + None } + } - crate::ImplItem::Const(konst) => { - let sig = konst.signature(self.db); - if segment.name == *sig.name() { - Some(konst.into()) - } else { - None - } + crate::ImplItem::Const(konst) => { + let sig = konst.signature(self.db); + if segment.name == *sig.name() { + Some(konst.into()) + } else { + None } + } - // FIXME: Resolve associated types - crate::ImplItem::TypeAlias(_) => None, - }; - match matching_def { - Some(_) => { - self.write_assoc_resolution(id, item); - return matching_def; - } - None => None, + // FIXME: Resolve associated types + crate::ImplItem::TypeAlias(_) => None, + }; + match matching_def { + Some(_) => { + self.write_assoc_resolution(id, item); + return matching_def; } - }) + None => None, + } })?; resolved = Resolution::Def(item.into()); diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index ba516313c..dca56a434 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -112,33 +112,19 @@ impl CrateImplBlocks { } } -/// Rudimentary check whether an impl exists for a given type and trait; this -/// will actually be done by chalk. -pub(crate) fn implements(db: &impl HirDatabase, trait_ref: TraitRef) -> bool { - // FIXME use all trait impls in the whole crate graph - let krate = trait_ref.trait_.module(db).krate(db); - let krate = match krate { - Some(krate) => krate, - None => return false, - }; - let crate_impl_blocks = db.impls_in_crate(krate); - let mut impl_blocks = crate_impl_blocks.lookup_impl_blocks_for_trait(&trait_ref.trait_); - impl_blocks.any(|impl_block| &impl_block.target_ty(db) == trait_ref.self_ty()) -} - -fn def_crate(db: &impl HirDatabase, cur_krate: Crate, ty: &Ty) -> Option { +fn def_crate(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option { match ty { Ty::Apply(a_ty) => match a_ty.ctor { TypeCtor::Adt(def_id) => def_id.krate(db), - TypeCtor::Bool => lang_item_lookup(db, cur_krate, "bool")?.krate(db), - TypeCtor::Char => lang_item_lookup(db, cur_krate, "char")?.krate(db), + TypeCtor::Bool => lang_item_lookup(db, cur_crate, "bool")?.krate(db), + TypeCtor::Char => lang_item_lookup(db, cur_crate, "char")?.krate(db), TypeCtor::Float(UncertainFloatTy::Known(f)) => { - lang_item_lookup(db, cur_krate, f.ty_to_string())?.krate(db) + lang_item_lookup(db, cur_crate, f.ty_to_string())?.krate(db) } TypeCtor::Int(UncertainIntTy::Known(i)) => { - lang_item_lookup(db, cur_krate, i.ty_to_string())?.krate(db) + lang_item_lookup(db, cur_crate, i.ty_to_string())?.krate(db) } - TypeCtor::Str => lang_item_lookup(db, cur_krate, "str")?.krate(db), + TypeCtor::Str => lang_item_lookup(db, cur_crate, "str")?.krate(db), _ => None, }, _ => None, @@ -175,7 +161,7 @@ impl Ty { // find in the end takes &self, we still do the autoderef step (just as // rustc does an autoderef and then autoref again). - let krate = resolver.module().map(|t| t.0.krate())?; + let krate = resolver.krate()?; for derefed_ty in self.autoderef(db) { if let Some(result) = derefed_ty.iterate_inherent_methods(db, name, krate, &mut callback) diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index c49147b9e..c41752ae7 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -39,7 +39,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { hir::ModuleDef::Struct(s) => { let ty = s.ty(ctx.db); let krate = ctx.module.and_then(|m| m.krate(ctx.db)); - krate.map_or((), |krate| { + if let Some(krate) = krate { ty.iterate_impl_items(ctx.db, krate, |item| { match item { hir::ImplItem::Method(func) => { @@ -53,7 +53,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { } None::<()> }); - }); + } } _ => return, }; -- cgit v1.2.3 From 8ac3d1f9aa892fc891b69c7d8d00d39b9371d246 Mon Sep 17 00:00:00 2001 From: Marco Groppo Date: Thu, 18 Apr 2019 20:34:10 +0200 Subject: lang_item_lookup is now a salsa query. --- crates/ra_hir/src/db.rs | 7 +++-- crates/ra_hir/src/lang_item.rs | 48 +++++++++++++++---------------- crates/ra_hir/src/ty/method_resolution.rs | 11 ++++--- 3 files changed, 34 insertions(+), 32 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index b27efcbe3..8af0a3176 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use ra_syntax::{SyntaxNode, TreeArc, SourceFile, ast}; +use ra_syntax::{SyntaxNode, TreeArc, SourceFile, SmolStr, ast}; use ra_db::{SourceDatabase, salsa}; use crate::{ @@ -16,7 +16,7 @@ use crate::{ generics::{GenericParams, GenericDef}, type_ref::TypeRef, traits::TraitData, Trait, ty::TraitRef, - lang_item::LangItems, + lang_item::{LangItems, LangItemTarget}, ids }; @@ -104,6 +104,9 @@ pub trait DefDatabase: SourceDatabase { #[salsa::invoke(crate::lang_item::LangItems::lang_items_query)] fn lang_items(&self, krate: Crate) -> Arc; + + #[salsa::invoke(crate::lang_item::LangItems::lang_item_query)] + fn lang_item(&self, start_crate: Crate, item: SmolStr) -> Option; } #[salsa::query_group(HirDatabaseStorage)] diff --git a/crates/ra_hir/src/lang_item.rs b/crates/ra_hir/src/lang_item.rs index a25d419e7..5f3f91cba 100644 --- a/crates/ra_hir/src/lang_item.rs +++ b/crates/ra_hir/src/lang_item.rs @@ -40,7 +40,7 @@ impl LangItems { self.items.get(item) } - /// Salsa query. This will query a specific crate for lang items. + /// Salsa query. This will look for lang items in a specific crate. pub(crate) fn lang_items_query(db: &impl DefDatabase, krate: Crate) -> Arc { let mut lang_items = LangItems { items: FxHashMap::default() }; @@ -51,6 +51,29 @@ impl LangItems { Arc::new(lang_items) } + /// Salsa query. Look for a lang item, starting from the specified crate and recursively + /// traversing its dependencies. + pub(crate) fn lang_item_query( + db: &impl DefDatabase, + start_crate: Crate, + item: SmolStr, + ) -> Option { + let lang_items = db.lang_items(start_crate); + let start_crate_target = lang_items.items.get(&item); + if let Some(target) = start_crate_target { + Some(*target) + } else { + for dep in start_crate.dependencies(db) { + let dep_crate = dep.krate; + let dep_target = db.lang_item(dep_crate, item.clone()); + if dep_target.is_some() { + return dep_target; + } + } + None + } + } + fn collect_lang_items_recursive(&mut self, db: &impl DefDatabase, module: &Module) { // Look for impl targets let (impl_blocks, source_map) = db.impls_in_module_with_source_map(module.clone()); @@ -77,26 +100,3 @@ impl LangItems { } } } - -/// Look for a lang item, starting from the specified crate and recursively traversing its -/// dependencies. -pub(crate) fn lang_item_lookup( - db: &impl DefDatabase, - start_krate: Crate, - item: &str, -) -> Option { - let lang_items = db.lang_items(start_krate); - let start_krate_target = lang_items.items.get(item); - if start_krate_target.is_some() { - start_krate_target.map(|t| *t) - } else { - for dep in start_krate.dependencies(db) { - let dep_krate = dep.krate; - let dep_target = lang_item_lookup(db, dep_krate, item); - if dep_target.is_some() { - return dep_target; - } - } - None - } -} diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index dca56a434..ea6e0dc0f 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -14,7 +14,6 @@ use crate::{ resolve::Resolver, traits::TraitItem, generics::HasGenericParams, - lang_item::lang_item_lookup, ty::primitive::{UncertainIntTy, UncertainFloatTy} }; use super::{TraitRef, Substs}; @@ -116,15 +115,15 @@ fn def_crate(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option match ty { Ty::Apply(a_ty) => match a_ty.ctor { TypeCtor::Adt(def_id) => def_id.krate(db), - TypeCtor::Bool => lang_item_lookup(db, cur_crate, "bool")?.krate(db), - TypeCtor::Char => lang_item_lookup(db, cur_crate, "char")?.krate(db), + TypeCtor::Bool => db.lang_item(cur_crate, "bool".into())?.krate(db), + TypeCtor::Char => db.lang_item(cur_crate, "char".into())?.krate(db), TypeCtor::Float(UncertainFloatTy::Known(f)) => { - lang_item_lookup(db, cur_crate, f.ty_to_string())?.krate(db) + db.lang_item(cur_crate, f.ty_to_string().into())?.krate(db) } TypeCtor::Int(UncertainIntTy::Known(i)) => { - lang_item_lookup(db, cur_crate, i.ty_to_string())?.krate(db) + db.lang_item(cur_crate, i.ty_to_string().into())?.krate(db) } - TypeCtor::Str => lang_item_lookup(db, cur_crate, "str")?.krate(db), + TypeCtor::Str => db.lang_item(cur_crate, "str".into())?.krate(db), _ => None, }, _ => None, -- cgit v1.2.3