From 8692977d2798831d0aea434277ee54d589aa9be3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 23 Nov 2019 12:58:01 +0300 Subject: Move lang_items to hir_def --- crates/ra_hir/src/db.rs | 23 ++--- crates/ra_hir/src/lang_item.rs | 154 ------------------------------ crates/ra_hir/src/lib.rs | 1 - crates/ra_hir/src/ty/autoderef.rs | 7 +- crates/ra_hir/src/ty/infer/coerce.rs | 7 +- crates/ra_hir/src/ty/method_resolution.rs | 47 +++++---- crates/ra_hir/src/ty/traits/chalk.rs | 5 +- crates/ra_hir_def/src/db.rs | 16 +++- crates/ra_hir_def/src/lang_item.rs | 120 +++++++++++++++++++++++ crates/ra_hir_def/src/lib.rs | 1 + 10 files changed, 179 insertions(+), 202 deletions(-) delete mode 100644 crates/ra_hir/src/lang_item.rs create mode 100644 crates/ra_hir_def/src/lang_item.rs 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 @@ use std::sync::Arc; use ra_db::salsa; -use ra_syntax::SmolStr; use crate::{ debug::HirDebugDatabase, ids, - lang_item::{LangItemTarget, LangItems}, ty::{ method_resolution::CrateImplBlocks, traits::{AssocTyValue, Impl}, CallableDef, FnSig, GenericPredicate, InferenceResult, Namespace, Substs, Ty, TypableDef, TypeCtor, }, - Crate, DefWithBody, GenericDef, ImplBlock, Module, StructField, Trait, + Crate, DefWithBody, GenericDef, ImplBlock, StructField, Trait, }; pub use hir_def::db::{ - BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQuery, DefDatabase2, - DefDatabase2Storage, EnumDataQuery, ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, - ImplDataQuery, InternDatabase, InternDatabaseStorage, RawItemsQuery, - RawItemsWithSourceMapQuery, StaticDataQuery, StructDataQuery, TraitDataQuery, - TypeAliasDataQuery, + BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQuery, CrateLangItemsQuery, + DefDatabase2, DefDatabase2Storage, EnumDataQuery, ExprScopesQuery, FunctionDataQuery, + GenericParamsQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage, LangItemQuery, + ModuleLangItemsQuery, RawItemsQuery, RawItemsWithSourceMapQuery, StaticDataQuery, + StructDataQuery, TraitDataQuery, TypeAliasDataQuery, }; pub use hir_expand::db::{ AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, @@ -34,15 +32,6 @@ pub use hir_expand::db::{ #[salsa::query_group(DefDatabaseStorage)] #[salsa::requires(AstDatabase)] pub trait DefDatabase: HirDebugDatabase + DefDatabase2 { - #[salsa::invoke(LangItems::module_lang_items_query)] - fn module_lang_items(&self, module: Module) -> Option>; - - #[salsa::invoke(LangItems::crate_lang_items_query)] - fn crate_lang_items(&self, krate: Crate) -> Arc; - - #[salsa::invoke(LangItems::lang_item_query)] - fn lang_item(&self, start_crate: Crate, item: SmolStr) -> Option; - #[salsa::invoke(crate::code_model::docs::documentation_query)] fn documentation(&self, def: crate::DocDef) -> Option; } 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 @@ -//! FIXME: write short doc here - -use std::sync::Arc; - -use hir_def::{AdtId, AttrDefId, ModuleDefId}; -use ra_syntax::SmolStr; -use rustc_hash::FxHashMap; - -use crate::{ - db::{AstDatabase, DefDatabase, HirDatabase}, - Crate, Enum, Function, ImplBlock, Module, Static, Struct, Trait, -}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum LangItemTarget { - Enum(Enum), - Function(Function), - ImplBlock(ImplBlock), - Static(Static), - Struct(Struct), - Trait(Trait), -} - -impl LangItemTarget { - pub(crate) fn krate(&self, db: &impl HirDatabase) -> Option { - Some(match self { - LangItemTarget::Enum(e) => e.module(db).krate(), - LangItemTarget::Function(f) => f.module(db).krate(), - LangItemTarget::ImplBlock(i) => i.krate(db), - LangItemTarget::Static(s) => s.module(db).krate(), - LangItemTarget::Struct(s) => s.module(db).krate(), - LangItemTarget::Trait(t) => t.module(db).krate(), - }) - } -} - -#[derive(Default, 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 look for lang items in a specific crate. - pub(crate) fn crate_lang_items_query( - db: &(impl DefDatabase + AstDatabase), - krate: Crate, - ) -> Arc { - let mut lang_items = LangItems::default(); - - if let Some(module) = krate.root_module(db) { - lang_items.collect_lang_items_recursive(db, module); - } - - Arc::new(lang_items) - } - - pub(crate) fn module_lang_items_query( - db: &(impl DefDatabase + AstDatabase), - module: Module, - ) -> Option> { - let mut lang_items = LangItems::default(); - lang_items.collect_lang_items(db, module); - if lang_items.items.is_empty() { - None - } else { - Some(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.crate_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(&mut self, db: &(impl DefDatabase + AstDatabase), module: Module) { - // Look for impl targets - let def_map = db.crate_def_map(module.id.krate); - let module_data = &def_map[module.id.module_id]; - for &impl_block in module_data.impls.iter() { - self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlock) - } - - for def in module_data.scope.declarations() { - match def { - ModuleDefId::TraitId(trait_) => { - self.collect_lang_item(db, trait_, LangItemTarget::Trait) - } - ModuleDefId::AdtId(AdtId::EnumId(e)) => { - self.collect_lang_item(db, e, LangItemTarget::Enum) - } - ModuleDefId::AdtId(AdtId::StructId(s)) => { - self.collect_lang_item(db, s, LangItemTarget::Struct) - } - ModuleDefId::FunctionId(f) => { - self.collect_lang_item(db, f, LangItemTarget::Function) - } - ModuleDefId::StaticId(s) => self.collect_lang_item(db, s, LangItemTarget::Static), - _ => {} - } - } - } - - fn collect_lang_items_recursive( - &mut self, - db: &(impl DefDatabase + AstDatabase), - module: Module, - ) { - if let Some(module_lang_items) = db.module_lang_items(module) { - self.items.extend(module_lang_items.items.iter().map(|(k, v)| (k.clone(), *v))) - } - - // Look for lang items in the children - for child in module.children(db) { - self.collect_lang_items_recursive(db, child); - } - } - - fn collect_lang_item( - &mut self, - db: &(impl DefDatabase + AstDatabase), - item: T, - constructor: fn(D) -> LangItemTarget, - ) where - T: Into + Copy, - D: From, - { - let attrs = db.attrs(item.into()); - if let Some(lang_item_name) = attrs.find_string_value("lang") { - self.items.entry(lang_item_name).or_insert_with(|| constructor(D::from(item))); - } - } -} 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; mod ty; mod impl_block; mod expr; -mod lang_item; pub mod diagnostics; mod util; 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 @@ use std::iter::successors; -use hir_def::resolver::Resolver; +use hir_def::{lang_item::LangItemTarget, resolver::Resolver}; use hir_expand::name; use log::{info, warn}; +use crate::{db::HirDatabase, Trait}; + use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; -use crate::db::HirDatabase; const AUTODEREF_RECURSION_LIMIT: usize = 10; @@ -41,7 +42,7 @@ fn deref_by_trait( ) -> Option> { let krate = resolver.krate()?; let deref_trait = match db.lang_item(krate.into(), "deref".into())? { - crate::lang_item::LangItemTarget::Trait(t) => t, + LangItemTarget::TraitId(t) => Trait::from(t), _ => return None, }; 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 @@ //! //! See: https://doc.rust-lang.org/nomicon/coercions.html -use hir_def::resolver::Resolver; +use hir_def::{lang_item::LangItemTarget, resolver::Resolver}; use rustc_hash::FxHashMap; use test_utils::tested_by; use crate::{ db::HirDatabase, - lang_item::LangItemTarget, ty::{autoderef, Substs, Ty, TypeCtor, TypeWalk}, Adt, Mutability, }; @@ -50,7 +49,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ) -> FxHashMap<(TypeCtor, TypeCtor), usize> { let krate = resolver.krate().unwrap(); let impls = match db.lang_item(krate.into(), "coerce_unsized".into()) { - Some(LangItemTarget::Trait(trait_)) => db.impls_for_trait(krate.into(), trait_), + Some(LangItemTarget::TraitId(trait_)) => { + db.impls_for_trait(krate.into(), trait_.into()) + } _ => return FxHashMap::default(), }; 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 @@ use std::sync::Arc; use arrayvec::ArrayVec; -use hir_def::resolver::Resolver; +use hir_def::{lang_item::LangItemTarget, resolver::Resolver, AstItemDef}; use rustc_hash::FxHashMap; use crate::{ @@ -91,34 +91,43 @@ fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option {{ - let mut v = ArrayVec::<[Crate; 2]>::new(); + ($($name:expr),+ $(,)?) => {{ + let mut v = ArrayVec::<[LangItemTarget; 2]>::new(); $( - v.extend($db.lang_item($cur_crate, $name.into()).and_then(|item| item.krate($db))); + v.extend(db.lang_item(cur_crate.crate_id, $name.into())); )+ - Some(v) + v }}; } - match ty { + let lang_item_targets = match ty { Ty::Apply(a_ty) => match a_ty.ctor { - TypeCtor::Adt(def_id) => Some(std::iter::once(def_id.krate(db)?).collect()), - TypeCtor::Bool => lang_item_crate!(db, cur_crate, "bool"), - TypeCtor::Char => lang_item_crate!(db, cur_crate, "char"), + TypeCtor::Adt(def_id) => return Some(std::iter::once(def_id.krate(db)?).collect()), + TypeCtor::Bool => lang_item_crate!("bool"), + TypeCtor::Char => lang_item_crate!("char"), TypeCtor::Float(Uncertain::Known(f)) => match f.bitness { // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) - FloatBitness::X32 => lang_item_crate!(db, cur_crate, "f32", "f32_runtime"), - FloatBitness::X64 => lang_item_crate!(db, cur_crate, "f64", "f64_runtime"), + FloatBitness::X32 => lang_item_crate!("f32", "f32_runtime"), + FloatBitness::X64 => lang_item_crate!("f64", "f64_runtime"), }, - TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(db, cur_crate, i.ty_to_string()), - TypeCtor::Str => lang_item_crate!(db, cur_crate, "str_alloc", "str"), - TypeCtor::Slice => lang_item_crate!(db, cur_crate, "slice_alloc", "slice"), - TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!(db, cur_crate, "const_ptr"), - TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!(db, cur_crate, "mut_ptr"), - _ => None, + TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(i.ty_to_string()), + TypeCtor::Str => lang_item_crate!("str_alloc", "str"), + TypeCtor::Slice => lang_item_crate!("slice_alloc", "slice"), + TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!("const_ptr"), + TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"), + _ => return None, }, - _ => None, - } + _ => return None, + }; + let res = lang_item_targets + .into_iter() + .filter_map(|it| match it { + LangItemTarget::ImplBlockId(it) => Some(it), + _ => None, + }) + .map(|it| it.module(db).krate.into()) + .collect(); + Some(res) } /// 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::{ }; use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; +use hir_def::lang_item::LangItemTarget; use hir_expand::name; use ra_db::salsa::{InternId, InternKey}; @@ -832,9 +833,9 @@ fn closure_fn_trait_output_assoc_ty_value( } fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option { - let target = db.lang_item(krate, fn_trait.lang_item_name().into())?; + let target = db.lang_item(krate.crate_id, fn_trait.lang_item_name().into())?; match target { - crate::lang_item::LangItemTarget::Trait(t) => Some(t), + LangItemTarget::TraitId(t) => Some(t.into()), _ => None, } } 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; use hir_expand::{db::AstDatabase, HirFileId}; use ra_db::{salsa, CrateId, SourceDatabase}; -use ra_syntax::ast; +use ra_syntax::{ast, SmolStr}; use crate::{ adt::{EnumData, StructData}, @@ -11,12 +11,13 @@ use crate::{ body::{scope::ExprScopes, Body, BodySourceMap}, data::{ConstData, FunctionData, ImplData, TraitData, TypeAliasData}, generics::GenericParams, + lang_item::{LangItemTarget, LangItems}, nameres::{ raw::{ImportSourceMap, RawItems}, CrateDefMap, }, - AttrDefId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, ImplId, ItemLoc, StaticId, - StructOrUnionId, TraitId, TypeAliasId, + AttrDefId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, ImplId, ItemLoc, ModuleId, + StaticId, StructOrUnionId, TraitId, TypeAliasId, }; #[salsa::query_group(InternDatabaseStorage)] @@ -91,4 +92,13 @@ pub trait DefDatabase2: InternDatabase + AstDatabase { #[salsa::invoke(Attrs::attrs_query)] fn attrs(&self, def: AttrDefId) -> Attrs; + + #[salsa::invoke(LangItems::module_lang_items_query)] + fn module_lang_items(&self, module: ModuleId) -> Option>; + + #[salsa::invoke(LangItems::crate_lang_items_query)] + fn crate_lang_items(&self, krate: CrateId) -> Arc; + + #[salsa::invoke(LangItems::lang_item_query)] + fn lang_item(&self, start_crate: CrateId, item: SmolStr) -> Option; } 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 @@ +//! Collects lang items: items marked with `#[lang = "..."]` attribute. +//! +//! This attribute to tell the compiler about semi built-in std library +//! features, such as Fn family of traits. +use std::sync::Arc; + +use ra_syntax::SmolStr; +use rustc_hash::FxHashMap; + +use crate::{ + db::DefDatabase2, AdtId, AttrDefId, CrateId, EnumId, FunctionId, ImplId, ModuleDefId, ModuleId, + StaticId, StructId, TraitId, +}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum LangItemTarget { + EnumId(EnumId), + FunctionId(FunctionId), + ImplBlockId(ImplId), + StaticId(StaticId), + StructId(StructId), + TraitId(TraitId), +} + +#[derive(Default, 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 look for lang items in a specific crate. + pub(crate) fn crate_lang_items_query(db: &impl DefDatabase2, krate: CrateId) -> Arc { + let mut lang_items = LangItems::default(); + + let crate_def_map = db.crate_def_map(krate); + + crate_def_map + .modules() + .filter_map(|module_id| db.module_lang_items(ModuleId { krate, module_id })) + .for_each(|it| lang_items.items.extend(it.items.iter().map(|(k, v)| (k.clone(), *v)))); + + Arc::new(lang_items) + } + + pub(crate) fn module_lang_items_query( + db: &impl DefDatabase2, + module: ModuleId, + ) -> Option> { + let mut lang_items = LangItems::default(); + lang_items.collect_lang_items(db, module); + if lang_items.items.is_empty() { + None + } else { + Some(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 DefDatabase2, + start_crate: CrateId, + item: SmolStr, + ) -> Option { + let lang_items = db.crate_lang_items(start_crate); + let start_crate_target = lang_items.items.get(&item); + if let Some(target) = start_crate_target { + return Some(*target); + } + db.crate_graph() + .dependencies(start_crate) + .find_map(|dep| db.lang_item(dep.crate_id, item.clone())) + } + + fn collect_lang_items(&mut self, db: &impl DefDatabase2, module: ModuleId) { + // Look for impl targets + let def_map = db.crate_def_map(module.krate); + let module_data = &def_map[module.module_id]; + for &impl_block in module_data.impls.iter() { + self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlockId) + } + + for def in module_data.scope.declarations() { + match def { + ModuleDefId::TraitId(trait_) => { + self.collect_lang_item(db, trait_, LangItemTarget::TraitId) + } + ModuleDefId::AdtId(AdtId::EnumId(e)) => { + self.collect_lang_item(db, e, LangItemTarget::EnumId) + } + ModuleDefId::AdtId(AdtId::StructId(s)) => { + self.collect_lang_item(db, s, LangItemTarget::StructId) + } + ModuleDefId::FunctionId(f) => { + self.collect_lang_item(db, f, LangItemTarget::FunctionId) + } + ModuleDefId::StaticId(s) => self.collect_lang_item(db, s, LangItemTarget::StaticId), + _ => {} + } + } + } + + fn collect_lang_item( + &mut self, + db: &impl DefDatabase2, + item: T, + constructor: fn(T) -> LangItemTarget, + ) where + T: Into + Copy, + { + let attrs = db.attrs(item.into()); + if let Some(lang_item_name) = attrs.find_string_value("lang") { + self.items.entry(lang_item_name).or_insert_with(|| constructor(item)); + } + } +} 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; pub mod generics; pub mod resolver; pub mod data; +pub mod lang_item; mod trace; -- cgit v1.2.3