aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/code_model.rs150
-rw-r--r--crates/ra_hir/src/code_model/attrs.rs91
-rw-r--r--crates/ra_hir/src/code_model/docs.rs97
-rw-r--r--crates/ra_hir/src/code_model/src.rs112
-rw-r--r--crates/ra_hir/src/db.rs38
-rw-r--r--crates/ra_hir/src/debug.rs2
-rw-r--r--crates/ra_hir/src/from_id.rs46
-rw-r--r--crates/ra_hir/src/lang_item.rs160
-rw-r--r--crates/ra_hir/src/lib.rs13
-rw-r--r--crates/ra_hir/src/test_db.rs3
-rw-r--r--crates/ra_hir/src/ty/autoderef.rs7
-rw-r--r--crates/ra_hir/src/ty/infer/coerce.rs7
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs47
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs5
14 files changed, 266 insertions, 512 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 9f8c6c4a5..fd7776fb7 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -1,8 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3pub(crate) mod src; 3pub(crate) mod src;
4pub(crate) mod docs;
5pub(crate) mod attrs;
6 4
7use std::sync::Arc; 5use std::sync::Arc;
8 6
@@ -10,18 +8,20 @@ use hir_def::{
10 adt::VariantData, 8 adt::VariantData,
11 body::scope::ExprScopes, 9 body::scope::ExprScopes,
12 builtin_type::BuiltinType, 10 builtin_type::BuiltinType,
13 nameres::per_ns::PerNs, 11 docs::Documentation,
12 per_ns::PerNs,
14 resolver::{HasResolver, TypeNs}, 13 resolver::{HasResolver, TypeNs},
15 type_ref::TypeRef, 14 type_ref::TypeRef,
16 ContainerId, CrateModuleId, HasModule, ImplId, LocalEnumVariantId, LocalStructFieldId, Lookup, 15 ContainerId, HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId,
17 ModuleId, UnionId, 16 LocalStructFieldId, Lookup, ModuleId, UnionId,
18}; 17};
19use hir_expand::{ 18use hir_expand::{
20 diagnostics::DiagnosticSink, 19 diagnostics::DiagnosticSink,
21 name::{self, AsName}, 20 name::{self, AsName},
21 AstId,
22}; 22};
23use ra_db::{CrateId, Edition}; 23use ra_db::{CrateId, Edition, FileId, FilePosition};
24use ra_syntax::ast; 24use ra_syntax::{ast, AstNode, SyntaxNode};
25 25
26use crate::{ 26use crate::{
27 db::{DefDatabase, HirDatabase}, 27 db::{DefDatabase, HirDatabase},
@@ -31,7 +31,7 @@ use crate::{
31 TypeAliasId, 31 TypeAliasId,
32 }, 32 },
33 ty::{InferenceResult, Namespace, TraitRef}, 33 ty::{InferenceResult, Namespace, TraitRef},
34 Either, HasSource, ImportId, Name, Source, Ty, 34 Either, HasSource, Name, Source, Ty,
35}; 35};
36 36
37/// hir::Crate describes a single crate. It's the main interface with which 37/// hir::Crate describes a single crate. It's the main interface with which
@@ -79,6 +79,64 @@ impl Crate {
79 } 79 }
80} 80}
81 81
82pub enum ModuleSource {
83 SourceFile(ast::SourceFile),
84 Module(ast::Module),
85}
86
87impl ModuleSource {
88 pub fn new(
89 db: &impl DefDatabase,
90 file_id: Option<FileId>,
91 decl_id: Option<AstId<ast::Module>>,
92 ) -> ModuleSource {
93 match (file_id, decl_id) {
94 (Some(file_id), _) => {
95 let source_file = db.parse(file_id).tree();
96 ModuleSource::SourceFile(source_file)
97 }
98 (None, Some(item_id)) => {
99 let module = item_id.to_node(db);
100 assert!(module.item_list().is_some(), "expected inline module");
101 ModuleSource::Module(module)
102 }
103 (None, None) => panic!(),
104 }
105 }
106
107 // FIXME: this methods do not belong here
108 pub fn from_position(db: &impl DefDatabase, position: FilePosition) -> ModuleSource {
109 let parse = db.parse(position.file_id);
110 match &ra_syntax::algo::find_node_at_offset::<ast::Module>(
111 parse.tree().syntax(),
112 position.offset,
113 ) {
114 Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()),
115 _ => {
116 let source_file = parse.tree();
117 ModuleSource::SourceFile(source_file)
118 }
119 }
120 }
121
122 pub fn from_child_node(db: &impl DefDatabase, child: Source<&SyntaxNode>) -> ModuleSource {
123 if let Some(m) =
124 child.value.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi())
125 {
126 ModuleSource::Module(m)
127 } else {
128 let file_id = child.file_id.original_file(db);
129 let source_file = db.parse(file_id).tree();
130 ModuleSource::SourceFile(source_file)
131 }
132 }
133
134 pub fn from_file_id(db: &impl DefDatabase, file_id: FileId) -> ModuleSource {
135 let source_file = db.parse(file_id).tree();
136 ModuleSource::SourceFile(source_file)
137 }
138}
139
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 140#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
83pub struct Module { 141pub struct Module {
84 pub(crate) id: ModuleId, 142 pub(crate) id: ModuleId,
@@ -110,10 +168,10 @@ impl_froms!(
110 BuiltinType 168 BuiltinType
111); 169);
112 170
113pub use hir_def::ModuleSource; 171pub use hir_def::attr::Attrs;
114 172
115impl Module { 173impl Module {
116 pub(crate) fn new(krate: Crate, crate_module_id: CrateModuleId) -> Module { 174 pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module {
117 Module { id: ModuleId { krate: krate.crate_id, module_id: crate_module_id } } 175 Module { id: ModuleId { krate: krate.crate_id, module_id: crate_module_id } }
118 } 176 }
119 177
@@ -130,17 +188,6 @@ impl Module {
130 }) 188 })
131 } 189 }
132 190
133 /// Returns the syntax of the last path segment corresponding to this import
134 pub fn import_source(
135 self,
136 db: &impl HirDatabase,
137 import: ImportId,
138 ) -> Either<ast::UseTree, ast::ExternCrateItem> {
139 let src = self.definition_source(db);
140 let (_, source_map) = db.raw_items_with_source_map(src.file_id);
141 source_map.get(&src.value, import)
142 }
143
144 /// Returns the crate this module is part of. 191 /// Returns the crate this module is part of.
145 pub fn krate(self) -> Crate { 192 pub fn krate(self) -> Crate {
146 Crate { crate_id: self.id.krate } 193 Crate { crate_id: self.id.krate }
@@ -190,11 +237,13 @@ impl Module {
190 } 237 }
191 238
192 /// Returns a `ModuleScope`: a set of items, visible in this module. 239 /// Returns a `ModuleScope`: a set of items, visible in this module.
193 pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef, Option<ImportId>)> { 240 pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef, Option<Import>)> {
194 db.crate_def_map(self.id.krate)[self.id.module_id] 241 db.crate_def_map(self.id.krate)[self.id.module_id]
195 .scope 242 .scope
196 .entries() 243 .entries()
197 .map(|(name, res)| (name.clone(), res.def.into(), res.import)) 244 .map(|(name, res)| {
245 (name.clone(), res.def.into(), res.import.map(|id| Import { parent: self, id }))
246 })
198 .collect() 247 .collect()
199 } 248 }
200 249
@@ -232,11 +281,16 @@ impl Module {
232 def_map[self.id.module_id].impls.iter().copied().map(ImplBlock::from).collect() 281 def_map[self.id.module_id].impls.iter().copied().map(ImplBlock::from).collect()
233 } 282 }
234 283
235 fn with_module_id(self, module_id: CrateModuleId) -> Module { 284 fn with_module_id(self, module_id: LocalModuleId) -> Module {
236 Module::new(self.krate(), module_id) 285 Module::new(self.krate(), module_id)
237 } 286 }
238} 287}
239 288
289pub struct Import {
290 pub(crate) parent: Module,
291 pub(crate) id: LocalImportId,
292}
293
240#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 294#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
241pub struct StructField { 295pub struct StructField {
242 pub(crate) parent: VariantDef, 296 pub(crate) parent: VariantDef,
@@ -991,3 +1045,51 @@ impl From<PerNs> for ScopeDef {
991 .unwrap_or(ScopeDef::Unknown) 1045 .unwrap_or(ScopeDef::Unknown)
992 } 1046 }
993} 1047}
1048
1049#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1050pub enum AttrDef {
1051 Module(Module),
1052 StructField(StructField),
1053 Adt(Adt),
1054 Function(Function),
1055 EnumVariant(EnumVariant),
1056 Static(Static),
1057 Const(Const),
1058 Trait(Trait),
1059 TypeAlias(TypeAlias),
1060 MacroDef(MacroDef),
1061}
1062
1063impl_froms!(
1064 AttrDef: Module,
1065 StructField,
1066 Adt(Struct, Enum, Union),
1067 EnumVariant,
1068 Static,
1069 Const,
1070 Function,
1071 Trait,
1072 TypeAlias,
1073 MacroDef
1074);
1075
1076pub trait HasAttrs {
1077 fn attrs(self, db: &impl DefDatabase) -> Attrs;
1078}
1079
1080impl<T: Into<AttrDef>> HasAttrs for T {
1081 fn attrs(self, db: &impl DefDatabase) -> Attrs {
1082 let def: AttrDef = self.into();
1083 db.attrs(def.into())
1084 }
1085}
1086
1087pub trait Docs {
1088 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation>;
1089}
1090impl<T: Into<AttrDef> + Copy> Docs for T {
1091 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
1092 let def: AttrDef = (*self).into();
1093 db.documentation(def.into())
1094 }
1095}
diff --git a/crates/ra_hir/src/code_model/attrs.rs b/crates/ra_hir/src/code_model/attrs.rs
deleted file mode 100644
index 96da8c88c..000000000
--- a/crates/ra_hir/src/code_model/attrs.rs
+++ /dev/null
@@ -1,91 +0,0 @@
1//! FIXME: write short doc here
2
3use crate::{
4 db::{AstDatabase, DefDatabase, HirDatabase},
5 Adt, Const, Enum, EnumVariant, FieldSource, Function, HasSource, MacroDef, Module, Static,
6 Struct, StructField, Trait, TypeAlias, Union,
7};
8use hir_def::attr::{Attr, Attrs};
9use hir_expand::hygiene::Hygiene;
10use ra_syntax::ast;
11
12#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
13pub enum AttrDef {
14 Module(Module),
15 StructField(StructField),
16 Adt(Adt),
17 Function(Function),
18 EnumVariant(EnumVariant),
19 Static(Static),
20 Const(Const),
21 Trait(Trait),
22 TypeAlias(TypeAlias),
23 MacroDef(MacroDef),
24}
25
26impl_froms!(
27 AttrDef: Module,
28 StructField,
29 Adt(Struct, Enum, Union),
30 EnumVariant,
31 Static,
32 Const,
33 Function,
34 Trait,
35 TypeAlias,
36 MacroDef
37);
38
39pub trait HasAttrs {
40 fn attrs(&self, db: &impl HirDatabase) -> Attrs;
41}
42
43pub(crate) fn attributes_query(db: &(impl DefDatabase + AstDatabase), def: AttrDef) -> Attrs {
44 match def {
45 AttrDef::Module(it) => {
46 let src = match it.declaration_source(db) {
47 Some(it) => it,
48 None => return Attrs::default(),
49 };
50 let hygiene = Hygiene::new(db, src.file_id);
51 Attr::from_attrs_owner(&src.value, &hygiene)
52 }
53 AttrDef::StructField(it) => match it.source(db).value {
54 FieldSource::Named(named) => {
55 let src = it.source(db);
56 let hygiene = Hygiene::new(db, src.file_id);
57 Attr::from_attrs_owner(&named, &hygiene)
58 }
59 FieldSource::Pos(..) => Attrs::default(),
60 },
61 AttrDef::Adt(it) => match it {
62 Adt::Struct(it) => attrs_from_ast(it, db),
63 Adt::Enum(it) => attrs_from_ast(it, db),
64 Adt::Union(it) => attrs_from_ast(it, db),
65 },
66 AttrDef::EnumVariant(it) => attrs_from_ast(it, db),
67 AttrDef::Static(it) => attrs_from_ast(it, db),
68 AttrDef::Const(it) => attrs_from_ast(it, db),
69 AttrDef::Function(it) => attrs_from_ast(it, db),
70 AttrDef::Trait(it) => attrs_from_ast(it, db),
71 AttrDef::TypeAlias(it) => attrs_from_ast(it, db),
72 AttrDef::MacroDef(it) => attrs_from_ast(it, db),
73 }
74}
75
76fn attrs_from_ast<T, D>(node: T, db: &D) -> Attrs
77where
78 T: HasSource,
79 T::Ast: ast::AttrsOwner,
80 D: DefDatabase + AstDatabase,
81{
82 let src = node.source(db);
83 let hygiene = Hygiene::new(db, src.file_id);
84 Attr::from_attrs_owner(&src.value, &hygiene)
85}
86
87impl<T: Into<AttrDef> + Copy> HasAttrs for T {
88 fn attrs(&self, db: &impl HirDatabase) -> Attrs {
89 db.attrs((*self).into())
90 }
91}
diff --git a/crates/ra_hir/src/code_model/docs.rs b/crates/ra_hir/src/code_model/docs.rs
deleted file mode 100644
index e40efef34..000000000
--- a/crates/ra_hir/src/code_model/docs.rs
+++ /dev/null
@@ -1,97 +0,0 @@
1//! FIXME: write short doc here
2
3use std::sync::Arc;
4
5use ra_syntax::ast;
6
7use crate::{
8 db::{AstDatabase, DefDatabase, HirDatabase},
9 Adt, Const, Enum, EnumVariant, FieldSource, Function, HasSource, MacroDef, Module, Static,
10 Struct, StructField, Trait, TypeAlias, Union,
11};
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
14pub enum DocDef {
15 Module(Module),
16 StructField(StructField),
17 Adt(Adt),
18 EnumVariant(EnumVariant),
19 Static(Static),
20 Const(Const),
21 Function(Function),
22 Trait(Trait),
23 TypeAlias(TypeAlias),
24 MacroDef(MacroDef),
25}
26
27impl_froms!(
28 DocDef: Module,
29 StructField,
30 Adt(Struct, Enum, Union),
31 EnumVariant,
32 Static,
33 Const,
34 Function,
35 Trait,
36 TypeAlias,
37 MacroDef
38);
39
40/// Holds documentation
41#[derive(Debug, Clone, PartialEq, Eq)]
42pub struct Documentation(Arc<str>);
43
44impl Documentation {
45 fn new(s: &str) -> Documentation {
46 Documentation(s.into())
47 }
48
49 pub fn as_str(&self) -> &str {
50 &*self.0
51 }
52}
53
54impl Into<String> for Documentation {
55 fn into(self) -> String {
56 self.as_str().to_owned()
57 }
58}
59
60pub trait Docs {
61 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation>;
62}
63
64pub(crate) fn docs_from_ast(node: &impl ast::DocCommentsOwner) -> Option<Documentation> {
65 node.doc_comment_text().map(|it| Documentation::new(&it))
66}
67
68pub(crate) fn documentation_query(
69 db: &(impl DefDatabase + AstDatabase),
70 def: DocDef,
71) -> Option<Documentation> {
72 match def {
73 DocDef::Module(it) => docs_from_ast(&it.declaration_source(db)?.value),
74 DocDef::StructField(it) => match it.source(db).value {
75 FieldSource::Named(named) => docs_from_ast(&named),
76 FieldSource::Pos(..) => None,
77 },
78 DocDef::Adt(it) => match it {
79 Adt::Struct(it) => docs_from_ast(&it.source(db).value),
80 Adt::Enum(it) => docs_from_ast(&it.source(db).value),
81 Adt::Union(it) => docs_from_ast(&it.source(db).value),
82 },
83 DocDef::EnumVariant(it) => docs_from_ast(&it.source(db).value),
84 DocDef::Static(it) => docs_from_ast(&it.source(db).value),
85 DocDef::Const(it) => docs_from_ast(&it.source(db).value),
86 DocDef::Function(it) => docs_from_ast(&it.source(db).value),
87 DocDef::Trait(it) => docs_from_ast(&it.source(db).value),
88 DocDef::TypeAlias(it) => docs_from_ast(&it.source(db).value),
89 DocDef::MacroDef(it) => docs_from_ast(&it.source(db).value),
90 }
91}
92
93impl<T: Into<DocDef> + Copy> Docs for T {
94 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
95 db.documentation((*self).into())
96 }
97}
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
index fc466c1f0..b7bafe23d 100644
--- a/crates/ra_hir/src/code_model/src.rs
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -1,151 +1,127 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir_def::{HasSource as _, Lookup}; 3use hir_def::{HasChildSource, HasSource as _, Lookup, VariantId};
4use hir_expand::either::Either;
4use ra_syntax::ast::{self, AstNode}; 5use ra_syntax::ast::{self, AstNode};
5 6
6use crate::{ 7use crate::{
7 db::{AstDatabase, DefDatabase, HirDatabase}, 8 db::{DefDatabase, HirDatabase},
8 ids::AstItemDef, 9 ids::AstItemDef,
9 Const, Either, Enum, EnumVariant, FieldSource, Function, HasBody, HirFileId, MacroDef, Module, 10 Const, Enum, EnumVariant, FieldSource, Function, HasBody, Import, MacroDef, Module,
10 ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef, 11 ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union,
11}; 12};
12 13
13pub use hir_expand::Source; 14pub use hir_expand::Source;
14 15
15pub trait HasSource { 16pub trait HasSource {
16 type Ast; 17 type Ast;
17 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<Self::Ast>; 18 fn source(self, db: &impl DefDatabase) -> Source<Self::Ast>;
18} 19}
19 20
20/// NB: Module is !HasSource, because it has two source nodes at the same time: 21/// NB: Module is !HasSource, because it has two source nodes at the same time:
21/// definition and declaration. 22/// definition and declaration.
22impl Module { 23impl Module {
23 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. 24 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
24 pub fn definition_source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ModuleSource> { 25 pub fn definition_source(self, db: &impl DefDatabase) -> Source<ModuleSource> {
25 let def_map = db.crate_def_map(self.id.krate); 26 let def_map = db.crate_def_map(self.id.krate);
26 let decl_id = def_map[self.id.module_id].declaration; 27 let src = def_map[self.id.module_id].definition_source(db);
27 let file_id = def_map[self.id.module_id].definition; 28 src.map(|it| match it {
28 let value = ModuleSource::new(db, file_id, decl_id); 29 Either::A(it) => ModuleSource::SourceFile(it),
29 let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id()); 30 Either::B(it) => ModuleSource::Module(it),
30 Source { file_id, value } 31 })
31 } 32 }
32 33
33 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. 34 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
34 /// `None` for the crate root. 35 /// `None` for the crate root.
35 pub fn declaration_source( 36 pub fn declaration_source(self, db: &impl DefDatabase) -> Option<Source<ast::Module>> {
36 self,
37 db: &(impl DefDatabase + AstDatabase),
38 ) -> Option<Source<ast::Module>> {
39 let def_map = db.crate_def_map(self.id.krate); 37 let def_map = db.crate_def_map(self.id.krate);
40 let decl = def_map[self.id.module_id].declaration?; 38 def_map[self.id.module_id].declaration_source(db)
41 let value = decl.to_node(db);
42 Some(Source { file_id: decl.file_id(), value })
43 } 39 }
44} 40}
45 41
46impl HasSource for StructField { 42impl HasSource for StructField {
47 type Ast = FieldSource; 43 type Ast = FieldSource;
48 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> { 44 fn source(self, db: &impl DefDatabase) -> Source<FieldSource> {
49 let var_data = self.parent.variant_data(db); 45 let var = VariantId::from(self.parent);
50 let fields = var_data.fields().unwrap(); 46 let src = var.child_source(db);
51 let ss; 47 src.map(|it| match it[self.id].clone() {
52 let es; 48 Either::A(it) => FieldSource::Pos(it),
53 let (file_id, struct_kind) = match self.parent { 49 Either::B(it) => FieldSource::Named(it),
54 VariantDef::Struct(s) => { 50 })
55 ss = s.source(db);
56 (ss.file_id, ss.value.kind())
57 }
58 VariantDef::EnumVariant(e) => {
59 es = e.source(db);
60 (es.file_id, es.value.kind())
61 }
62 };
63
64 let field_sources = match struct_kind {
65 ast::StructKind::Tuple(fl) => fl.fields().map(|it| FieldSource::Pos(it)).collect(),
66 ast::StructKind::Record(fl) => fl.fields().map(|it| FieldSource::Named(it)).collect(),
67 ast::StructKind::Unit => Vec::new(),
68 };
69 let value = field_sources
70 .into_iter()
71 .zip(fields.iter())
72 .find(|(_syntax, (id, _))| *id == self.id)
73 .unwrap()
74 .0;
75 Source { file_id, value }
76 } 51 }
77} 52}
78impl HasSource for Struct { 53impl HasSource for Struct {
79 type Ast = ast::StructDef; 54 type Ast = ast::StructDef;
80 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::StructDef> { 55 fn source(self, db: &impl DefDatabase) -> Source<ast::StructDef> {
81 self.id.0.source(db) 56 self.id.0.source(db)
82 } 57 }
83} 58}
84impl HasSource for Union { 59impl HasSource for Union {
85 type Ast = ast::StructDef; 60 type Ast = ast::StructDef;
86 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::StructDef> { 61 fn source(self, db: &impl DefDatabase) -> Source<ast::StructDef> {
87 self.id.0.source(db) 62 self.id.0.source(db)
88 } 63 }
89} 64}
90impl HasSource for Enum { 65impl HasSource for Enum {
91 type Ast = ast::EnumDef; 66 type Ast = ast::EnumDef;
92 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::EnumDef> { 67 fn source(self, db: &impl DefDatabase) -> Source<ast::EnumDef> {
93 self.id.source(db) 68 self.id.source(db)
94 } 69 }
95} 70}
96impl HasSource for EnumVariant { 71impl HasSource for EnumVariant {
97 type Ast = ast::EnumVariant; 72 type Ast = ast::EnumVariant;
98 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::EnumVariant> { 73 fn source(self, db: &impl DefDatabase) -> Source<ast::EnumVariant> {
99 let enum_data = db.enum_data(self.parent.id); 74 self.parent.id.child_source(db).map(|map| map[self.id].clone())
100 let src = self.parent.id.source(db);
101 let value = src
102 .value
103 .variant_list()
104 .into_iter()
105 .flat_map(|it| it.variants())
106 .zip(enum_data.variants.iter())
107 .find(|(_syntax, (id, _))| *id == self.id)
108 .unwrap()
109 .0;
110 Source { file_id: src.file_id, value }
111 } 75 }
112} 76}
113impl HasSource for Function { 77impl HasSource for Function {
114 type Ast = ast::FnDef; 78 type Ast = ast::FnDef;
115 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::FnDef> { 79 fn source(self, db: &impl DefDatabase) -> Source<ast::FnDef> {
116 self.id.lookup(db).source(db) 80 self.id.lookup(db).source(db)
117 } 81 }
118} 82}
119impl HasSource for Const { 83impl HasSource for Const {
120 type Ast = ast::ConstDef; 84 type Ast = ast::ConstDef;
121 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::ConstDef> { 85 fn source(self, db: &impl DefDatabase) -> Source<ast::ConstDef> {
122 self.id.lookup(db).source(db) 86 self.id.lookup(db).source(db)
123 } 87 }
124} 88}
125impl HasSource for Static { 89impl HasSource for Static {
126 type Ast = ast::StaticDef; 90 type Ast = ast::StaticDef;
127 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::StaticDef> { 91 fn source(self, db: &impl DefDatabase) -> Source<ast::StaticDef> {
128 self.id.source(db) 92 self.id.source(db)
129 } 93 }
130} 94}
131impl HasSource for Trait { 95impl HasSource for Trait {
132 type Ast = ast::TraitDef; 96 type Ast = ast::TraitDef;
133 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::TraitDef> { 97 fn source(self, db: &impl DefDatabase) -> Source<ast::TraitDef> {
134 self.id.source(db) 98 self.id.source(db)
135 } 99 }
136} 100}
137impl HasSource for TypeAlias { 101impl HasSource for TypeAlias {
138 type Ast = ast::TypeAliasDef; 102 type Ast = ast::TypeAliasDef;
139 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::TypeAliasDef> { 103 fn source(self, db: &impl DefDatabase) -> Source<ast::TypeAliasDef> {
140 self.id.lookup(db).source(db) 104 self.id.lookup(db).source(db)
141 } 105 }
142} 106}
143impl HasSource for MacroDef { 107impl HasSource for MacroDef {
144 type Ast = ast::MacroCall; 108 type Ast = ast::MacroCall;
145 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::MacroCall> { 109 fn source(self, db: &impl DefDatabase) -> Source<ast::MacroCall> {
146 Source { file_id: self.id.ast_id.file_id(), value: self.id.ast_id.to_node(db) } 110 Source { file_id: self.id.ast_id.file_id(), value: self.id.ast_id.to_node(db) }
147 } 111 }
148} 112}
113impl HasSource for Import {
114 type Ast = Either<ast::UseTree, ast::ExternCrateItem>;
115
116 /// Returns the syntax of the last path segment corresponding to this import
117 fn source(self, db: &impl DefDatabase) -> Source<Self::Ast> {
118 let src = self.parent.definition_source(db);
119 let (_, source_map) = db.raw_items_with_source_map(src.file_id);
120 let root = db.parse_or_expand(src.file_id).unwrap();
121 let ptr = source_map.get(self.id);
122 src.with_value(ptr.map(|it| it.to_node(&root), |it| it.to_node(&root)))
123 }
124}
149 125
150pub trait HasBodySource: HasBody + HasSource 126pub trait HasBodySource: HasBody + HasSource
151where 127where
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 85d46b485..3ae5df8d5 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -2,58 +2,34 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::attr::Attrs;
6use ra_db::salsa; 5use ra_db::salsa;
7use ra_syntax::SmolStr;
8 6
9use crate::{ 7use crate::{
10 debug::HirDebugDatabase,
11 ids, 8 ids,
12 lang_item::{LangItemTarget, LangItems},
13 ty::{ 9 ty::{
14 method_resolution::CrateImplBlocks, 10 method_resolution::CrateImplBlocks,
15 traits::{AssocTyValue, Impl}, 11 traits::{AssocTyValue, Impl},
16 CallableDef, FnSig, GenericPredicate, InferenceResult, Namespace, Substs, Ty, TypableDef, 12 CallableDef, FnSig, GenericPredicate, InferenceResult, Namespace, Substs, Ty, TypableDef,
17 TypeCtor, 13 TypeCtor,
18 }, 14 },
19 Crate, DefWithBody, GenericDef, ImplBlock, Module, StructField, Trait, 15 Crate, DefWithBody, GenericDef, ImplBlock, StructField, Trait,
20}; 16};
21 17
22pub use hir_def::db::{ 18pub use hir_def::db::{
23 BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQuery, DefDatabase2, 19 BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQuery, CrateLangItemsQuery,
24 DefDatabase2Storage, EnumDataQuery, ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, 20 DefDatabase, DefDatabaseStorage, DocumentationQuery, EnumDataQuery, ExprScopesQuery,
25 ImplDataQuery, InternDatabase, InternDatabaseStorage, RawItemsQuery, 21 FunctionDataQuery, GenericParamsQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage,
26 RawItemsWithSourceMapQuery, StaticDataQuery, StructDataQuery, TraitDataQuery, 22 LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, RawItemsWithSourceMapQuery,
27 TypeAliasDataQuery, 23 StaticDataQuery, StructDataQuery, TraitDataQuery, TypeAliasDataQuery,
28}; 24};
29pub use hir_expand::db::{ 25pub use hir_expand::db::{
30 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, 26 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery,
31 ParseMacroQuery, 27 ParseMacroQuery,
32}; 28};
33 29
34// This database uses `AstDatabase` internally,
35#[salsa::query_group(DefDatabaseStorage)]
36#[salsa::requires(AstDatabase)]
37pub trait DefDatabase: HirDebugDatabase + DefDatabase2 {
38 #[salsa::invoke(LangItems::module_lang_items_query)]
39 fn module_lang_items(&self, module: Module) -> Option<Arc<LangItems>>;
40
41 #[salsa::invoke(LangItems::crate_lang_items_query)]
42 fn crate_lang_items(&self, krate: Crate) -> Arc<LangItems>;
43
44 #[salsa::invoke(LangItems::lang_item_query)]
45 fn lang_item(&self, start_crate: Crate, item: SmolStr) -> Option<LangItemTarget>;
46
47 #[salsa::invoke(crate::code_model::docs::documentation_query)]
48 fn documentation(&self, def: crate::DocDef) -> Option<crate::Documentation>;
49
50 #[salsa::invoke(crate::code_model::attrs::attributes_query)]
51 fn attrs(&self, def: crate::AttrDef) -> Attrs;
52}
53
54#[salsa::query_group(HirDatabaseStorage)] 30#[salsa::query_group(HirDatabaseStorage)]
55#[salsa::requires(salsa::Database)] 31#[salsa::requires(salsa::Database)]
56pub trait HirDatabase: DefDatabase + AstDatabase { 32pub trait HirDatabase: DefDatabase {
57 #[salsa::invoke(crate::ty::infer_query)] 33 #[salsa::invoke(crate::ty::infer_query)]
58 fn infer(&self, def: DefWithBody) -> Arc<InferenceResult>; 34 fn infer(&self, def: DefWithBody) -> Arc<InferenceResult>;
59 35
diff --git a/crates/ra_hir/src/debug.rs b/crates/ra_hir/src/debug.rs
index 4f3e922c3..8ec371f6e 100644
--- a/crates/ra_hir/src/debug.rs
+++ b/crates/ra_hir/src/debug.rs
@@ -1,3 +1,5 @@
1//! XXX: This does not work at the moment.
2//!
1//! printf debugging infrastructure for rust-analyzer. 3//! printf debugging infrastructure for rust-analyzer.
2//! 4//!
3//! When you print a hir type, like a module, using `eprintln!("{:?}", module)`, 5//! When you print a hir type, like a module, using `eprintln!("{:?}", module)`,
diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs
index e8ed04056..529ac8251 100644
--- a/crates/ra_hir/src/from_id.rs
+++ b/crates/ra_hir/src/from_id.rs
@@ -4,14 +4,14 @@
4//! are splitting the hir. 4//! are splitting the hir.
5 5
6use hir_def::{ 6use hir_def::{
7 AdtId, AssocItemId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, 7 AdtId, AssocItemId, AttrDefId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
8 ModuleDefId, StaticId, StructId, TypeAliasId, UnionId, 8 GenericDefId, ModuleDefId, StaticId, StructFieldId, StructId, TypeAliasId, UnionId, VariantId,
9}; 9};
10 10
11use crate::{ 11use crate::{
12 ty::{CallableDef, TypableDef}, 12 ty::{CallableDef, TypableDef},
13 Adt, AssocItem, Const, Crate, DefWithBody, EnumVariant, Function, GenericDef, ModuleDef, 13 Adt, AssocItem, AttrDef, Const, Crate, DefWithBody, EnumVariant, Function, GenericDef,
14 Static, TypeAlias, 14 ModuleDef, Static, StructField, TypeAlias, VariantDef,
15}; 15};
16 16
17impl From<ra_db::CrateId> for Crate { 17impl From<ra_db::CrateId> for Crate {
@@ -70,6 +70,12 @@ impl From<EnumVariantId> for EnumVariant {
70 } 70 }
71} 71}
72 72
73impl From<EnumVariant> for EnumVariantId {
74 fn from(def: EnumVariant) -> Self {
75 EnumVariantId { parent: def.parent.id, local_id: def.id }
76 }
77}
78
73impl From<ModuleDefId> for ModuleDef { 79impl From<ModuleDefId> for ModuleDef {
74 fn from(id: ModuleDefId) -> Self { 80 fn from(id: ModuleDefId) -> Self {
75 match id { 81 match id {
@@ -219,3 +225,35 @@ impl From<CallableDef> for GenericDefId {
219 } 225 }
220 } 226 }
221} 227}
228
229impl From<VariantDef> for VariantId {
230 fn from(def: VariantDef) -> Self {
231 match def {
232 VariantDef::Struct(it) => VariantId::StructId(it.id),
233 VariantDef::EnumVariant(it) => VariantId::EnumVariantId(it.into()),
234 }
235 }
236}
237
238impl From<StructField> for StructFieldId {
239 fn from(def: StructField) -> Self {
240 StructFieldId { parent: def.parent.into(), local_id: def.id }
241 }
242}
243
244impl From<AttrDef> for AttrDefId {
245 fn from(def: AttrDef) -> Self {
246 match def {
247 AttrDef::Module(it) => AttrDefId::ModuleId(it.id),
248 AttrDef::StructField(it) => AttrDefId::StructFieldId(it.into()),
249 AttrDef::Adt(it) => AttrDefId::AdtId(it.into()),
250 AttrDef::Function(it) => AttrDefId::FunctionId(it.id),
251 AttrDef::EnumVariant(it) => AttrDefId::EnumVariantId(it.into()),
252 AttrDef::Static(it) => AttrDefId::StaticId(it.id),
253 AttrDef::Const(it) => AttrDefId::ConstId(it.id),
254 AttrDef::Trait(it) => AttrDefId::TraitId(it.id),
255 AttrDef::TypeAlias(it) => AttrDefId::TypeAliasId(it.id),
256 AttrDef::MacroDef(it) => AttrDefId::MacroDefId(it.id),
257 }
258 }
259}
diff --git a/crates/ra_hir/src/lang_item.rs b/crates/ra_hir/src/lang_item.rs
deleted file mode 100644
index 89fd85f59..000000000
--- a/crates/ra_hir/src/lang_item.rs
+++ /dev/null
@@ -1,160 +0,0 @@
1//! FIXME: write short doc here
2
3use rustc_hash::FxHashMap;
4use std::sync::Arc;
5
6use ra_syntax::{ast::AttrsOwner, SmolStr};
7
8use crate::{
9 db::{AstDatabase, DefDatabase, HirDatabase},
10 Adt, Crate, Enum, Function, HasSource, ImplBlock, Module, ModuleDef, Static, Struct, Trait,
11};
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14pub enum LangItemTarget {
15 Enum(Enum),
16 Function(Function),
17 ImplBlock(ImplBlock),
18 Static(Static),
19 Struct(Struct),
20 Trait(Trait),
21}
22
23impl LangItemTarget {
24 pub(crate) fn krate(&self, db: &impl HirDatabase) -> Option<Crate> {
25 Some(match self {
26 LangItemTarget::Enum(e) => e.module(db).krate(),
27 LangItemTarget::Function(f) => f.module(db).krate(),
28 LangItemTarget::ImplBlock(i) => i.krate(db),
29 LangItemTarget::Static(s) => s.module(db).krate(),
30 LangItemTarget::Struct(s) => s.module(db).krate(),
31 LangItemTarget::Trait(t) => t.module(db).krate(),
32 })
33 }
34}
35
36#[derive(Default, Debug, Clone, PartialEq, Eq)]
37pub struct LangItems {
38 items: FxHashMap<SmolStr, LangItemTarget>,
39}
40
41impl LangItems {
42 pub fn target<'a>(&'a self, item: &str) -> Option<&'a LangItemTarget> {
43 self.items.get(item)
44 }
45
46 /// Salsa query. This will look for lang items in a specific crate.
47 pub(crate) fn crate_lang_items_query(
48 db: &(impl DefDatabase + AstDatabase),
49 krate: Crate,
50 ) -> Arc<LangItems> {
51 let mut lang_items = LangItems::default();
52
53 if let Some(module) = krate.root_module(db) {
54 lang_items.collect_lang_items_recursive(db, module);
55 }
56
57 Arc::new(lang_items)
58 }
59
60 pub(crate) fn module_lang_items_query(
61 db: &(impl DefDatabase + AstDatabase),
62 module: Module,
63 ) -> Option<Arc<LangItems>> {
64 let mut lang_items = LangItems::default();
65 lang_items.collect_lang_items(db, module);
66 if lang_items.items.is_empty() {
67 None
68 } else {
69 Some(Arc::new(lang_items))
70 }
71 }
72
73 /// Salsa query. Look for a lang item, starting from the specified crate and recursively
74 /// traversing its dependencies.
75 pub(crate) fn lang_item_query(
76 db: &impl DefDatabase,
77 start_crate: Crate,
78 item: SmolStr,
79 ) -> Option<LangItemTarget> {
80 let lang_items = db.crate_lang_items(start_crate);
81 let start_crate_target = lang_items.items.get(&item);
82 if let Some(target) = start_crate_target {
83 Some(*target)
84 } else {
85 for dep in start_crate.dependencies(db) {
86 let dep_crate = dep.krate;
87 let dep_target = db.lang_item(dep_crate, item.clone());
88 if dep_target.is_some() {
89 return dep_target;
90 }
91 }
92 None
93 }
94 }
95
96 fn collect_lang_items(&mut self, db: &(impl DefDatabase + AstDatabase), module: Module) {
97 // Look for impl targets
98 for impl_block in module.impl_blocks(db) {
99 let src = impl_block.source(db);
100 if let Some(lang_item_name) = lang_item_name(&src.value) {
101 self.items
102 .entry(lang_item_name)
103 .or_insert_with(|| LangItemTarget::ImplBlock(impl_block));
104 }
105 }
106
107 for def in module.declarations(db) {
108 match def {
109 ModuleDef::Trait(trait_) => {
110 self.collect_lang_item(db, trait_, LangItemTarget::Trait)
111 }
112 ModuleDef::Adt(Adt::Enum(e)) => self.collect_lang_item(db, e, LangItemTarget::Enum),
113 ModuleDef::Adt(Adt::Struct(s)) => {
114 self.collect_lang_item(db, s, LangItemTarget::Struct)
115 }
116 ModuleDef::Function(f) => self.collect_lang_item(db, f, LangItemTarget::Function),
117 ModuleDef::Static(s) => self.collect_lang_item(db, s, LangItemTarget::Static),
118 _ => {}
119 }
120 }
121 }
122
123 fn collect_lang_items_recursive(
124 &mut self,
125 db: &(impl DefDatabase + AstDatabase),
126 module: Module,
127 ) {
128 if let Some(module_lang_items) = db.module_lang_items(module) {
129 self.items.extend(module_lang_items.items.iter().map(|(k, v)| (k.clone(), *v)))
130 }
131
132 // Look for lang items in the children
133 for child in module.children(db) {
134 self.collect_lang_items_recursive(db, child);
135 }
136 }
137
138 fn collect_lang_item<T, N>(
139 &mut self,
140 db: &(impl DefDatabase + AstDatabase),
141 item: T,
142 constructor: fn(T) -> LangItemTarget,
143 ) where
144 T: Copy + HasSource<Ast = N>,
145 N: AttrsOwner,
146 {
147 let node = item.source(db).value;
148 if let Some(lang_item_name) = lang_item_name(&node) {
149 self.items.entry(lang_item_name).or_insert_with(|| constructor(item));
150 }
151 }
152}
153
154fn lang_item_name<T: AttrsOwner>(node: &T) -> Option<SmolStr> {
155 node.attrs()
156 .filter_map(|a| a.as_simple_key_value())
157 .filter(|(key, _)| key == "lang")
158 .map(|(_, val)| val)
159 .nth(0)
160}
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index e164c9b32..e51d4d063 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -35,7 +35,6 @@ mod ids;
35mod ty; 35mod ty;
36mod impl_block; 36mod impl_block;
37mod expr; 37mod expr;
38mod lang_item;
39pub mod diagnostics; 38pub mod diagnostics;
40mod util; 39mod util;
41 40
@@ -51,13 +50,11 @@ mod marks;
51 50
52pub use crate::{ 51pub use crate::{
53 code_model::{ 52 code_model::{
54 attrs::{AttrDef, HasAttrs},
55 docs::{DocDef, Docs, Documentation},
56 src::{HasBodySource, HasSource}, 53 src::{HasBodySource, HasSource},
57 Adt, AssocItem, Const, Container, Crate, CrateDependency, DefWithBody, Enum, EnumVariant, 54 Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency, DefWithBody, Docs, Enum,
58 FieldSource, Function, GenericDef, GenericParam, HasBody, ImplBlock, Local, MacroDef, 55 EnumVariant, FieldSource, Function, GenericDef, GenericParam, HasAttrs, HasBody, ImplBlock,
59 Module, ModuleDef, ModuleSource, ScopeDef, Static, Struct, StructField, Trait, TypeAlias, 56 Import, Local, MacroDef, Module, ModuleDef, ModuleSource, ScopeDef, Static, Struct,
60 Union, VariantDef, 57 StructField, Trait, TypeAlias, Union, VariantDef,
61 }, 58 },
62 expr::ExprScopes, 59 expr::ExprScopes,
63 from_source::FromSource, 60 from_source::FromSource,
@@ -72,7 +69,7 @@ pub use crate::{
72 69
73pub use hir_def::{ 70pub use hir_def::{
74 builtin_type::BuiltinType, 71 builtin_type::BuiltinType,
75 nameres::{per_ns::PerNs, raw::ImportId}, 72 docs::Documentation,
76 path::{Path, PathKind}, 73 path::{Path, PathKind},
77 type_ref::Mutability, 74 type_ref::Mutability,
78}; 75};
diff --git a/crates/ra_hir/src/test_db.rs b/crates/ra_hir/src/test_db.rs
index 1caa2e875..03c7ac155 100644
--- a/crates/ra_hir/src/test_db.rs
+++ b/crates/ra_hir/src/test_db.rs
@@ -2,7 +2,7 @@
2 2
3use std::{panic, sync::Arc}; 3use std::{panic, sync::Arc};
4 4
5use hir_def::{db::DefDatabase2, ModuleId}; 5use hir_def::{db::DefDatabase, ModuleId};
6use hir_expand::diagnostics::DiagnosticSink; 6use hir_expand::diagnostics::DiagnosticSink;
7use parking_lot::Mutex; 7use parking_lot::Mutex;
8use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath, SourceDatabase}; 8use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath, SourceDatabase};
@@ -15,7 +15,6 @@ use crate::{db, debug::HirDebugHelper};
15 db::InternDatabaseStorage, 15 db::InternDatabaseStorage,
16 db::AstDatabaseStorage, 16 db::AstDatabaseStorage,
17 db::DefDatabaseStorage, 17 db::DefDatabaseStorage,
18 db::DefDatabase2Storage,
19 db::HirDatabaseStorage 18 db::HirDatabaseStorage
20)] 19)]
21#[derive(Debug, Default)] 20#[derive(Debug, Default)]
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
6use std::iter::successors; 6use std::iter::successors;
7 7
8use hir_def::resolver::Resolver; 8use hir_def::{lang_item::LangItemTarget, resolver::Resolver};
9use hir_expand::name; 9use hir_expand::name;
10use log::{info, warn}; 10use log::{info, warn};
11 11
12use crate::{db::HirDatabase, Trait};
13
12use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; 14use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk};
13use crate::db::HirDatabase;
14 15
15const AUTODEREF_RECURSION_LIMIT: usize = 10; 16const 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
7use hir_def::resolver::Resolver; 7use hir_def::{lang_item::LangItemTarget, resolver::Resolver};
8use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
9use test_utils::tested_by; 9use test_utils::tested_by;
10 10
11use crate::{ 11use 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 @@
5use std::sync::Arc; 5use std::sync::Arc;
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::resolver::Resolver; 8use hir_def::{lang_item::LangItemTarget, resolver::Resolver, AstItemDef};
9use rustc_hash::FxHashMap; 9use rustc_hash::FxHashMap;
10 10
11use crate::{ 11use 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};
10use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; 10use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum};
11 11
12use hir_def::lang_item::LangItemTarget;
12use hir_expand::name; 13use hir_expand::name;
13 14
14use ra_db::salsa::{InternId, InternKey}; 15use ra_db::salsa::{InternId, InternKey};
@@ -832,9 +833,9 @@ fn closure_fn_trait_output_assoc_ty_value(
832} 833}
833 834
834fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { 835fn 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}