aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def
diff options
context:
space:
mode:
authorSeivan Heidari <[email protected]>2019-11-25 00:54:54 +0000
committerSeivan Heidari <[email protected]>2019-11-25 00:54:54 +0000
commit15ea338ac991707d330288ba4d1bf5daa0fc75d9 (patch)
tree16aeab28bcdb07d36aae28e3fb4a385614865a48 /crates/ra_hir_def
parenteb7363d167c7a9f7c73cb950b621eb1dce493318 (diff)
parentf7f9757b6b144385ab8ce57b15764473b1f57331 (diff)
Merge branch 'master' of https://github.com/rust-analyzer/rust-analyzer into feature/themes
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r--crates/ra_hir_def/src/adt.rs169
-rw-r--r--crates/ra_hir_def/src/attr.rs156
-rw-r--r--crates/ra_hir_def/src/body.rs50
-rw-r--r--crates/ra_hir_def/src/body/lower.rs9
-rw-r--r--crates/ra_hir_def/src/body/scope.rs12
-rw-r--r--crates/ra_hir_def/src/data.rs216
-rw-r--r--crates/ra_hir_def/src/db.rs61
-rw-r--r--crates/ra_hir_def/src/docs.rs71
-rw-r--r--crates/ra_hir_def/src/generics.rs8
-rw-r--r--crates/ra_hir_def/src/impls.rs86
-rw-r--r--crates/ra_hir_def/src/lang_item.rs121
-rw-r--r--crates/ra_hir_def/src/lib.rs258
-rw-r--r--crates/ra_hir_def/src/nameres.rs130
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs141
-rw-r--r--crates/ra_hir_def/src/nameres/mod_resolution.rs4
-rw-r--r--crates/ra_hir_def/src/nameres/path_resolution.rs17
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs76
-rw-r--r--crates/ra_hir_def/src/nameres/tests.rs6
-rw-r--r--crates/ra_hir_def/src/nameres/tests/mod_resolution.rs2
-rw-r--r--crates/ra_hir_def/src/path.rs15
-rw-r--r--crates/ra_hir_def/src/per_ns.rs (renamed from crates/ra_hir_def/src/nameres/per_ns.rs)15
-rw-r--r--crates/ra_hir_def/src/resolver.rs101
-rw-r--r--crates/ra_hir_def/src/test_db.rs2
-rw-r--r--crates/ra_hir_def/src/trace.rs59
-rw-r--r--crates/ra_hir_def/src/traits.rs66
-rw-r--r--crates/ra_hir_def/src/type_ref.rs8
26 files changed, 1166 insertions, 693 deletions
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index d04f54e15..c9f30923e 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -2,13 +2,17 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_expand::name::{AsName, Name}; 5use hir_expand::{
6use ra_arena::Arena; 6 either::Either,
7 name::{AsName, Name},
8 Source,
9};
10use ra_arena::{map::ArenaMap, Arena};
7use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; 11use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
8 12
9use crate::{ 13use crate::{
10 db::DefDatabase2, type_ref::TypeRef, AstItemDef, EnumId, LocalEnumVariantId, 14 db::DefDatabase, trace::Trace, type_ref::TypeRef, AstItemDef, EnumId, HasChildSource,
11 LocalStructFieldId, StructOrUnionId, 15 LocalEnumVariantId, LocalStructFieldId, StructOrUnionId, VariantId,
12}; 16};
13 17
14/// Note that we use `StructData` for unions as well! 18/// Note that we use `StructData` for unions as well!
@@ -30,13 +34,9 @@ pub struct EnumVariantData {
30 pub variant_data: Arc<VariantData>, 34 pub variant_data: Arc<VariantData>,
31} 35}
32 36
33/// Fields of an enum variant or struct
34#[derive(Debug, Clone, PartialEq, Eq)]
35pub struct VariantData(VariantDataInner);
36
37#[derive(Debug, Clone, PartialEq, Eq)] 37#[derive(Debug, Clone, PartialEq, Eq)]
38enum VariantDataInner { 38pub enum VariantData {
39 Struct(Arena<LocalStructFieldId, StructFieldData>), 39 Record(Arena<LocalStructFieldId, StructFieldData>),
40 Tuple(Arena<LocalStructFieldId, StructFieldData>), 40 Tuple(Arena<LocalStructFieldId, StructFieldData>),
41 Unit, 41 Unit,
42} 42}
@@ -49,10 +49,7 @@ pub struct StructFieldData {
49} 49}
50 50
51impl StructData { 51impl StructData {
52 pub(crate) fn struct_data_query( 52 pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructOrUnionId) -> Arc<StructData> {
53 db: &impl DefDatabase2,
54 id: StructOrUnionId,
55 ) -> Arc<StructData> {
56 let src = id.source(db); 53 let src = id.source(db);
57 let name = src.value.name().map(|n| n.as_name()); 54 let name = src.value.name().map(|n| n.as_name());
58 let variant_data = VariantData::new(src.value.kind()); 55 let variant_data = VariantData::new(src.value.kind());
@@ -62,20 +59,12 @@ impl StructData {
62} 59}
63 60
64impl EnumData { 61impl EnumData {
65 pub(crate) fn enum_data_query(db: &impl DefDatabase2, e: EnumId) -> Arc<EnumData> { 62 pub(crate) fn enum_data_query(db: &impl DefDatabase, e: EnumId) -> Arc<EnumData> {
66 let src = e.source(db); 63 let src = e.source(db);
67 let name = src.value.name().map(|n| n.as_name()); 64 let name = src.value.name().map(|n| n.as_name());
68 let variants = src 65 let mut trace = Trace::new_for_arena();
69 .value 66 lower_enum(&mut trace, &src.value);
70 .variant_list() 67 Arc::new(EnumData { name, variants: trace.into_arena() })
71 .into_iter()
72 .flat_map(|it| it.variants())
73 .map(|var| EnumVariantData {
74 name: var.name().map(|it| it.as_name()),
75 variant_data: Arc::new(VariantData::new(var.kind())),
76 })
77 .collect();
78 Arc::new(EnumData { name, variants })
79 } 68 }
80 69
81 pub(crate) fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> { 70 pub(crate) fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> {
@@ -84,39 +73,117 @@ impl EnumData {
84 } 73 }
85} 74}
86 75
76impl HasChildSource for EnumId {
77 type ChildId = LocalEnumVariantId;
78 type Value = ast::EnumVariant;
79 fn child_source(&self, db: &impl DefDatabase) -> Source<ArenaMap<Self::ChildId, Self::Value>> {
80 let src = self.source(db);
81 let mut trace = Trace::new_for_map();
82 lower_enum(&mut trace, &src.value);
83 src.with_value(trace.into_map())
84 }
85}
86
87fn lower_enum(
88 trace: &mut Trace<LocalEnumVariantId, EnumVariantData, ast::EnumVariant>,
89 ast: &ast::EnumDef,
90) {
91 for var in ast.variant_list().into_iter().flat_map(|it| it.variants()) {
92 trace.alloc(
93 || var.clone(),
94 || EnumVariantData {
95 name: var.name().map(|it| it.as_name()),
96 variant_data: Arc::new(VariantData::new(var.kind())),
97 },
98 );
99 }
100}
101
87impl VariantData { 102impl VariantData {
88 fn new(flavor: ast::StructKind) -> Self { 103 fn new(flavor: ast::StructKind) -> Self {
89 let inner = match flavor { 104 let mut trace = Trace::new_for_arena();
90 ast::StructKind::Tuple(fl) => { 105 match lower_struct(&mut trace, &flavor) {
91 let fields = fl 106 StructKind::Tuple => VariantData::Tuple(trace.into_arena()),
92 .fields() 107 StructKind::Record => VariantData::Record(trace.into_arena()),
93 .enumerate() 108 StructKind::Unit => VariantData::Unit,
94 .map(|(i, fd)| StructFieldData { 109 }
110 }
111
112 pub fn fields(&self) -> &Arena<LocalStructFieldId, StructFieldData> {
113 const EMPTY: &Arena<LocalStructFieldId, StructFieldData> = &Arena::new();
114 match &self {
115 VariantData::Record(fields) | VariantData::Tuple(fields) => fields,
116 _ => EMPTY,
117 }
118 }
119
120 pub fn is_unit(&self) -> bool {
121 match self {
122 VariantData::Unit => true,
123 _ => false,
124 }
125 }
126}
127
128impl HasChildSource for VariantId {
129 type ChildId = LocalStructFieldId;
130 type Value = Either<ast::TupleFieldDef, ast::RecordFieldDef>;
131
132 fn child_source(&self, db: &impl DefDatabase) -> Source<ArenaMap<Self::ChildId, Self::Value>> {
133 let src = match self {
134 VariantId::EnumVariantId(it) => {
135 // I don't really like the fact that we call into parent source
136 // here, this might add to more queries then necessary.
137 let src = it.parent.child_source(db);
138 src.map(|map| map[it.local_id].kind())
139 }
140 VariantId::StructId(it) => it.0.source(db).map(|it| it.kind()),
141 };
142 let mut trace = Trace::new_for_map();
143 lower_struct(&mut trace, &src.value);
144 src.with_value(trace.into_map())
145 }
146}
147
148enum StructKind {
149 Tuple,
150 Record,
151 Unit,
152}
153
154fn lower_struct(
155 trace: &mut Trace<
156 LocalStructFieldId,
157 StructFieldData,
158 Either<ast::TupleFieldDef, ast::RecordFieldDef>,
159 >,
160 ast: &ast::StructKind,
161) -> StructKind {
162 match ast {
163 ast::StructKind::Tuple(fl) => {
164 for (i, fd) in fl.fields().enumerate() {
165 trace.alloc(
166 || Either::A(fd.clone()),
167 || StructFieldData {
95 name: Name::new_tuple_field(i), 168 name: Name::new_tuple_field(i),
96 type_ref: TypeRef::from_ast_opt(fd.type_ref()), 169 type_ref: TypeRef::from_ast_opt(fd.type_ref()),
97 }) 170 },
98 .collect(); 171 );
99 VariantDataInner::Tuple(fields)
100 } 172 }
101 ast::StructKind::Named(fl) => { 173 StructKind::Tuple
102 let fields = fl 174 }
103 .fields() 175 ast::StructKind::Record(fl) => {
104 .map(|fd| StructFieldData { 176 for fd in fl.fields() {
177 trace.alloc(
178 || Either::B(fd.clone()),
179 || StructFieldData {
105 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), 180 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
106 type_ref: TypeRef::from_ast_opt(fd.ascribed_type()), 181 type_ref: TypeRef::from_ast_opt(fd.ascribed_type()),
107 }) 182 },
108 .collect(); 183 );
109 VariantDataInner::Struct(fields)
110 } 184 }
111 ast::StructKind::Unit => VariantDataInner::Unit, 185 StructKind::Record
112 };
113 VariantData(inner)
114 }
115
116 pub fn fields(&self) -> Option<&Arena<LocalStructFieldId, StructFieldData>> {
117 match &self.0 {
118 VariantDataInner::Struct(fields) | VariantDataInner::Tuple(fields) => Some(fields),
119 _ => None,
120 } 186 }
187 ast::StructKind::Unit => StructKind::Unit,
121 } 188 }
122} 189}
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 0e961ca12..53456fc08 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -1,17 +1,93 @@
1//! A higher level attributes based on TokenTree, with also some shortcuts. 1//! A higher level attributes based on TokenTree, with also some shortcuts.
2 2
3use std::sync::Arc; 3use std::{ops, sync::Arc};
4 4
5use hir_expand::hygiene::Hygiene; 5use hir_expand::{either::Either, hygiene::Hygiene, AstId, Source};
6use mbe::ast_to_token_tree; 6use mbe::ast_to_token_tree;
7use ra_cfg::CfgOptions;
8use ra_syntax::{ 7use ra_syntax::{
9 ast::{self, AstNode, AttrsOwner}, 8 ast::{self, AstNode, AttrsOwner},
10 SmolStr, 9 SmolStr,
11}; 10};
12use tt::Subtree; 11use tt::Subtree;
13 12
14use crate::path::Path; 13use crate::{
14 db::DefDatabase, path::Path, AdtId, AstItemDef, AttrDefId, HasChildSource, HasSource, Lookup,
15};
16
17#[derive(Default, Debug, Clone, PartialEq, Eq)]
18pub struct Attrs {
19 entries: Option<Arc<[Attr]>>,
20}
21
22impl ops::Deref for Attrs {
23 type Target = [Attr];
24
25 fn deref(&self) -> &[Attr] {
26 match &self.entries {
27 Some(it) => &*it,
28 None => &[],
29 }
30 }
31}
32
33impl Attrs {
34 pub(crate) fn attrs_query(db: &impl DefDatabase, def: AttrDefId) -> Attrs {
35 match def {
36 AttrDefId::ModuleId(module) => {
37 let def_map = db.crate_def_map(module.krate);
38 let src = match def_map[module.module_id].declaration_source(db) {
39 Some(it) => it,
40 None => return Attrs::default(),
41 };
42 Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner))
43 }
44 AttrDefId::StructFieldId(it) => {
45 let src = it.parent.child_source(db);
46 match &src.value[it.local_id] {
47 Either::A(_tuple) => Attrs::default(),
48 Either::B(record) => Attrs::from_attrs_owner(db, src.with_value(record)),
49 }
50 }
51 AttrDefId::EnumVariantId(var_id) => {
52 let src = var_id.parent.child_source(db);
53 let src = src.as_ref().map(|it| &it[var_id.local_id]);
54 Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner))
55 }
56 AttrDefId::AdtId(it) => match it {
57 AdtId::StructId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db),
58 AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
59 AdtId::UnionId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db),
60 },
61 AttrDefId::TraitId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
62 AttrDefId::MacroDefId(it) => attrs_from_ast(it.ast_id, db),
63 AttrDefId::ImplId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
64 AttrDefId::ConstId(it) => attrs_from_loc(it.lookup(db), db),
65 AttrDefId::StaticId(it) => attrs_from_loc(it.lookup(db), db),
66 AttrDefId::FunctionId(it) => attrs_from_loc(it.lookup(db), db),
67 AttrDefId::TypeAliasId(it) => attrs_from_loc(it.lookup(db), db),
68 }
69 }
70
71 fn from_attrs_owner(db: &impl DefDatabase, owner: Source<&dyn AttrsOwner>) -> Attrs {
72 let hygiene = Hygiene::new(db, owner.file_id);
73 Attrs::new(owner.value, &hygiene)
74 }
75
76 pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs {
77 let mut attrs = owner.attrs().peekable();
78 let entries = if attrs.peek().is_none() {
79 // Avoid heap allocation
80 None
81 } else {
82 Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).collect())
83 };
84 Attrs { entries }
85 }
86
87 pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> {
88 AttrQuery { attrs: self, key }
89 }
90}
15 91
16#[derive(Debug, Clone, PartialEq, Eq)] 92#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct Attr { 93pub struct Attr {
@@ -26,7 +102,7 @@ pub enum AttrInput {
26} 102}
27 103
28impl Attr { 104impl Attr {
29 pub(crate) fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> { 105 fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> {
30 let path = Path::from_src(ast.path()?, hygiene)?; 106 let path = Path::from_src(ast.path()?, hygiene)?;
31 let input = match ast.input() { 107 let input = match ast.input() {
32 None => None, 108 None => None,
@@ -42,43 +118,55 @@ impl Attr {
42 118
43 Some(Attr { path, input }) 119 Some(Attr { path, input })
44 } 120 }
121}
45 122
46 pub fn from_attrs_owner(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Option<Arc<[Attr]>> { 123pub struct AttrQuery<'a> {
47 let mut attrs = owner.attrs().peekable(); 124 attrs: &'a Attrs,
48 if attrs.peek().is_none() { 125 key: &'static str,
49 // Avoid heap allocation 126}
50 return None;
51 }
52 Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).collect())
53 }
54 127
55 pub fn is_simple_atom(&self, name: &str) -> bool { 128impl<'a> AttrQuery<'a> {
56 // FIXME: Avoid cloning 129 pub fn tt_values(self) -> impl Iterator<Item = &'a Subtree> {
57 self.path.as_ident().map_or(false, |s| s.to_string() == name) 130 self.attrs().filter_map(|attr| match attr.input.as_ref()? {
131 AttrInput::TokenTree(it) => Some(it),
132 _ => None,
133 })
58 } 134 }
59 135
60 // FIXME: handle cfg_attr :-) 136 pub fn string_value(self) -> Option<&'a SmolStr> {
61 pub fn as_cfg(&self) -> Option<&Subtree> { 137 self.attrs().find_map(|attr| match attr.input.as_ref()? {
62 if !self.is_simple_atom("cfg") { 138 AttrInput::Literal(it) => Some(it),
63 return None;
64 }
65 match &self.input {
66 Some(AttrInput::TokenTree(subtree)) => Some(subtree),
67 _ => None, 139 _ => None,
68 } 140 })
69 } 141 }
70 142
71 pub fn as_path(&self) -> Option<&SmolStr> { 143 pub fn exists(self) -> bool {
72 if !self.is_simple_atom("path") { 144 self.attrs().next().is_some()
73 return None;
74 }
75 match &self.input {
76 Some(AttrInput::Literal(it)) => Some(it),
77 _ => None,
78 }
79 } 145 }
80 146
81 pub fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> Option<bool> { 147 fn attrs(self) -> impl Iterator<Item = &'a Attr> {
82 cfg_options.is_cfg_enabled(self.as_cfg()?) 148 let key = self.key;
149 self.attrs
150 .iter()
151 .filter(move |attr| attr.path.as_ident().map_or(false, |s| s.to_string() == key))
83 } 152 }
84} 153}
154
155fn attrs_from_ast<D, N>(src: AstId<N>, db: &D) -> Attrs
156where
157 N: ast::AttrsOwner,
158 D: DefDatabase,
159{
160 let src = Source::new(src.file_id(), src.to_node(db));
161 Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner))
162}
163
164fn attrs_from_loc<T, D>(node: T, db: &D) -> Attrs
165where
166 T: HasSource,
167 T::Value: ast::AttrsOwner,
168 D: DefDatabase,
169{
170 let src = node.source(db);
171 Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner))
172}
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index dfb79a30a..d77ccb272 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -1,4 +1,5 @@
1//! FIXME: write short doc here 1//! Defines `Body`: a lowered representation of bodies of functions, statics and
2//! consts.
2mod lower; 3mod lower;
3pub mod scope; 4pub mod scope;
4 5
@@ -13,14 +14,14 @@ use ra_syntax::{ast, AstNode, AstPtr};
13use rustc_hash::FxHashMap; 14use rustc_hash::FxHashMap;
14 15
15use crate::{ 16use crate::{
16 db::DefDatabase2, 17 db::DefDatabase,
17 expr::{Expr, ExprId, Pat, PatId}, 18 expr::{Expr, ExprId, Pat, PatId},
18 nameres::CrateDefMap, 19 nameres::CrateDefMap,
19 path::Path, 20 path::Path,
20 AstItemDef, DefWithBodyId, HasModule, HasSource, Lookup, ModuleId, 21 DefWithBodyId, HasModule, HasSource, Lookup, ModuleId,
21}; 22};
22 23
23pub struct Expander { 24struct Expander {
24 crate_def_map: Arc<CrateDefMap>, 25 crate_def_map: Arc<CrateDefMap>,
25 current_file_id: HirFileId, 26 current_file_id: HirFileId,
26 hygiene: Hygiene, 27 hygiene: Hygiene,
@@ -28,7 +29,7 @@ pub struct Expander {
28} 29}
29 30
30impl Expander { 31impl Expander {
31 pub fn new(db: &impl DefDatabase2, current_file_id: HirFileId, module: ModuleId) -> Expander { 32 fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander {
32 let crate_def_map = db.crate_def_map(module.krate); 33 let crate_def_map = db.crate_def_map(module.krate);
33 let hygiene = Hygiene::new(db, current_file_id); 34 let hygiene = Hygiene::new(db, current_file_id);
34 Expander { crate_def_map, current_file_id, hygiene, module } 35 Expander { crate_def_map, current_file_id, hygiene, module }
@@ -36,7 +37,7 @@ impl Expander {
36 37
37 fn enter_expand( 38 fn enter_expand(
38 &mut self, 39 &mut self,
39 db: &impl DefDatabase2, 40 db: &impl DefDatabase,
40 macro_call: ast::MacroCall, 41 macro_call: ast::MacroCall,
41 ) -> Option<(Mark, ast::Expr)> { 42 ) -> Option<(Mark, ast::Expr)> {
42 let ast_id = AstId::new( 43 let ast_id = AstId::new(
@@ -67,7 +68,7 @@ impl Expander {
67 None 68 None
68 } 69 }
69 70
70 fn exit(&mut self, db: &impl DefDatabase2, mark: Mark) { 71 fn exit(&mut self, db: &impl DefDatabase, mark: Mark) {
71 self.hygiene = Hygiene::new(db, mark.file_id); 72 self.hygiene = Hygiene::new(db, mark.file_id);
72 self.current_file_id = mark.file_id; 73 self.current_file_id = mark.file_id;
73 std::mem::forget(mark); 74 std::mem::forget(mark);
@@ -81,8 +82,8 @@ impl Expander {
81 Path::from_src(path, &self.hygiene) 82 Path::from_src(path, &self.hygiene)
82 } 83 }
83 84
84 fn resolve_path_as_macro(&self, db: &impl DefDatabase2, path: &Path) -> Option<MacroDefId> { 85 fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> {
85 self.crate_def_map.resolve_path(db, self.module.module_id, path).0.get_macros() 86 self.crate_def_map.resolve_path(db, self.module.module_id, path).0.take_macros()
86 } 87 }
87} 88}
88 89
@@ -101,17 +102,17 @@ impl Drop for Mark {
101/// The body of an item (function, const etc.). 102/// The body of an item (function, const etc.).
102#[derive(Debug, Eq, PartialEq)] 103#[derive(Debug, Eq, PartialEq)]
103pub struct Body { 104pub struct Body {
104 exprs: Arena<ExprId, Expr>, 105 pub exprs: Arena<ExprId, Expr>,
105 pats: Arena<PatId, Pat>, 106 pub pats: Arena<PatId, Pat>,
106 /// The patterns for the function's parameters. While the parameter types are 107 /// The patterns for the function's parameters. While the parameter types are
107 /// part of the function signature, the patterns are not (they don't change 108 /// part of the function signature, the patterns are not (they don't change
108 /// the external type of the function). 109 /// the external type of the function).
109 /// 110 ///
110 /// If this `Body` is for the body of a constant, this will just be 111 /// If this `Body` is for the body of a constant, this will just be
111 /// empty. 112 /// empty.
112 params: Vec<PatId>, 113 pub params: Vec<PatId>,
113 /// The `ExprId` of the actual body expression. 114 /// The `ExprId` of the actual body expression.
114 body_expr: ExprId, 115 pub body_expr: ExprId,
115} 116}
116 117
117pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>; 118pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>;
@@ -142,7 +143,7 @@ pub struct BodySourceMap {
142 143
143impl Body { 144impl Body {
144 pub(crate) fn body_with_source_map_query( 145 pub(crate) fn body_with_source_map_query(
145 db: &impl DefDatabase2, 146 db: &impl DefDatabase,
146 def: DefWithBodyId, 147 def: DefWithBodyId,
147 ) -> (Arc<Body>, Arc<BodySourceMap>) { 148 ) -> (Arc<Body>, Arc<BodySourceMap>) {
148 let mut params = None; 149 let mut params = None;
@@ -160,6 +161,7 @@ impl Body {
160 (src.file_id, c.module(db), src.value.body()) 161 (src.file_id, c.module(db), src.value.body())
161 } 162 }
162 DefWithBodyId::StaticId(s) => { 163 DefWithBodyId::StaticId(s) => {
164 let s = s.lookup(db);
163 let src = s.source(db); 165 let src = s.source(db);
164 (src.file_id, s.module(db), src.value.body()) 166 (src.file_id, s.module(db), src.value.body())
165 } 167 }
@@ -169,34 +171,18 @@ impl Body {
169 (Arc::new(body), Arc::new(source_map)) 171 (Arc::new(body), Arc::new(source_map))
170 } 172 }
171 173
172 pub(crate) fn body_query(db: &impl DefDatabase2, def: DefWithBodyId) -> Arc<Body> { 174 pub(crate) fn body_query(db: &impl DefDatabase, def: DefWithBodyId) -> Arc<Body> {
173 db.body_with_source_map(def).0 175 db.body_with_source_map(def).0
174 } 176 }
175 177
176 fn new( 178 fn new(
177 db: &impl DefDatabase2, 179 db: &impl DefDatabase,
178 expander: Expander, 180 expander: Expander,
179 params: Option<ast::ParamList>, 181 params: Option<ast::ParamList>,
180 body: Option<ast::Expr>, 182 body: Option<ast::Expr>,
181 ) -> (Body, BodySourceMap) { 183 ) -> (Body, BodySourceMap) {
182 lower::lower(db, expander, params, body) 184 lower::lower(db, expander, params, body)
183 } 185 }
184
185 pub fn params(&self) -> &[PatId] {
186 &self.params
187 }
188
189 pub fn body_expr(&self) -> ExprId {
190 self.body_expr
191 }
192
193 pub fn exprs(&self) -> impl Iterator<Item = (ExprId, &Expr)> {
194 self.exprs.iter()
195 }
196
197 pub fn pats(&self) -> impl Iterator<Item = (PatId, &Pat)> {
198 self.pats.iter()
199 }
200} 186}
201 187
202impl Index<ExprId> for Body { 188impl Index<ExprId> for Body {
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index d8e911aa5..331736cb2 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -1,4 +1,5 @@
1//! FIXME: write short doc here 1//! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr`
2//! representation.
2 3
3use hir_expand::{ 4use hir_expand::{
4 either::Either, 5 either::Either,
@@ -17,7 +18,7 @@ use test_utils::tested_by;
17use crate::{ 18use crate::{
18 body::{Body, BodySourceMap, Expander, PatPtr}, 19 body::{Body, BodySourceMap, Expander, PatPtr},
19 builtin_type::{BuiltinFloat, BuiltinInt}, 20 builtin_type::{BuiltinFloat, BuiltinInt},
20 db::DefDatabase2, 21 db::DefDatabase,
21 expr::{ 22 expr::{
22 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp, 23 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp,
23 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, 24 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
@@ -28,7 +29,7 @@ use crate::{
28}; 29};
29 30
30pub(super) fn lower( 31pub(super) fn lower(
31 db: &impl DefDatabase2, 32 db: &impl DefDatabase,
32 expander: Expander, 33 expander: Expander,
33 params: Option<ast::ParamList>, 34 params: Option<ast::ParamList>,
34 body: Option<ast::Expr>, 35 body: Option<ast::Expr>,
@@ -57,7 +58,7 @@ struct ExprCollector<DB> {
57 58
58impl<'a, DB> ExprCollector<&'a DB> 59impl<'a, DB> ExprCollector<&'a DB>
59where 60where
60 DB: DefDatabase2, 61 DB: DefDatabase,
61{ 62{
62 fn collect( 63 fn collect(
63 mut self, 64 mut self,
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs
index 58740b679..625aa39dd 100644
--- a/crates/ra_hir_def/src/body/scope.rs
+++ b/crates/ra_hir_def/src/body/scope.rs
@@ -1,4 +1,4 @@
1//! FIXME: write short doc here 1//! Name resolution for expressions.
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use hir_expand::name::Name; 4use hir_expand::name::Name;
@@ -7,7 +7,7 @@ use rustc_hash::FxHashMap;
7 7
8use crate::{ 8use crate::{
9 body::Body, 9 body::Body,
10 db::DefDatabase2, 10 db::DefDatabase,
11 expr::{Expr, ExprId, Pat, PatId, Statement}, 11 expr::{Expr, ExprId, Pat, PatId, Statement},
12 DefWithBodyId, 12 DefWithBodyId,
13}; 13};
@@ -45,7 +45,7 @@ pub struct ScopeData {
45} 45}
46 46
47impl ExprScopes { 47impl ExprScopes {
48 pub(crate) fn expr_scopes_query(db: &impl DefDatabase2, def: DefWithBodyId) -> Arc<ExprScopes> { 48 pub(crate) fn expr_scopes_query(db: &impl DefDatabase, def: DefWithBodyId) -> Arc<ExprScopes> {
49 let body = db.body(def); 49 let body = db.body(def);
50 Arc::new(ExprScopes::new(&*body)) 50 Arc::new(ExprScopes::new(&*body))
51 } 51 }
@@ -54,8 +54,8 @@ impl ExprScopes {
54 let mut scopes = 54 let mut scopes =
55 ExprScopes { scopes: Arena::default(), scope_by_expr: FxHashMap::default() }; 55 ExprScopes { scopes: Arena::default(), scope_by_expr: FxHashMap::default() };
56 let root = scopes.root_scope(); 56 let root = scopes.root_scope();
57 scopes.add_params_bindings(body, root, body.params()); 57 scopes.add_params_bindings(body, root, &body.params);
58 compute_expr_scopes(body.body_expr(), body, &mut scopes, root); 58 compute_expr_scopes(body.body_expr, body, &mut scopes, root);
59 scopes 59 scopes
60 } 60 }
61 61
@@ -176,7 +176,7 @@ mod tests {
176 use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; 176 use ra_syntax::{algo::find_node_at_offset, ast, AstNode};
177 use test_utils::{assert_eq_text, covers, extract_offset}; 177 use test_utils::{assert_eq_text, covers, extract_offset};
178 178
179 use crate::{db::DefDatabase2, test_db::TestDB, FunctionId, ModuleDefId}; 179 use crate::{db::DefDatabase, test_db::TestDB, FunctionId, ModuleDefId};
180 180
181 fn find_function(db: &TestDB, file_id: FileId) -> FunctionId { 181 fn find_function(db: &TestDB, file_id: FileId) -> FunctionId {
182 let krate = db.test_crate(); 182 let krate = db.test_crate();
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
new file mode 100644
index 000000000..68bea34df
--- /dev/null
+++ b/crates/ra_hir_def/src/data.rs
@@ -0,0 +1,216 @@
1//! Contains basic data about various HIR declarations.
2
3use std::sync::Arc;
4
5use hir_expand::{
6 name::{self, AsName, Name},
7 AstId,
8};
9use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
10
11use crate::{
12 db::DefDatabase,
13 type_ref::{Mutability, TypeRef},
14 AssocItemId, AstItemDef, ConstId, ConstLoc, ContainerId, FunctionId, FunctionLoc, HasSource,
15 ImplId, Intern, Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
16};
17
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct FunctionData {
20 pub name: Name,
21 pub params: Vec<TypeRef>,
22 pub ret_type: TypeRef,
23 /// True if the first param is `self`. This is relevant to decide whether this
24 /// can be called as a method.
25 pub has_self_param: bool,
26}
27
28impl FunctionData {
29 pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> {
30 let src = func.lookup(db).source(db);
31 let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
32 let mut params = Vec::new();
33 let mut has_self_param = false;
34 if let Some(param_list) = src.value.param_list() {
35 if let Some(self_param) = param_list.self_param() {
36 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
37 TypeRef::from_ast(type_ref)
38 } else {
39 let self_type = TypeRef::Path(name::SELF_TYPE.into());
40 match self_param.kind() {
41 ast::SelfParamKind::Owned => self_type,
42 ast::SelfParamKind::Ref => {
43 TypeRef::Reference(Box::new(self_type), Mutability::Shared)
44 }
45 ast::SelfParamKind::MutRef => {
46 TypeRef::Reference(Box::new(self_type), Mutability::Mut)
47 }
48 }
49 };
50 params.push(self_type);
51 has_self_param = true;
52 }
53 for param in param_list.params() {
54 let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
55 params.push(type_ref);
56 }
57 }
58 let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
59 TypeRef::from_ast(type_ref)
60 } else {
61 TypeRef::unit()
62 };
63
64 let sig = FunctionData { name, params, ret_type, has_self_param };
65 Arc::new(sig)
66 }
67}
68
69#[derive(Debug, Clone, PartialEq, Eq)]
70pub struct TypeAliasData {
71 pub name: Name,
72 pub type_ref: Option<TypeRef>,
73}
74
75impl TypeAliasData {
76 pub(crate) fn type_alias_data_query(
77 db: &impl DefDatabase,
78 typ: TypeAliasId,
79 ) -> Arc<TypeAliasData> {
80 let node = typ.lookup(db).source(db).value;
81 let name = node.name().map_or_else(Name::missing, |n| n.as_name());
82 let type_ref = node.type_ref().map(TypeRef::from_ast);
83 Arc::new(TypeAliasData { name, type_ref })
84 }
85}
86
87#[derive(Debug, Clone, PartialEq, Eq)]
88pub struct TraitData {
89 pub name: Option<Name>,
90 pub items: Vec<AssocItemId>,
91 pub auto: bool,
92}
93
94impl TraitData {
95 pub(crate) fn trait_data_query(db: &impl DefDatabase, tr: TraitId) -> Arc<TraitData> {
96 let src = tr.source(db);
97 let name = src.value.name().map(|n| n.as_name());
98 let auto = src.value.is_auto();
99 let ast_id_map = db.ast_id_map(src.file_id);
100 let items = if let Some(item_list) = src.value.item_list() {
101 item_list
102 .impl_items()
103 .map(|item_node| match item_node {
104 ast::ImplItem::FnDef(it) => FunctionLoc {
105 container: ContainerId::TraitId(tr),
106 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
107 }
108 .intern(db)
109 .into(),
110 ast::ImplItem::ConstDef(it) => ConstLoc {
111 container: ContainerId::TraitId(tr),
112 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
113 }
114 .intern(db)
115 .into(),
116 ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc {
117 container: ContainerId::TraitId(tr),
118 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
119 }
120 .intern(db)
121 .into(),
122 })
123 .collect()
124 } else {
125 Vec::new()
126 };
127 Arc::new(TraitData { name, items, auto })
128 }
129
130 pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
131 self.items.iter().filter_map(|item| match item {
132 AssocItemId::TypeAliasId(t) => Some(*t),
133 _ => None,
134 })
135 }
136}
137
138#[derive(Debug, Clone, PartialEq, Eq)]
139pub struct ImplData {
140 pub target_trait: Option<TypeRef>,
141 pub target_type: TypeRef,
142 pub items: Vec<AssocItemId>,
143 pub is_negative: bool,
144}
145
146impl ImplData {
147 pub(crate) fn impl_data_query(db: &impl DefDatabase, id: ImplId) -> Arc<ImplData> {
148 let src = id.source(db);
149 let items = db.ast_id_map(src.file_id);
150
151 let target_trait = src.value.target_trait().map(TypeRef::from_ast);
152 let target_type = TypeRef::from_ast_opt(src.value.target_type());
153 let is_negative = src.value.is_negative();
154
155 let items = if let Some(item_list) = src.value.item_list() {
156 item_list
157 .impl_items()
158 .map(|item_node| match item_node {
159 ast::ImplItem::FnDef(it) => {
160 let def = FunctionLoc {
161 container: ContainerId::ImplId(id),
162 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
163 }
164 .intern(db);
165 def.into()
166 }
167 ast::ImplItem::ConstDef(it) => {
168 let def = ConstLoc {
169 container: ContainerId::ImplId(id),
170 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
171 }
172 .intern(db);
173 def.into()
174 }
175 ast::ImplItem::TypeAliasDef(it) => {
176 let def = TypeAliasLoc {
177 container: ContainerId::ImplId(id),
178 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
179 }
180 .intern(db);
181 def.into()
182 }
183 })
184 .collect()
185 } else {
186 Vec::new()
187 };
188
189 let res = ImplData { target_trait, target_type, items, is_negative };
190 Arc::new(res)
191 }
192}
193
194#[derive(Debug, Clone, PartialEq, Eq)]
195pub struct ConstData {
196 pub name: Option<Name>,
197 pub type_ref: TypeRef,
198}
199
200impl ConstData {
201 pub(crate) fn const_data_query(db: &impl DefDatabase, konst: ConstId) -> Arc<ConstData> {
202 let node = konst.lookup(db).source(db).value;
203 Arc::new(ConstData::new(&node))
204 }
205
206 pub(crate) fn static_data_query(db: &impl DefDatabase, konst: StaticId) -> Arc<ConstData> {
207 let node = konst.lookup(db).source(db).value;
208 Arc::new(ConstData::new(&node))
209 }
210
211 fn new<N: NameOwner + TypeAscriptionOwner>(node: &N) -> ConstData {
212 let name = node.name().map(|n| n.as_name());
213 let type_ref = TypeRef::from_ast_opt(node.ascribed_type());
214 ConstData { name, type_ref }
215 }
216}
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index 844f8bbe8..32adb11bd 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -3,43 +3,47 @@ use std::sync::Arc;
3 3
4use hir_expand::{db::AstDatabase, HirFileId}; 4use hir_expand::{db::AstDatabase, HirFileId};
5use ra_db::{salsa, CrateId, SourceDatabase}; 5use ra_db::{salsa, CrateId, SourceDatabase};
6use ra_syntax::ast; 6use ra_syntax::{ast, SmolStr};
7 7
8use crate::{ 8use crate::{
9 adt::{EnumData, StructData}, 9 adt::{EnumData, StructData},
10 attr::Attrs,
10 body::{scope::ExprScopes, Body, BodySourceMap}, 11 body::{scope::ExprScopes, Body, BodySourceMap},
12 data::{ConstData, FunctionData, ImplData, TraitData, TypeAliasData},
13 docs::Documentation,
11 generics::GenericParams, 14 generics::GenericParams,
12 impls::ImplData, 15 lang_item::{LangItemTarget, LangItems},
13 nameres::{ 16 nameres::{
14 raw::{ImportSourceMap, RawItems}, 17 raw::{ImportSourceMap, RawItems},
15 CrateDefMap, 18 CrateDefMap,
16 }, 19 },
17 traits::TraitData, 20 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId,
18 DefWithBodyId, EnumId, GenericDefId, ImplId, ItemLoc, StructOrUnionId, TraitId, 21 ImplId, ItemLoc, ModuleId, StaticId, StaticLoc, StructOrUnionId, TraitId, TypeAliasId,
22 TypeAliasLoc,
19}; 23};
20 24
21#[salsa::query_group(InternDatabaseStorage)] 25#[salsa::query_group(InternDatabaseStorage)]
22pub trait InternDatabase: SourceDatabase { 26pub trait InternDatabase: SourceDatabase {
23 #[salsa::interned] 27 #[salsa::interned]
24 fn intern_function(&self, loc: crate::FunctionLoc) -> crate::FunctionId; 28 fn intern_function(&self, loc: FunctionLoc) -> FunctionId;
25 #[salsa::interned] 29 #[salsa::interned]
26 fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> crate::StructOrUnionId; 30 fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> StructOrUnionId;
27 #[salsa::interned] 31 #[salsa::interned]
28 fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> crate::EnumId; 32 fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> EnumId;
29 #[salsa::interned] 33 #[salsa::interned]
30 fn intern_const(&self, loc: crate::ConstLoc) -> crate::ConstId; 34 fn intern_const(&self, loc: ConstLoc) -> ConstId;
31 #[salsa::interned] 35 #[salsa::interned]
32 fn intern_static(&self, loc: ItemLoc<ast::StaticDef>) -> crate::StaticId; 36 fn intern_static(&self, loc: StaticLoc) -> StaticId;
33 #[salsa::interned] 37 #[salsa::interned]
34 fn intern_trait(&self, loc: ItemLoc<ast::TraitDef>) -> crate::TraitId; 38 fn intern_trait(&self, loc: ItemLoc<ast::TraitDef>) -> TraitId;
35 #[salsa::interned] 39 #[salsa::interned]
36 fn intern_type_alias(&self, loc: crate::TypeAliasLoc) -> crate::TypeAliasId; 40 fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId;
37 #[salsa::interned] 41 #[salsa::interned]
38 fn intern_impl(&self, loc: ItemLoc<ast::ImplBlock>) -> crate::ImplId; 42 fn intern_impl(&self, loc: ItemLoc<ast::ImplBlock>) -> ImplId;
39} 43}
40 44
41#[salsa::query_group(DefDatabase2Storage)] 45#[salsa::query_group(DefDatabaseStorage)]
42pub trait DefDatabase2: InternDatabase + AstDatabase { 46pub trait DefDatabase: InternDatabase + AstDatabase {
43 #[salsa::invoke(RawItems::raw_items_with_source_map_query)] 47 #[salsa::invoke(RawItems::raw_items_with_source_map_query)]
44 fn raw_items_with_source_map( 48 fn raw_items_with_source_map(
45 &self, 49 &self,
@@ -64,6 +68,18 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
64 #[salsa::invoke(TraitData::trait_data_query)] 68 #[salsa::invoke(TraitData::trait_data_query)]
65 fn trait_data(&self, e: TraitId) -> Arc<TraitData>; 69 fn trait_data(&self, e: TraitId) -> Arc<TraitData>;
66 70
71 #[salsa::invoke(TypeAliasData::type_alias_data_query)]
72 fn type_alias_data(&self, e: TypeAliasId) -> Arc<TypeAliasData>;
73
74 #[salsa::invoke(FunctionData::fn_data_query)]
75 fn function_data(&self, func: FunctionId) -> Arc<FunctionData>;
76
77 #[salsa::invoke(ConstData::const_data_query)]
78 fn const_data(&self, konst: ConstId) -> Arc<ConstData>;
79
80 #[salsa::invoke(ConstData::static_data_query)]
81 fn static_data(&self, konst: StaticId) -> Arc<ConstData>;
82
67 #[salsa::invoke(Body::body_with_source_map_query)] 83 #[salsa::invoke(Body::body_with_source_map_query)]
68 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>); 84 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>);
69 85
@@ -75,4 +91,21 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
75 91
76 #[salsa::invoke(GenericParams::generic_params_query)] 92 #[salsa::invoke(GenericParams::generic_params_query)]
77 fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>; 93 fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>;
94
95 #[salsa::invoke(Attrs::attrs_query)]
96 fn attrs(&self, def: AttrDefId) -> Attrs;
97
98 #[salsa::invoke(LangItems::module_lang_items_query)]
99 fn module_lang_items(&self, module: ModuleId) -> Option<Arc<LangItems>>;
100
101 #[salsa::invoke(LangItems::crate_lang_items_query)]
102 fn crate_lang_items(&self, krate: CrateId) -> Arc<LangItems>;
103
104 #[salsa::invoke(LangItems::lang_item_query)]
105 fn lang_item(&self, start_crate: CrateId, item: SmolStr) -> Option<LangItemTarget>;
106
107 // FIXME(https://github.com/rust-analyzer/rust-analyzer/issues/2148#issuecomment-550519102)
108 // Remove this query completely, in favor of `Attrs::docs` method
109 #[salsa::invoke(Documentation::documentation_query)]
110 fn documentation(&self, def: AttrDefId) -> Option<Documentation>;
78} 111}
diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs
new file mode 100644
index 000000000..90a8627bc
--- /dev/null
+++ b/crates/ra_hir_def/src/docs.rs
@@ -0,0 +1,71 @@
1//! Defines hir documentation.
2//!
3//! This really shouldn't exist, instead, we should deshugar doc comments into attributes, see
4//! https://github.com/rust-analyzer/rust-analyzer/issues/2148#issuecomment-550519102
5
6use std::sync::Arc;
7
8use hir_expand::either::Either;
9use ra_syntax::ast;
10
11use crate::{db::DefDatabase, AdtId, AstItemDef, AttrDefId, HasChildSource, HasSource, Lookup};
12
13/// Holds documentation
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub struct Documentation(Arc<str>);
16
17impl Into<String> for Documentation {
18 fn into(self) -> String {
19 self.as_str().to_owned()
20 }
21}
22
23impl Documentation {
24 fn new(s: &str) -> Documentation {
25 Documentation(s.into())
26 }
27
28 pub fn as_str(&self) -> &str {
29 &*self.0
30 }
31
32 pub(crate) fn documentation_query(
33 db: &impl DefDatabase,
34 def: AttrDefId,
35 ) -> Option<Documentation> {
36 match def {
37 AttrDefId::ModuleId(module) => {
38 let def_map = db.crate_def_map(module.krate);
39 let src = def_map[module.module_id].declaration_source(db)?;
40 docs_from_ast(&src.value)
41 }
42 AttrDefId::StructFieldId(it) => {
43 let src = it.parent.child_source(db);
44 match &src.value[it.local_id] {
45 Either::A(_tuple) => None,
46 Either::B(record) => docs_from_ast(record),
47 }
48 }
49 AttrDefId::AdtId(it) => match it {
50 AdtId::StructId(it) => docs_from_ast(&it.0.source(db).value),
51 AdtId::EnumId(it) => docs_from_ast(&it.source(db).value),
52 AdtId::UnionId(it) => docs_from_ast(&it.0.source(db).value),
53 },
54 AttrDefId::EnumVariantId(it) => {
55 let src = it.parent.child_source(db);
56 docs_from_ast(&src.value[it.local_id])
57 }
58 AttrDefId::TraitId(it) => docs_from_ast(&it.source(db).value),
59 AttrDefId::MacroDefId(it) => docs_from_ast(&it.ast_id.to_node(db)),
60 AttrDefId::ConstId(it) => docs_from_ast(&it.lookup(db).source(db).value),
61 AttrDefId::StaticId(it) => docs_from_ast(&it.lookup(db).source(db).value),
62 AttrDefId::FunctionId(it) => docs_from_ast(&it.lookup(db).source(db).value),
63 AttrDefId::TypeAliasId(it) => docs_from_ast(&it.lookup(db).source(db).value),
64 AttrDefId::ImplId(_) => None,
65 }
66 }
67}
68
69pub(crate) fn docs_from_ast(node: &impl ast::DocCommentsOwner) -> Option<Documentation> {
70 node.doc_comment_text().map(|it| Documentation::new(&it))
71}
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
index 9e2e4c3cc..015fe772e 100644
--- a/crates/ra_hir_def/src/generics.rs
+++ b/crates/ra_hir_def/src/generics.rs
@@ -8,7 +8,7 @@ use hir_expand::name::{self, AsName, Name};
8use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; 8use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
9 9
10use crate::{ 10use crate::{
11 db::DefDatabase2, 11 db::DefDatabase,
12 type_ref::{TypeBound, TypeRef}, 12 type_ref::{TypeBound, TypeRef},
13 AdtId, AstItemDef, ContainerId, GenericDefId, HasSource, Lookup, 13 AdtId, AstItemDef, ContainerId, GenericDefId, HasSource, Lookup,
14}; 14};
@@ -42,7 +42,7 @@ pub struct WherePredicate {
42 42
43impl GenericParams { 43impl GenericParams {
44 pub(crate) fn generic_params_query( 44 pub(crate) fn generic_params_query(
45 db: &impl DefDatabase2, 45 db: &impl DefDatabase,
46 def: GenericDefId, 46 def: GenericDefId,
47 ) -> Arc<GenericParams> { 47 ) -> Arc<GenericParams> {
48 let parent_generics = parent_generic_def(db, def).map(|it| db.generic_params(it)); 48 let parent_generics = parent_generic_def(db, def).map(|it| db.generic_params(it));
@@ -50,7 +50,7 @@ impl GenericParams {
50 } 50 }
51 51
52 fn new( 52 fn new(
53 db: &impl DefDatabase2, 53 db: &impl DefDatabase,
54 def: GenericDefId, 54 def: GenericDefId,
55 parent_params: Option<Arc<GenericParams>>, 55 parent_params: Option<Arc<GenericParams>>,
56 ) -> GenericParams { 56 ) -> GenericParams {
@@ -168,7 +168,7 @@ impl GenericParams {
168 } 168 }
169} 169}
170 170
171fn parent_generic_def(db: &impl DefDatabase2, def: GenericDefId) -> Option<GenericDefId> { 171fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option<GenericDefId> {
172 let container = match def { 172 let container = match def {
173 GenericDefId::FunctionId(it) => it.lookup(db).container, 173 GenericDefId::FunctionId(it) => it.lookup(db).container,
174 GenericDefId::TypeAliasId(it) => it.lookup(db).container, 174 GenericDefId::TypeAliasId(it) => it.lookup(db).container,
diff --git a/crates/ra_hir_def/src/impls.rs b/crates/ra_hir_def/src/impls.rs
deleted file mode 100644
index 750a869f2..000000000
--- a/crates/ra_hir_def/src/impls.rs
+++ /dev/null
@@ -1,86 +0,0 @@
1//! Defines hir-level representation of impls.
2//!
3//! The handling is similar, but is not quite the same as for other items,
4//! because `impl`s don't have names.
5
6use std::sync::Arc;
7
8use hir_expand::AstId;
9use ra_syntax::ast;
10
11use crate::{
12 db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstLoc, ContainerId,
13 FunctionLoc, ImplId, Intern, TypeAliasLoc,
14};
15
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct ImplData {
18 target_trait: Option<TypeRef>,
19 target_type: TypeRef,
20 items: Vec<AssocItemId>,
21 negative: bool,
22}
23
24impl ImplData {
25 pub(crate) fn impl_data_query(db: &impl DefDatabase2, id: ImplId) -> Arc<ImplData> {
26 let src = id.source(db);
27 let items = db.ast_id_map(src.file_id);
28
29 let target_trait = src.value.target_trait().map(TypeRef::from_ast);
30 let target_type = TypeRef::from_ast_opt(src.value.target_type());
31 let negative = src.value.is_negative();
32
33 let items = if let Some(item_list) = src.value.item_list() {
34 item_list
35 .impl_items()
36 .map(|item_node| match item_node {
37 ast::ImplItem::FnDef(it) => {
38 let def = FunctionLoc {
39 container: ContainerId::ImplId(id),
40 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
41 }
42 .intern(db);
43 def.into()
44 }
45 ast::ImplItem::ConstDef(it) => {
46 let def = ConstLoc {
47 container: ContainerId::ImplId(id),
48 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
49 }
50 .intern(db);
51 def.into()
52 }
53 ast::ImplItem::TypeAliasDef(it) => {
54 let def = TypeAliasLoc {
55 container: ContainerId::ImplId(id),
56 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
57 }
58 .intern(db);
59 def.into()
60 }
61 })
62 .collect()
63 } else {
64 Vec::new()
65 };
66
67 let res = ImplData { target_trait, target_type, items, negative };
68 Arc::new(res)
69 }
70
71 pub fn target_trait(&self) -> Option<&TypeRef> {
72 self.target_trait.as_ref()
73 }
74
75 pub fn target_type(&self) -> &TypeRef {
76 &self.target_type
77 }
78
79 pub fn items(&self) -> &[AssocItemId] {
80 &self.items
81 }
82
83 pub fn is_negative(&self) -> bool {
84 self.negative
85 }
86}
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..f15c23db9
--- /dev/null
+++ b/crates/ra_hir_def/src/lang_item.rs
@@ -0,0 +1,121 @@
1//! Collects lang items: items marked with `#[lang = "..."]` attribute.
2//!
3//! This attribute to tell the compiler about semi built-in std library
4//! features, such as Fn family of traits.
5use std::sync::Arc;
6
7use ra_syntax::SmolStr;
8use rustc_hash::FxHashMap;
9
10use crate::{
11 db::DefDatabase, AdtId, AttrDefId, CrateId, EnumId, FunctionId, ImplId, ModuleDefId, ModuleId,
12 StaticId, StructId, TraitId,
13};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16pub enum LangItemTarget {
17 EnumId(EnumId),
18 FunctionId(FunctionId),
19 ImplBlockId(ImplId),
20 StaticId(StaticId),
21 StructId(StructId),
22 TraitId(TraitId),
23}
24
25#[derive(Default, Debug, Clone, PartialEq, Eq)]
26pub struct LangItems {
27 items: FxHashMap<SmolStr, LangItemTarget>,
28}
29
30impl LangItems {
31 pub fn target<'a>(&'a self, item: &str) -> Option<&'a LangItemTarget> {
32 self.items.get(item)
33 }
34
35 /// Salsa query. This will look for lang items in a specific crate.
36 pub(crate) fn crate_lang_items_query(db: &impl DefDatabase, 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 .iter()
44 .filter_map(|(module_id, _)| db.module_lang_items(ModuleId { krate, module_id }))
45 .for_each(|it| lang_items.items.extend(it.items.iter().map(|(k, v)| (k.clone(), *v))));
46
47 Arc::new(lang_items)
48 }
49
50 pub(crate) fn module_lang_items_query(
51 db: &impl DefDatabase,
52 module: ModuleId,
53 ) -> Option<Arc<LangItems>> {
54 let mut lang_items = LangItems::default();
55 lang_items.collect_lang_items(db, module);
56 if lang_items.items.is_empty() {
57 None
58 } else {
59 Some(Arc::new(lang_items))
60 }
61 }
62
63 /// Salsa query. Look for a lang item, starting from the specified crate and recursively
64 /// traversing its dependencies.
65 pub(crate) fn lang_item_query(
66 db: &impl DefDatabase,
67 start_crate: CrateId,
68 item: SmolStr,
69 ) -> Option<LangItemTarget> {
70 let lang_items = db.crate_lang_items(start_crate);
71 let start_crate_target = lang_items.items.get(&item);
72 if let Some(target) = start_crate_target {
73 return Some(*target);
74 }
75 db.crate_graph()
76 .dependencies(start_crate)
77 .find_map(|dep| db.lang_item(dep.crate_id, item.clone()))
78 }
79
80 fn collect_lang_items(&mut self, db: &impl DefDatabase, module: ModuleId) {
81 // Look for impl targets
82 let def_map = db.crate_def_map(module.krate);
83 let module_data = &def_map[module.module_id];
84 for &impl_block in module_data.impls.iter() {
85 self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlockId)
86 }
87
88 for def in module_data.scope.declarations() {
89 match def {
90 ModuleDefId::TraitId(trait_) => {
91 self.collect_lang_item(db, trait_, LangItemTarget::TraitId)
92 }
93 ModuleDefId::AdtId(AdtId::EnumId(e)) => {
94 self.collect_lang_item(db, e, LangItemTarget::EnumId)
95 }
96 ModuleDefId::AdtId(AdtId::StructId(s)) => {
97 self.collect_lang_item(db, s, LangItemTarget::StructId)
98 }
99 ModuleDefId::FunctionId(f) => {
100 self.collect_lang_item(db, f, LangItemTarget::FunctionId)
101 }
102 ModuleDefId::StaticId(s) => self.collect_lang_item(db, s, LangItemTarget::StaticId),
103 _ => {}
104 }
105 }
106 }
107
108 fn collect_lang_item<T>(
109 &mut self,
110 db: &impl DefDatabase,
111 item: T,
112 constructor: fn(T) -> LangItemTarget,
113 ) where
114 T: Into<AttrDefId> + Copy,
115 {
116 let attrs = db.attrs(item.into());
117 if let Some(lang_item_name) = attrs.by_key("lang").string_value() {
118 self.items.entry(lang_item_name.clone()).or_insert_with(|| constructor(item));
119 }
120 }
121}
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index d579f5c7e..8e8c2d749 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -8,121 +8,56 @@
8//! actually true. 8//! actually true.
9 9
10pub mod db; 10pub mod db;
11
11pub mod attr; 12pub mod attr;
12pub mod path; 13pub mod path;
13pub mod type_ref; 14pub mod type_ref;
14pub mod builtin_type; 15pub mod builtin_type;
15pub mod adt;
16pub mod impls;
17pub mod diagnostics; 16pub mod diagnostics;
17pub mod per_ns;
18
19pub mod adt;
20pub mod data;
21pub mod generics;
22pub mod lang_item;
23pub mod docs;
24
18pub mod expr; 25pub mod expr;
19pub mod body; 26pub mod body;
20pub mod generics;
21pub mod traits;
22pub mod resolver; 27pub mod resolver;
23 28
29mod trace;
30mod nameres;
31
24#[cfg(test)] 32#[cfg(test)]
25mod test_db; 33mod test_db;
26#[cfg(test)] 34#[cfg(test)]
27mod marks; 35mod marks;
28 36
29// FIXME: this should be private
30pub mod nameres;
31
32use std::hash::{Hash, Hasher}; 37use std::hash::{Hash, Hasher};
33 38
34use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, Source}; 39use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, MacroDefId, Source};
35use ra_arena::{impl_arena_id, RawId}; 40use ra_arena::{impl_arena_id, map::ArenaMap, RawId};
36use ra_db::{salsa, CrateId, FileId}; 41use ra_db::{impl_intern_key, salsa, CrateId};
37use ra_syntax::{ast, AstNode, SyntaxNode}; 42use ra_syntax::{ast, AstNode};
38 43
39use crate::{builtin_type::BuiltinType, db::InternDatabase}; 44use crate::{builtin_type::BuiltinType, db::InternDatabase};
40 45
41pub enum ModuleSource { 46#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
42 SourceFile(ast::SourceFile), 47pub struct LocalImportId(RawId);
43 Module(ast::Module), 48impl_arena_id!(LocalImportId);
44}
45
46impl ModuleSource {
47 pub fn new(
48 db: &impl db::DefDatabase2,
49 file_id: Option<FileId>,
50 decl_id: Option<AstId<ast::Module>>,
51 ) -> ModuleSource {
52 match (file_id, decl_id) {
53 (Some(file_id), _) => {
54 let source_file = db.parse(file_id).tree();
55 ModuleSource::SourceFile(source_file)
56 }
57 (None, Some(item_id)) => {
58 let module = item_id.to_node(db);
59 assert!(module.item_list().is_some(), "expected inline module");
60 ModuleSource::Module(module)
61 }
62 (None, None) => panic!(),
63 }
64 }
65
66 // FIXME: this methods do not belong here
67 pub fn from_position(
68 db: &impl db::DefDatabase2,
69 position: ra_db::FilePosition,
70 ) -> ModuleSource {
71 let parse = db.parse(position.file_id);
72 match &ra_syntax::algo::find_node_at_offset::<ast::Module>(
73 parse.tree().syntax(),
74 position.offset,
75 ) {
76 Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()),
77 _ => {
78 let source_file = parse.tree();
79 ModuleSource::SourceFile(source_file)
80 }
81 }
82 }
83
84 pub fn from_child_node(db: &impl db::DefDatabase2, child: Source<&SyntaxNode>) -> ModuleSource {
85 if let Some(m) =
86 child.value.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi())
87 {
88 ModuleSource::Module(m)
89 } else {
90 let file_id = child.file_id.original_file(db);
91 let source_file = db.parse(file_id).tree();
92 ModuleSource::SourceFile(source_file)
93 }
94 }
95
96 pub fn from_file_id(db: &impl db::DefDatabase2, file_id: FileId) -> ModuleSource {
97 let source_file = db.parse(file_id).tree();
98 ModuleSource::SourceFile(source_file)
99 }
100}
101 49
102#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 50#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
103pub struct ModuleId { 51pub struct ModuleId {
104 pub krate: CrateId, 52 pub krate: CrateId,
105 pub module_id: CrateModuleId, 53 pub module_id: LocalModuleId,
106} 54}
107 55
108/// An ID of a module, **local** to a specific crate 56/// An ID of a module, **local** to a specific crate
109// FIXME: rename to `LocalModuleId`. 57// FIXME: rename to `LocalModuleId`.
110#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 58#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
111pub struct CrateModuleId(RawId); 59pub struct LocalModuleId(RawId);
112impl_arena_id!(CrateModuleId); 60impl_arena_id!(LocalModuleId);
113
114macro_rules! impl_intern_key {
115 ($name:ident) => {
116 impl salsa::InternKey for $name {
117 fn from_intern_id(v: salsa::InternId) -> Self {
118 $name(v)
119 }
120 fn as_intern_id(&self) -> salsa::InternId {
121 self.0
122 }
123 }
124 };
125}
126 61
127#[derive(Debug)] 62#[derive(Debug)]
128pub struct ItemLoc<N: AstNode> { 63pub struct ItemLoc<N: AstNode> {
@@ -162,25 +97,10 @@ impl<'a, DB> LocationCtx<&'a DB> {
162 } 97 }
163} 98}
164 99
165impl<'a, DB: AstDatabase + InternDatabase> LocationCtx<&'a DB> {
166 pub fn to_def<N, DEF>(self, ast: &N) -> DEF
167 where
168 N: AstNode,
169 DEF: AstItemDef<N>,
170 {
171 DEF::from_ast(self, ast)
172 }
173}
174
175pub trait AstItemDef<N: AstNode>: salsa::InternKey + Clone { 100pub trait AstItemDef<N: AstNode>: salsa::InternKey + Clone {
176 fn intern(db: &impl InternDatabase, loc: ItemLoc<N>) -> Self; 101 fn intern(db: &impl InternDatabase, loc: ItemLoc<N>) -> Self;
177 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<N>; 102 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<N>;
178 103
179 fn from_ast(ctx: LocationCtx<&(impl AstDatabase + InternDatabase)>, ast: &N) -> Self {
180 let items = ctx.db.ast_id_map(ctx.file_id);
181 let item_id = items.ast_id(ast);
182 Self::from_ast_id(ctx, item_id)
183 }
184 fn from_ast_id(ctx: LocationCtx<&impl InternDatabase>, ast_id: FileAstId<N>) -> Self { 104 fn from_ast_id(ctx: LocationCtx<&impl InternDatabase>, ast_id: FileAstId<N>) -> Self {
185 let loc = ItemLoc { module: ctx.module, ast_id: AstId::new(ctx.file_id, ast_id) }; 105 let loc = ItemLoc { module: ctx.module, ast_id: AstId::new(ctx.file_id, ast_id) };
186 Self::intern(ctx.db, loc) 106 Self::intern(ctx.db, loc)
@@ -208,14 +128,14 @@ pub struct FunctionLoc {
208 128
209impl Intern for FunctionLoc { 129impl Intern for FunctionLoc {
210 type ID = FunctionId; 130 type ID = FunctionId;
211 fn intern(self, db: &impl db::DefDatabase2) -> FunctionId { 131 fn intern(self, db: &impl db::DefDatabase) -> FunctionId {
212 db.intern_function(self) 132 db.intern_function(self)
213 } 133 }
214} 134}
215 135
216impl Lookup for FunctionId { 136impl Lookup for FunctionId {
217 type Data = FunctionLoc; 137 type Data = FunctionLoc;
218 fn lookup(&self, db: &impl db::DefDatabase2) -> FunctionLoc { 138 fn lookup(&self, db: &impl db::DefDatabase) -> FunctionLoc {
219 db.lookup_intern_function(*self) 139 db.lookup_intern_function(*self)
220 } 140 }
221} 141}
@@ -272,15 +192,9 @@ pub struct LocalEnumVariantId(RawId);
272impl_arena_id!(LocalEnumVariantId); 192impl_arena_id!(LocalEnumVariantId);
273 193
274#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 194#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
275pub enum VariantId {
276 EnumVariantId(EnumVariantId),
277 StructId(StructId),
278}
279
280#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
281pub struct StructFieldId { 195pub struct StructFieldId {
282 parent: VariantId, 196 pub parent: VariantId,
283 local_id: LocalStructFieldId, 197 pub local_id: LocalStructFieldId,
284} 198}
285 199
286#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 200#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -298,14 +212,14 @@ pub struct ConstLoc {
298 212
299impl Intern for ConstLoc { 213impl Intern for ConstLoc {
300 type ID = ConstId; 214 type ID = ConstId;
301 fn intern(self, db: &impl db::DefDatabase2) -> ConstId { 215 fn intern(self, db: &impl db::DefDatabase) -> ConstId {
302 db.intern_const(self) 216 db.intern_const(self)
303 } 217 }
304} 218}
305 219
306impl Lookup for ConstId { 220impl Lookup for ConstId {
307 type Data = ConstLoc; 221 type Data = ConstLoc;
308 fn lookup(&self, db: &impl db::DefDatabase2) -> ConstLoc { 222 fn lookup(&self, db: &impl db::DefDatabase) -> ConstLoc {
309 db.lookup_intern_const(*self) 223 db.lookup_intern_const(*self)
310 } 224 }
311} 225}
@@ -313,12 +227,24 @@ impl Lookup for ConstId {
313#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 227#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
314pub struct StaticId(salsa::InternId); 228pub struct StaticId(salsa::InternId);
315impl_intern_key!(StaticId); 229impl_intern_key!(StaticId);
316impl AstItemDef<ast::StaticDef> for StaticId { 230
317 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::StaticDef>) -> Self { 231#[derive(Debug, Clone, PartialEq, Eq, Hash)]
318 db.intern_static(loc) 232pub struct StaticLoc {
233 pub container: ModuleId,
234 pub ast_id: AstId<ast::StaticDef>,
235}
236
237impl Intern for StaticLoc {
238 type ID = StaticId;
239 fn intern(self, db: &impl db::DefDatabase) -> StaticId {
240 db.intern_static(self)
319 } 241 }
320 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::StaticDef> { 242}
321 db.lookup_intern_static(self) 243
244impl Lookup for StaticId {
245 type Data = StaticLoc;
246 fn lookup(&self, db: &impl db::DefDatabase) -> StaticLoc {
247 db.lookup_intern_static(*self)
322 } 248 }
323} 249}
324 250
@@ -346,14 +272,14 @@ pub struct TypeAliasLoc {
346 272
347impl Intern for TypeAliasLoc { 273impl Intern for TypeAliasLoc {
348 type ID = TypeAliasId; 274 type ID = TypeAliasId;
349 fn intern(self, db: &impl db::DefDatabase2) -> TypeAliasId { 275 fn intern(self, db: &impl db::DefDatabase) -> TypeAliasId {
350 db.intern_type_alias(self) 276 db.intern_type_alias(self)
351 } 277 }
352} 278}
353 279
354impl Lookup for TypeAliasId { 280impl Lookup for TypeAliasId {
355 type Data = TypeAliasLoc; 281 type Data = TypeAliasLoc;
356 fn lookup(&self, db: &impl db::DefDatabase2) -> TypeAliasLoc { 282 fn lookup(&self, db: &impl db::DefDatabase) -> TypeAliasLoc {
357 db.lookup_intern_type_alias(*self) 283 db.lookup_intern_type_alias(*self)
358 } 284 }
359} 285}
@@ -476,22 +402,58 @@ impl_froms!(
476 ConstId 402 ConstId
477); 403);
478 404
405#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
406pub enum AttrDefId {
407 ModuleId(ModuleId),
408 StructFieldId(StructFieldId),
409 AdtId(AdtId),
410 FunctionId(FunctionId),
411 EnumVariantId(EnumVariantId),
412 StaticId(StaticId),
413 ConstId(ConstId),
414 TraitId(TraitId),
415 TypeAliasId(TypeAliasId),
416 MacroDefId(MacroDefId),
417 ImplId(ImplId),
418}
419
420impl_froms!(
421 AttrDefId: ModuleId,
422 StructFieldId,
423 AdtId(StructId, EnumId, UnionId),
424 EnumVariantId,
425 StaticId,
426 ConstId,
427 FunctionId,
428 TraitId,
429 TypeAliasId,
430 MacroDefId,
431 ImplId
432);
433
434#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
435pub enum VariantId {
436 EnumVariantId(EnumVariantId),
437 StructId(StructId),
438}
439impl_froms!(VariantId: EnumVariantId, StructId);
440
479trait Intern { 441trait Intern {
480 type ID; 442 type ID;
481 fn intern(self, db: &impl db::DefDatabase2) -> Self::ID; 443 fn intern(self, db: &impl db::DefDatabase) -> Self::ID;
482} 444}
483 445
484pub trait Lookup { 446pub trait Lookup {
485 type Data; 447 type Data;
486 fn lookup(&self, db: &impl db::DefDatabase2) -> Self::Data; 448 fn lookup(&self, db: &impl db::DefDatabase) -> Self::Data;
487} 449}
488 450
489pub trait HasModule { 451pub trait HasModule {
490 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId; 452 fn module(&self, db: &impl db::DefDatabase) -> ModuleId;
491} 453}
492 454
493impl HasModule for FunctionLoc { 455impl HasModule for FunctionLoc {
494 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId { 456 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
495 match self.container { 457 match self.container {
496 ContainerId::ModuleId(it) => it, 458 ContainerId::ModuleId(it) => it,
497 ContainerId::ImplId(it) => it.module(db), 459 ContainerId::ImplId(it) => it.module(db),
@@ -501,7 +463,7 @@ impl HasModule for FunctionLoc {
501} 463}
502 464
503impl HasModule for TypeAliasLoc { 465impl HasModule for TypeAliasLoc {
504 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId { 466 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
505 match self.container { 467 match self.container {
506 ContainerId::ModuleId(it) => it, 468 ContainerId::ModuleId(it) => it,
507 ContainerId::ImplId(it) => it.module(db), 469 ContainerId::ImplId(it) => it.module(db),
@@ -511,7 +473,7 @@ impl HasModule for TypeAliasLoc {
511} 473}
512 474
513impl HasModule for ConstLoc { 475impl HasModule for ConstLoc {
514 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId { 476 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
515 match self.container { 477 match self.container {
516 ContainerId::ModuleId(it) => it, 478 ContainerId::ModuleId(it) => it,
517 ContainerId::ImplId(it) => it.module(db), 479 ContainerId::ImplId(it) => it.module(db),
@@ -520,15 +482,31 @@ impl HasModule for ConstLoc {
520 } 482 }
521} 483}
522 484
485impl HasModule for AdtId {
486 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
487 match self {
488 AdtId::StructId(it) => it.0.module(db),
489 AdtId::UnionId(it) => it.0.module(db),
490 AdtId::EnumId(it) => it.module(db),
491 }
492 }
493}
494
495impl HasModule for StaticLoc {
496 fn module(&self, _db: &impl db::DefDatabase) -> ModuleId {
497 self.container
498 }
499}
500
523pub trait HasSource { 501pub trait HasSource {
524 type Value; 502 type Value;
525 fn source(&self, db: &impl db::DefDatabase2) -> Source<Self::Value>; 503 fn source(&self, db: &impl db::DefDatabase) -> Source<Self::Value>;
526} 504}
527 505
528impl HasSource for FunctionLoc { 506impl HasSource for FunctionLoc {
529 type Value = ast::FnDef; 507 type Value = ast::FnDef;
530 508
531 fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::FnDef> { 509 fn source(&self, db: &impl db::DefDatabase) -> Source<ast::FnDef> {
532 let node = self.ast_id.to_node(db); 510 let node = self.ast_id.to_node(db);
533 Source::new(self.ast_id.file_id(), node) 511 Source::new(self.ast_id.file_id(), node)
534 } 512 }
@@ -537,7 +515,7 @@ impl HasSource for FunctionLoc {
537impl HasSource for TypeAliasLoc { 515impl HasSource for TypeAliasLoc {
538 type Value = ast::TypeAliasDef; 516 type Value = ast::TypeAliasDef;
539 517
540 fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::TypeAliasDef> { 518 fn source(&self, db: &impl db::DefDatabase) -> Source<ast::TypeAliasDef> {
541 let node = self.ast_id.to_node(db); 519 let node = self.ast_id.to_node(db);
542 Source::new(self.ast_id.file_id(), node) 520 Source::new(self.ast_id.file_id(), node)
543 } 521 }
@@ -546,8 +524,26 @@ impl HasSource for TypeAliasLoc {
546impl HasSource for ConstLoc { 524impl HasSource for ConstLoc {
547 type Value = ast::ConstDef; 525 type Value = ast::ConstDef;
548 526
549 fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::ConstDef> { 527 fn source(&self, db: &impl db::DefDatabase) -> Source<ast::ConstDef> {
550 let node = self.ast_id.to_node(db); 528 let node = self.ast_id.to_node(db);
551 Source::new(self.ast_id.file_id(), node) 529 Source::new(self.ast_id.file_id(), node)
552 } 530 }
553} 531}
532
533impl HasSource for StaticLoc {
534 type Value = ast::StaticDef;
535
536 fn source(&self, db: &impl db::DefDatabase) -> Source<ast::StaticDef> {
537 let node = self.ast_id.to_node(db);
538 Source::new(self.ast_id.file_id(), node)
539 }
540}
541
542pub trait HasChildSource {
543 type ChildId;
544 type Value;
545 fn child_source(
546 &self,
547 db: &impl db::DefDatabase,
548 ) -> Source<ArenaMap<Self::ChildId, Self::Value>>;
549}
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs
index c01e020ef..2359386c2 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -47,8 +47,7 @@
47//! path and, upon success, we run macro expansion and "collect module" phase on 47//! path and, upon success, we run macro expansion and "collect module" phase on
48//! the result 48//! the result
49 49
50pub mod raw; 50pub(crate) mod raw;
51pub mod per_ns;
52mod collector; 51mod collector;
53mod mod_resolution; 52mod mod_resolution;
54mod path_resolution; 53mod path_resolution;
@@ -58,70 +57,63 @@ mod tests;
58 57
59use std::sync::Arc; 58use std::sync::Arc;
60 59
61use hir_expand::{ast_id_map::FileAstId, diagnostics::DiagnosticSink, name::Name, MacroDefId}; 60use hir_expand::{
61 ast_id_map::FileAstId, diagnostics::DiagnosticSink, either::Either, name::Name, MacroDefId,
62 Source,
63};
62use once_cell::sync::Lazy; 64use once_cell::sync::Lazy;
63use ra_arena::Arena; 65use ra_arena::Arena;
64use ra_db::{CrateId, Edition, FileId}; 66use ra_db::{CrateId, Edition, FileId};
65use ra_prof::profile; 67use ra_prof::profile;
66use ra_syntax::ast; 68use ra_syntax::ast;
67use rustc_hash::{FxHashMap, FxHashSet}; 69use rustc_hash::FxHashMap;
68 70
69use crate::{ 71use crate::{
70 builtin_type::BuiltinType, 72 builtin_type::BuiltinType,
71 db::DefDatabase2, 73 db::DefDatabase,
72 nameres::{ 74 nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
73 diagnostics::DefDiagnostic, path_resolution::ResolveMode, per_ns::PerNs, raw::ImportId,
74 },
75 path::Path, 75 path::Path,
76 AstId, CrateModuleId, FunctionId, ImplId, ModuleDefId, ModuleId, TraitId, 76 per_ns::PerNs,
77 AstId, FunctionId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId,
77}; 78};
78 79
79/// Contains all top-level defs from a macro-expanded crate 80/// Contains all top-level defs from a macro-expanded crate
80#[derive(Debug, PartialEq, Eq)] 81#[derive(Debug, PartialEq, Eq)]
81pub struct CrateDefMap { 82pub struct CrateDefMap {
82 krate: CrateId, 83 pub root: LocalModuleId,
83 edition: Edition, 84 pub modules: Arena<LocalModuleId, ModuleData>,
85 pub(crate) krate: CrateId,
84 /// The prelude module for this crate. This either comes from an import 86 /// The prelude module for this crate. This either comes from an import
85 /// marked with the `prelude_import` attribute, or (in the normal case) from 87 /// marked with the `prelude_import` attribute, or (in the normal case) from
86 /// a dependency (`std` or `core`). 88 /// a dependency (`std` or `core`).
87 prelude: Option<ModuleId>, 89 pub(crate) prelude: Option<ModuleId>,
88 extern_prelude: FxHashMap<Name, ModuleDefId>, 90 pub(crate) extern_prelude: FxHashMap<Name, ModuleDefId>,
89 root: CrateModuleId,
90 modules: Arena<CrateModuleId, ModuleData>,
91
92 /// Some macros are not well-behavior, which leads to infinite loop
93 /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } }
94 /// We mark it down and skip it in collector
95 ///
96 /// FIXME:
97 /// Right now it only handle a poison macro in a single crate,
98 /// such that if other crate try to call that macro,
99 /// the whole process will do again until it became poisoned in that crate.
100 /// We should handle this macro set globally
101 /// However, do we want to put it as a global variable?
102 poison_macros: FxHashSet<MacroDefId>,
103 91
92 edition: Edition,
104 diagnostics: Vec<DefDiagnostic>, 93 diagnostics: Vec<DefDiagnostic>,
105} 94}
106 95
107impl std::ops::Index<CrateModuleId> for CrateDefMap { 96impl std::ops::Index<LocalModuleId> for CrateDefMap {
108 type Output = ModuleData; 97 type Output = ModuleData;
109 fn index(&self, id: CrateModuleId) -> &ModuleData { 98 fn index(&self, id: LocalModuleId) -> &ModuleData {
110 &self.modules[id] 99 &self.modules[id]
111 } 100 }
112} 101}
113 102
114#[derive(Default, Debug, PartialEq, Eq)] 103#[derive(Default, Debug, PartialEq, Eq)]
115pub struct ModuleData { 104pub struct ModuleData {
116 pub parent: Option<CrateModuleId>, 105 pub parent: Option<LocalModuleId>,
117 pub children: FxHashMap<Name, CrateModuleId>, 106 pub children: FxHashMap<Name, LocalModuleId>,
118 pub scope: ModuleScope, 107 pub scope: ModuleScope,
108
109 // FIXME: these can't be both null, we need a three-state enum here.
119 /// None for root 110 /// None for root
120 pub declaration: Option<AstId<ast::Module>>, 111 pub declaration: Option<AstId<ast::Module>>,
121 /// None for inline modules. 112 /// None for inline modules.
122 /// 113 ///
123 /// Note that non-inline modules, by definition, live inside non-macro file. 114 /// Note that non-inline modules, by definition, live inside non-macro file.
124 pub definition: Option<FileId>, 115 pub definition: Option<FileId>,
116
125 pub impls: Vec<ImplId>, 117 pub impls: Vec<ImplId>,
126} 118}
127 119
@@ -177,7 +169,7 @@ impl ModuleScope {
177 pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { 169 pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
178 self.items 170 self.items
179 .iter() 171 .iter()
180 .filter_map(|(name, res)| res.def.get_macros().map(|macro_| (name, macro_))) 172 .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_)))
181 } 173 }
182 174
183 /// Iterate over all legacy textual scoped macros visable at the end of the module 175 /// Iterate over all legacy textual scoped macros visable at the end of the module
@@ -207,21 +199,21 @@ pub struct Resolution {
207 /// None for unresolved 199 /// None for unresolved
208 pub def: PerNs, 200 pub def: PerNs,
209 /// ident by which this is imported into local scope. 201 /// ident by which this is imported into local scope.
210 pub import: Option<ImportId>, 202 pub import: Option<LocalImportId>,
211} 203}
212 204
213impl CrateDefMap { 205impl CrateDefMap {
214 pub(crate) fn crate_def_map_query( 206 pub(crate) fn crate_def_map_query(
215 // Note that this doesn't have `+ AstDatabase`! 207 // Note that this doesn't have `+ AstDatabase`!
216 // This gurantess that `CrateDefMap` is stable across reparses. 208 // This gurantess that `CrateDefMap` is stable across reparses.
217 db: &impl DefDatabase2, 209 db: &impl DefDatabase,
218 krate: CrateId, 210 krate: CrateId,
219 ) -> Arc<CrateDefMap> { 211 ) -> Arc<CrateDefMap> {
220 let _p = profile("crate_def_map_query"); 212 let _p = profile("crate_def_map_query");
221 let def_map = { 213 let def_map = {
222 let crate_graph = db.crate_graph(); 214 let crate_graph = db.crate_graph();
223 let edition = crate_graph.edition(krate); 215 let edition = crate_graph.edition(krate);
224 let mut modules: Arena<CrateModuleId, ModuleData> = Arena::default(); 216 let mut modules: Arena<LocalModuleId, ModuleData> = Arena::default();
225 let root = modules.alloc(ModuleData::default()); 217 let root = modules.alloc(ModuleData::default());
226 CrateDefMap { 218 CrateDefMap {
227 krate, 219 krate,
@@ -230,7 +222,6 @@ impl CrateDefMap {
230 prelude: None, 222 prelude: None,
231 root, 223 root,
232 modules, 224 modules,
233 poison_macros: FxHashSet::default(),
234 diagnostics: Vec::new(), 225 diagnostics: Vec::new(),
235 } 226 }
236 }; 227 };
@@ -238,50 +229,53 @@ impl CrateDefMap {
238 Arc::new(def_map) 229 Arc::new(def_map)
239 } 230 }
240 231
241 pub fn krate(&self) -> CrateId {
242 self.krate
243 }
244
245 pub fn root(&self) -> CrateModuleId {
246 self.root
247 }
248
249 pub fn prelude(&self) -> Option<ModuleId> {
250 self.prelude
251 }
252
253 pub fn extern_prelude(&self) -> &FxHashMap<Name, ModuleDefId> {
254 &self.extern_prelude
255 }
256
257 pub fn add_diagnostics( 232 pub fn add_diagnostics(
258 &self, 233 &self,
259 db: &impl DefDatabase2, 234 db: &impl DefDatabase,
260 module: CrateModuleId, 235 module: LocalModuleId,
261 sink: &mut DiagnosticSink, 236 sink: &mut DiagnosticSink,
262 ) { 237 ) {
263 self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink)) 238 self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink))
264 } 239 }
265 240
266 pub fn resolve_path( 241 pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ {
242 self.modules
243 .iter()
244 .filter(move |(_id, data)| data.definition == Some(file_id))
245 .map(|(id, _data)| id)
246 }
247
248 pub(crate) fn resolve_path(
267 &self, 249 &self,
268 db: &impl DefDatabase2, 250 db: &impl DefDatabase,
269 original_module: CrateModuleId, 251 original_module: LocalModuleId,
270 path: &Path, 252 path: &Path,
271 ) -> (PerNs, Option<usize>) { 253 ) -> (PerNs, Option<usize>) {
272 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path); 254 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path);
273 (res.resolved_def, res.segment_index) 255 (res.resolved_def, res.segment_index)
274 } 256 }
257}
275 258
276 pub fn modules(&self) -> impl Iterator<Item = CrateModuleId> + '_ { 259impl ModuleData {
277 self.modules.iter().map(|(id, _data)| id) 260 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
261 pub fn definition_source(
262 &self,
263 db: &impl DefDatabase,
264 ) -> Source<Either<ast::SourceFile, ast::Module>> {
265 if let Some(file_id) = self.definition {
266 let sf = db.parse(file_id).tree();
267 return Source::new(file_id.into(), Either::A(sf));
268 }
269 let decl = self.declaration.unwrap();
270 Source::new(decl.file_id(), Either::B(decl.to_node(db)))
278 } 271 }
279 272
280 pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = CrateModuleId> + '_ { 273 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
281 self.modules 274 /// `None` for the crate root.
282 .iter() 275 pub fn declaration_source(&self, db: &impl DefDatabase) -> Option<Source<ast::Module>> {
283 .filter(move |(_id, data)| data.definition == Some(file_id)) 276 let decl = self.declaration?;
284 .map(|(id, _data)| id) 277 let value = decl.to_node(db);
278 Some(Source { file_id: decl.file_id(), value })
285 } 279 }
286} 280}
287 281
@@ -290,12 +284,12 @@ mod diagnostics {
290 use ra_db::RelativePathBuf; 284 use ra_db::RelativePathBuf;
291 use ra_syntax::{ast, AstPtr}; 285 use ra_syntax::{ast, AstPtr};
292 286
293 use crate::{db::DefDatabase2, diagnostics::UnresolvedModule, nameres::CrateModuleId, AstId}; 287 use crate::{db::DefDatabase, diagnostics::UnresolvedModule, nameres::LocalModuleId, AstId};
294 288
295 #[derive(Debug, PartialEq, Eq)] 289 #[derive(Debug, PartialEq, Eq)]
296 pub(super) enum DefDiagnostic { 290 pub(super) enum DefDiagnostic {
297 UnresolvedModule { 291 UnresolvedModule {
298 module: CrateModuleId, 292 module: LocalModuleId,
299 declaration: AstId<ast::Module>, 293 declaration: AstId<ast::Module>,
300 candidate: RelativePathBuf, 294 candidate: RelativePathBuf,
301 }, 295 },
@@ -304,8 +298,8 @@ mod diagnostics {
304 impl DefDiagnostic { 298 impl DefDiagnostic {
305 pub(super) fn add_to( 299 pub(super) fn add_to(
306 &self, 300 &self,
307 db: &impl DefDatabase2, 301 db: &impl DefDatabase,
308 target_module: CrateModuleId, 302 target_module: LocalModuleId,
309 sink: &mut DiagnosticSink, 303 sink: &mut DiagnosticSink,
310 ) { 304 ) {
311 match self { 305 match self {
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index aae3dcadf..41becf8df 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -1,4 +1,7 @@
1//! FIXME: write short doc here 1//! The core of the module-level name resolution algorithm.
2//!
3//! `DefCollector::collect` contains the fixed-point iteration loop which
4//! resolves imports and expands macros.
2 5
3use hir_expand::{ 6use hir_expand::{
4 builtin_macro::find_builtin_macro, 7 builtin_macro::find_builtin_macro,
@@ -7,24 +10,25 @@ use hir_expand::{
7}; 10};
8use ra_cfg::CfgOptions; 11use ra_cfg::CfgOptions;
9use ra_db::{CrateId, FileId}; 12use ra_db::{CrateId, FileId};
10use ra_syntax::{ast, SmolStr}; 13use ra_syntax::ast;
11use rustc_hash::FxHashMap; 14use rustc_hash::{FxHashMap, FxHashSet};
12use test_utils::tested_by; 15use test_utils::tested_by;
13 16
14use crate::{ 17use crate::{
15 attr::Attr, 18 attr::Attrs,
16 db::DefDatabase2, 19 db::DefDatabase,
17 nameres::{ 20 nameres::{
18 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, 21 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
19 per_ns::PerNs, raw, CrateDefMap, ModuleData, Resolution, ResolveMode, 22 raw, CrateDefMap, ModuleData, Resolution, ResolveMode,
20 }, 23 },
21 path::{Path, PathKind}, 24 path::{Path, PathKind},
22 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, CrateModuleId, EnumId, EnumVariantId, 25 per_ns::PerNs,
23 FunctionLoc, ImplId, Intern, LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, 26 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplId,
27 Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructId,
24 StructOrUnionId, TraitId, TypeAliasLoc, UnionId, 28 StructOrUnionId, TraitId, TypeAliasLoc, UnionId,
25}; 29};
26 30
27pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap { 31pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
28 let crate_graph = db.crate_graph(); 32 let crate_graph = db.crate_graph();
29 33
30 // populate external prelude 34 // populate external prelude
@@ -56,6 +60,7 @@ pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) ->
56 unexpanded_macros: Vec::new(), 60 unexpanded_macros: Vec::new(),
57 mod_dirs: FxHashMap::default(), 61 mod_dirs: FxHashMap::default(),
58 macro_stack_monitor: MacroStackMonitor::default(), 62 macro_stack_monitor: MacroStackMonitor::default(),
63 poison_macros: FxHashSet::default(),
59 cfg_options, 64 cfg_options,
60 }; 65 };
61 collector.collect(); 66 collector.collect();
@@ -94,21 +99,32 @@ impl MacroStackMonitor {
94struct DefCollector<'a, DB> { 99struct DefCollector<'a, DB> {
95 db: &'a DB, 100 db: &'a DB,
96 def_map: CrateDefMap, 101 def_map: CrateDefMap,
97 glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>, 102 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, LocalImportId)>>,
98 unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>, 103 unresolved_imports: Vec<(LocalModuleId, LocalImportId, raw::ImportData)>,
99 unexpanded_macros: Vec<(CrateModuleId, AstId<ast::MacroCall>, Path)>, 104 unexpanded_macros: Vec<(LocalModuleId, AstId<ast::MacroCall>, Path)>,
100 mod_dirs: FxHashMap<CrateModuleId, ModDir>, 105 mod_dirs: FxHashMap<LocalModuleId, ModDir>,
101 106
102 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly 107 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly
103 /// To prevent stack overflow, we add a deep counter here for prevent that. 108 /// To prevent stack overflow, we add a deep counter here for prevent that.
104 macro_stack_monitor: MacroStackMonitor, 109 macro_stack_monitor: MacroStackMonitor,
110 /// Some macros are not well-behavior, which leads to infinite loop
111 /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } }
112 /// We mark it down and skip it in collector
113 ///
114 /// FIXME:
115 /// Right now it only handle a poison macro in a single crate,
116 /// such that if other crate try to call that macro,
117 /// the whole process will do again until it became poisoned in that crate.
118 /// We should handle this macro set globally
119 /// However, do we want to put it as a global variable?
120 poison_macros: FxHashSet<MacroDefId>,
105 121
106 cfg_options: &'a CfgOptions, 122 cfg_options: &'a CfgOptions,
107} 123}
108 124
109impl<DB> DefCollector<'_, DB> 125impl<DB> DefCollector<'_, DB>
110where 126where
111 DB: DefDatabase2, 127 DB: DefDatabase,
112{ 128{
113 fn collect(&mut self) { 129 fn collect(&mut self) {
114 let crate_graph = self.db.crate_graph(); 130 let crate_graph = self.db.crate_graph();
@@ -173,7 +189,7 @@ where
173 /// ``` 189 /// ```
174 fn define_macro( 190 fn define_macro(
175 &mut self, 191 &mut self,
176 module_id: CrateModuleId, 192 module_id: LocalModuleId,
177 name: Name, 193 name: Name,
178 macro_: MacroDefId, 194 macro_: MacroDefId,
179 export: bool, 195 export: bool,
@@ -200,7 +216,7 @@ where
200 /// the definition of current module. 216 /// the definition of current module.
201 /// And also, `macro_use` on a module will import all legacy macros visable inside to 217 /// And also, `macro_use` on a module will import all legacy macros visable inside to
202 /// current legacy scope, with possible shadowing. 218 /// current legacy scope, with possible shadowing.
203 fn define_legacy_macro(&mut self, module_id: CrateModuleId, name: Name, macro_: MacroDefId) { 219 fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, macro_: MacroDefId) {
204 // Always shadowing 220 // Always shadowing
205 self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_); 221 self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_);
206 } 222 }
@@ -208,7 +224,7 @@ where
208 /// Import macros from `#[macro_use] extern crate`. 224 /// Import macros from `#[macro_use] extern crate`.
209 fn import_macros_from_extern_crate( 225 fn import_macros_from_extern_crate(
210 &mut self, 226 &mut self,
211 current_module_id: CrateModuleId, 227 current_module_id: LocalModuleId,
212 import: &raw::ImportData, 228 import: &raw::ImportData,
213 ) { 229 ) {
214 log::debug!( 230 log::debug!(
@@ -235,7 +251,7 @@ where
235 /// Exported macros are just all macros in the root module scope. 251 /// Exported macros are just all macros in the root module scope.
236 /// Note that it contains not only all `#[macro_export]` macros, but also all aliases 252 /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
237 /// created by `use` in the root module, ignoring the visibility of `use`. 253 /// created by `use` in the root module, ignoring the visibility of `use`.
238 fn import_all_macros_exported(&mut self, current_module_id: CrateModuleId, krate: CrateId) { 254 fn import_all_macros_exported(&mut self, current_module_id: LocalModuleId, krate: CrateId) {
239 let def_map = self.db.crate_def_map(krate); 255 let def_map = self.db.crate_def_map(krate);
240 for (name, def) in def_map[def_map.root].scope.macros() { 256 for (name, def) in def_map[def_map.root].scope.macros() {
241 // `macro_use` only bring things into legacy scope. 257 // `macro_use` only bring things into legacy scope.
@@ -265,7 +281,7 @@ where
265 281
266 fn resolve_import( 282 fn resolve_import(
267 &self, 283 &self,
268 module_id: CrateModuleId, 284 module_id: LocalModuleId,
269 import: &raw::ImportData, 285 import: &raw::ImportData,
270 ) -> (PerNs, ReachedFixedPoint) { 286 ) -> (PerNs, ReachedFixedPoint) {
271 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); 287 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
@@ -291,9 +307,9 @@ where
291 307
292 fn record_resolved_import( 308 fn record_resolved_import(
293 &mut self, 309 &mut self,
294 module_id: CrateModuleId, 310 module_id: LocalModuleId,
295 def: PerNs, 311 def: PerNs,
296 import_id: raw::ImportId, 312 import_id: LocalImportId,
297 import: &raw::ImportData, 313 import: &raw::ImportData,
298 ) { 314 ) {
299 if import.is_glob { 315 if import.is_glob {
@@ -387,8 +403,8 @@ where
387 403
388 fn update( 404 fn update(
389 &mut self, 405 &mut self,
390 module_id: CrateModuleId, 406 module_id: LocalModuleId,
391 import: Option<raw::ImportId>, 407 import: Option<LocalImportId>,
392 resolutions: &[(Name, Resolution)], 408 resolutions: &[(Name, Resolution)],
393 ) { 409 ) {
394 self.update_recursive(module_id, import, resolutions, 0) 410 self.update_recursive(module_id, import, resolutions, 0)
@@ -396,8 +412,8 @@ where
396 412
397 fn update_recursive( 413 fn update_recursive(
398 &mut self, 414 &mut self,
399 module_id: CrateModuleId, 415 module_id: LocalModuleId,
400 import: Option<raw::ImportId>, 416 import: Option<LocalImportId>,
401 resolutions: &[(Name, Resolution)], 417 resolutions: &[(Name, Resolution)],
402 depth: usize, 418 depth: usize,
403 ) { 419 ) {
@@ -463,7 +479,7 @@ where
463 path, 479 path,
464 ); 480 );
465 481
466 if let Some(def) = resolved_res.resolved_def.get_macros() { 482 if let Some(def) = resolved_res.resolved_def.take_macros() {
467 let call_id = self.db.intern_macro(MacroCallLoc { def, ast_id: *ast_id }); 483 let call_id = self.db.intern_macro(MacroCallLoc { def, ast_id: *ast_id });
468 resolved.push((*module_id, call_id, def)); 484 resolved.push((*module_id, call_id, def));
469 res = ReachedFixedPoint::No; 485 res = ReachedFixedPoint::No;
@@ -484,11 +500,11 @@ where
484 500
485 fn collect_macro_expansion( 501 fn collect_macro_expansion(
486 &mut self, 502 &mut self,
487 module_id: CrateModuleId, 503 module_id: LocalModuleId,
488 macro_call_id: MacroCallId, 504 macro_call_id: MacroCallId,
489 macro_def_id: MacroDefId, 505 macro_def_id: MacroDefId,
490 ) { 506 ) {
491 if self.def_map.poison_macros.contains(&macro_def_id) { 507 if self.poison_macros.contains(&macro_def_id) {
492 return; 508 return;
493 } 509 }
494 510
@@ -508,7 +524,7 @@ where
508 .collect(raw_items.items()); 524 .collect(raw_items.items());
509 } else { 525 } else {
510 log::error!("Too deep macro expansion: {:?}", macro_call_id); 526 log::error!("Too deep macro expansion: {:?}", macro_call_id);
511 self.def_map.poison_macros.insert(macro_def_id); 527 self.poison_macros.insert(macro_def_id);
512 } 528 }
513 529
514 self.macro_stack_monitor.decrease(macro_def_id); 530 self.macro_stack_monitor.decrease(macro_def_id);
@@ -522,7 +538,7 @@ where
522/// Walks a single module, populating defs, imports and macros 538/// Walks a single module, populating defs, imports and macros
523struct ModCollector<'a, D> { 539struct ModCollector<'a, D> {
524 def_collector: D, 540 def_collector: D,
525 module_id: CrateModuleId, 541 module_id: LocalModuleId,
526 file_id: HirFileId, 542 file_id: HirFileId,
527 raw_items: &'a raw::RawItems, 543 raw_items: &'a raw::RawItems,
528 mod_dir: ModDir, 544 mod_dir: ModDir,
@@ -530,7 +546,7 @@ struct ModCollector<'a, D> {
530 546
531impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>> 547impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>>
532where 548where
533 DB: DefDatabase2, 549 DB: DefDatabase,
534{ 550{
535 fn collect(&mut self, items: &[raw::RawItem]) { 551 fn collect(&mut self, items: &[raw::RawItem]) {
536 // Note: don't assert that inserted value is fresh: it's simply not true 552 // Note: don't assert that inserted value is fresh: it's simply not true
@@ -549,7 +565,7 @@ where
549 // `#[macro_use] extern crate` is hoisted to imports macros before collecting 565 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
550 // any other items. 566 // any other items.
551 for item in items { 567 for item in items {
552 if self.is_cfg_enabled(item.attrs()) { 568 if self.is_cfg_enabled(&item.attrs) {
553 if let raw::RawItemKind::Import(import_id) = item.kind { 569 if let raw::RawItemKind::Import(import_id) = item.kind {
554 let import = self.raw_items[import_id].clone(); 570 let import = self.raw_items[import_id].clone();
555 if import.is_extern_crate && import.is_macro_use { 571 if import.is_extern_crate && import.is_macro_use {
@@ -560,10 +576,10 @@ where
560 } 576 }
561 577
562 for item in items { 578 for item in items {
563 if self.is_cfg_enabled(item.attrs()) { 579 if self.is_cfg_enabled(&item.attrs) {
564 match item.kind { 580 match item.kind {
565 raw::RawItemKind::Module(m) => { 581 raw::RawItemKind::Module(m) => {
566 self.collect_module(&self.raw_items[m], item.attrs()) 582 self.collect_module(&self.raw_items[m], &item.attrs)
567 } 583 }
568 raw::RawItemKind::Import(import_id) => self 584 raw::RawItemKind::Import(import_id) => self
569 .def_collector 585 .def_collector
@@ -585,9 +601,9 @@ where
585 } 601 }
586 } 602 }
587 603
588 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &[Attr]) { 604 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &Attrs) {
589 let path_attr = self.path_attr(attrs); 605 let path_attr = attrs.by_key("path").string_value();
590 let is_macro_use = self.is_macro_use(attrs); 606 let is_macro_use = attrs.by_key("macro_use").exists();
591 match module { 607 match module {
592 // inline module, just recurse 608 // inline module, just recurse
593 raw::ModuleData::Definition { name, items, ast_id } => { 609 raw::ModuleData::Definition { name, items, ast_id } => {
@@ -647,7 +663,7 @@ where
647 name: Name, 663 name: Name,
648 declaration: AstId<ast::Module>, 664 declaration: AstId<ast::Module>,
649 definition: Option<FileId>, 665 definition: Option<FileId>,
650 ) -> CrateModuleId { 666 ) -> LocalModuleId {
651 let modules = &mut self.def_collector.def_map.modules; 667 let modules = &mut self.def_collector.def_map.modules;
652 let res = modules.alloc(ModuleData::default()); 668 let res = modules.alloc(ModuleData::default());
653 modules[res].parent = Some(self.module_id); 669 modules[res].parent = Some(self.module_id);
@@ -702,7 +718,10 @@ where
702 PerNs::values(def.into()) 718 PerNs::values(def.into())
703 } 719 }
704 raw::DefKind::Static(ast_id) => { 720 raw::DefKind::Static(ast_id) => {
705 PerNs::values(StaticId::from_ast_id(ctx, ast_id).into()) 721 let def = StaticLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) }
722 .intern(self.def_collector.db);
723
724 PerNs::values(def.into())
706 } 725 }
707 raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()), 726 raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()),
708 raw::DefKind::TypeAlias(ast_id) => { 727 raw::DefKind::TypeAlias(ast_id) => {
@@ -772,23 +791,19 @@ where
772 self.def_collector.unexpanded_macros.push((self.module_id, ast_id, path)); 791 self.def_collector.unexpanded_macros.push((self.module_id, ast_id, path));
773 } 792 }
774 793
775 fn import_all_legacy_macros(&mut self, module_id: CrateModuleId) { 794 fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
776 let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone(); 795 let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone();
777 for (name, macro_) in macros { 796 for (name, macro_) in macros {
778 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_); 797 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
779 } 798 }
780 } 799 }
781 800
782 fn is_cfg_enabled(&self, attrs: &[Attr]) -> bool { 801 fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
783 attrs.iter().all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false)) 802 // FIXME: handle cfg_attr :-)
784 } 803 attrs
785 804 .by_key("cfg")
786 fn path_attr<'a>(&self, attrs: &'a [Attr]) -> Option<&'a SmolStr> { 805 .tt_values()
787 attrs.iter().find_map(|attr| attr.as_path()) 806 .all(|tt| self.def_collector.cfg_options.is_cfg_enabled(tt) != Some(false))
788 }
789
790 fn is_macro_use<'a>(&self, attrs: &'a [Attr]) -> bool {
791 attrs.iter().any(|attr| attr.is_simple_atom("macro_use"))
792 } 807 }
793} 808}
794 809
@@ -802,15 +817,15 @@ mod tests {
802 use ra_db::{fixture::WithFixture, SourceDatabase}; 817 use ra_db::{fixture::WithFixture, SourceDatabase};
803 use rustc_hash::FxHashSet; 818 use rustc_hash::FxHashSet;
804 819
805 use crate::{db::DefDatabase2, test_db::TestDB}; 820 use crate::{db::DefDatabase, test_db::TestDB};
806 821
807 use super::*; 822 use super::*;
808 823
809 fn do_collect_defs( 824 fn do_collect_defs(
810 db: &impl DefDatabase2, 825 db: &impl DefDatabase,
811 def_map: CrateDefMap, 826 def_map: CrateDefMap,
812 monitor: MacroStackMonitor, 827 monitor: MacroStackMonitor,
813 ) -> CrateDefMap { 828 ) -> (CrateDefMap, FxHashSet<MacroDefId>) {
814 let mut collector = DefCollector { 829 let mut collector = DefCollector {
815 db, 830 db,
816 def_map, 831 def_map,
@@ -819,19 +834,24 @@ mod tests {
819 unexpanded_macros: Vec::new(), 834 unexpanded_macros: Vec::new(),
820 mod_dirs: FxHashMap::default(), 835 mod_dirs: FxHashMap::default(),
821 macro_stack_monitor: monitor, 836 macro_stack_monitor: monitor,
837 poison_macros: FxHashSet::default(),
822 cfg_options: &CfgOptions::default(), 838 cfg_options: &CfgOptions::default(),
823 }; 839 };
824 collector.collect(); 840 collector.collect();
825 collector.finish() 841 (collector.def_map, collector.poison_macros)
826 } 842 }
827 843
828 fn do_limited_resolve(code: &str, limit: u32, poison_limit: u32) -> CrateDefMap { 844 fn do_limited_resolve(
845 code: &str,
846 limit: u32,
847 poison_limit: u32,
848 ) -> (CrateDefMap, FxHashSet<MacroDefId>) {
829 let (db, _file_id) = TestDB::with_single_file(&code); 849 let (db, _file_id) = TestDB::with_single_file(&code);
830 let krate = db.test_crate(); 850 let krate = db.test_crate();
831 851
832 let def_map = { 852 let def_map = {
833 let edition = db.crate_graph().edition(krate); 853 let edition = db.crate_graph().edition(krate);
834 let mut modules: Arena<CrateModuleId, ModuleData> = Arena::default(); 854 let mut modules: Arena<LocalModuleId, ModuleData> = Arena::default();
835 let root = modules.alloc(ModuleData::default()); 855 let root = modules.alloc(ModuleData::default());
836 CrateDefMap { 856 CrateDefMap {
837 krate, 857 krate,
@@ -840,7 +860,6 @@ mod tests {
840 prelude: None, 860 prelude: None,
841 root, 861 root,
842 modules, 862 modules,
843 poison_macros: FxHashSet::default(),
844 diagnostics: Vec::new(), 863 diagnostics: Vec::new(),
845 } 864 }
846 }; 865 };
@@ -870,7 +889,7 @@ foo!(KABOOM);
870 889
871 #[test] 890 #[test]
872 fn test_macro_expand_poisoned() { 891 fn test_macro_expand_poisoned() {
873 let def = do_limited_resolve( 892 let (_, poison_macros) = do_limited_resolve(
874 r#" 893 r#"
875 macro_rules! foo { 894 macro_rules! foo {
876 ($ty:ty) => { foo!($ty); } 895 ($ty:ty) => { foo!($ty); }
@@ -881,12 +900,12 @@ foo!(KABOOM);
881 16, 900 16,
882 ); 901 );
883 902
884 assert_eq!(def.poison_macros.len(), 1); 903 assert_eq!(poison_macros.len(), 1);
885 } 904 }
886 905
887 #[test] 906 #[test]
888 fn test_macro_expand_normal() { 907 fn test_macro_expand_normal() {
889 let def = do_limited_resolve( 908 let (_, poison_macros) = do_limited_resolve(
890 r#" 909 r#"
891 macro_rules! foo { 910 macro_rules! foo {
892 ($ident:ident) => { struct $ident {} } 911 ($ident:ident) => { struct $ident {} }
@@ -897,6 +916,6 @@ foo!(Bar);
897 16, 916 16,
898 ); 917 );
899 918
900 assert_eq!(def.poison_macros.len(), 0); 919 assert_eq!(poison_macros.len(), 0);
901 } 920 }
902} 921}
diff --git a/crates/ra_hir_def/src/nameres/mod_resolution.rs b/crates/ra_hir_def/src/nameres/mod_resolution.rs
index b3b1379d0..14fb8ba3a 100644
--- a/crates/ra_hir_def/src/nameres/mod_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/mod_resolution.rs
@@ -3,7 +3,7 @@ use hir_expand::name::Name;
3use ra_db::{FileId, RelativePathBuf}; 3use ra_db::{FileId, RelativePathBuf};
4use ra_syntax::SmolStr; 4use ra_syntax::SmolStr;
5 5
6use crate::{db::DefDatabase2, HirFileId}; 6use crate::{db::DefDatabase, HirFileId};
7 7
8#[derive(Clone, Debug)] 8#[derive(Clone, Debug)]
9pub(super) struct ModDir { 9pub(super) struct ModDir {
@@ -40,7 +40,7 @@ impl ModDir {
40 40
41 pub(super) fn resolve_declaration( 41 pub(super) fn resolve_declaration(
42 &self, 42 &self,
43 db: &impl DefDatabase2, 43 db: &impl DefDatabase,
44 file_id: HirFileId, 44 file_id: HirFileId,
45 name: &Name, 45 name: &Name,
46 attr_path: Option<&SmolStr>, 46 attr_path: Option<&SmolStr>,
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs
index 95692f826..9455f22bb 100644
--- a/crates/ra_hir_def/src/nameres/path_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/path_resolution.rs
@@ -15,10 +15,11 @@ use ra_db::Edition;
15use test_utils::tested_by; 15use test_utils::tested_by;
16 16
17use crate::{ 17use crate::{
18 db::DefDatabase2, 18 db::DefDatabase,
19 nameres::{per_ns::PerNs, CrateDefMap}, 19 nameres::CrateDefMap,
20 path::{Path, PathKind}, 20 path::{Path, PathKind},
21 AdtId, CrateModuleId, EnumVariantId, ModuleDefId, ModuleId, 21 per_ns::PerNs,
22 AdtId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId,
22}; 23};
23 24
24#[derive(Debug, Clone, Copy, PartialEq, Eq)] 25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -63,9 +64,9 @@ impl CrateDefMap {
63 // the result. 64 // the result.
64 pub(super) fn resolve_path_fp_with_macro( 65 pub(super) fn resolve_path_fp_with_macro(
65 &self, 66 &self,
66 db: &impl DefDatabase2, 67 db: &impl DefDatabase,
67 mode: ResolveMode, 68 mode: ResolveMode,
68 original_module: CrateModuleId, 69 original_module: LocalModuleId,
69 path: &Path, 70 path: &Path,
70 ) -> ResolvePathResult { 71 ) -> ResolvePathResult {
71 let mut segments = path.segments.iter().enumerate(); 72 let mut segments = path.segments.iter().enumerate();
@@ -216,8 +217,8 @@ impl CrateDefMap {
216 217
217 fn resolve_name_in_module( 218 fn resolve_name_in_module(
218 &self, 219 &self,
219 db: &impl DefDatabase2, 220 db: &impl DefDatabase,
220 module: CrateModuleId, 221 module: LocalModuleId,
221 name: &Name, 222 name: &Name,
222 ) -> PerNs { 223 ) -> PerNs {
223 // Resolve in: 224 // Resolve in:
@@ -243,7 +244,7 @@ impl CrateDefMap {
243 from_crate_root.or(from_extern_prelude) 244 from_crate_root.or(from_extern_prelude)
244 } 245 }
245 246
246 fn resolve_in_prelude(&self, db: &impl DefDatabase2, name: &Name) -> PerNs { 247 fn resolve_in_prelude(&self, db: &impl DefDatabase, name: &Name) -> PerNs {
247 if let Some(prelude) = self.prelude { 248 if let Some(prelude) = self.prelude {
248 let keep; 249 let keep;
249 let def_map = if prelude.krate == self.krate { 250 let def_map = if prelude.krate == self.krate {
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 7c68fd638..401af031c 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -1,4 +1,9 @@
1//! FIXME: write short doc here 1//! Lowers syntax tree of a rust file into a raw representation of containing
2//! items, *without* attaching them to a module structure.
3//!
4//! That is, raw items don't have semantics, just as syntax, but, unlike syntax,
5//! they don't change with trivial source code edits, making them a great tool
6//! for building salsa recomputation firewalls.
2 7
3use std::{ops::Index, sync::Arc}; 8use std::{ops::Index, sync::Arc};
4 9
@@ -12,11 +17,14 @@ use hir_expand::{
12use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; 17use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
13use ra_syntax::{ 18use ra_syntax::{
14 ast::{self, AttrsOwner, NameOwner}, 19 ast::{self, AttrsOwner, NameOwner},
15 AstNode, AstPtr, SourceFile, 20 AstNode, AstPtr,
16}; 21};
17use test_utils::tested_by; 22use test_utils::tested_by;
18 23
19use crate::{attr::Attr, db::DefDatabase2, path::Path, FileAstId, HirFileId, ModuleSource, Source}; 24use crate::{
25 attr::Attrs, db::DefDatabase, path::Path, trace::Trace, FileAstId, HirFileId, LocalImportId,
26 Source,
27};
20 28
21/// `RawItems` is a set of top-level items in a file (except for impls). 29/// `RawItems` is a set of top-level items in a file (except for impls).
22/// 30///
@@ -25,7 +33,7 @@ use crate::{attr::Attr, db::DefDatabase2, path::Path, FileAstId, HirFileId, Modu
25#[derive(Debug, Default, PartialEq, Eq)] 33#[derive(Debug, Default, PartialEq, Eq)]
26pub struct RawItems { 34pub struct RawItems {
27 modules: Arena<Module, ModuleData>, 35 modules: Arena<Module, ModuleData>,
28 imports: Arena<ImportId, ImportData>, 36 imports: Arena<LocalImportId, ImportData>,
29 defs: Arena<Def, DefData>, 37 defs: Arena<Def, DefData>,
30 macros: Arena<Macro, MacroData>, 38 macros: Arena<Macro, MacroData>,
31 impls: Arena<Impl, ImplData>, 39 impls: Arena<Impl, ImplData>,
@@ -35,47 +43,33 @@ pub struct RawItems {
35 43
36#[derive(Debug, Default, PartialEq, Eq)] 44#[derive(Debug, Default, PartialEq, Eq)]
37pub struct ImportSourceMap { 45pub struct ImportSourceMap {
38 map: ArenaMap<ImportId, ImportSourcePtr>, 46 map: ArenaMap<LocalImportId, ImportSourcePtr>,
39} 47}
40 48
41type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>; 49type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>;
42type ImportSource = Either<ast::UseTree, ast::ExternCrateItem>;
43
44fn to_node(ptr: ImportSourcePtr, file: &SourceFile) -> ImportSource {
45 ptr.map(|ptr| ptr.to_node(file.syntax()), |ptr| ptr.to_node(file.syntax()))
46}
47 50
48impl ImportSourceMap { 51impl ImportSourceMap {
49 fn insert(&mut self, import: ImportId, ptr: ImportSourcePtr) { 52 pub fn get(&self, import: LocalImportId) -> ImportSourcePtr {
50 self.map.insert(import, ptr) 53 self.map[import].clone()
51 }
52
53 pub fn get(&self, source: &ModuleSource, import: ImportId) -> ImportSource {
54 let file = match source {
55 ModuleSource::SourceFile(file) => file.clone(),
56 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
57 };
58
59 to_node(self.map[import], &file)
60 } 54 }
61} 55}
62 56
63impl RawItems { 57impl RawItems {
64 pub(crate) fn raw_items_query( 58 pub(crate) fn raw_items_query(
65 db: &(impl DefDatabase2 + AstDatabase), 59 db: &(impl DefDatabase + AstDatabase),
66 file_id: HirFileId, 60 file_id: HirFileId,
67 ) -> Arc<RawItems> { 61 ) -> Arc<RawItems> {
68 db.raw_items_with_source_map(file_id).0 62 db.raw_items_with_source_map(file_id).0
69 } 63 }
70 64
71 pub(crate) fn raw_items_with_source_map_query( 65 pub(crate) fn raw_items_with_source_map_query(
72 db: &(impl DefDatabase2 + AstDatabase), 66 db: &(impl DefDatabase + AstDatabase),
73 file_id: HirFileId, 67 file_id: HirFileId,
74 ) -> (Arc<RawItems>, Arc<ImportSourceMap>) { 68 ) -> (Arc<RawItems>, Arc<ImportSourceMap>) {
75 let mut collector = RawItemsCollector { 69 let mut collector = RawItemsCollector {
76 raw_items: RawItems::default(), 70 raw_items: RawItems::default(),
77 source_ast_id_map: db.ast_id_map(file_id), 71 source_ast_id_map: db.ast_id_map(file_id),
78 source_map: ImportSourceMap::default(), 72 imports: Trace::new(),
79 file_id, 73 file_id,
80 hygiene: Hygiene::new(db, file_id), 74 hygiene: Hygiene::new(db, file_id),
81 }; 75 };
@@ -86,7 +80,11 @@ impl RawItems {
86 collector.process_module(None, item_list); 80 collector.process_module(None, item_list);
87 } 81 }
88 } 82 }
89 (Arc::new(collector.raw_items), Arc::new(collector.source_map)) 83 let mut raw_items = collector.raw_items;
84 let (arena, map) = collector.imports.into_arena_and_map();
85 raw_items.imports = arena;
86 let source_map = ImportSourceMap { map };
87 (Arc::new(raw_items), Arc::new(source_map))
90 } 88 }
91 89
92 pub(super) fn items(&self) -> &[RawItem] { 90 pub(super) fn items(&self) -> &[RawItem] {
@@ -101,9 +99,9 @@ impl Index<Module> for RawItems {
101 } 99 }
102} 100}
103 101
104impl Index<ImportId> for RawItems { 102impl Index<LocalImportId> for RawItems {
105 type Output = ImportData; 103 type Output = ImportData;
106 fn index(&self, idx: ImportId) -> &ImportData { 104 fn index(&self, idx: LocalImportId) -> &ImportData {
107 &self.imports[idx] 105 &self.imports[idx]
108 } 106 }
109} 107}
@@ -129,25 +127,16 @@ impl Index<Impl> for RawItems {
129 } 127 }
130} 128}
131 129
132// Avoid heap allocation on items without attributes.
133type Attrs = Option<Arc<[Attr]>>;
134
135#[derive(Debug, PartialEq, Eq, Clone)] 130#[derive(Debug, PartialEq, Eq, Clone)]
136pub(super) struct RawItem { 131pub(super) struct RawItem {
137 attrs: Attrs, 132 pub(super) attrs: Attrs,
138 pub(super) kind: RawItemKind, 133 pub(super) kind: RawItemKind,
139} 134}
140 135
141impl RawItem {
142 pub(super) fn attrs(&self) -> &[Attr] {
143 self.attrs.as_ref().map_or(&[], |it| &*it)
144 }
145}
146
147#[derive(Debug, PartialEq, Eq, Clone, Copy)] 136#[derive(Debug, PartialEq, Eq, Clone, Copy)]
148pub(super) enum RawItemKind { 137pub(super) enum RawItemKind {
149 Module(Module), 138 Module(Module),
150 Import(ImportId), 139 Import(LocalImportId),
151 Def(Def), 140 Def(Def),
152 Macro(Macro), 141 Macro(Macro),
153 Impl(Impl), 142 Impl(Impl),
@@ -163,10 +152,6 @@ pub(super) enum ModuleData {
163 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> }, 152 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> },
164} 153}
165 154
166#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
167pub struct ImportId(RawId);
168impl_arena_id!(ImportId);
169
170#[derive(Debug, Clone, PartialEq, Eq)] 155#[derive(Debug, Clone, PartialEq, Eq)]
171pub struct ImportData { 156pub struct ImportData {
172 pub(super) path: Path, 157 pub(super) path: Path,
@@ -223,8 +208,8 @@ pub(super) struct ImplData {
223 208
224struct RawItemsCollector { 209struct RawItemsCollector {
225 raw_items: RawItems, 210 raw_items: RawItems,
211 imports: Trace<LocalImportId, ImportData, ImportSourcePtr>,
226 source_ast_id_map: Arc<AstIdMap>, 212 source_ast_id_map: Arc<AstIdMap>,
227 source_map: ImportSourceMap,
228 file_id: HirFileId, 213 file_id: HirFileId,
229 hygiene: Hygiene, 214 hygiene: Hygiene,
230} 215}
@@ -408,8 +393,7 @@ impl RawItemsCollector {
408 data: ImportData, 393 data: ImportData,
409 source: ImportSourcePtr, 394 source: ImportSourcePtr,
410 ) { 395 ) {
411 let import = self.raw_items.imports.alloc(data); 396 let import = self.imports.alloc(|| source, || data);
412 self.source_map.insert(import, source);
413 self.push_item(current_module, attrs, RawItemKind::Import(import)) 397 self.push_item(current_module, attrs, RawItemKind::Import(import))
414 } 398 }
415 399
@@ -425,6 +409,6 @@ impl RawItemsCollector {
425 } 409 }
426 410
427 fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { 411 fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs {
428 Attr::from_attrs_owner(item, &self.hygiene) 412 Attrs::new(item, &self.hygiene)
429 } 413 }
430} 414}
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs
index 256f7d4be..f502f1cb3 100644
--- a/crates/ra_hir_def/src/nameres/tests.rs
+++ b/crates/ra_hir_def/src/nameres/tests.rs
@@ -10,7 +10,7 @@ use insta::assert_snapshot;
10use ra_db::{fixture::WithFixture, SourceDatabase}; 10use ra_db::{fixture::WithFixture, SourceDatabase};
11use test_utils::covers; 11use test_utils::covers;
12 12
13use crate::{db::DefDatabase2, nameres::*, test_db::TestDB, CrateModuleId}; 13use crate::{db::DefDatabase, nameres::*, test_db::TestDB, LocalModuleId};
14 14
15fn def_map(fixtute: &str) -> String { 15fn def_map(fixtute: &str) -> String {
16 let dm = compute_crate_def_map(fixtute); 16 let dm = compute_crate_def_map(fixtute);
@@ -25,10 +25,10 @@ fn compute_crate_def_map(fixture: &str) -> Arc<CrateDefMap> {
25 25
26fn render_crate_def_map(map: &CrateDefMap) -> String { 26fn render_crate_def_map(map: &CrateDefMap) -> String {
27 let mut buf = String::new(); 27 let mut buf = String::new();
28 go(&mut buf, map, "\ncrate", map.root()); 28 go(&mut buf, map, "\ncrate", map.root);
29 return buf.trim().to_string(); 29 return buf.trim().to_string();
30 30
31 fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: CrateModuleId) { 31 fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: LocalModuleId) {
32 *buf += path; 32 *buf += path;
33 *buf += "\n"; 33 *buf += "\n";
34 34
diff --git a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
index eb7b85c07..e11530062 100644
--- a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
@@ -665,7 +665,7 @@ fn unresolved_module_diagnostics() {
665 @r###" 665 @r###"
666 [ 666 [
667 UnresolvedModule { 667 UnresolvedModule {
668 module: CrateModuleId( 668 module: LocalModuleId(
669 0, 669 0,
670 ), 670 ),
671 declaration: AstId { 671 declaration: AstId {
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index 626ebffdc..0e606fd0e 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -1,4 +1,4 @@
1//! FIXME: write short doc here 1//! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`.
2 2
3use std::{iter, sync::Arc}; 3use std::{iter, sync::Arc};
4 4
@@ -66,7 +66,7 @@ pub enum PathKind {
66 66
67impl Path { 67impl Path {
68 /// Calls `cb` with all paths, represented by this use item. 68 /// Calls `cb` with all paths, represented by this use item.
69 pub fn expand_use_item( 69 pub(crate) fn expand_use_item(
70 item_src: Source<ast::UseItem>, 70 item_src: Source<ast::UseItem>,
71 hygiene: &Hygiene, 71 hygiene: &Hygiene,
72 mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>), 72 mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>),
@@ -76,7 +76,10 @@ impl Path {
76 } 76 }
77 } 77 }
78 78
79 pub fn from_simple_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> Path { 79 pub(crate) fn from_simple_segments(
80 kind: PathKind,
81 segments: impl IntoIterator<Item = Name>,
82 ) -> Path {
80 Path { 83 Path {
81 kind, 84 kind,
82 segments: segments 85 segments: segments
@@ -94,7 +97,7 @@ impl Path {
94 97
95 /// Converts an `ast::Path` to `Path`. Works with use trees. 98 /// Converts an `ast::Path` to `Path`. Works with use trees.
96 /// It correctly handles `$crate` based path from macro call. 99 /// It correctly handles `$crate` based path from macro call.
97 pub fn from_src(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> { 100 pub(crate) fn from_src(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
98 let mut kind = PathKind::Plain; 101 let mut kind = PathKind::Plain;
99 let mut segments = Vec::new(); 102 let mut segments = Vec::new();
100 loop { 103 loop {
@@ -192,7 +195,7 @@ impl Path {
192 } 195 }
193 196
194 /// Converts an `ast::NameRef` into a single-identifier `Path`. 197 /// Converts an `ast::NameRef` into a single-identifier `Path`.
195 pub fn from_name_ref(name_ref: &ast::NameRef) -> Path { 198 pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path {
196 name_ref.as_name().into() 199 name_ref.as_name().into()
197 } 200 }
198 201
@@ -227,7 +230,7 @@ impl Path {
227} 230}
228 231
229impl GenericArgs { 232impl GenericArgs {
230 pub fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> { 233 pub(crate) fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> {
231 let mut args = Vec::new(); 234 let mut args = Vec::new();
232 for type_arg in node.type_args() { 235 for type_arg in node.type_args() {
233 let type_ref = TypeRef::from_ast_opt(type_arg.type_ref()); 236 let type_ref = TypeRef::from_ast_opt(type_arg.type_ref());
diff --git a/crates/ra_hir_def/src/nameres/per_ns.rs b/crates/ra_hir_def/src/per_ns.rs
index 717ed1ef9..00e866bf9 100644
--- a/crates/ra_hir_def/src/nameres/per_ns.rs
+++ b/crates/ra_hir_def/src/per_ns.rs
@@ -1,4 +1,7 @@
1//! FIXME: write short doc here 1//! In rust, it is possible to have a value, a type and a macro with the same
2//! name without conflicts.
3//!
4//! `PerNs` (per namespace) captures this.
2 5
3use hir_expand::MacroDefId; 6use hir_expand::MacroDefId;
4 7
@@ -44,10 +47,6 @@ impl PerNs {
44 self.types.is_none() && self.values.is_none() && self.macros.is_none() 47 self.types.is_none() && self.values.is_none() && self.macros.is_none()
45 } 48 }
46 49
47 pub fn is_all(&self) -> bool {
48 self.types.is_some() && self.values.is_some() && self.macros.is_some()
49 }
50
51 pub fn take_types(self) -> Option<ModuleDefId> { 50 pub fn take_types(self) -> Option<ModuleDefId> {
52 self.types 51 self.types
53 } 52 }
@@ -56,14 +55,10 @@ impl PerNs {
56 self.values 55 self.values
57 } 56 }
58 57
59 pub fn get_macros(&self) -> Option<MacroDefId> { 58 pub fn take_macros(self) -> Option<MacroDefId> {
60 self.macros 59 self.macros
61 } 60 }
62 61
63 pub fn only_macros(&self) -> PerNs {
64 PerNs { types: None, values: None, macros: self.macros }
65 }
66
67 pub fn or(self, other: PerNs) -> PerNs { 62 pub fn or(self, other: PerNs) -> PerNs {
68 PerNs { 63 PerNs {
69 types: self.types.or(other.types), 64 types: self.types.or(other.types),
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index 7b5c3ec06..95b3c926d 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -11,14 +11,15 @@ use rustc_hash::FxHashSet;
11use crate::{ 11use crate::{
12 body::scope::{ExprScopes, ScopeId}, 12 body::scope::{ExprScopes, ScopeId},
13 builtin_type::BuiltinType, 13 builtin_type::BuiltinType,
14 db::DefDatabase2, 14 db::DefDatabase,
15 expr::{ExprId, PatId}, 15 expr::{ExprId, PatId},
16 generics::GenericParams, 16 generics::GenericParams,
17 nameres::{per_ns::PerNs, CrateDefMap}, 17 nameres::CrateDefMap,
18 path::{Path, PathKind}, 18 path::{Path, PathKind},
19 AdtId, AstItemDef, ConstId, ContainerId, CrateModuleId, DefWithBodyId, EnumId, EnumVariantId, 19 per_ns::PerNs,
20 FunctionId, GenericDefId, ImplId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, 20 AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
21 TypeAliasId, 21 GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId,
22 StructId, TraitId, TypeAliasId,
22}; 23};
23 24
24#[derive(Debug, Clone, Default)] 25#[derive(Debug, Clone, Default)]
@@ -28,20 +29,20 @@ pub struct Resolver {
28 29
29// FIXME how to store these best 30// FIXME how to store these best
30#[derive(Debug, Clone)] 31#[derive(Debug, Clone)]
31pub(crate) struct ModuleItemMap { 32struct ModuleItemMap {
32 crate_def_map: Arc<CrateDefMap>, 33 crate_def_map: Arc<CrateDefMap>,
33 module_id: CrateModuleId, 34 module_id: LocalModuleId,
34} 35}
35 36
36#[derive(Debug, Clone)] 37#[derive(Debug, Clone)]
37pub(crate) struct ExprScope { 38struct ExprScope {
38 owner: DefWithBodyId, 39 owner: DefWithBodyId,
39 expr_scopes: Arc<ExprScopes>, 40 expr_scopes: Arc<ExprScopes>,
40 scope_id: ScopeId, 41 scope_id: ScopeId,
41} 42}
42 43
43#[derive(Debug, Clone)] 44#[derive(Debug, Clone)]
44pub(crate) enum Scope { 45enum Scope {
45 /// All the items and imported names of a module 46 /// All the items and imported names of a module
46 ModuleScope(ModuleItemMap), 47 ModuleScope(ModuleItemMap),
47 /// Brings the generic parameters of an item into scope 48 /// Brings the generic parameters of an item into scope
@@ -87,7 +88,7 @@ pub enum ValueNs {
87 88
88impl Resolver { 89impl Resolver {
89 /// Resolve known trait from std, like `std::futures::Future` 90 /// Resolve known trait from std, like `std::futures::Future`
90 pub fn resolve_known_trait(&self, db: &impl DefDatabase2, path: &Path) -> Option<TraitId> { 91 pub fn resolve_known_trait(&self, db: &impl DefDatabase, path: &Path) -> Option<TraitId> {
91 let res = self.resolve_module_path(db, path).take_types()?; 92 let res = self.resolve_module_path(db, path).take_types()?;
92 match res { 93 match res {
93 ModuleDefId::TraitId(it) => Some(it), 94 ModuleDefId::TraitId(it) => Some(it),
@@ -96,7 +97,7 @@ impl Resolver {
96 } 97 }
97 98
98 /// Resolve known struct from std, like `std::boxed::Box` 99 /// Resolve known struct from std, like `std::boxed::Box`
99 pub fn resolve_known_struct(&self, db: &impl DefDatabase2, path: &Path) -> Option<StructId> { 100 pub fn resolve_known_struct(&self, db: &impl DefDatabase, path: &Path) -> Option<StructId> {
100 let res = self.resolve_module_path(db, path).take_types()?; 101 let res = self.resolve_module_path(db, path).take_types()?;
101 match res { 102 match res {
102 ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it), 103 ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it),
@@ -105,7 +106,7 @@ impl Resolver {
105 } 106 }
106 107
107 /// Resolve known enum from std, like `std::result::Result` 108 /// Resolve known enum from std, like `std::result::Result`
108 pub fn resolve_known_enum(&self, db: &impl DefDatabase2, path: &Path) -> Option<EnumId> { 109 pub fn resolve_known_enum(&self, db: &impl DefDatabase, path: &Path) -> Option<EnumId> {
109 let res = self.resolve_module_path(db, path).take_types()?; 110 let res = self.resolve_module_path(db, path).take_types()?;
110 match res { 111 match res {
111 ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it), 112 ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it),
@@ -114,7 +115,7 @@ impl Resolver {
114 } 115 }
115 116
116 /// pub only for source-binder 117 /// pub only for source-binder
117 pub fn resolve_module_path(&self, db: &impl DefDatabase2, path: &Path) -> PerNs { 118 pub fn resolve_module_path(&self, db: &impl DefDatabase, path: &Path) -> PerNs {
118 let (item_map, module) = match self.module() { 119 let (item_map, module) = match self.module() {
119 Some(it) => it, 120 Some(it) => it,
120 None => return PerNs::none(), 121 None => return PerNs::none(),
@@ -128,7 +129,7 @@ impl Resolver {
128 129
129 pub fn resolve_path_in_type_ns( 130 pub fn resolve_path_in_type_ns(
130 &self, 131 &self,
131 db: &impl DefDatabase2, 132 db: &impl DefDatabase,
132 path: &Path, 133 path: &Path,
133 ) -> Option<(TypeNs, Option<usize>)> { 134 ) -> Option<(TypeNs, Option<usize>)> {
134 if path.is_type_relative() { 135 if path.is_type_relative() {
@@ -184,7 +185,7 @@ impl Resolver {
184 185
185 pub fn resolve_path_in_type_ns_fully( 186 pub fn resolve_path_in_type_ns_fully(
186 &self, 187 &self,
187 db: &impl DefDatabase2, 188 db: &impl DefDatabase,
188 path: &Path, 189 path: &Path,
189 ) -> Option<TypeNs> { 190 ) -> Option<TypeNs> {
190 let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?; 191 let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?;
@@ -196,7 +197,7 @@ impl Resolver {
196 197
197 pub fn resolve_path_in_value_ns<'p>( 198 pub fn resolve_path_in_value_ns<'p>(
198 &self, 199 &self,
199 db: &impl DefDatabase2, 200 db: &impl DefDatabase,
200 path: &'p Path, 201 path: &'p Path,
201 ) -> Option<ResolveValueResult> { 202 ) -> Option<ResolveValueResult> {
202 if path.is_type_relative() { 203 if path.is_type_relative() {
@@ -296,7 +297,7 @@ impl Resolver {
296 297
297 pub fn resolve_path_in_value_ns_fully( 298 pub fn resolve_path_in_value_ns_fully(
298 &self, 299 &self,
299 db: &impl DefDatabase2, 300 db: &impl DefDatabase,
300 path: &Path, 301 path: &Path,
301 ) -> Option<ValueNs> { 302 ) -> Option<ValueNs> {
302 match self.resolve_path_in_value_ns(db, path)? { 303 match self.resolve_path_in_value_ns(db, path)? {
@@ -305,22 +306,22 @@ impl Resolver {
305 } 306 }
306 } 307 }
307 308
308 pub fn resolve_path_as_macro(&self, db: &impl DefDatabase2, path: &Path) -> Option<MacroDefId> { 309 pub fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> {
309 let (item_map, module) = self.module()?; 310 let (item_map, module) = self.module()?;
310 item_map.resolve_path(db, module, path).0.get_macros() 311 item_map.resolve_path(db, module, path).0.take_macros()
311 } 312 }
312 313
313 pub fn process_all_names(&self, db: &impl DefDatabase2, f: &mut dyn FnMut(Name, ScopeDef)) { 314 pub fn process_all_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) {
314 for scope in self.scopes.iter().rev() { 315 for scope in self.scopes.iter().rev() {
315 scope.process_names(db, f); 316 scope.process_names(db, f);
316 } 317 }
317 } 318 }
318 319
319 pub fn traits_in_scope(&self, db: &impl DefDatabase2) -> FxHashSet<TraitId> { 320 pub fn traits_in_scope(&self, db: &impl DefDatabase) -> FxHashSet<TraitId> {
320 let mut traits = FxHashSet::default(); 321 let mut traits = FxHashSet::default();
321 for scope in &self.scopes { 322 for scope in &self.scopes {
322 if let Scope::ModuleScope(m) = scope { 323 if let Scope::ModuleScope(m) = scope {
323 if let Some(prelude) = m.crate_def_map.prelude() { 324 if let Some(prelude) = m.crate_def_map.prelude {
324 let prelude_def_map = db.crate_def_map(prelude.krate); 325 let prelude_def_map = db.crate_def_map(prelude.krate);
325 traits.extend(prelude_def_map[prelude.module_id].scope.traits()); 326 traits.extend(prelude_def_map[prelude.module_id].scope.traits());
326 } 327 }
@@ -330,7 +331,7 @@ impl Resolver {
330 traits 331 traits
331 } 332 }
332 333
333 fn module(&self) -> Option<(&CrateDefMap, CrateModuleId)> { 334 fn module(&self) -> Option<(&CrateDefMap, LocalModuleId)> {
334 self.scopes.iter().rev().find_map(|scope| match scope { 335 self.scopes.iter().rev().find_map(|scope| match scope {
335 Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)), 336 Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)),
336 337
@@ -339,7 +340,7 @@ impl Resolver {
339 } 340 }
340 341
341 pub fn krate(&self) -> Option<CrateId> { 342 pub fn krate(&self) -> Option<CrateId> {
342 self.module().map(|t| t.0.krate()) 343 self.module().map(|t| t.0.krate)
343 } 344 }
344 345
345 pub fn where_predicates_in_scope<'a>( 346 pub fn where_predicates_in_scope<'a>(
@@ -378,7 +379,7 @@ pub enum ScopeDef {
378} 379}
379 380
380impl Scope { 381impl Scope {
381 fn process_names(&self, db: &impl DefDatabase2, f: &mut dyn FnMut(Name, ScopeDef)) { 382 fn process_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) {
382 match self { 383 match self {
383 Scope::ModuleScope(m) => { 384 Scope::ModuleScope(m) => {
384 // FIXME: should we provide `self` here? 385 // FIXME: should we provide `self` here?
@@ -394,10 +395,10 @@ impl Scope {
394 m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| { 395 m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| {
395 f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_))); 396 f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_)));
396 }); 397 });
397 m.crate_def_map.extern_prelude().iter().for_each(|(name, &def)| { 398 m.crate_def_map.extern_prelude.iter().for_each(|(name, &def)| {
398 f(name.clone(), ScopeDef::PerNs(PerNs::types(def.into()))); 399 f(name.clone(), ScopeDef::PerNs(PerNs::types(def.into())));
399 }); 400 });
400 if let Some(prelude) = m.crate_def_map.prelude() { 401 if let Some(prelude) = m.crate_def_map.prelude {
401 let prelude_def_map = db.crate_def_map(prelude.krate); 402 let prelude_def_map = db.crate_def_map(prelude.krate);
402 prelude_def_map[prelude.module_id].scope.entries().for_each(|(name, res)| { 403 prelude_def_map[prelude.module_id].scope.entries().for_each(|(name, res)| {
403 f(name.clone(), ScopeDef::PerNs(res.def)); 404 f(name.clone(), ScopeDef::PerNs(res.def));
@@ -425,17 +426,13 @@ impl Scope {
425} 426}
426 427
427// needs arbitrary_self_types to be a method... or maybe move to the def? 428// needs arbitrary_self_types to be a method... or maybe move to the def?
428pub fn resolver_for_expr( 429pub fn resolver_for_expr(db: &impl DefDatabase, owner: DefWithBodyId, expr_id: ExprId) -> Resolver {
429 db: &impl DefDatabase2,
430 owner: DefWithBodyId,
431 expr_id: ExprId,
432) -> Resolver {
433 let scopes = db.expr_scopes(owner); 430 let scopes = db.expr_scopes(owner);
434 resolver_for_scope(db, owner, scopes.scope_for(expr_id)) 431 resolver_for_scope(db, owner, scopes.scope_for(expr_id))
435} 432}
436 433
437pub fn resolver_for_scope( 434pub fn resolver_for_scope(
438 db: &impl DefDatabase2, 435 db: &impl DefDatabase,
439 owner: DefWithBodyId, 436 owner: DefWithBodyId,
440 scope_id: Option<ScopeId>, 437 scope_id: Option<ScopeId>,
441) -> Resolver { 438) -> Resolver {
@@ -454,7 +451,7 @@ impl Resolver {
454 self 451 self
455 } 452 }
456 453
457 fn push_generic_params_scope(self, db: &impl DefDatabase2, def: GenericDefId) -> Resolver { 454 fn push_generic_params_scope(self, db: &impl DefDatabase, def: GenericDefId) -> Resolver {
458 let params = db.generic_params(def); 455 let params = db.generic_params(def);
459 if params.params.is_empty() { 456 if params.params.is_empty() {
460 self 457 self
@@ -470,7 +467,7 @@ impl Resolver {
470 fn push_module_scope( 467 fn push_module_scope(
471 self, 468 self,
472 crate_def_map: Arc<CrateDefMap>, 469 crate_def_map: Arc<CrateDefMap>,
473 module_id: CrateModuleId, 470 module_id: LocalModuleId,
474 ) -> Resolver { 471 ) -> Resolver {
475 self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) 472 self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id }))
476 } 473 }
@@ -487,32 +484,26 @@ impl Resolver {
487 484
488pub trait HasResolver { 485pub trait HasResolver {
489 /// Builds a resolver for type references inside this def. 486 /// Builds a resolver for type references inside this def.
490 fn resolver(self, db: &impl DefDatabase2) -> Resolver; 487 fn resolver(self, db: &impl DefDatabase) -> Resolver;
491} 488}
492 489
493impl HasResolver for ModuleId { 490impl HasResolver for ModuleId {
494 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 491 fn resolver(self, db: &impl DefDatabase) -> Resolver {
495 let def_map = db.crate_def_map(self.krate); 492 let def_map = db.crate_def_map(self.krate);
496 Resolver::default().push_module_scope(def_map, self.module_id) 493 Resolver::default().push_module_scope(def_map, self.module_id)
497 } 494 }
498} 495}
499 496
500impl HasResolver for TraitId { 497impl HasResolver for TraitId {
501 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 498 fn resolver(self, db: &impl DefDatabase) -> Resolver {
502 self.module(db).resolver(db).push_generic_params_scope(db, self.into()) 499 self.module(db).resolver(db).push_generic_params_scope(db, self.into())
503 } 500 }
504} 501}
505 502
506impl<T: Into<AdtId>> HasResolver for T { 503impl<T: Into<AdtId>> HasResolver for T {
507 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 504 fn resolver(self, db: &impl DefDatabase) -> Resolver {
508 let def = self.into(); 505 let def = self.into();
509 let module = match def { 506 def.module(db)
510 AdtId::StructId(it) => it.0.module(db),
511 AdtId::UnionId(it) => it.0.module(db),
512 AdtId::EnumId(it) => it.module(db),
513 };
514
515 module
516 .resolver(db) 507 .resolver(db)
517 .push_generic_params_scope(db, def.into()) 508 .push_generic_params_scope(db, def.into())
518 .push_scope(Scope::AdtScope(def)) 509 .push_scope(Scope::AdtScope(def))
@@ -520,13 +511,13 @@ impl<T: Into<AdtId>> HasResolver for T {
520} 511}
521 512
522impl HasResolver for FunctionId { 513impl HasResolver for FunctionId {
523 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 514 fn resolver(self, db: &impl DefDatabase) -> Resolver {
524 self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into()) 515 self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into())
525 } 516 }
526} 517}
527 518
528impl HasResolver for DefWithBodyId { 519impl HasResolver for DefWithBodyId {
529 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 520 fn resolver(self, db: &impl DefDatabase) -> Resolver {
530 match self { 521 match self {
531 DefWithBodyId::ConstId(c) => c.resolver(db), 522 DefWithBodyId::ConstId(c) => c.resolver(db),
532 DefWithBodyId::FunctionId(f) => f.resolver(db), 523 DefWithBodyId::FunctionId(f) => f.resolver(db),
@@ -536,25 +527,25 @@ impl HasResolver for DefWithBodyId {
536} 527}
537 528
538impl HasResolver for ConstId { 529impl HasResolver for ConstId {
539 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 530 fn resolver(self, db: &impl DefDatabase) -> Resolver {
540 self.lookup(db).container.resolver(db) 531 self.lookup(db).container.resolver(db)
541 } 532 }
542} 533}
543 534
544impl HasResolver for StaticId { 535impl HasResolver for StaticId {
545 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 536 fn resolver(self, db: &impl DefDatabase) -> Resolver {
546 self.module(db).resolver(db) 537 self.lookup(db).container.resolver(db)
547 } 538 }
548} 539}
549 540
550impl HasResolver for TypeAliasId { 541impl HasResolver for TypeAliasId {
551 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 542 fn resolver(self, db: &impl DefDatabase) -> Resolver {
552 self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into()) 543 self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into())
553 } 544 }
554} 545}
555 546
556impl HasResolver for ContainerId { 547impl HasResolver for ContainerId {
557 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 548 fn resolver(self, db: &impl DefDatabase) -> Resolver {
558 match self { 549 match self {
559 ContainerId::TraitId(it) => it.resolver(db), 550 ContainerId::TraitId(it) => it.resolver(db),
560 ContainerId::ImplId(it) => it.resolver(db), 551 ContainerId::ImplId(it) => it.resolver(db),
@@ -564,7 +555,7 @@ impl HasResolver for ContainerId {
564} 555}
565 556
566impl HasResolver for GenericDefId { 557impl HasResolver for GenericDefId {
567 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 558 fn resolver(self, db: &impl DefDatabase) -> Resolver {
568 match self { 559 match self {
569 GenericDefId::FunctionId(inner) => inner.resolver(db), 560 GenericDefId::FunctionId(inner) => inner.resolver(db),
570 GenericDefId::AdtId(adt) => adt.resolver(db), 561 GenericDefId::AdtId(adt) => adt.resolver(db),
@@ -578,7 +569,7 @@ impl HasResolver for GenericDefId {
578} 569}
579 570
580impl HasResolver for ImplId { 571impl HasResolver for ImplId {
581 fn resolver(self, db: &impl DefDatabase2) -> Resolver { 572 fn resolver(self, db: &impl DefDatabase) -> Resolver {
582 self.module(db) 573 self.module(db)
583 .resolver(db) 574 .resolver(db)
584 .push_generic_params_scope(db, self.into()) 575 .push_generic_params_scope(db, self.into())
diff --git a/crates/ra_hir_def/src/test_db.rs b/crates/ra_hir_def/src/test_db.rs
index 8ee8e40d0..439e8a412 100644
--- a/crates/ra_hir_def/src/test_db.rs
+++ b/crates/ra_hir_def/src/test_db.rs
@@ -12,7 +12,7 @@ use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath
12 ra_db::SourceDatabaseStorage, 12 ra_db::SourceDatabaseStorage,
13 hir_expand::db::AstDatabaseStorage, 13 hir_expand::db::AstDatabaseStorage,
14 crate::db::InternDatabaseStorage, 14 crate::db::InternDatabaseStorage,
15 crate::db::DefDatabase2Storage 15 crate::db::DefDatabaseStorage
16)] 16)]
17#[derive(Debug, Default)] 17#[derive(Debug, Default)]
18pub struct TestDB { 18pub struct TestDB {
diff --git a/crates/ra_hir_def/src/trace.rs b/crates/ra_hir_def/src/trace.rs
new file mode 100644
index 000000000..2bcd707bc
--- /dev/null
+++ b/crates/ra_hir_def/src/trace.rs
@@ -0,0 +1,59 @@
1//! Trace is a pretty niche data structure which is used when lowering a CST
2//! into HIR.
3//!
4//! Lowering process calculates two bits of information:
5//! * the lowered syntax itself
6//! * a mapping between lowered syntax and original syntax
7//!
8//! Due to the way salsa works, the mapping is usually hot lava, as it contains
9//! absolute offsets. The `Trace` structure (inspired, at least in name, by
10//! Kotlin's `BindingTrace`) allows use the same code to compute both
11//! projections.
12use ra_arena::{map::ArenaMap, Arena, ArenaId, RawId};
13
14pub(crate) struct Trace<ID: ArenaId, T, V> {
15 arena: Option<Arena<ID, T>>,
16 map: Option<ArenaMap<ID, V>>,
17 len: u32,
18}
19
20impl<ID: ra_arena::ArenaId + Copy, T, V> Trace<ID, T, V> {
21 pub(crate) fn new() -> Trace<ID, T, V> {
22 Trace { arena: Some(Arena::default()), map: Some(ArenaMap::default()), len: 0 }
23 }
24
25 pub(crate) fn new_for_arena() -> Trace<ID, T, V> {
26 Trace { arena: Some(Arena::default()), map: None, len: 0 }
27 }
28
29 pub(crate) fn new_for_map() -> Trace<ID, T, V> {
30 Trace { arena: None, map: Some(ArenaMap::default()), len: 0 }
31 }
32
33 pub(crate) fn alloc(&mut self, value: impl FnOnce() -> V, data: impl FnOnce() -> T) -> ID {
34 let id = if let Some(arena) = &mut self.arena {
35 arena.alloc(data())
36 } else {
37 let id = ID::from_raw(RawId::from(self.len));
38 self.len += 1;
39 id
40 };
41
42 if let Some(map) = &mut self.map {
43 map.insert(id, value());
44 }
45 id
46 }
47
48 pub(crate) fn into_arena(mut self) -> Arena<ID, T> {
49 self.arena.take().unwrap()
50 }
51
52 pub(crate) fn into_map(mut self) -> ArenaMap<ID, V> {
53 self.map.take().unwrap()
54 }
55
56 pub(crate) fn into_arena_and_map(mut self) -> (Arena<ID, T>, ArenaMap<ID, V>) {
57 (self.arena.take().unwrap(), self.map.take().unwrap())
58 }
59}
diff --git a/crates/ra_hir_def/src/traits.rs b/crates/ra_hir_def/src/traits.rs
deleted file mode 100644
index 6c2d5b2a9..000000000
--- a/crates/ra_hir_def/src/traits.rs
+++ /dev/null
@@ -1,66 +0,0 @@
1//! HIR for trait definitions.
2
3use std::sync::Arc;
4
5use hir_expand::{
6 name::{AsName, Name},
7 AstId,
8};
9
10use ra_syntax::ast::{self, NameOwner};
11
12use crate::{
13 db::DefDatabase2, AssocItemId, AstItemDef, ConstLoc, ContainerId, FunctionLoc, Intern, TraitId,
14 TypeAliasId, TypeAliasLoc,
15};
16
17#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct TraitData {
19 pub name: Option<Name>,
20 pub items: Vec<AssocItemId>,
21 pub auto: bool,
22}
23
24impl TraitData {
25 pub(crate) fn trait_data_query(db: &impl DefDatabase2, tr: TraitId) -> Arc<TraitData> {
26 let src = tr.source(db);
27 let name = src.value.name().map(|n| n.as_name());
28 let auto = src.value.is_auto();
29 let ast_id_map = db.ast_id_map(src.file_id);
30 let items = if let Some(item_list) = src.value.item_list() {
31 item_list
32 .impl_items()
33 .map(|item_node| match item_node {
34 ast::ImplItem::FnDef(it) => FunctionLoc {
35 container: ContainerId::TraitId(tr),
36 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
37 }
38 .intern(db)
39 .into(),
40 ast::ImplItem::ConstDef(it) => ConstLoc {
41 container: ContainerId::TraitId(tr),
42 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
43 }
44 .intern(db)
45 .into(),
46 ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc {
47 container: ContainerId::TraitId(tr),
48 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
49 }
50 .intern(db)
51 .into(),
52 })
53 .collect()
54 } else {
55 Vec::new()
56 };
57 Arc::new(TraitData { name, items, auto })
58 }
59
60 pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
61 self.items.iter().filter_map(|item| match item {
62 AssocItemId::TypeAliasId(t) => Some(*t),
63 _ => None,
64 })
65 }
66}
diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs
index 8af061116..5f10e9a88 100644
--- a/crates/ra_hir_def/src/type_ref.rs
+++ b/crates/ra_hir_def/src/type_ref.rs
@@ -64,7 +64,7 @@ pub enum TypeBound {
64 64
65impl TypeRef { 65impl TypeRef {
66 /// Converts an `ast::TypeRef` to a `hir::TypeRef`. 66 /// Converts an `ast::TypeRef` to a `hir::TypeRef`.
67 pub fn from_ast(node: ast::TypeRef) -> Self { 67 pub(crate) fn from_ast(node: ast::TypeRef) -> Self {
68 match node { 68 match node {
69 ast::TypeRef::ParenType(inner) => TypeRef::from_ast_opt(inner.type_ref()), 69 ast::TypeRef::ParenType(inner) => TypeRef::from_ast_opt(inner.type_ref()),
70 ast::TypeRef::TupleType(inner) => { 70 ast::TypeRef::TupleType(inner) => {
@@ -113,7 +113,7 @@ impl TypeRef {
113 } 113 }
114 } 114 }
115 115
116 pub fn from_ast_opt(node: Option<ast::TypeRef>) -> Self { 116 pub(crate) fn from_ast_opt(node: Option<ast::TypeRef>) -> Self {
117 if let Some(node) = node { 117 if let Some(node) = node {
118 TypeRef::from_ast(node) 118 TypeRef::from_ast(node)
119 } else { 119 } else {
@@ -121,7 +121,7 @@ impl TypeRef {
121 } 121 }
122 } 122 }
123 123
124 pub fn unit() -> TypeRef { 124 pub(crate) fn unit() -> TypeRef {
125 TypeRef::Tuple(Vec::new()) 125 TypeRef::Tuple(Vec::new())
126 } 126 }
127} 127}
@@ -135,7 +135,7 @@ pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>)
135} 135}
136 136
137impl TypeBound { 137impl TypeBound {
138 pub fn from_ast(node: ast::TypeBound) -> Self { 138 pub(crate) fn from_ast(node: ast::TypeBound) -> Self {
139 match node.kind() { 139 match node.kind() {
140 ast::TypeBoundKind::PathType(path_type) => { 140 ast::TypeBoundKind::PathType(path_type) => {
141 let path = match path_type.path() { 141 let path = match path_type.path() {