aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r--crates/ra_hir_def/Cargo.toml3
-rw-r--r--crates/ra_hir_def/src/adt.rs30
-rw-r--r--crates/ra_hir_def/src/attr.rs31
-rw-r--r--crates/ra_hir_def/src/body.rs108
-rw-r--r--crates/ra_hir_def/src/body/lower.rs108
-rw-r--r--crates/ra_hir_def/src/body/scope.rs10
-rw-r--r--crates/ra_hir_def/src/builtin_type.rs42
-rw-r--r--crates/ra_hir_def/src/child_by_source.rs177
-rw-r--r--crates/ra_hir_def/src/data.rs154
-rw-r--r--crates/ra_hir_def/src/db.rs29
-rw-r--r--crates/ra_hir_def/src/diagnostics.rs6
-rw-r--r--crates/ra_hir_def/src/docs.rs22
-rw-r--r--crates/ra_hir_def/src/dyn_map.rs108
-rw-r--r--crates/ra_hir_def/src/expr.rs15
-rw-r--r--crates/ra_hir_def/src/generics.rs174
-rw-r--r--crates/ra_hir_def/src/item_scope.rs172
-rw-r--r--crates/ra_hir_def/src/keys.rs56
-rw-r--r--crates/ra_hir_def/src/lang_item.rs2
-rw-r--r--crates/ra_hir_def/src/lib.rs346
-rw-r--r--crates/ra_hir_def/src/marks.rs1
-rw-r--r--crates/ra_hir_def/src/nameres.rs224
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs637
-rw-r--r--crates/ra_hir_def/src/nameres/path_resolution.rs105
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs105
-rw-r--r--crates/ra_hir_def/src/nameres/tests.rs53
-rw-r--r--crates/ra_hir_def/src/nameres/tests/globs.rs21
-rw-r--r--crates/ra_hir_def/src/nameres/tests/incremental.rs4
-rw-r--r--crates/ra_hir_def/src/nameres/tests/macros.rs24
-rw-r--r--crates/ra_hir_def/src/nameres/tests/mod_resolution.rs4
-rw-r--r--crates/ra_hir_def/src/path.rs527
-rw-r--r--crates/ra_hir_def/src/path/lower.rs178
-rw-r--r--crates/ra_hir_def/src/path/lower/lower_use.rs118
-rw-r--r--crates/ra_hir_def/src/per_ns.rs2
-rw-r--r--crates/ra_hir_def/src/resolver.rs296
-rw-r--r--crates/ra_hir_def/src/src.rs36
-rw-r--r--crates/ra_hir_def/src/trace.rs8
36 files changed, 2422 insertions, 1514 deletions
diff --git a/crates/ra_hir_def/Cargo.toml b/crates/ra_hir_def/Cargo.toml
index 7e65f4c1d..2c368f690 100644
--- a/crates/ra_hir_def/Cargo.toml
+++ b/crates/ra_hir_def/Cargo.toml
@@ -11,6 +11,9 @@ doctest = false
11log = "0.4.5" 11log = "0.4.5"
12once_cell = "1.0.1" 12once_cell = "1.0.1"
13rustc-hash = "1.0" 13rustc-hash = "1.0"
14either = "1.5"
15anymap = "0.12"
16drop_bomb = "0.1.4"
14 17
15ra_arena = { path = "../ra_arena" } 18ra_arena = { path = "../ra_arena" }
16ra_db = { path = "../ra_db" } 19ra_db = { path = "../ra_db" }
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index 3666529b0..d9ea693e3 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -2,17 +2,18 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use either::Either;
5use hir_expand::{ 6use hir_expand::{
6 either::Either,
7 name::{AsName, Name}, 7 name::{AsName, Name},
8 Source, 8 InFile,
9}; 9};
10use ra_arena::{map::ArenaMap, Arena}; 10use ra_arena::{map::ArenaMap, Arena};
11use ra_prof::profile;
11use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; 12use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
12 13
13use crate::{ 14use crate::{
14 db::DefDatabase, trace::Trace, type_ref::TypeRef, AstItemDef, EnumId, HasChildSource, 15 db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, type_ref::TypeRef, EnumId,
15 LocalEnumVariantId, LocalStructFieldId, StructId, UnionId, VariantId, 16 LocalEnumVariantId, LocalStructFieldId, Lookup, StructId, UnionId, VariantId,
16}; 17};
17 18
18/// Note that we use `StructData` for unions as well! 19/// Note that we use `StructData` for unions as well!
@@ -50,14 +51,14 @@ pub struct StructFieldData {
50 51
51impl StructData { 52impl StructData {
52 pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructId) -> Arc<StructData> { 53 pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructId) -> Arc<StructData> {
53 let src = id.source(db); 54 let src = id.lookup(db).source(db);
54 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 55 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
55 let variant_data = VariantData::new(src.value.kind()); 56 let variant_data = VariantData::new(src.value.kind());
56 let variant_data = Arc::new(variant_data); 57 let variant_data = Arc::new(variant_data);
57 Arc::new(StructData { name, variant_data }) 58 Arc::new(StructData { name, variant_data })
58 } 59 }
59 pub(crate) fn union_data_query(db: &impl DefDatabase, id: UnionId) -> Arc<StructData> { 60 pub(crate) fn union_data_query(db: &impl DefDatabase, id: UnionId) -> Arc<StructData> {
60 let src = id.source(db); 61 let src = id.lookup(db).source(db);
61 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 62 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
62 let variant_data = VariantData::new( 63 let variant_data = VariantData::new(
63 src.value 64 src.value
@@ -72,7 +73,8 @@ impl StructData {
72 73
73impl EnumData { 74impl EnumData {
74 pub(crate) fn enum_data_query(db: &impl DefDatabase, e: EnumId) -> Arc<EnumData> { 75 pub(crate) fn enum_data_query(db: &impl DefDatabase, e: EnumId) -> Arc<EnumData> {
75 let src = e.source(db); 76 let _p = profile("enum_data_query");
77 let src = e.lookup(db).source(db);
76 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 78 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
77 let mut trace = Trace::new_for_arena(); 79 let mut trace = Trace::new_for_arena();
78 lower_enum(&mut trace, &src.value); 80 lower_enum(&mut trace, &src.value);
@@ -88,8 +90,8 @@ impl EnumData {
88impl HasChildSource for EnumId { 90impl HasChildSource for EnumId {
89 type ChildId = LocalEnumVariantId; 91 type ChildId = LocalEnumVariantId;
90 type Value = ast::EnumVariant; 92 type Value = ast::EnumVariant;
91 fn child_source(&self, db: &impl DefDatabase) -> Source<ArenaMap<Self::ChildId, Self::Value>> { 93 fn child_source(&self, db: &impl DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> {
92 let src = self.source(db); 94 let src = self.lookup(db).source(db);
93 let mut trace = Trace::new_for_map(); 95 let mut trace = Trace::new_for_map();
94 lower_enum(&mut trace, &src.value); 96 lower_enum(&mut trace, &src.value);
95 src.with_value(trace.into_map()) 97 src.with_value(trace.into_map())
@@ -145,7 +147,7 @@ impl HasChildSource for VariantId {
145 type ChildId = LocalStructFieldId; 147 type ChildId = LocalStructFieldId;
146 type Value = Either<ast::TupleFieldDef, ast::RecordFieldDef>; 148 type Value = Either<ast::TupleFieldDef, ast::RecordFieldDef>;
147 149
148 fn child_source(&self, db: &impl DefDatabase) -> Source<ArenaMap<Self::ChildId, Self::Value>> { 150 fn child_source(&self, db: &impl DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> {
149 let src = match self { 151 let src = match self {
150 VariantId::EnumVariantId(it) => { 152 VariantId::EnumVariantId(it) => {
151 // I don't really like the fact that we call into parent source 153 // I don't really like the fact that we call into parent source
@@ -153,8 +155,8 @@ impl HasChildSource for VariantId {
153 let src = it.parent.child_source(db); 155 let src = it.parent.child_source(db);
154 src.map(|map| map[it.local_id].kind()) 156 src.map(|map| map[it.local_id].kind())
155 } 157 }
156 VariantId::StructId(it) => it.source(db).map(|it| it.kind()), 158 VariantId::StructId(it) => it.lookup(db).source(db).map(|it| it.kind()),
157 VariantId::UnionId(it) => it.source(db).map(|it| { 159 VariantId::UnionId(it) => it.lookup(db).source(db).map(|it| {
158 it.record_field_def_list() 160 it.record_field_def_list()
159 .map(ast::StructKind::Record) 161 .map(ast::StructKind::Record)
160 .unwrap_or(ast::StructKind::Unit) 162 .unwrap_or(ast::StructKind::Unit)
@@ -184,7 +186,7 @@ fn lower_struct(
184 ast::StructKind::Tuple(fl) => { 186 ast::StructKind::Tuple(fl) => {
185 for (i, fd) in fl.fields().enumerate() { 187 for (i, fd) in fl.fields().enumerate() {
186 trace.alloc( 188 trace.alloc(
187 || Either::A(fd.clone()), 189 || Either::Left(fd.clone()),
188 || StructFieldData { 190 || StructFieldData {
189 name: Name::new_tuple_field(i), 191 name: Name::new_tuple_field(i),
190 type_ref: TypeRef::from_ast_opt(fd.type_ref()), 192 type_ref: TypeRef::from_ast_opt(fd.type_ref()),
@@ -196,7 +198,7 @@ fn lower_struct(
196 ast::StructKind::Record(fl) => { 198 ast::StructKind::Record(fl) => {
197 for fd in fl.fields() { 199 for fd in fl.fields() {
198 trace.alloc( 200 trace.alloc(
199 || Either::B(fd.clone()), 201 || Either::Right(fd.clone()),
200 || StructFieldData { 202 || StructFieldData {
201 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), 203 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
202 type_ref: TypeRef::from_ast_opt(fd.ascribed_type()), 204 type_ref: TypeRef::from_ast_opt(fd.ascribed_type()),
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index fffb22201..9efa4970c 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -2,7 +2,8 @@
2 2
3use std::{ops, sync::Arc}; 3use std::{ops, sync::Arc};
4 4
5use hir_expand::{either::Either, hygiene::Hygiene, AstId, Source}; 5use either::Either;
6use hir_expand::{hygiene::Hygiene, AstId, InFile};
6use mbe::ast_to_token_tree; 7use mbe::ast_to_token_tree;
7use ra_syntax::{ 8use ra_syntax::{
8 ast::{self, AstNode, AttrsOwner}, 9 ast::{self, AstNode, AttrsOwner},
@@ -11,7 +12,7 @@ use ra_syntax::{
11use tt::Subtree; 12use tt::Subtree;
12 13
13use crate::{ 14use crate::{
14 db::DefDatabase, path::Path, AdtId, AstItemDef, AttrDefId, HasChildSource, HasSource, Lookup, 15 db::DefDatabase, path::ModPath, src::HasChildSource, src::HasSource, AdtId, AttrDefId, Lookup,
15}; 16};
16 17
17#[derive(Default, Debug, Clone, PartialEq, Eq)] 18#[derive(Default, Debug, Clone, PartialEq, Eq)]
@@ -44,8 +45,8 @@ impl Attrs {
44 AttrDefId::StructFieldId(it) => { 45 AttrDefId::StructFieldId(it) => {
45 let src = it.parent.child_source(db); 46 let src = it.parent.child_source(db);
46 match &src.value[it.local_id] { 47 match &src.value[it.local_id] {
47 Either::A(_tuple) => Attrs::default(), 48 Either::Left(_tuple) => Attrs::default(),
48 Either::B(record) => Attrs::from_attrs_owner(db, src.with_value(record)), 49 Either::Right(record) => Attrs::from_attrs_owner(db, src.with_value(record)),
49 } 50 }
50 } 51 }
51 AttrDefId::EnumVariantId(var_id) => { 52 AttrDefId::EnumVariantId(var_id) => {
@@ -54,13 +55,15 @@ impl Attrs {
54 Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner)) 55 Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner))
55 } 56 }
56 AttrDefId::AdtId(it) => match it { 57 AttrDefId::AdtId(it) => match it {
57 AdtId::StructId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), 58 AdtId::StructId(it) => attrs_from_loc(it.lookup(db), db),
58 AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), 59 AdtId::EnumId(it) => attrs_from_loc(it.lookup(db), db),
59 AdtId::UnionId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), 60 AdtId::UnionId(it) => attrs_from_loc(it.lookup(db), db),
60 }, 61 },
61 AttrDefId::TraitId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), 62 AttrDefId::TraitId(it) => attrs_from_loc(it.lookup(db), db),
62 AttrDefId::MacroDefId(it) => attrs_from_ast(it.ast_id, db), 63 AttrDefId::MacroDefId(it) => {
63 AttrDefId::ImplId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), 64 it.ast_id.map_or_else(Default::default, |ast_id| attrs_from_ast(ast_id, db))
65 }
66 AttrDefId::ImplId(it) => attrs_from_loc(it.lookup(db), db),
64 AttrDefId::ConstId(it) => attrs_from_loc(it.lookup(db), db), 67 AttrDefId::ConstId(it) => attrs_from_loc(it.lookup(db), db),
65 AttrDefId::StaticId(it) => attrs_from_loc(it.lookup(db), db), 68 AttrDefId::StaticId(it) => attrs_from_loc(it.lookup(db), db),
66 AttrDefId::FunctionId(it) => attrs_from_loc(it.lookup(db), db), 69 AttrDefId::FunctionId(it) => attrs_from_loc(it.lookup(db), db),
@@ -68,7 +71,7 @@ impl Attrs {
68 } 71 }
69 } 72 }
70 73
71 fn from_attrs_owner(db: &impl DefDatabase, owner: Source<&dyn AttrsOwner>) -> Attrs { 74 fn from_attrs_owner(db: &impl DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Attrs {
72 let hygiene = Hygiene::new(db, owner.file_id); 75 let hygiene = Hygiene::new(db, owner.file_id);
73 Attrs::new(owner.value, &hygiene) 76 Attrs::new(owner.value, &hygiene)
74 } 77 }
@@ -91,7 +94,7 @@ impl Attrs {
91 94
92#[derive(Debug, Clone, PartialEq, Eq)] 95#[derive(Debug, Clone, PartialEq, Eq)]
93pub struct Attr { 96pub struct Attr {
94 pub(crate) path: Path, 97 pub(crate) path: ModPath,
95 pub(crate) input: Option<AttrInput>, 98 pub(crate) input: Option<AttrInput>,
96} 99}
97 100
@@ -103,7 +106,7 @@ pub enum AttrInput {
103 106
104impl Attr { 107impl Attr {
105 fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> { 108 fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> {
106 let path = Path::from_src(ast.path()?, hygiene)?; 109 let path = ModPath::from_src(ast.path()?, hygiene)?;
107 let input = match ast.input() { 110 let input = match ast.input() {
108 None => None, 111 None => None,
109 Some(ast::AttrInput::Literal(lit)) => { 112 Some(ast::AttrInput::Literal(lit)) => {
@@ -157,7 +160,7 @@ where
157 N: ast::AttrsOwner, 160 N: ast::AttrsOwner,
158 D: DefDatabase, 161 D: DefDatabase,
159{ 162{
160 let src = Source::new(src.file_id(), src.to_node(db)); 163 let src = InFile::new(src.file_id, src.to_node(db));
161 Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner)) 164 Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner))
162} 165}
163 166
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index a57a0176d..d3e4c50ae 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -3,58 +3,75 @@
3mod lower; 3mod lower;
4pub mod scope; 4pub mod scope;
5 5
6use std::{ops::Index, sync::Arc}; 6use std::{mem, ops::Index, sync::Arc};
7 7
8use drop_bomb::DropBomb;
9use either::Either;
8use hir_expand::{ 10use hir_expand::{
9 either::Either, hygiene::Hygiene, AstId, HirFileId, MacroDefId, MacroFileKind, Source, 11 ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId,
10}; 12};
11use ra_arena::{map::ArenaMap, Arena}; 13use ra_arena::{map::ArenaMap, Arena};
14use ra_prof::profile;
12use ra_syntax::{ast, AstNode, AstPtr}; 15use ra_syntax::{ast, AstNode, AstPtr};
13use rustc_hash::FxHashMap; 16use rustc_hash::FxHashMap;
14 17
15use crate::{ 18use crate::{
16 db::DefDatabase, 19 db::DefDatabase,
17 expr::{Expr, ExprId, Pat, PatId}, 20 expr::{Expr, ExprId, Pat, PatId},
21 item_scope::BuiltinShadowMode,
22 item_scope::ItemScope,
18 nameres::CrateDefMap, 23 nameres::CrateDefMap,
19 path::Path, 24 path::{ModPath, Path},
20 DefWithBodyId, HasModule, HasSource, Lookup, ModuleId, 25 src::HasSource,
26 DefWithBodyId, HasModule, Lookup, ModuleId,
21}; 27};
22 28
23struct Expander { 29pub(crate) struct Expander {
24 crate_def_map: Arc<CrateDefMap>, 30 crate_def_map: Arc<CrateDefMap>,
25 current_file_id: HirFileId, 31 current_file_id: HirFileId,
26 hygiene: Hygiene, 32 hygiene: Hygiene,
33 ast_id_map: Arc<AstIdMap>,
27 module: ModuleId, 34 module: ModuleId,
28} 35}
29 36
30impl Expander { 37impl Expander {
31 fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander { 38 pub(crate) fn new(
39 db: &impl DefDatabase,
40 current_file_id: HirFileId,
41 module: ModuleId,
42 ) -> Expander {
32 let crate_def_map = db.crate_def_map(module.krate); 43 let crate_def_map = db.crate_def_map(module.krate);
33 let hygiene = Hygiene::new(db, current_file_id); 44 let hygiene = Hygiene::new(db, current_file_id);
34 Expander { crate_def_map, current_file_id, hygiene, module } 45 let ast_id_map = db.ast_id_map(current_file_id);
46 Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module }
35 } 47 }
36 48
37 fn enter_expand( 49 pub(crate) fn enter_expand<T: ast::AstNode, DB: DefDatabase>(
38 &mut self, 50 &mut self,
39 db: &impl DefDatabase, 51 db: &DB,
40 macro_call: ast::MacroCall, 52 macro_call: ast::MacroCall,
41 ) -> Option<(Mark, ast::Expr)> { 53 ) -> Option<(Mark, T)> {
42 let ast_id = AstId::new( 54 let ast_id = AstId::new(
43 self.current_file_id, 55 self.current_file_id,
44 db.ast_id_map(self.current_file_id).ast_id(&macro_call), 56 db.ast_id_map(self.current_file_id).ast_id(&macro_call),
45 ); 57 );
46 58
47 if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) { 59 if let Some(path) = macro_call.path().and_then(|path| self.parse_mod_path(path)) {
48 if let Some(def) = self.resolve_path_as_macro(db, &path) { 60 if let Some(def) = self.resolve_path_as_macro(db, &path) {
49 let call_id = def.as_call_id(db, ast_id); 61 let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id));
50 let file_id = call_id.as_file(MacroFileKind::Expr); 62 let file_id = call_id.as_file();
51 if let Some(node) = db.parse_or_expand(file_id) { 63 if let Some(node) = db.parse_or_expand(file_id) {
52 if let Some(expr) = ast::Expr::cast(node) { 64 if let Some(expr) = T::cast(node) {
53 log::debug!("macro expansion {:#?}", expr.syntax()); 65 log::debug!("macro expansion {:#?}", expr.syntax());
54 66
55 let mark = Mark { file_id: self.current_file_id }; 67 let mark = Mark {
68 file_id: self.current_file_id,
69 ast_id_map: mem::take(&mut self.ast_id_map),
70 bomb: DropBomb::new("expansion mark dropped"),
71 };
56 self.hygiene = Hygiene::new(db, file_id); 72 self.hygiene = Hygiene::new(db, file_id);
57 self.current_file_id = file_id; 73 self.current_file_id = file_id;
74 self.ast_id_map = db.ast_id_map(file_id);
58 75
59 return Some((mark, expr)); 76 return Some((mark, expr));
60 } 77 }
@@ -67,37 +84,44 @@ impl Expander {
67 None 84 None
68 } 85 }
69 86
70 fn exit(&mut self, db: &impl DefDatabase, mark: Mark) { 87 pub(crate) fn exit(&mut self, db: &impl DefDatabase, mut mark: Mark) {
71 self.hygiene = Hygiene::new(db, mark.file_id); 88 self.hygiene = Hygiene::new(db, mark.file_id);
72 self.current_file_id = mark.file_id; 89 self.current_file_id = mark.file_id;
73 std::mem::forget(mark); 90 self.ast_id_map = mem::take(&mut mark.ast_id_map);
91 mark.bomb.defuse();
74 } 92 }
75 93
76 fn to_source<T>(&self, value: T) -> Source<T> { 94 pub(crate) fn to_source<T>(&self, value: T) -> InFile<T> {
77 Source { file_id: self.current_file_id, value } 95 InFile { file_id: self.current_file_id, value }
78 } 96 }
79 97
80 fn parse_path(&mut self, path: ast::Path) -> Option<Path> { 98 fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
81 Path::from_src(path, &self.hygiene) 99 Path::from_src(path, &self.hygiene)
82 } 100 }
83 101
84 fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> { 102 fn parse_mod_path(&mut self, path: ast::Path) -> Option<ModPath> {
85 self.crate_def_map.resolve_path(db, self.module.local_id, path).0.take_macros() 103 ModPath::from_src(path, &self.hygiene)
86 } 104 }
87}
88 105
89struct Mark { 106 fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &ModPath) -> Option<MacroDefId> {
90 file_id: HirFileId, 107 self.crate_def_map
91} 108 .resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other)
109 .0
110 .take_macros()
111 }
92 112
93impl Drop for Mark { 113 fn ast_id<N: AstNode>(&self, item: &N) -> AstId<N> {
94 fn drop(&mut self) { 114 let file_local_id = self.ast_id_map.ast_id(item);
95 if !std::thread::panicking() { 115 AstId::new(self.current_file_id, file_local_id)
96 panic!("dropped mark")
97 }
98 } 116 }
99} 117}
100 118
119pub(crate) struct Mark {
120 file_id: HirFileId,
121 ast_id_map: Arc<AstIdMap>,
122 bomb: DropBomb,
123}
124
101/// The body of an item (function, const etc.). 125/// The body of an item (function, const etc.).
102#[derive(Debug, Eq, PartialEq)] 126#[derive(Debug, Eq, PartialEq)]
103pub struct Body { 127pub struct Body {
@@ -112,13 +136,14 @@ pub struct Body {
112 pub params: Vec<PatId>, 136 pub params: Vec<PatId>,
113 /// The `ExprId` of the actual body expression. 137 /// The `ExprId` of the actual body expression.
114 pub body_expr: ExprId, 138 pub body_expr: ExprId,
139 pub item_scope: ItemScope,
115} 140}
116 141
117pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>; 142pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>;
118pub type ExprSource = Source<ExprPtr>; 143pub type ExprSource = InFile<ExprPtr>;
119 144
120pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>; 145pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
121pub type PatSource = Source<PatPtr>; 146pub type PatSource = InFile<PatPtr>;
122 147
123/// An item body together with the mapping from syntax nodes to HIR expression 148/// An item body together with the mapping from syntax nodes to HIR expression
124/// IDs. This is needed to go from e.g. a position in a file to the HIR 149/// IDs. This is needed to go from e.g. a position in a file to the HIR
@@ -145,6 +170,7 @@ impl Body {
145 db: &impl DefDatabase, 170 db: &impl DefDatabase,
146 def: DefWithBodyId, 171 def: DefWithBodyId,
147 ) -> (Arc<Body>, Arc<BodySourceMap>) { 172 ) -> (Arc<Body>, Arc<BodySourceMap>) {
173 let _p = profile("body_with_source_map_query");
148 let mut params = None; 174 let mut params = None;
149 175
150 let (file_id, module, body) = match def { 176 let (file_id, module, body) = match def {
@@ -166,7 +192,7 @@ impl Body {
166 } 192 }
167 }; 193 };
168 let expander = Expander::new(db, file_id, module); 194 let expander = Expander::new(db, file_id, module);
169 let (body, source_map) = Body::new(db, expander, params, body); 195 let (body, source_map) = Body::new(db, def, expander, params, body);
170 (Arc::new(body), Arc::new(source_map)) 196 (Arc::new(body), Arc::new(source_map))
171 } 197 }
172 198
@@ -176,11 +202,12 @@ impl Body {
176 202
177 fn new( 203 fn new(
178 db: &impl DefDatabase, 204 db: &impl DefDatabase,
205 def: DefWithBodyId,
179 expander: Expander, 206 expander: Expander,
180 params: Option<ast::ParamList>, 207 params: Option<ast::ParamList>,
181 body: Option<ast::Expr>, 208 body: Option<ast::Expr>,
182 ) -> (Body, BodySourceMap) { 209 ) -> (Body, BodySourceMap) {
183 lower::lower(db, expander, params, body) 210 lower::lower(db, def, expander, params, body)
184 } 211 }
185} 212}
186 213
@@ -205,8 +232,13 @@ impl BodySourceMap {
205 self.expr_map_back.get(expr).copied() 232 self.expr_map_back.get(expr).copied()
206 } 233 }
207 234
208 pub fn node_expr(&self, node: Source<&ast::Expr>) -> Option<ExprId> { 235 pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option<ExprId> {
209 let src = node.map(|it| Either::A(AstPtr::new(it))); 236 let src = node.map(|it| Either::Left(AstPtr::new(it)));
237 self.expr_map.get(&src).cloned()
238 }
239
240 pub fn field_init_shorthand_expr(&self, node: InFile<&ast::RecordField>) -> Option<ExprId> {
241 let src = node.map(|it| Either::Right(AstPtr::new(it)));
210 self.expr_map.get(&src).cloned() 242 self.expr_map.get(&src).cloned()
211 } 243 }
212 244
@@ -214,8 +246,8 @@ impl BodySourceMap {
214 self.pat_map_back.get(pat).copied() 246 self.pat_map_back.get(pat).copied()
215 } 247 }
216 248
217 pub fn node_pat(&self, node: Source<&ast::Pat>) -> Option<PatId> { 249 pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<PatId> {
218 let src = node.map(|it| Either::A(AstPtr::new(it))); 250 let src = node.map(|it| Either::Left(AstPtr::new(it)));
219 self.pat_map.get(&src).cloned() 251 self.pat_map.get(&src).cloned()
220 } 252 }
221 253
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 331736cb2..5323af097 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -1,14 +1,13 @@
1//! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr` 1//! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr`
2//! representation. 2//! representation.
3 3
4use hir_expand::{ 4use either::Either;
5 either::Either, 5
6 name::{self, AsName, Name}, 6use hir_expand::name::{name, AsName, Name};
7};
8use ra_arena::Arena; 7use ra_arena::Arena;
9use ra_syntax::{ 8use ra_syntax::{
10 ast::{ 9 ast::{
11 self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, NameOwner, 10 self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner,
12 TypeAscriptionOwner, 11 TypeAscriptionOwner,
13 }, 12 },
14 AstNode, AstPtr, 13 AstNode, AstPtr,
@@ -26,23 +25,28 @@ use crate::{
26 path::GenericArgs, 25 path::GenericArgs,
27 path::Path, 26 path::Path,
28 type_ref::{Mutability, TypeRef}, 27 type_ref::{Mutability, TypeRef},
28 ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, StaticLoc,
29 StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
29}; 30};
30 31
31pub(super) fn lower( 32pub(super) fn lower(
32 db: &impl DefDatabase, 33 db: &impl DefDatabase,
34 def: DefWithBodyId,
33 expander: Expander, 35 expander: Expander,
34 params: Option<ast::ParamList>, 36 params: Option<ast::ParamList>,
35 body: Option<ast::Expr>, 37 body: Option<ast::Expr>,
36) -> (Body, BodySourceMap) { 38) -> (Body, BodySourceMap) {
37 ExprCollector { 39 ExprCollector {
38 expander,
39 db, 40 db,
41 def,
42 expander,
40 source_map: BodySourceMap::default(), 43 source_map: BodySourceMap::default(),
41 body: Body { 44 body: Body {
42 exprs: Arena::default(), 45 exprs: Arena::default(),
43 pats: Arena::default(), 46 pats: Arena::default(),
44 params: Vec::new(), 47 params: Vec::new(),
45 body_expr: ExprId::dummy(), 48 body_expr: ExprId::dummy(),
49 item_scope: Default::default(),
46 }, 50 },
47 } 51 }
48 .collect(params, body) 52 .collect(params, body)
@@ -50,6 +54,7 @@ pub(super) fn lower(
50 54
51struct ExprCollector<DB> { 55struct ExprCollector<DB> {
52 db: DB, 56 db: DB,
57 def: DefWithBodyId,
53 expander: Expander, 58 expander: Expander,
54 59
55 body: Body, 60 body: Body,
@@ -70,11 +75,11 @@ where
70 let ptr = AstPtr::new(&self_param); 75 let ptr = AstPtr::new(&self_param);
71 let param_pat = self.alloc_pat( 76 let param_pat = self.alloc_pat(
72 Pat::Bind { 77 Pat::Bind {
73 name: name::SELF_PARAM, 78 name: name![self],
74 mode: BindingAnnotation::Unannotated, 79 mode: BindingAnnotation::Unannotated,
75 subpat: None, 80 subpat: None,
76 }, 81 },
77 Either::B(ptr), 82 Either::Right(ptr),
78 ); 83 );
79 self.body.params.push(param_pat); 84 self.body.params.push(param_pat);
80 } 85 }
@@ -94,7 +99,7 @@ where
94 } 99 }
95 100
96 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { 101 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
97 let ptr = Either::A(ptr); 102 let ptr = Either::Left(ptr);
98 let id = self.body.exprs.alloc(expr); 103 let id = self.body.exprs.alloc(expr);
99 let src = self.expander.to_source(ptr); 104 let src = self.expander.to_source(ptr);
100 self.source_map.expr_map.insert(src, id); 105 self.source_map.expr_map.insert(src, id);
@@ -107,7 +112,7 @@ where
107 self.body.exprs.alloc(expr) 112 self.body.exprs.alloc(expr)
108 } 113 }
109 fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr<ast::RecordField>) -> ExprId { 114 fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr<ast::RecordField>) -> ExprId {
110 let ptr = Either::B(ptr); 115 let ptr = Either::Right(ptr);
111 let id = self.body.exprs.alloc(expr); 116 let id = self.body.exprs.alloc(expr);
112 let src = self.expander.to_source(ptr); 117 let src = self.expander.to_source(ptr);
113 self.source_map.expr_map.insert(src, id); 118 self.source_map.expr_map.insert(src, id);
@@ -277,7 +282,7 @@ where
277 ast::Expr::ParenExpr(e) => { 282 ast::Expr::ParenExpr(e) => {
278 let inner = self.collect_expr_opt(e.expr()); 283 let inner = self.collect_expr_opt(e.expr());
279 // make the paren expr point to the inner expression as well 284 // make the paren expr point to the inner expression as well
280 let src = self.expander.to_source(Either::A(syntax_ptr)); 285 let src = self.expander.to_source(Either::Left(syntax_ptr));
281 self.source_map.expr_map.insert(src, inner); 286 self.source_map.expr_map.insert(src, inner);
282 inner 287 inner
283 } 288 }
@@ -367,8 +372,9 @@ where
367 arg_types.push(type_ref); 372 arg_types.push(type_ref);
368 } 373 }
369 } 374 }
375 let ret_type = e.ret_type().and_then(|r| r.type_ref()).map(TypeRef::from_ast);
370 let body = self.collect_expr_opt(e.body()); 376 let body = self.collect_expr_opt(e.body());
371 self.alloc_expr(Expr::Lambda { args, arg_types, body }, syntax_ptr) 377 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
372 } 378 }
373 ast::Expr::BinExpr(e) => { 379 ast::Expr::BinExpr(e) => {
374 let lhs = self.collect_expr_opt(e.lhs()); 380 let lhs = self.collect_expr_opt(e.lhs());
@@ -429,10 +435,17 @@ where
429 let index = self.collect_expr_opt(e.index()); 435 let index = self.collect_expr_opt(e.index());
430 self.alloc_expr(Expr::Index { base, index }, syntax_ptr) 436 self.alloc_expr(Expr::Index { base, index }, syntax_ptr)
431 } 437 }
432 438 ast::Expr::RangeExpr(e) => {
433 // FIXME implement HIR for these: 439 let lhs = e.start().map(|lhs| self.collect_expr(lhs));
434 ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 440 let rhs = e.end().map(|rhs| self.collect_expr(rhs));
435 ast::Expr::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 441 match e.op_kind() {
442 Some(range_type) => {
443 self.alloc_expr(Expr::Range { lhs, rhs, range_type }, syntax_ptr)
444 }
445 None => self.alloc_expr(Expr::Missing, syntax_ptr),
446 }
447 }
448 // FIXME expand to statements in statement position
436 ast::Expr::MacroCall(e) => match self.expander.enter_expand(self.db, e) { 449 ast::Expr::MacroCall(e) => match self.expander.enter_expand(self.db, e) {
437 Some((mark, expansion)) => { 450 Some((mark, expansion)) => {
438 let id = self.collect_expr(expansion); 451 let id = self.collect_expr(expansion);
@@ -441,6 +454,9 @@ where
441 } 454 }
442 None => self.alloc_expr(Expr::Missing, syntax_ptr), 455 None => self.alloc_expr(Expr::Missing, syntax_ptr),
443 }, 456 },
457
458 // FIXME implement HIR for these:
459 ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
444 } 460 }
445 } 461 }
446 462
@@ -458,6 +474,7 @@ where
458 Some(block) => block, 474 Some(block) => block,
459 None => return self.alloc_expr(Expr::Missing, syntax_node_ptr), 475 None => return self.alloc_expr(Expr::Missing, syntax_node_ptr),
460 }; 476 };
477 self.collect_block_items(&block);
461 let statements = block 478 let statements = block
462 .statements() 479 .statements()
463 .map(|s| match s { 480 .map(|s| match s {
@@ -474,6 +491,63 @@ where
474 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) 491 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr)
475 } 492 }
476 493
494 fn collect_block_items(&mut self, block: &ast::Block) {
495 let container = ContainerId::DefWithBodyId(self.def);
496 for item in block.items() {
497 let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
498 ast::ModuleItem::FnDef(def) => {
499 let ast_id = self.expander.ast_id(&def);
500 (
501 FunctionLoc { container: container.into(), ast_id }.intern(self.db).into(),
502 def.name(),
503 )
504 }
505 ast::ModuleItem::TypeAliasDef(def) => {
506 let ast_id = self.expander.ast_id(&def);
507 (
508 TypeAliasLoc { container: container.into(), ast_id }.intern(self.db).into(),
509 def.name(),
510 )
511 }
512 ast::ModuleItem::ConstDef(def) => {
513 let ast_id = self.expander.ast_id(&def);
514 (
515 ConstLoc { container: container.into(), ast_id }.intern(self.db).into(),
516 def.name(),
517 )
518 }
519 ast::ModuleItem::StaticDef(def) => {
520 let ast_id = self.expander.ast_id(&def);
521 (StaticLoc { container, ast_id }.intern(self.db).into(), def.name())
522 }
523 ast::ModuleItem::StructDef(def) => {
524 let ast_id = self.expander.ast_id(&def);
525 (StructLoc { container, ast_id }.intern(self.db).into(), def.name())
526 }
527 ast::ModuleItem::EnumDef(def) => {
528 let ast_id = self.expander.ast_id(&def);
529 (EnumLoc { container, ast_id }.intern(self.db).into(), def.name())
530 }
531 ast::ModuleItem::UnionDef(def) => {
532 let ast_id = self.expander.ast_id(&def);
533 (UnionLoc { container, ast_id }.intern(self.db).into(), def.name())
534 }
535 ast::ModuleItem::TraitDef(def) => {
536 let ast_id = self.expander.ast_id(&def);
537 (TraitLoc { container, ast_id }.intern(self.db).into(), def.name())
538 }
539 ast::ModuleItem::ImplBlock(_)
540 | ast::ModuleItem::UseItem(_)
541 | ast::ModuleItem::ExternCrateItem(_)
542 | ast::ModuleItem::Module(_) => continue,
543 };
544 self.body.item_scope.define_def(def);
545 if let Some(name) = name {
546 self.body.item_scope.push_res(name.as_name(), def.into());
547 }
548 }
549 }
550
477 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId { 551 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
478 if let Some(block) = expr { 552 if let Some(block) = expr {
479 self.collect_block(block) 553 self.collect_block(block)
@@ -541,7 +615,7 @@ where
541 ast::Pat::SlicePat(_) | ast::Pat::RangePat(_) => Pat::Missing, 615 ast::Pat::SlicePat(_) | ast::Pat::RangePat(_) => Pat::Missing,
542 }; 616 };
543 let ptr = AstPtr::new(&pat); 617 let ptr = AstPtr::new(&pat);
544 self.alloc_pat(pattern, Either::A(ptr)) 618 self.alloc_pat(pattern, Either::Left(ptr))
545 } 619 }
546 620
547 fn collect_pat_opt(&mut self, pat: Option<ast::Pat>) -> PatId { 621 fn collect_pat_opt(&mut self, pat: Option<ast::Pat>) -> PatId {
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs
index 625aa39dd..a63552327 100644
--- a/crates/ra_hir_def/src/body/scope.rs
+++ b/crates/ra_hir_def/src/body/scope.rs
@@ -171,7 +171,7 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
171 171
172#[cfg(test)] 172#[cfg(test)]
173mod tests { 173mod tests {
174 use hir_expand::{name::AsName, Source}; 174 use hir_expand::{name::AsName, InFile};
175 use ra_db::{fixture::WithFixture, FileId, SourceDatabase}; 175 use ra_db::{fixture::WithFixture, FileId, SourceDatabase};
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};
@@ -183,8 +183,8 @@ mod tests {
183 let crate_def_map = db.crate_def_map(krate); 183 let crate_def_map = db.crate_def_map(krate);
184 184
185 let module = crate_def_map.modules_for_file(file_id).next().unwrap(); 185 let module = crate_def_map.modules_for_file(file_id).next().unwrap();
186 let (_, res) = crate_def_map[module].scope.entries().next().unwrap(); 186 let (_, def) = crate_def_map[module].scope.entries().next().unwrap();
187 match res.def.take_values().unwrap() { 187 match def.take_values().unwrap() {
188 ModuleDefId::FunctionId(it) => it, 188 ModuleDefId::FunctionId(it) => it,
189 _ => panic!(), 189 _ => panic!(),
190 } 190 }
@@ -211,7 +211,7 @@ mod tests {
211 let (_body, source_map) = db.body_with_source_map(function.into()); 211 let (_body, source_map) = db.body_with_source_map(function.into());
212 212
213 let expr_id = source_map 213 let expr_id = source_map
214 .node_expr(Source { file_id: file_id.into(), value: &marker.into() }) 214 .node_expr(InFile { file_id: file_id.into(), value: &marker.into() })
215 .unwrap(); 215 .unwrap();
216 let scope = scopes.scope_for(expr_id); 216 let scope = scopes.scope_for(expr_id);
217 217
@@ -318,7 +318,7 @@ mod tests {
318 let expr_scope = { 318 let expr_scope = {
319 let expr_ast = name_ref.syntax().ancestors().find_map(ast::Expr::cast).unwrap(); 319 let expr_ast = name_ref.syntax().ancestors().find_map(ast::Expr::cast).unwrap();
320 let expr_id = 320 let expr_id =
321 source_map.node_expr(Source { file_id: file_id.into(), value: &expr_ast }).unwrap(); 321 source_map.node_expr(InFile { file_id: file_id.into(), value: &expr_ast }).unwrap();
322 scopes.scope_for(expr_id).unwrap() 322 scopes.scope_for(expr_id).unwrap()
323 }; 323 };
324 324
diff --git a/crates/ra_hir_def/src/builtin_type.rs b/crates/ra_hir_def/src/builtin_type.rs
index 5e8157144..d14901a9b 100644
--- a/crates/ra_hir_def/src/builtin_type.rs
+++ b/crates/ra_hir_def/src/builtin_type.rs
@@ -5,7 +5,7 @@
5 5
6use std::fmt; 6use std::fmt;
7 7
8use hir_expand::name::{self, Name}; 8use hir_expand::name::{name, Name};
9 9
10#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 10#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
11pub enum Signedness { 11pub enum Signedness {
@@ -52,26 +52,26 @@ pub enum BuiltinType {
52impl BuiltinType { 52impl BuiltinType {
53 #[rustfmt::skip] 53 #[rustfmt::skip]
54 pub const ALL: &'static [(Name, BuiltinType)] = &[ 54 pub const ALL: &'static [(Name, BuiltinType)] = &[
55 (name::CHAR, BuiltinType::Char), 55 (name![char], BuiltinType::Char),
56 (name::BOOL, BuiltinType::Bool), 56 (name![bool], BuiltinType::Bool),
57 (name::STR, BuiltinType::Str ), 57 (name![str], BuiltinType::Str),
58 58
59 (name::ISIZE, BuiltinType::Int(BuiltinInt::ISIZE)), 59 (name![isize], BuiltinType::Int(BuiltinInt::ISIZE)),
60 (name::I8, BuiltinType::Int(BuiltinInt::I8)), 60 (name![i8], BuiltinType::Int(BuiltinInt::I8)),
61 (name::I16, BuiltinType::Int(BuiltinInt::I16)), 61 (name![i16], BuiltinType::Int(BuiltinInt::I16)),
62 (name::I32, BuiltinType::Int(BuiltinInt::I32)), 62 (name![i32], BuiltinType::Int(BuiltinInt::I32)),
63 (name::I64, BuiltinType::Int(BuiltinInt::I64)), 63 (name![i64], BuiltinType::Int(BuiltinInt::I64)),
64 (name::I128, BuiltinType::Int(BuiltinInt::I128)), 64 (name![i128], BuiltinType::Int(BuiltinInt::I128)),
65 65
66 (name::USIZE, BuiltinType::Int(BuiltinInt::USIZE)), 66 (name![usize], BuiltinType::Int(BuiltinInt::USIZE)),
67 (name::U8, BuiltinType::Int(BuiltinInt::U8)), 67 (name![u8], BuiltinType::Int(BuiltinInt::U8)),
68 (name::U16, BuiltinType::Int(BuiltinInt::U16)), 68 (name![u16], BuiltinType::Int(BuiltinInt::U16)),
69 (name::U32, BuiltinType::Int(BuiltinInt::U32)), 69 (name![u32], BuiltinType::Int(BuiltinInt::U32)),
70 (name::U64, BuiltinType::Int(BuiltinInt::U64)), 70 (name![u64], BuiltinType::Int(BuiltinInt::U64)),
71 (name::U128, BuiltinType::Int(BuiltinInt::U128)), 71 (name![u128], BuiltinType::Int(BuiltinInt::U128)),
72 72
73 (name::F32, BuiltinType::Float(BuiltinFloat::F32)), 73 (name![f32], BuiltinType::Float(BuiltinFloat::F32)),
74 (name::F64, BuiltinType::Float(BuiltinFloat::F64)), 74 (name![f64], BuiltinType::Float(BuiltinFloat::F64)),
75 ]; 75 ];
76} 76}
77 77
diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs
new file mode 100644
index 000000000..8b6c773ee
--- /dev/null
+++ b/crates/ra_hir_def/src/child_by_source.rs
@@ -0,0 +1,177 @@
1//! When *constructing* `hir`, we start at some parent syntax node and recursively
2//! lower the children.
3//!
4//! This modules allows one to go in the opposite direction: start with a syntax
5//! node for a *child*, and get its hir.
6
7use either::Either;
8
9use crate::{
10 db::DefDatabase,
11 dyn_map::DynMap,
12 item_scope::ItemScope,
13 keys,
14 src::{HasChildSource, HasSource},
15 AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, ImplId, Lookup, ModuleDefId,
16 ModuleId, StructFieldId, TraitId, VariantId,
17};
18
19pub trait ChildBySource {
20 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap;
21}
22
23impl ChildBySource for TraitId {
24 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
25 let mut res = DynMap::default();
26
27 let data = db.trait_data(*self);
28 for (_name, item) in data.items.iter() {
29 match *item {
30 AssocItemId::FunctionId(func) => {
31 let src = func.lookup(db).source(db);
32 res[keys::FUNCTION].insert(src, func)
33 }
34 AssocItemId::ConstId(konst) => {
35 let src = konst.lookup(db).source(db);
36 res[keys::CONST].insert(src, konst)
37 }
38 AssocItemId::TypeAliasId(ty) => {
39 let src = ty.lookup(db).source(db);
40 res[keys::TYPE_ALIAS].insert(src, ty)
41 }
42 }
43 }
44
45 res
46 }
47}
48
49impl ChildBySource for ImplId {
50 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
51 let mut res = DynMap::default();
52
53 let data = db.impl_data(*self);
54 for &item in data.items.iter() {
55 match item {
56 AssocItemId::FunctionId(func) => {
57 let src = func.lookup(db).source(db);
58 res[keys::FUNCTION].insert(src, func)
59 }
60 AssocItemId::ConstId(konst) => {
61 let src = konst.lookup(db).source(db);
62 res[keys::CONST].insert(src, konst)
63 }
64 AssocItemId::TypeAliasId(ty) => {
65 let src = ty.lookup(db).source(db);
66 res[keys::TYPE_ALIAS].insert(src, ty)
67 }
68 }
69 }
70
71 res
72 }
73}
74
75impl ChildBySource for ModuleId {
76 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
77 let crate_def_map = db.crate_def_map(self.krate);
78 let module_data = &crate_def_map[self.local_id];
79 module_data.scope.child_by_source(db)
80 }
81}
82
83impl ChildBySource for ItemScope {
84 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
85 let mut res = DynMap::default();
86 self.declarations().for_each(|item| add_module_def(db, &mut res, item));
87 self.impls().for_each(|imp| add_impl(db, &mut res, imp));
88 return res;
89
90 fn add_module_def(db: &impl DefDatabase, map: &mut DynMap, item: ModuleDefId) {
91 match item {
92 ModuleDefId::FunctionId(func) => {
93 let src = func.lookup(db).source(db);
94 map[keys::FUNCTION].insert(src, func)
95 }
96 ModuleDefId::ConstId(konst) => {
97 let src = konst.lookup(db).source(db);
98 map[keys::CONST].insert(src, konst)
99 }
100 ModuleDefId::StaticId(statik) => {
101 let src = statik.lookup(db).source(db);
102 map[keys::STATIC].insert(src, statik)
103 }
104 ModuleDefId::TypeAliasId(ty) => {
105 let src = ty.lookup(db).source(db);
106 map[keys::TYPE_ALIAS].insert(src, ty)
107 }
108 ModuleDefId::TraitId(trait_) => {
109 let src = trait_.lookup(db).source(db);
110 map[keys::TRAIT].insert(src, trait_)
111 }
112 ModuleDefId::AdtId(adt) => match adt {
113 AdtId::StructId(strukt) => {
114 let src = strukt.lookup(db).source(db);
115 map[keys::STRUCT].insert(src, strukt)
116 }
117 AdtId::UnionId(union_) => {
118 let src = union_.lookup(db).source(db);
119 map[keys::UNION].insert(src, union_)
120 }
121 AdtId::EnumId(enum_) => {
122 let src = enum_.lookup(db).source(db);
123 map[keys::ENUM].insert(src, enum_)
124 }
125 },
126 _ => (),
127 }
128 }
129 fn add_impl(db: &impl DefDatabase, map: &mut DynMap, imp: ImplId) {
130 let src = imp.lookup(db).source(db);
131 map[keys::IMPL].insert(src, imp)
132 }
133 }
134}
135
136impl ChildBySource for VariantId {
137 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
138 let mut res = DynMap::default();
139
140 let arena_map = self.child_source(db);
141 let arena_map = arena_map.as_ref();
142 for (local_id, source) in arena_map.value.iter() {
143 let id = StructFieldId { parent: *self, local_id };
144 match source {
145 Either::Left(source) => {
146 res[keys::TUPLE_FIELD].insert(arena_map.with_value(source.clone()), id)
147 }
148 Either::Right(source) => {
149 res[keys::RECORD_FIELD].insert(arena_map.with_value(source.clone()), id)
150 }
151 }
152 }
153 res
154 }
155}
156
157impl ChildBySource for EnumId {
158 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
159 let mut res = DynMap::default();
160
161 let arena_map = self.child_source(db);
162 let arena_map = arena_map.as_ref();
163 for (local_id, source) in arena_map.value.iter() {
164 let id = EnumVariantId { parent: *self, local_id };
165 res[keys::ENUM_VARIANT].insert(arena_map.with_value(source.clone()), id)
166 }
167
168 res
169 }
170}
171
172impl ChildBySource for DefWithBodyId {
173 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
174 let body = db.body(*self);
175 body.item_scope.child_by_source(db)
176 }
177}
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index fee10b237..1aa9a9b7d 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -3,16 +3,17 @@
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_expand::{ 5use hir_expand::{
6 name::{self, AsName, Name}, 6 name::{name, AsName, Name},
7 AstId, 7 AstId, InFile,
8}; 8};
9use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; 9use ra_syntax::ast::{self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner};
10 10
11use crate::{ 11use crate::{
12 db::DefDatabase, 12 db::DefDatabase,
13 src::HasSource,
13 type_ref::{Mutability, TypeRef}, 14 type_ref::{Mutability, TypeRef},
14 AssocItemId, AstItemDef, ConstId, ConstLoc, ContainerId, FunctionId, FunctionLoc, HasSource, 15 AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule,
15 ImplId, Intern, Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc, 16 ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
16}; 17};
17 18
18#[derive(Debug, Clone, PartialEq, Eq)] 19#[derive(Debug, Clone, PartialEq, Eq)]
@@ -36,7 +37,7 @@ impl FunctionData {
36 let self_type = if let Some(type_ref) = self_param.ascribed_type() { 37 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
37 TypeRef::from_ast(type_ref) 38 TypeRef::from_ast(type_ref)
38 } else { 39 } else {
39 let self_type = TypeRef::Path(name::SELF_TYPE.into()); 40 let self_type = TypeRef::Path(name![Self].into());
40 match self_param.kind() { 41 match self_param.kind() {
41 ast::SelfParamKind::Owned => self_type, 42 ast::SelfParamKind::Owned => self_type,
42 ast::SelfParamKind::Ref => { 43 ast::SelfParamKind::Ref => {
@@ -93,12 +94,12 @@ pub struct TraitData {
93 94
94impl TraitData { 95impl TraitData {
95 pub(crate) fn trait_data_query(db: &impl DefDatabase, tr: TraitId) -> Arc<TraitData> { 96 pub(crate) fn trait_data_query(db: &impl DefDatabase, tr: TraitId) -> Arc<TraitData> {
96 let src = tr.source(db); 97 let src = tr.lookup(db).source(db);
97 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 98 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
98 let auto = src.value.is_auto(); 99 let auto = src.value.is_auto();
99 let ast_id_map = db.ast_id_map(src.file_id); 100 let ast_id_map = db.ast_id_map(src.file_id);
100 101
101 let container = ContainerId::TraitId(tr); 102 let container = AssocContainerId::TraitId(tr);
102 let items = if let Some(item_list) = src.value.item_list() { 103 let items = if let Some(item_list) = src.value.item_list() {
103 item_list 104 item_list
104 .impl_items() 105 .impl_items()
@@ -166,46 +167,24 @@ pub struct ImplData {
166 167
167impl ImplData { 168impl ImplData {
168 pub(crate) fn impl_data_query(db: &impl DefDatabase, id: ImplId) -> Arc<ImplData> { 169 pub(crate) fn impl_data_query(db: &impl DefDatabase, id: ImplId) -> Arc<ImplData> {
169 let src = id.source(db); 170 let impl_loc = id.lookup(db);
170 let items = db.ast_id_map(src.file_id); 171 let src = impl_loc.source(db);
171 172
172 let target_trait = src.value.target_trait().map(TypeRef::from_ast); 173 let target_trait = src.value.target_trait().map(TypeRef::from_ast);
173 let target_type = TypeRef::from_ast_opt(src.value.target_type()); 174 let target_type = TypeRef::from_ast_opt(src.value.target_type());
174 let is_negative = src.value.is_negative(); 175 let is_negative = src.value.is_negative();
176 let module_id = impl_loc.container.module(db);
175 177
176 let items = if let Some(item_list) = src.value.item_list() { 178 let mut items = Vec::new();
177 item_list 179 if let Some(item_list) = src.value.item_list() {
178 .impl_items() 180 items.extend(collect_impl_items(db, item_list.impl_items(), src.file_id, id));
179 .map(|item_node| match item_node { 181 items.extend(collect_impl_items_in_macros(
180 ast::ImplItem::FnDef(it) => { 182 db,
181 let def = FunctionLoc { 183 module_id,
182 container: ContainerId::ImplId(id), 184 &src.with_value(item_list),
183 ast_id: AstId::new(src.file_id, items.ast_id(&it)), 185 id,
184 } 186 ));
185 .intern(db); 187 }
186 def.into()
187 }
188 ast::ImplItem::ConstDef(it) => {
189 let def = ConstLoc {
190 container: ContainerId::ImplId(id),
191 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
192 }
193 .intern(db);
194 def.into()
195 }
196 ast::ImplItem::TypeAliasDef(it) => {
197 let def = TypeAliasLoc {
198 container: ContainerId::ImplId(id),
199 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
200 }
201 .intern(db);
202 def.into()
203 }
204 })
205 .collect()
206 } else {
207 Vec::new()
208 };
209 188
210 let res = ImplData { target_trait, target_type, items, is_negative }; 189 let res = ImplData { target_trait, target_type, items, is_negative };
211 Arc::new(res) 190 Arc::new(res)
@@ -236,3 +215,92 @@ impl ConstData {
236 ConstData { name, type_ref } 215 ConstData { name, type_ref }
237 } 216 }
238} 217}
218
219fn collect_impl_items_in_macros(
220 db: &impl DefDatabase,
221 module_id: ModuleId,
222 impl_block: &InFile<ast::ItemList>,
223 id: ImplId,
224) -> Vec<AssocItemId> {
225 let mut expander = Expander::new(db, impl_block.file_id, module_id);
226 let mut res = Vec::new();
227
228 // We set a limit to protect against infinite recursion
229 let limit = 100;
230
231 for m in impl_block.value.syntax().children().filter_map(ast::MacroCall::cast) {
232 res.extend(collect_impl_items_in_macro(db, &mut expander, m, id, limit))
233 }
234
235 res
236}
237
238fn collect_impl_items_in_macro(
239 db: &impl DefDatabase,
240 expander: &mut Expander,
241 m: ast::MacroCall,
242 id: ImplId,
243 limit: usize,
244) -> Vec<AssocItemId> {
245 if limit == 0 {
246 return Vec::new();
247 }
248
249 if let Some((mark, items)) = expander.enter_expand(db, m) {
250 let items: InFile<ast::MacroItems> = expander.to_source(items);
251 let mut res = collect_impl_items(
252 db,
253 items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())),
254 items.file_id,
255 id,
256 );
257 // Recursive collect macros
258 // Note that ast::ModuleItem do not include ast::MacroCall
259 // We cannot use ModuleItemOwner::items here
260 for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) {
261 res.extend(collect_impl_items_in_macro(db, expander, it, id, limit - 1))
262 }
263 expander.exit(db, mark);
264 res
265 } else {
266 Vec::new()
267 }
268}
269
270fn collect_impl_items(
271 db: &impl DefDatabase,
272 impl_items: impl Iterator<Item = ImplItem>,
273 file_id: crate::HirFileId,
274 id: ImplId,
275) -> Vec<AssocItemId> {
276 let items = db.ast_id_map(file_id);
277
278 impl_items
279 .map(|item_node| match item_node {
280 ast::ImplItem::FnDef(it) => {
281 let def = FunctionLoc {
282 container: AssocContainerId::ImplId(id),
283 ast_id: AstId::new(file_id, items.ast_id(&it)),
284 }
285 .intern(db);
286 def.into()
287 }
288 ast::ImplItem::ConstDef(it) => {
289 let def = ConstLoc {
290 container: AssocContainerId::ImplId(id),
291 ast_id: AstId::new(file_id, items.ast_id(&it)),
292 }
293 .intern(db);
294 def.into()
295 }
296 ast::ImplItem::TypeAliasDef(it) => {
297 let def = TypeAliasLoc {
298 container: AssocContainerId::ImplId(id),
299 ast_id: AstId::new(file_id, items.ast_id(&it)),
300 }
301 .intern(db);
302 def.into()
303 }
304 })
305 .collect()
306}
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index ef5611ffc..c55fd4111 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -3,7 +3,7 @@ use std::sync::Arc;
3 3
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, SmolStr}; 6use ra_syntax::SmolStr;
7 7
8use crate::{ 8use crate::{
9 adt::{EnumData, StructData}, 9 adt::{EnumData, StructData},
@@ -13,13 +13,10 @@ use crate::{
13 docs::Documentation, 13 docs::Documentation,
14 generics::GenericParams, 14 generics::GenericParams,
15 lang_item::{LangItemTarget, LangItems}, 15 lang_item::{LangItemTarget, LangItems},
16 nameres::{ 16 nameres::{raw::RawItems, CrateDefMap},
17 raw::{ImportSourceMap, RawItems}, 17 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc,
18 CrateDefMap, 18 GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId,
19 }, 19 TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc,
20 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId,
21 ImplId, ItemLoc, ModuleId, StaticId, StaticLoc, StructId, TraitId, TypeAliasId, TypeAliasLoc,
22 UnionId,
23}; 20};
24 21
25#[salsa::query_group(InternDatabaseStorage)] 22#[salsa::query_group(InternDatabaseStorage)]
@@ -27,31 +24,25 @@ pub trait InternDatabase: SourceDatabase {
27 #[salsa::interned] 24 #[salsa::interned]
28 fn intern_function(&self, loc: FunctionLoc) -> FunctionId; 25 fn intern_function(&self, loc: FunctionLoc) -> FunctionId;
29 #[salsa::interned] 26 #[salsa::interned]
30 fn intern_struct(&self, loc: ItemLoc<ast::StructDef>) -> StructId; 27 fn intern_struct(&self, loc: StructLoc) -> StructId;
31 #[salsa::interned] 28 #[salsa::interned]
32 fn intern_union(&self, loc: ItemLoc<ast::UnionDef>) -> UnionId; 29 fn intern_union(&self, loc: UnionLoc) -> UnionId;
33 #[salsa::interned] 30 #[salsa::interned]
34 fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> EnumId; 31 fn intern_enum(&self, loc: EnumLoc) -> EnumId;
35 #[salsa::interned] 32 #[salsa::interned]
36 fn intern_const(&self, loc: ConstLoc) -> ConstId; 33 fn intern_const(&self, loc: ConstLoc) -> ConstId;
37 #[salsa::interned] 34 #[salsa::interned]
38 fn intern_static(&self, loc: StaticLoc) -> StaticId; 35 fn intern_static(&self, loc: StaticLoc) -> StaticId;
39 #[salsa::interned] 36 #[salsa::interned]
40 fn intern_trait(&self, loc: ItemLoc<ast::TraitDef>) -> TraitId; 37 fn intern_trait(&self, loc: TraitLoc) -> TraitId;
41 #[salsa::interned] 38 #[salsa::interned]
42 fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId; 39 fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId;
43 #[salsa::interned] 40 #[salsa::interned]
44 fn intern_impl(&self, loc: ItemLoc<ast::ImplBlock>) -> ImplId; 41 fn intern_impl(&self, loc: ImplLoc) -> ImplId;
45} 42}
46 43
47#[salsa::query_group(DefDatabaseStorage)] 44#[salsa::query_group(DefDatabaseStorage)]
48pub trait DefDatabase: InternDatabase + AstDatabase { 45pub trait DefDatabase: InternDatabase + AstDatabase {
49 #[salsa::invoke(RawItems::raw_items_with_source_map_query)]
50 fn raw_items_with_source_map(
51 &self,
52 file_id: HirFileId,
53 ) -> (Arc<RawItems>, Arc<ImportSourceMap>);
54
55 #[salsa::invoke(RawItems::raw_items_query)] 46 #[salsa::invoke(RawItems::raw_items_query)]
56 fn raw_items(&self, file_id: HirFileId) -> Arc<RawItems>; 47 fn raw_items(&self, file_id: HirFileId) -> Arc<RawItems>;
57 48
diff --git a/crates/ra_hir_def/src/diagnostics.rs b/crates/ra_hir_def/src/diagnostics.rs
index eda9b2269..095498429 100644
--- a/crates/ra_hir_def/src/diagnostics.rs
+++ b/crates/ra_hir_def/src/diagnostics.rs
@@ -6,7 +6,7 @@ use hir_expand::diagnostics::Diagnostic;
6use ra_db::RelativePathBuf; 6use ra_db::RelativePathBuf;
7use ra_syntax::{ast, AstPtr, SyntaxNodePtr}; 7use ra_syntax::{ast, AstPtr, SyntaxNodePtr};
8 8
9use hir_expand::{HirFileId, Source}; 9use hir_expand::{HirFileId, InFile};
10 10
11#[derive(Debug)] 11#[derive(Debug)]
12pub struct UnresolvedModule { 12pub struct UnresolvedModule {
@@ -19,8 +19,8 @@ impl Diagnostic for UnresolvedModule {
19 fn message(&self) -> String { 19 fn message(&self) -> String {
20 "unresolved module".to_string() 20 "unresolved module".to_string()
21 } 21 }
22 fn source(&self) -> Source<SyntaxNodePtr> { 22 fn source(&self) -> InFile<SyntaxNodePtr> {
23 Source { file_id: self.file, value: self.decl.into() } 23 InFile { file_id: self.file, value: self.decl.into() }
24 } 24 }
25 fn as_any(&self) -> &(dyn Any + Send + 'static) { 25 fn as_any(&self) -> &(dyn Any + Send + 'static) {
26 self 26 self
diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs
index 34ed9b7a5..b29f142e3 100644
--- a/crates/ra_hir_def/src/docs.rs
+++ b/crates/ra_hir_def/src/docs.rs
@@ -5,10 +5,14 @@
5 5
6use std::sync::Arc; 6use std::sync::Arc;
7 7
8use hir_expand::either::Either; 8use either::Either;
9use ra_syntax::ast; 9use ra_syntax::ast;
10 10
11use crate::{db::DefDatabase, AdtId, AstItemDef, AttrDefId, HasChildSource, HasSource, Lookup}; 11use crate::{
12 db::DefDatabase,
13 src::{HasChildSource, HasSource},
14 AdtId, AttrDefId, Lookup,
15};
12 16
13/// Holds documentation 17/// Holds documentation
14#[derive(Debug, Clone, PartialEq, Eq)] 18#[derive(Debug, Clone, PartialEq, Eq)]
@@ -42,21 +46,21 @@ impl Documentation {
42 AttrDefId::StructFieldId(it) => { 46 AttrDefId::StructFieldId(it) => {
43 let src = it.parent.child_source(db); 47 let src = it.parent.child_source(db);
44 match &src.value[it.local_id] { 48 match &src.value[it.local_id] {
45 Either::A(_tuple) => None, 49 Either::Left(_tuple) => None,
46 Either::B(record) => docs_from_ast(record), 50 Either::Right(record) => docs_from_ast(record),
47 } 51 }
48 } 52 }
49 AttrDefId::AdtId(it) => match it { 53 AttrDefId::AdtId(it) => match it {
50 AdtId::StructId(it) => docs_from_ast(&it.source(db).value), 54 AdtId::StructId(it) => docs_from_ast(&it.lookup(db).source(db).value),
51 AdtId::EnumId(it) => docs_from_ast(&it.source(db).value), 55 AdtId::EnumId(it) => docs_from_ast(&it.lookup(db).source(db).value),
52 AdtId::UnionId(it) => docs_from_ast(&it.source(db).value), 56 AdtId::UnionId(it) => docs_from_ast(&it.lookup(db).source(db).value),
53 }, 57 },
54 AttrDefId::EnumVariantId(it) => { 58 AttrDefId::EnumVariantId(it) => {
55 let src = it.parent.child_source(db); 59 let src = it.parent.child_source(db);
56 docs_from_ast(&src.value[it.local_id]) 60 docs_from_ast(&src.value[it.local_id])
57 } 61 }
58 AttrDefId::TraitId(it) => docs_from_ast(&it.source(db).value), 62 AttrDefId::TraitId(it) => docs_from_ast(&it.lookup(db).source(db).value),
59 AttrDefId::MacroDefId(it) => docs_from_ast(&it.ast_id.to_node(db)), 63 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), 64 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), 65 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), 66 AttrDefId::FunctionId(it) => docs_from_ast(&it.lookup(db).source(db).value),
diff --git a/crates/ra_hir_def/src/dyn_map.rs b/crates/ra_hir_def/src/dyn_map.rs
new file mode 100644
index 000000000..6f269d7b0
--- /dev/null
+++ b/crates/ra_hir_def/src/dyn_map.rs
@@ -0,0 +1,108 @@
1//! This module defines a `DynMap` -- a container for heterogeneous maps.
2//!
3//! This means that `DynMap` stores a bunch of hash maps inside, and those maps
4//! can be of different types.
5//!
6//! It is used like this:
7//!
8//! ```
9//! // keys define submaps of a `DynMap`
10//! const STRING_TO_U32: Key<String, u32> = Key::new();
11//! const U32_TO_VEC: Key<u32, Vec<bool>> = Key::new();
12//!
13//! // Note: concrete type, no type params!
14//! let mut map = DynMap::new();
15//!
16//! // To access a specific map, index the `DynMap` by `Key`:
17//! map[STRING_TO_U32].insert("hello".to_string(), 92);
18//! let value = map[U32_TO_VEC].get(92);
19//! assert!(value.is_none());
20//! ```
21//!
22//! This is a work of fiction. Any similarities to Kotlin's `BindingContext` are
23//! a coincidence.
24use std::{
25 hash::Hash,
26 marker::PhantomData,
27 ops::{Index, IndexMut},
28};
29
30use anymap::Map;
31use rustc_hash::FxHashMap;
32
33pub struct Key<K, V, P = (K, V)> {
34 _phantom: PhantomData<(K, V, P)>,
35}
36
37impl<K, V, P> Key<K, V, P> {
38 pub(crate) const fn new() -> Key<K, V, P> {
39 Key { _phantom: PhantomData }
40 }
41}
42
43impl<K, V, P> Copy for Key<K, V, P> {}
44
45impl<K, V, P> Clone for Key<K, V, P> {
46 fn clone(&self) -> Key<K, V, P> {
47 *self
48 }
49}
50
51pub trait Policy {
52 type K;
53 type V;
54
55 fn insert(map: &mut DynMap, key: Self::K, value: Self::V);
56 fn get<'a>(map: &'a DynMap, key: &Self::K) -> Option<&'a Self::V>;
57}
58
59impl<K: Hash + Eq + 'static, V: 'static> Policy for (K, V) {
60 type K = K;
61 type V = V;
62 fn insert(map: &mut DynMap, key: K, value: V) {
63 map.map.entry::<FxHashMap<K, V>>().or_insert_with(Default::default).insert(key, value);
64 }
65 fn get<'a>(map: &'a DynMap, key: &K) -> Option<&'a V> {
66 map.map.get::<FxHashMap<K, V>>()?.get(key)
67 }
68}
69
70pub struct DynMap {
71 pub(crate) map: Map,
72}
73
74impl Default for DynMap {
75 fn default() -> Self {
76 DynMap { map: Map::new() }
77 }
78}
79
80#[repr(transparent)]
81pub struct KeyMap<KEY> {
82 map: DynMap,
83 _phantom: PhantomData<KEY>,
84}
85
86impl<P: Policy> KeyMap<Key<P::K, P::V, P>> {
87 pub fn insert(&mut self, key: P::K, value: P::V) {
88 P::insert(&mut self.map, key, value)
89 }
90 pub fn get(&self, key: &P::K) -> Option<&P::V> {
91 P::get(&self.map, key)
92 }
93}
94
95impl<P: Policy> Index<Key<P::K, P::V, P>> for DynMap {
96 type Output = KeyMap<Key<P::K, P::V, P>>;
97 fn index(&self, _key: Key<P::K, P::V, P>) -> &Self::Output {
98 // Safe due to `#[repr(transparent)]`.
99 unsafe { std::mem::transmute::<&DynMap, &KeyMap<Key<P::K, P::V, P>>>(self) }
100 }
101}
102
103impl<P: Policy> IndexMut<Key<P::K, P::V, P>> for DynMap {
104 fn index_mut(&mut self, _key: Key<P::K, P::V, P>) -> &mut Self::Output {
105 // Safe due to `#[repr(transparent)]`.
106 unsafe { std::mem::transmute::<&mut DynMap, &mut KeyMap<Key<P::K, P::V, P>>>(self) }
107 }
108}
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs
index 04c1d8f69..a75ef9970 100644
--- a/crates/ra_hir_def/src/expr.rs
+++ b/crates/ra_hir_def/src/expr.rs
@@ -14,6 +14,7 @@
14 14
15use hir_expand::name::Name; 15use hir_expand::name::Name;
16use ra_arena::{impl_arena_id, RawId}; 16use ra_arena::{impl_arena_id, RawId};
17use ra_syntax::ast::RangeOp;
17 18
18use crate::{ 19use crate::{
19 builtin_type::{BuiltinFloat, BuiltinInt}, 20 builtin_type::{BuiltinFloat, BuiltinInt},
@@ -130,6 +131,11 @@ pub enum Expr {
130 rhs: ExprId, 131 rhs: ExprId,
131 op: Option<BinaryOp>, 132 op: Option<BinaryOp>,
132 }, 133 },
134 Range {
135 lhs: Option<ExprId>,
136 rhs: Option<ExprId>,
137 range_type: RangeOp,
138 },
133 Index { 139 Index {
134 base: ExprId, 140 base: ExprId,
135 index: ExprId, 141 index: ExprId,
@@ -137,6 +143,7 @@ pub enum Expr {
137 Lambda { 143 Lambda {
138 args: Vec<PatId>, 144 args: Vec<PatId>,
139 arg_types: Vec<Option<TypeRef>>, 145 arg_types: Vec<Option<TypeRef>>,
146 ret_type: Option<TypeRef>,
140 body: ExprId, 147 body: ExprId,
141 }, 148 },
142 Tuple { 149 Tuple {
@@ -288,6 +295,14 @@ impl Expr {
288 f(*lhs); 295 f(*lhs);
289 f(*rhs); 296 f(*rhs);
290 } 297 }
298 Expr::Range { lhs, rhs, .. } => {
299 if let Some(lhs) = rhs {
300 f(*lhs);
301 }
302 if let Some(rhs) = lhs {
303 f(*rhs);
304 }
305 }
291 Expr::Index { base, index } => { 306 Expr::Index { base, index } => {
292 f(*base); 307 f(*base);
293 f(*index); 308 f(*index);
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
index 3f94e40e4..e9c28c730 100644
--- a/crates/ra_hir_def/src/generics.rs
+++ b/crates/ra_hir_def/src/generics.rs
@@ -4,20 +4,29 @@
4//! in rustc. 4//! in rustc.
5use std::sync::Arc; 5use std::sync::Arc;
6 6
7use hir_expand::name::{self, AsName, Name}; 7use either::Either;
8use hir_expand::{
9 name::{name, AsName, Name},
10 InFile,
11};
12use ra_arena::{map::ArenaMap, Arena};
13use ra_db::FileId;
8use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; 14use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
9 15
10use crate::{ 16use crate::{
17 child_by_source::ChildBySource,
11 db::DefDatabase, 18 db::DefDatabase,
19 dyn_map::DynMap,
20 keys,
21 src::HasChildSource,
22 src::HasSource,
12 type_ref::{TypeBound, TypeRef}, 23 type_ref::{TypeBound, TypeRef},
13 AdtId, AstItemDef, ContainerId, GenericDefId, HasSource, Lookup, 24 AdtId, GenericDefId, LocalTypeParamId, Lookup, TypeParamId,
14}; 25};
15 26
16/// Data about a generic parameter (to a function, struct, impl, ...). 27/// Data about a generic parameter (to a function, struct, impl, ...).
17#[derive(Clone, PartialEq, Eq, Debug)] 28#[derive(Clone, PartialEq, Eq, Debug)]
18pub struct GenericParam { 29pub struct TypeParamData {
19 // FIXME: give generic params proper IDs
20 pub idx: u32,
21 pub name: Name, 30 pub name: Name,
22 pub default: Option<TypeRef>, 31 pub default: Option<TypeRef>,
23} 32}
@@ -25,8 +34,8 @@ pub struct GenericParam {
25/// Data about the generic parameters of a function, struct, impl, etc. 34/// Data about the generic parameters of a function, struct, impl, etc.
26#[derive(Clone, PartialEq, Eq, Debug)] 35#[derive(Clone, PartialEq, Eq, Debug)]
27pub struct GenericParams { 36pub struct GenericParams {
28 pub parent_params: Option<Arc<GenericParams>>, 37 pub types: Arena<LocalTypeParamId, TypeParamData>,
29 pub params: Vec<GenericParam>, 38 // lifetimes: Arena<LocalLifetimeParamId, LifetimeParamData>,
30 pub where_predicates: Vec<WherePredicate>, 39 pub where_predicates: Vec<WherePredicate>,
31} 40}
32 41
@@ -40,63 +49,87 @@ pub struct WherePredicate {
40 pub bound: TypeBound, 49 pub bound: TypeBound,
41} 50}
42 51
52type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::TraitDef, ast::TypeParam>>;
53
43impl GenericParams { 54impl GenericParams {
44 pub(crate) fn generic_params_query( 55 pub(crate) fn generic_params_query(
45 db: &impl DefDatabase, 56 db: &impl DefDatabase,
46 def: GenericDefId, 57 def: GenericDefId,
47 ) -> Arc<GenericParams> { 58 ) -> Arc<GenericParams> {
48 let parent_generics = parent_generic_def(db, def).map(|it| db.generic_params(it)); 59 let (params, _source_map) = GenericParams::new(db, def.into());
49 Arc::new(GenericParams::new(db, def.into(), parent_generics)) 60 Arc::new(params)
50 } 61 }
51 62
52 fn new( 63 fn new(db: &impl DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) {
53 db: &impl DefDatabase, 64 let mut generics = GenericParams { types: Arena::default(), where_predicates: Vec::new() };
54 def: GenericDefId, 65 let mut sm = ArenaMap::default();
55 parent_params: Option<Arc<GenericParams>>,
56 ) -> GenericParams {
57 let mut generics =
58 GenericParams { params: Vec::new(), parent_params, where_predicates: Vec::new() };
59 let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32;
60 // FIXME: add `: Sized` bound for everything except for `Self` in traits 66 // FIXME: add `: Sized` bound for everything except for `Self` in traits
61 match def { 67 let file_id = match def {
62 GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start), 68 GenericDefId::FunctionId(it) => {
63 GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value, start), 69 let src = it.lookup(db).source(db);
64 GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value, start), 70 generics.fill(&mut sm, &src.value);
65 GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start), 71 src.file_id
72 }
73 GenericDefId::AdtId(AdtId::StructId(it)) => {
74 let src = it.lookup(db).source(db);
75 generics.fill(&mut sm, &src.value);
76 src.file_id
77 }
78 GenericDefId::AdtId(AdtId::UnionId(it)) => {
79 let src = it.lookup(db).source(db);
80 generics.fill(&mut sm, &src.value);
81 src.file_id
82 }
83 GenericDefId::AdtId(AdtId::EnumId(it)) => {
84 let src = it.lookup(db).source(db);
85 generics.fill(&mut sm, &src.value);
86 src.file_id
87 }
66 GenericDefId::TraitId(it) => { 88 GenericDefId::TraitId(it) => {
89 let src = it.lookup(db).source(db);
90
67 // traits get the Self type as an implicit first type parameter 91 // traits get the Self type as an implicit first type parameter
68 generics.params.push(GenericParam { 92 let self_param_id =
69 idx: start, 93 generics.types.alloc(TypeParamData { name: name![Self], default: None });
70 name: name::SELF_TYPE, 94 sm.insert(self_param_id, Either::Left(src.value.clone()));
71 default: None,
72 });
73 generics.fill(&it.source(db).value, start + 1);
74 // add super traits as bounds on Self 95 // add super traits as bounds on Self
75 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar 96 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
76 let self_param = TypeRef::Path(name::SELF_TYPE.into()); 97 let self_param = TypeRef::Path(name![Self].into());
77 generics.fill_bounds(&it.source(db).value, self_param); 98 generics.fill_bounds(&src.value, self_param);
99
100 generics.fill(&mut sm, &src.value);
101 src.file_id
102 }
103 GenericDefId::TypeAliasId(it) => {
104 let src = it.lookup(db).source(db);
105 generics.fill(&mut sm, &src.value);
106 src.file_id
78 } 107 }
79 GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value, start),
80 // Note that we don't add `Self` here: in `impl`s, `Self` is not a 108 // Note that we don't add `Self` here: in `impl`s, `Self` is not a
81 // type-parameter, but rather is a type-alias for impl's target 109 // type-parameter, but rather is a type-alias for impl's target
82 // type, so this is handled by the resolver. 110 // type, so this is handled by the resolver.
83 GenericDefId::ImplId(it) => generics.fill(&it.source(db).value, start), 111 GenericDefId::ImplId(it) => {
84 GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {} 112 let src = it.lookup(db).source(db);
85 } 113 generics.fill(&mut sm, &src.value);
114 src.file_id
115 }
116 // We won't be using this ID anyway
117 GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => FileId(!0).into(),
118 };
86 119
87 generics 120 (generics, InFile::new(file_id, sm))
88 } 121 }
89 122
90 fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) { 123 fn fill(&mut self, sm: &mut SourceMap, node: &dyn TypeParamsOwner) {
91 if let Some(params) = node.type_param_list() { 124 if let Some(params) = node.type_param_list() {
92 self.fill_params(params, start) 125 self.fill_params(sm, params)
93 } 126 }
94 if let Some(where_clause) = node.where_clause() { 127 if let Some(where_clause) = node.where_clause() {
95 self.fill_where_predicates(where_clause); 128 self.fill_where_predicates(where_clause);
96 } 129 }
97 } 130 }
98 131
99 fn fill_bounds(&mut self, node: &impl ast::TypeBoundsOwner, type_ref: TypeRef) { 132 fn fill_bounds(&mut self, node: &dyn ast::TypeBoundsOwner, type_ref: TypeRef) {
100 for bound in 133 for bound in
101 node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) 134 node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds())
102 { 135 {
@@ -104,13 +137,14 @@ impl GenericParams {
104 } 137 }
105 } 138 }
106 139
107 fn fill_params(&mut self, params: ast::TypeParamList, start: u32) { 140 fn fill_params(&mut self, sm: &mut SourceMap, params: ast::TypeParamList) {
108 for (idx, type_param) in params.type_params().enumerate() { 141 for type_param in params.type_params() {
109 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); 142 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
110 // FIXME: Use `Path::from_src` 143 // FIXME: Use `Path::from_src`
111 let default = type_param.default_type().map(TypeRef::from_ast); 144 let default = type_param.default_type().map(TypeRef::from_ast);
112 let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default }; 145 let param = TypeParamData { name: name.clone(), default };
113 self.params.push(param); 146 let param_id = self.types.alloc(param);
147 sm.insert(param_id, Either::Right(type_param.clone()));
114 148
115 let type_ref = TypeRef::Path(name.into()); 149 let type_ref = TypeRef::Path(name.into());
116 self.fill_bounds(&type_param, type_ref); 150 self.fill_bounds(&type_param, type_ref);
@@ -139,45 +173,31 @@ impl GenericParams {
139 self.where_predicates.push(WherePredicate { type_ref, bound }); 173 self.where_predicates.push(WherePredicate { type_ref, bound });
140 } 174 }
141 175
142 pub fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { 176 pub fn find_by_name(&self, name: &Name) -> Option<LocalTypeParamId> {
143 self.params.iter().find(|p| &p.name == name) 177 self.types.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None })
144 }
145
146 pub fn count_parent_params(&self) -> usize {
147 self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0)
148 }
149
150 pub fn count_params_including_parent(&self) -> usize {
151 let parent_count = self.count_parent_params();
152 parent_count + self.params.len()
153 }
154
155 fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParam)) {
156 if let Some(parent) = &self.parent_params {
157 parent.for_each_param(f);
158 }
159 self.params.iter().for_each(f);
160 } 178 }
179}
161 180
162 pub fn params_including_parent(&self) -> Vec<&GenericParam> { 181impl HasChildSource for GenericDefId {
163 let mut vec = Vec::with_capacity(self.count_params_including_parent()); 182 type ChildId = LocalTypeParamId;
164 self.for_each_param(&mut |p| vec.push(p)); 183 type Value = Either<ast::TraitDef, ast::TypeParam>;
165 vec 184 fn child_source(&self, db: &impl DefDatabase) -> InFile<SourceMap> {
185 let (_, sm) = GenericParams::new(db, *self);
186 sm
166 } 187 }
167} 188}
168 189
169fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option<GenericDefId> { 190impl ChildBySource for GenericDefId {
170 let container = match def { 191 fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
171 GenericDefId::FunctionId(it) => it.lookup(db).container, 192 let mut res = DynMap::default();
172 GenericDefId::TypeAliasId(it) => it.lookup(db).container, 193 let arena_map = self.child_source(db);
173 GenericDefId::ConstId(it) => it.lookup(db).container, 194 let arena_map = arena_map.as_ref();
174 GenericDefId::EnumVariantId(it) => return Some(it.parent.into()), 195 for (local_id, src) in arena_map.value.iter() {
175 GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) => return None, 196 let id = TypeParamId { parent: *self, local_id };
176 }; 197 if let Either::Right(type_param) = src {
177 198 res[keys::TYPE_PARAM].insert(arena_map.with_value(type_param.clone()), id)
178 match container { 199 }
179 ContainerId::ImplId(it) => Some(it.into()), 200 }
180 ContainerId::TraitId(it) => Some(it.into()), 201 res
181 ContainerId::ModuleId(_) => None,
182 } 202 }
183} 203}
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs
new file mode 100644
index 000000000..b0288ee8d
--- /dev/null
+++ b/crates/ra_hir_def/src/item_scope.rs
@@ -0,0 +1,172 @@
1//! Describes items defined or visible (ie, imported) in a certain scope.
2//! This is shared between modules and blocks.
3
4use hir_expand::name::Name;
5use once_cell::sync::Lazy;
6use rustc_hash::FxHashMap;
7
8use crate::{per_ns::PerNs, AdtId, BuiltinType, ImplId, MacroDefId, ModuleDefId, TraitId};
9
10#[derive(Debug, Default, PartialEq, Eq)]
11pub struct ItemScope {
12 visible: FxHashMap<Name, PerNs>,
13 defs: Vec<ModuleDefId>,
14 impls: Vec<ImplId>,
15 /// Macros visible in current module in legacy textual scope
16 ///
17 /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first.
18 /// If it yields no result, then it turns to module scoped `macros`.
19 /// It macros with name qualified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped,
20 /// and only normal scoped `macros` will be searched in.
21 ///
22 /// Note that this automatically inherit macros defined textually before the definition of module itself.
23 ///
24 /// Module scoped macros will be inserted into `items` instead of here.
25 // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
26 // be all resolved to the last one defined if shadowing happens.
27 legacy_macros: FxHashMap<Name, MacroDefId>,
28}
29
30static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| {
31 BuiltinType::ALL
32 .iter()
33 .map(|(name, ty)| (name.clone(), PerNs::types(ty.clone().into())))
34 .collect()
35});
36
37/// Shadow mode for builtin type which can be shadowed by module.
38#[derive(Debug, Copy, Clone, PartialEq, Eq)]
39pub(crate) enum BuiltinShadowMode {
40 // Prefer Module
41 Module,
42 // Prefer Other Types
43 Other,
44}
45
46/// Legacy macros can only be accessed through special methods like `get_legacy_macros`.
47/// Other methods will only resolve values, types and module scoped macros only.
48impl ItemScope {
49 pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a {
50 //FIXME: shadowing
51 self.visible.iter().chain(BUILTIN_SCOPE.iter()).map(|(n, def)| (n, *def))
52 }
53
54 pub fn entries_without_primitives<'a>(
55 &'a self,
56 ) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a {
57 self.visible.iter().map(|(n, def)| (n, *def))
58 }
59
60 pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
61 self.defs.iter().copied()
62 }
63
64 pub fn impls(&self) -> impl Iterator<Item = ImplId> + ExactSizeIterator + '_ {
65 self.impls.iter().copied()
66 }
67
68 /// Iterate over all module scoped macros
69 pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
70 self.visible.iter().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_)))
71 }
72
73 /// Iterate over all legacy textual scoped macros visible at the end of the module
74 pub(crate) fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
75 self.legacy_macros.iter().map(|(name, def)| (name, *def))
76 }
77
78 /// Get a name from current module scope, legacy macros are not included
79 pub(crate) fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> PerNs {
80 match shadow {
81 BuiltinShadowMode::Module => self
82 .visible
83 .get(name)
84 .or_else(|| BUILTIN_SCOPE.get(name))
85 .copied()
86 .unwrap_or_else(PerNs::none),
87 BuiltinShadowMode::Other => {
88 let item = self.visible.get(name).copied();
89 if let Some(def) = item {
90 if let Some(ModuleDefId::ModuleId(_)) = def.take_types() {
91 return BUILTIN_SCOPE
92 .get(name)
93 .copied()
94 .or(item)
95 .unwrap_or_else(PerNs::none);
96 }
97 }
98
99 item.or_else(|| BUILTIN_SCOPE.get(name).copied()).unwrap_or_else(PerNs::none)
100 }
101 }
102 }
103
104 pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
105 self.visible.values().filter_map(|def| match def.take_types() {
106 Some(ModuleDefId::TraitId(t)) => Some(t),
107 _ => None,
108 })
109 }
110
111 pub(crate) fn define_def(&mut self, def: ModuleDefId) {
112 self.defs.push(def)
113 }
114
115 pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<MacroDefId> {
116 self.legacy_macros.get(name).copied()
117 }
118
119 pub(crate) fn define_impl(&mut self, imp: ImplId) {
120 self.impls.push(imp)
121 }
122
123 pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroDefId) {
124 self.legacy_macros.insert(name, mac);
125 }
126
127 pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool {
128 let mut changed = false;
129 let existing = self.visible.entry(name.clone()).or_default();
130
131 if existing.types.is_none() && def.types.is_some() {
132 existing.types = def.types;
133 changed = true;
134 }
135 if existing.values.is_none() && def.values.is_some() {
136 existing.values = def.values;
137 changed = true;
138 }
139 if existing.macros.is_none() && def.macros.is_some() {
140 existing.macros = def.macros;
141 changed = true;
142 }
143
144 changed
145 }
146
147 pub(crate) fn collect_resolutions(&self) -> Vec<(Name, PerNs)> {
148 self.visible.iter().map(|(name, res)| (name.clone(), res.clone())).collect()
149 }
150
151 pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> {
152 self.legacy_macros.clone()
153 }
154}
155
156impl From<ModuleDefId> for PerNs {
157 fn from(def: ModuleDefId) -> PerNs {
158 match def {
159 ModuleDefId::ModuleId(_) => PerNs::types(def),
160 ModuleDefId::FunctionId(_) => PerNs::values(def),
161 ModuleDefId::AdtId(adt) => match adt {
162 AdtId::StructId(_) | AdtId::UnionId(_) => PerNs::both(def, def),
163 AdtId::EnumId(_) => PerNs::types(def),
164 },
165 ModuleDefId::EnumVariantId(_) => PerNs::both(def, def),
166 ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def),
167 ModuleDefId::TraitId(_) => PerNs::types(def),
168 ModuleDefId::TypeAliasId(_) => PerNs::types(def),
169 ModuleDefId::BuiltinType(_) => PerNs::types(def),
170 }
171 }
172}
diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs
new file mode 100644
index 000000000..d844f7a62
--- /dev/null
+++ b/crates/ra_hir_def/src/keys.rs
@@ -0,0 +1,56 @@
1//! keys to be used with `DynMap`
2
3use std::marker::PhantomData;
4
5use hir_expand::InFile;
6use ra_syntax::{ast, AstNode, AstPtr};
7use rustc_hash::FxHashMap;
8
9use crate::{
10 dyn_map::{DynMap, Policy},
11 ConstId, EnumId, EnumVariantId, FunctionId, ImplId, StaticId, StructFieldId, StructId, TraitId,
12 TypeAliasId, TypeParamId, UnionId,
13};
14
15pub type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>;
16
17pub const FUNCTION: Key<ast::FnDef, FunctionId> = Key::new();
18pub const CONST: Key<ast::ConstDef, ConstId> = Key::new();
19pub const STATIC: Key<ast::StaticDef, StaticId> = Key::new();
20pub const TYPE_ALIAS: Key<ast::TypeAliasDef, TypeAliasId> = Key::new();
21pub const IMPL: Key<ast::ImplBlock, ImplId> = Key::new();
22pub const TRAIT: Key<ast::TraitDef, TraitId> = Key::new();
23pub const STRUCT: Key<ast::StructDef, StructId> = Key::new();
24pub const UNION: Key<ast::UnionDef, UnionId> = Key::new();
25pub const ENUM: Key<ast::EnumDef, EnumId> = Key::new();
26
27pub const ENUM_VARIANT: Key<ast::EnumVariant, EnumVariantId> = Key::new();
28pub const TUPLE_FIELD: Key<ast::TupleFieldDef, StructFieldId> = Key::new();
29pub const RECORD_FIELD: Key<ast::RecordFieldDef, StructFieldId> = Key::new();
30pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new();
31
32/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
33/// equal if they point to exactly the same object.
34///
35/// In general, we do not guarantee that we have exactly one instance of a
36/// syntax tree for each file. We probably should add such guarantee, but, for
37/// the time being, we will use identity-less AstPtr comparison.
38pub struct AstPtrPolicy<AST, ID> {
39 _phantom: PhantomData<(AST, ID)>,
40}
41
42impl<AST: AstNode + 'static, ID: 'static> Policy for AstPtrPolicy<AST, ID> {
43 type K = InFile<AST>;
44 type V = ID;
45 fn insert(map: &mut DynMap, key: InFile<AST>, value: ID) {
46 let key = key.as_ref().map(AstPtr::new);
47 map.map
48 .entry::<FxHashMap<InFile<AstPtr<AST>>, ID>>()
49 .or_insert_with(Default::default)
50 .insert(key, value);
51 }
52 fn get<'a>(map: &'a DynMap, key: &InFile<AST>) -> Option<&'a ID> {
53 let key = key.as_ref().map(AstPtr::new);
54 map.map.get::<FxHashMap<InFile<AstPtr<AST>>, ID>>()?.get(&key)
55 }
56}
diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs
index f4fdbdcfc..cef061837 100644
--- a/crates/ra_hir_def/src/lang_item.rs
+++ b/crates/ra_hir_def/src/lang_item.rs
@@ -81,7 +81,7 @@ impl LangItems {
81 // Look for impl targets 81 // Look for impl targets
82 let def_map = db.crate_def_map(module.krate); 82 let def_map = db.crate_def_map(module.krate);
83 let module_data = &def_map[module.local_id]; 83 let module_data = &def_map[module.local_id];
84 for &impl_block in module_data.impls.iter() { 84 for impl_block in module_data.scope.impls() {
85 self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlockId) 85 self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlockId)
86 } 86 }
87 87
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index bc5530896..f6c7f38d1 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -15,6 +15,10 @@ pub mod type_ref;
15pub mod builtin_type; 15pub mod builtin_type;
16pub mod diagnostics; 16pub mod diagnostics;
17pub mod per_ns; 17pub mod per_ns;
18pub mod item_scope;
19
20pub mod dyn_map;
21pub mod keys;
18 22
19pub mod adt; 23pub mod adt;
20pub mod data; 24pub mod data;
@@ -29,23 +33,23 @@ pub mod resolver;
29mod trace; 33mod trace;
30pub mod nameres; 34pub mod nameres;
31 35
36pub mod src;
37pub mod child_by_source;
38
32#[cfg(test)] 39#[cfg(test)]
33mod test_db; 40mod test_db;
34#[cfg(test)] 41#[cfg(test)]
35mod marks; 42mod marks;
36 43
37use std::hash::{Hash, Hasher}; 44use std::hash::Hash;
38 45
39use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, MacroDefId, Source}; 46use hir_expand::{ast_id_map::FileAstId, AstId, HirFileId, InFile, MacroDefId};
40use ra_arena::{impl_arena_id, map::ArenaMap, RawId}; 47use ra_arena::{impl_arena_id, RawId};
41use ra_db::{impl_intern_key, salsa, CrateId}; 48use ra_db::{impl_intern_key, salsa, CrateId};
42use ra_syntax::{ast, AstNode}; 49use ra_syntax::{ast, AstNode};
43 50
44use crate::{builtin_type::BuiltinType, db::InternDatabase}; 51use crate::body::Expander;
45 52use crate::builtin_type::BuiltinType;
46#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
47pub struct LocalImportId(RawId);
48impl_arena_id!(LocalImportId);
49 53
50#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 54#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
51pub struct ModuleId { 55pub struct ModuleId {
@@ -59,122 +63,57 @@ pub struct ModuleId {
59pub struct LocalModuleId(RawId); 63pub struct LocalModuleId(RawId);
60impl_arena_id!(LocalModuleId); 64impl_arena_id!(LocalModuleId);
61 65
62#[derive(Debug)] 66#[derive(Debug, Clone, PartialEq, Eq, Hash)]
63pub struct ItemLoc<N: AstNode> { 67pub struct ItemLoc<N: AstNode> {
64 pub(crate) module: ModuleId, 68 pub container: ContainerId,
65 ast_id: AstId<N>, 69 pub ast_id: AstId<N>,
66}
67
68impl<N: AstNode> PartialEq for ItemLoc<N> {
69 fn eq(&self, other: &Self) -> bool {
70 self.module == other.module && self.ast_id == other.ast_id
71 }
72}
73impl<N: AstNode> Eq for ItemLoc<N> {}
74impl<N: AstNode> Hash for ItemLoc<N> {
75 fn hash<H: Hasher>(&self, hasher: &mut H) {
76 self.module.hash(hasher);
77 self.ast_id.hash(hasher);
78 }
79}
80
81impl<N: AstNode> Clone for ItemLoc<N> {
82 fn clone(&self) -> ItemLoc<N> {
83 ItemLoc { module: self.module, ast_id: self.ast_id }
84 }
85} 70}
86 71
87#[derive(Clone, Copy)] 72#[derive(Debug, Clone, PartialEq, Eq, Hash)]
88pub struct LocationCtx<DB> { 73pub struct AssocItemLoc<N: AstNode> {
89 db: DB, 74 pub container: AssocContainerId,
90 module: ModuleId, 75 pub ast_id: AstId<N>,
91 file_id: HirFileId,
92} 76}
93 77
94impl<'a, DB> LocationCtx<&'a DB> { 78macro_rules! impl_intern {
95 pub fn new(db: &'a DB, module: ModuleId, file_id: HirFileId) -> LocationCtx<&'a DB> { 79 ($id:ident, $loc:ident, $intern:ident, $lookup:ident) => {
96 LocationCtx { db, module, file_id } 80 impl_intern_key!($id);
97 }
98}
99 81
100pub trait AstItemDef<N: AstNode>: salsa::InternKey + Clone { 82 impl Intern for $loc {
101 fn intern(db: &impl InternDatabase, loc: ItemLoc<N>) -> Self; 83 type ID = $id;
102 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<N>; 84 fn intern(self, db: &impl db::DefDatabase) -> $id {
85 db.$intern(self)
86 }
87 }
103 88
104 fn from_ast_id(ctx: LocationCtx<&impl InternDatabase>, ast_id: FileAstId<N>) -> Self { 89 impl Lookup for $id {
105 let loc = ItemLoc { module: ctx.module, ast_id: AstId::new(ctx.file_id, ast_id) }; 90 type Data = $loc;
106 Self::intern(ctx.db, loc) 91 fn lookup(&self, db: &impl db::DefDatabase) -> $loc {
107 } 92 db.$lookup(*self)
108 fn source(self, db: &(impl AstDatabase + InternDatabase)) -> Source<N> { 93 }
109 let loc = self.lookup_intern(db); 94 }
110 let value = loc.ast_id.to_node(db); 95 };
111 Source { file_id: loc.ast_id.file_id(), value }
112 }
113 fn module(self, db: &impl InternDatabase) -> ModuleId {
114 let loc = self.lookup_intern(db);
115 loc.module
116 }
117} 96}
118 97
119#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 98#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
120pub struct FunctionId(salsa::InternId); 99pub struct FunctionId(salsa::InternId);
121impl_intern_key!(FunctionId); 100type FunctionLoc = AssocItemLoc<ast::FnDef>;
122 101impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function);
123#[derive(Debug, Clone, PartialEq, Eq, Hash)]
124pub struct FunctionLoc {
125 pub container: ContainerId,
126 pub ast_id: AstId<ast::FnDef>,
127}
128
129impl Intern for FunctionLoc {
130 type ID = FunctionId;
131 fn intern(self, db: &impl db::DefDatabase) -> FunctionId {
132 db.intern_function(self)
133 }
134}
135
136impl Lookup for FunctionId {
137 type Data = FunctionLoc;
138 fn lookup(&self, db: &impl db::DefDatabase) -> FunctionLoc {
139 db.lookup_intern_function(*self)
140 }
141}
142 102
143#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 103#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
144pub struct StructId(salsa::InternId); 104pub struct StructId(salsa::InternId);
145impl_intern_key!(StructId); 105type StructLoc = ItemLoc<ast::StructDef>;
146impl AstItemDef<ast::StructDef> for StructId { 106impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct);
147 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::StructDef>) -> Self {
148 db.intern_struct(loc)
149 }
150 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::StructDef> {
151 db.lookup_intern_struct(self)
152 }
153}
154 107
155#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 108#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
156pub struct UnionId(salsa::InternId); 109pub struct UnionId(salsa::InternId);
157impl_intern_key!(UnionId); 110pub type UnionLoc = ItemLoc<ast::UnionDef>;
158impl AstItemDef<ast::UnionDef> for UnionId { 111impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union);
159 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::UnionDef>) -> Self {
160 db.intern_union(loc)
161 }
162 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::UnionDef> {
163 db.lookup_intern_union(self)
164 }
165}
166 112
167#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 113#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
168pub struct EnumId(salsa::InternId); 114pub struct EnumId(salsa::InternId);
169impl_intern_key!(EnumId); 115pub type EnumLoc = ItemLoc<ast::EnumDef>;
170impl AstItemDef<ast::EnumDef> for EnumId { 116impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
171 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::EnumDef>) -> Self {
172 db.intern_enum(loc)
173 }
174 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::EnumDef> {
175 db.lookup_intern_enum(self)
176 }
177}
178 117
179// FIXME: rename to `VariantId`, only enums can ave variants 118// FIXME: rename to `VariantId`, only enums can ave variants
180#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 119#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -199,98 +138,38 @@ impl_arena_id!(LocalStructFieldId);
199 138
200#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 139#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
201pub struct ConstId(salsa::InternId); 140pub struct ConstId(salsa::InternId);
202impl_intern_key!(ConstId); 141type ConstLoc = AssocItemLoc<ast::ConstDef>;
203#[derive(Debug, Clone, PartialEq, Eq, Hash)] 142impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const);
204pub struct ConstLoc {
205 pub container: ContainerId,
206 pub ast_id: AstId<ast::ConstDef>,
207}
208
209impl Intern for ConstLoc {
210 type ID = ConstId;
211 fn intern(self, db: &impl db::DefDatabase) -> ConstId {
212 db.intern_const(self)
213 }
214}
215
216impl Lookup for ConstId {
217 type Data = ConstLoc;
218 fn lookup(&self, db: &impl db::DefDatabase) -> ConstLoc {
219 db.lookup_intern_const(*self)
220 }
221}
222 143
223#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 144#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
224pub struct StaticId(salsa::InternId); 145pub struct StaticId(salsa::InternId);
225impl_intern_key!(StaticId); 146pub type StaticLoc = ItemLoc<ast::StaticDef>;
226 147impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static);
227#[derive(Debug, Clone, PartialEq, Eq, Hash)]
228pub struct StaticLoc {
229 pub container: ModuleId,
230 pub ast_id: AstId<ast::StaticDef>,
231}
232
233impl Intern for StaticLoc {
234 type ID = StaticId;
235 fn intern(self, db: &impl db::DefDatabase) -> StaticId {
236 db.intern_static(self)
237 }
238}
239
240impl Lookup for StaticId {
241 type Data = StaticLoc;
242 fn lookup(&self, db: &impl db::DefDatabase) -> StaticLoc {
243 db.lookup_intern_static(*self)
244 }
245}
246 148
247#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 149#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
248pub struct TraitId(salsa::InternId); 150pub struct TraitId(salsa::InternId);
249impl_intern_key!(TraitId); 151pub type TraitLoc = ItemLoc<ast::TraitDef>;
250impl AstItemDef<ast::TraitDef> for TraitId { 152impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait);
251 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::TraitDef>) -> Self {
252 db.intern_trait(loc)
253 }
254 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::TraitDef> {
255 db.lookup_intern_trait(self)
256 }
257}
258 153
259#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 154#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
260pub struct TypeAliasId(salsa::InternId); 155pub struct TypeAliasId(salsa::InternId);
261impl_intern_key!(TypeAliasId); 156type TypeAliasLoc = AssocItemLoc<ast::TypeAliasDef>;
262 157impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias);
263#[derive(Debug, Clone, PartialEq, Eq, Hash)]
264pub struct TypeAliasLoc {
265 pub container: ContainerId,
266 pub ast_id: AstId<ast::TypeAliasDef>,
267}
268 158
269impl Intern for TypeAliasLoc { 159#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
270 type ID = TypeAliasId; 160pub struct ImplId(salsa::InternId);
271 fn intern(self, db: &impl db::DefDatabase) -> TypeAliasId { 161type ImplLoc = ItemLoc<ast::ImplBlock>;
272 db.intern_type_alias(self) 162impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl);
273 }
274}
275 163
276impl Lookup for TypeAliasId { 164#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
277 type Data = TypeAliasLoc; 165pub struct TypeParamId {
278 fn lookup(&self, db: &impl db::DefDatabase) -> TypeAliasLoc { 166 pub parent: GenericDefId,
279 db.lookup_intern_type_alias(*self) 167 pub local_id: LocalTypeParamId,
280 }
281} 168}
282 169
283#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 170#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
284pub struct ImplId(salsa::InternId); 171pub struct LocalTypeParamId(RawId);
285impl_intern_key!(ImplId); 172impl_arena_id!(LocalTypeParamId);
286impl AstItemDef<ast::ImplBlock> for ImplId {
287 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::ImplBlock>) -> Self {
288 db.intern_impl(loc)
289 }
290 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::ImplBlock> {
291 db.lookup_intern_impl(self)
292 }
293}
294 173
295macro_rules! impl_froms { 174macro_rules! impl_froms {
296 ($e:ident: $($v:ident $(($($sv:ident),*))?),*) => { 175 ($e:ident: $($v:ident $(($($sv:ident),*))?),*) => {
@@ -314,9 +193,16 @@ macro_rules! impl_froms {
314#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 193#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
315pub enum ContainerId { 194pub enum ContainerId {
316 ModuleId(ModuleId), 195 ModuleId(ModuleId),
196 DefWithBodyId(DefWithBodyId),
197}
198
199#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
200pub enum AssocContainerId {
201 ContainerId(ContainerId),
317 ImplId(ImplId), 202 ImplId(ImplId),
318 TraitId(TraitId), 203 TraitId(TraitId),
319} 204}
205impl_froms!(AssocContainerId: ContainerId);
320 206
321/// A Data Type 207/// A Data Type
322#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 208#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@@ -459,43 +345,39 @@ pub trait HasModule {
459 fn module(&self, db: &impl db::DefDatabase) -> ModuleId; 345 fn module(&self, db: &impl db::DefDatabase) -> ModuleId;
460} 346}
461 347
462impl HasModule for FunctionLoc { 348impl HasModule for ContainerId {
463 fn module(&self, db: &impl db::DefDatabase) -> ModuleId { 349 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
464 match self.container { 350 match *self {
465 ContainerId::ModuleId(it) => it, 351 ContainerId::ModuleId(it) => it,
466 ContainerId::ImplId(it) => it.module(db), 352 ContainerId::DefWithBodyId(it) => it.module(db),
467 ContainerId::TraitId(it) => it.module(db),
468 } 353 }
469 } 354 }
470} 355}
471 356
472impl HasModule for TypeAliasLoc { 357impl HasModule for AssocContainerId {
473 fn module(&self, db: &impl db::DefDatabase) -> ModuleId { 358 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
474 match self.container { 359 match *self {
475 ContainerId::ModuleId(it) => it, 360 AssocContainerId::ContainerId(it) => it.module(db),
476 ContainerId::ImplId(it) => it.module(db), 361 AssocContainerId::ImplId(it) => it.lookup(db).container.module(db),
477 ContainerId::TraitId(it) => it.module(db), 362 AssocContainerId::TraitId(it) => it.lookup(db).container.module(db),
478 } 363 }
479 } 364 }
480} 365}
481 366
482impl HasModule for ConstLoc { 367impl<N: AstNode> HasModule for AssocItemLoc<N> {
483 fn module(&self, db: &impl db::DefDatabase) -> ModuleId { 368 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
484 match self.container { 369 self.container.module(db)
485 ContainerId::ModuleId(it) => it,
486 ContainerId::ImplId(it) => it.module(db),
487 ContainerId::TraitId(it) => it.module(db),
488 }
489 } 370 }
490} 371}
491 372
492impl HasModule for AdtId { 373impl HasModule for AdtId {
493 fn module(&self, db: &impl db::DefDatabase) -> ModuleId { 374 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
494 match self { 375 match self {
495 AdtId::StructId(it) => it.module(db), 376 AdtId::StructId(it) => it.lookup(db).container,
496 AdtId::UnionId(it) => it.module(db), 377 AdtId::UnionId(it) => it.lookup(db).container,
497 AdtId::EnumId(it) => it.module(db), 378 AdtId::EnumId(it) => it.lookup(db).container,
498 } 379 }
380 .module(db)
499 } 381 }
500} 382}
501 383
@@ -509,58 +391,22 @@ impl HasModule for DefWithBodyId {
509 } 391 }
510} 392}
511 393
512impl HasModule for StaticLoc { 394impl HasModule for GenericDefId {
513 fn module(&self, _db: &impl db::DefDatabase) -> ModuleId { 395 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
514 self.container 396 match self {
515 } 397 GenericDefId::FunctionId(it) => it.lookup(db).module(db),
516} 398 GenericDefId::AdtId(it) => it.module(db),
517 399 GenericDefId::TraitId(it) => it.lookup(db).container.module(db),
518pub trait HasSource { 400 GenericDefId::TypeAliasId(it) => it.lookup(db).module(db),
519 type Value; 401 GenericDefId::ImplId(it) => it.lookup(db).container.module(db),
520 fn source(&self, db: &impl db::DefDatabase) -> Source<Self::Value>; 402 GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container.module(db),
521} 403 GenericDefId::ConstId(it) => it.lookup(db).module(db),
522 404 }
523impl HasSource for FunctionLoc {
524 type Value = ast::FnDef;
525
526 fn source(&self, db: &impl db::DefDatabase) -> Source<ast::FnDef> {
527 let node = self.ast_id.to_node(db);
528 Source::new(self.ast_id.file_id(), node)
529 }
530}
531
532impl HasSource for TypeAliasLoc {
533 type Value = ast::TypeAliasDef;
534
535 fn source(&self, db: &impl db::DefDatabase) -> Source<ast::TypeAliasDef> {
536 let node = self.ast_id.to_node(db);
537 Source::new(self.ast_id.file_id(), node)
538 }
539}
540
541impl HasSource for ConstLoc {
542 type Value = ast::ConstDef;
543
544 fn source(&self, db: &impl db::DefDatabase) -> Source<ast::ConstDef> {
545 let node = self.ast_id.to_node(db);
546 Source::new(self.ast_id.file_id(), node)
547 } 405 }
548} 406}
549 407
550impl HasSource for StaticLoc { 408impl HasModule for StaticLoc {
551 type Value = ast::StaticDef; 409 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
552 410 self.container.module(db)
553 fn source(&self, db: &impl db::DefDatabase) -> Source<ast::StaticDef> {
554 let node = self.ast_id.to_node(db);
555 Source::new(self.ast_id.file_id(), node)
556 } 411 }
557} 412}
558
559pub trait HasChildSource {
560 type ChildId;
561 type Value;
562 fn child_source(
563 &self,
564 db: &impl db::DefDatabase,
565 ) -> Source<ArenaMap<Self::ChildId, Self::Value>>;
566}
diff --git a/crates/ra_hir_def/src/marks.rs b/crates/ra_hir_def/src/marks.rs
index 65239ca0a..457ba4abe 100644
--- a/crates/ra_hir_def/src/marks.rs
+++ b/crates/ra_hir_def/src/marks.rs
@@ -5,6 +5,7 @@ test_utils::marks!(
5 name_res_works_for_broken_modules 5 name_res_works_for_broken_modules
6 can_import_enum_variant 6 can_import_enum_variant
7 glob_enum 7 glob_enum
8 glob_enum_group
8 glob_across_crates 9 glob_across_crates
9 std_prelude 10 std_prelude
10 macro_rules_from_other_crates_are_visible_with_macro_use 11 macro_rules_from_other_crates_are_visible_with_macro_use
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs
index 2359386c2..5d4ca73a3 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -57,24 +57,23 @@ mod tests;
57 57
58use std::sync::Arc; 58use std::sync::Arc;
59 59
60use hir_expand::{ 60use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile};
61 ast_id_map::FileAstId, diagnostics::DiagnosticSink, either::Either, name::Name, MacroDefId,
62 Source,
63};
64use once_cell::sync::Lazy;
65use ra_arena::Arena; 61use ra_arena::Arena;
66use ra_db::{CrateId, Edition, FileId}; 62use ra_db::{CrateId, Edition, FileId, FilePosition};
67use ra_prof::profile; 63use ra_prof::profile;
68use ra_syntax::ast; 64use ra_syntax::{
65 ast::{self, AstNode},
66 SyntaxNode,
67};
69use rustc_hash::FxHashMap; 68use rustc_hash::FxHashMap;
70 69
71use crate::{ 70use crate::{
72 builtin_type::BuiltinType,
73 db::DefDatabase, 71 db::DefDatabase,
72 item_scope::{BuiltinShadowMode, ItemScope},
74 nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, 73 nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
75 path::Path, 74 path::ModPath,
76 per_ns::PerNs, 75 per_ns::PerNs,
77 AstId, FunctionId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId, 76 AstId, LocalModuleId, ModuleDefId, ModuleId,
78}; 77};
79 78
80/// Contains all top-level defs from a macro-expanded crate 79/// Contains all top-level defs from a macro-expanded crate
@@ -100,106 +99,76 @@ impl std::ops::Index<LocalModuleId> for CrateDefMap {
100 } 99 }
101} 100}
102 101
103#[derive(Default, Debug, PartialEq, Eq)] 102#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
104pub struct ModuleData { 103pub enum ModuleOrigin {
105 pub parent: Option<LocalModuleId>, 104 CrateRoot {
106 pub children: FxHashMap<Name, LocalModuleId>, 105 definition: FileId,
107 pub scope: ModuleScope, 106 },
108
109 // FIXME: these can't be both null, we need a three-state enum here.
110 /// None for root
111 pub declaration: Option<AstId<ast::Module>>,
112 /// None for inline modules.
113 ///
114 /// Note that non-inline modules, by definition, live inside non-macro file. 107 /// Note that non-inline modules, by definition, live inside non-macro file.
115 pub definition: Option<FileId>, 108 File {
116 109 declaration: AstId<ast::Module>,
117 pub impls: Vec<ImplId>, 110 definition: FileId,
118} 111 },
119 112 Inline {
120#[derive(Default, Debug, PartialEq, Eq)] 113 definition: AstId<ast::Module>,
121pub(crate) struct Declarations { 114 },
122 fns: FxHashMap<FileAstId<ast::FnDef>, FunctionId>,
123} 115}
124 116
125#[derive(Debug, Default, PartialEq, Eq)] 117impl Default for ModuleOrigin {
126pub struct ModuleScope { 118 fn default() -> Self {
127 items: FxHashMap<Name, Resolution>, 119 ModuleOrigin::CrateRoot { definition: FileId(0) }
128 /// Macros visable in current module in legacy textual scope
129 ///
130 /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first.
131 /// If it yields no result, then it turns to module scoped `macros`.
132 /// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped,
133 /// and only normal scoped `macros` will be searched in.
134 ///
135 /// Note that this automatically inherit macros defined textually before the definition of module itself.
136 ///
137 /// Module scoped macros will be inserted into `items` instead of here.
138 // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
139 // be all resolved to the last one defined if shadowing happens.
140 legacy_macros: FxHashMap<Name, MacroDefId>,
141}
142
143static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = Lazy::new(|| {
144 BuiltinType::ALL
145 .iter()
146 .map(|(name, ty)| {
147 (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None })
148 })
149 .collect()
150});
151
152/// Legacy macros can only be accessed through special methods like `get_legacy_macros`.
153/// Other methods will only resolve values, types and module scoped macros only.
154impl ModuleScope {
155 pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a {
156 //FIXME: shadowing
157 self.items.iter().chain(BUILTIN_SCOPE.iter())
158 }
159
160 pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
161 self.entries()
162 .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None })
163 .flat_map(|per_ns| {
164 per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter())
165 })
166 }
167
168 /// Iterate over all module scoped macros
169 pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
170 self.items
171 .iter()
172 .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_)))
173 } 120 }
121}
174 122
175 /// Iterate over all legacy textual scoped macros visable at the end of the module 123impl ModuleOrigin {
176 pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { 124 pub(crate) fn not_sure_file(file: Option<FileId>, declaration: AstId<ast::Module>) -> Self {
177 self.legacy_macros.iter().map(|(name, def)| (name, *def)) 125 match file {
126 None => ModuleOrigin::Inline { definition: declaration },
127 Some(definition) => ModuleOrigin::File { declaration, definition },
128 }
178 } 129 }
179 130
180 /// Get a name from current module scope, legacy macros are not included 131 fn declaration(&self) -> Option<AstId<ast::Module>> {
181 pub fn get(&self, name: &Name) -> Option<&Resolution> { 132 match self {
182 self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)) 133 ModuleOrigin::File { declaration: module, .. }
134 | ModuleOrigin::Inline { definition: module, .. } => Some(*module),
135 ModuleOrigin::CrateRoot { .. } => None,
136 }
183 } 137 }
184 138
185 pub fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a { 139 pub fn file_id(&self) -> Option<FileId> {
186 self.items.values().filter_map(|r| match r.def.take_types() { 140 match self {
187 Some(ModuleDefId::TraitId(t)) => Some(t), 141 ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
142 Some(*definition)
143 }
188 _ => None, 144 _ => None,
189 }) 145 }
190 } 146 }
191 147
192 fn get_legacy_macro(&self, name: &Name) -> Option<MacroDefId> { 148 /// Returns a node which defines this module.
193 self.legacy_macros.get(name).copied() 149 /// That is, a file or a `mod foo {}` with items.
150 fn definition_source(&self, db: &impl DefDatabase) -> InFile<ModuleSource> {
151 match self {
152 ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
153 let file_id = *definition;
154 let sf = db.parse(file_id).tree();
155 return InFile::new(file_id.into(), ModuleSource::SourceFile(sf));
156 }
157 ModuleOrigin::Inline { definition } => {
158 InFile::new(definition.file_id, ModuleSource::Module(definition.to_node(db)))
159 }
160 }
194 } 161 }
195} 162}
196 163
197#[derive(Debug, Clone, PartialEq, Eq, Default)] 164#[derive(Default, Debug, PartialEq, Eq)]
198pub struct Resolution { 165pub struct ModuleData {
199 /// None for unresolved 166 pub parent: Option<LocalModuleId>,
200 pub def: PerNs, 167 pub children: FxHashMap<Name, LocalModuleId>,
201 /// ident by which this is imported into local scope. 168 pub scope: ItemScope,
202 pub import: Option<LocalImportId>, 169
170 /// Where does this module come from?
171 pub origin: ModuleOrigin,
203} 172}
204 173
205impl CrateDefMap { 174impl CrateDefMap {
@@ -241,7 +210,7 @@ impl CrateDefMap {
241 pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ { 210 pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ {
242 self.modules 211 self.modules
243 .iter() 212 .iter()
244 .filter(move |(_id, data)| data.definition == Some(file_id)) 213 .filter(move |(_id, data)| data.origin.file_id() == Some(file_id))
245 .map(|(id, _data)| id) 214 .map(|(id, _data)| id)
246 } 215 }
247 216
@@ -249,33 +218,62 @@ impl CrateDefMap {
249 &self, 218 &self,
250 db: &impl DefDatabase, 219 db: &impl DefDatabase,
251 original_module: LocalModuleId, 220 original_module: LocalModuleId,
252 path: &Path, 221 path: &ModPath,
222 shadow: BuiltinShadowMode,
253 ) -> (PerNs, Option<usize>) { 223 ) -> (PerNs, Option<usize>) {
254 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path); 224 let res =
225 self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path, shadow);
255 (res.resolved_def, res.segment_index) 226 (res.resolved_def, res.segment_index)
256 } 227 }
257} 228}
258 229
259impl ModuleData { 230impl ModuleData {
260 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. 231 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
261 pub fn definition_source( 232 pub fn definition_source(&self, db: &impl DefDatabase) -> InFile<ModuleSource> {
262 &self, 233 self.origin.definition_source(db)
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)))
271 } 234 }
272 235
273 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. 236 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
274 /// `None` for the crate root. 237 /// `None` for the crate root or block.
275 pub fn declaration_source(&self, db: &impl DefDatabase) -> Option<Source<ast::Module>> { 238 pub fn declaration_source(&self, db: &impl DefDatabase) -> Option<InFile<ast::Module>> {
276 let decl = self.declaration?; 239 let decl = self.origin.declaration()?;
277 let value = decl.to_node(db); 240 let value = decl.to_node(db);
278 Some(Source { file_id: decl.file_id(), value }) 241 Some(InFile { file_id: decl.file_id, value })
242 }
243}
244
245#[derive(Debug, Clone, PartialEq, Eq)]
246pub enum ModuleSource {
247 SourceFile(ast::SourceFile),
248 Module(ast::Module),
249}
250
251impl ModuleSource {
252 // FIXME: this methods do not belong here
253 pub fn from_position(db: &impl DefDatabase, position: FilePosition) -> ModuleSource {
254 let parse = db.parse(position.file_id);
255 match &ra_syntax::algo::find_node_at_offset::<ast::Module>(
256 parse.tree().syntax(),
257 position.offset,
258 ) {
259 Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()),
260 _ => {
261 let source_file = parse.tree();
262 ModuleSource::SourceFile(source_file)
263 }
264 }
265 }
266
267 pub fn from_child_node(db: &impl DefDatabase, child: InFile<&SyntaxNode>) -> ModuleSource {
268 if let Some(m) =
269 child.value.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi())
270 {
271 ModuleSource::Module(m)
272 } else {
273 let file_id = child.file_id.original_file(db);
274 let source_file = db.parse(file_id).tree();
275 ModuleSource::SourceFile(source_file)
276 }
279 } 277 }
280} 278}
281 279
@@ -309,7 +307,7 @@ mod diagnostics {
309 } 307 }
310 let decl = declaration.to_node(db); 308 let decl = declaration.to_node(db);
311 sink.push(UnresolvedModule { 309 sink.push(UnresolvedModule {
312 file: declaration.file_id(), 310 file: declaration.file_id,
313 decl: AstPtr::new(&decl), 311 decl: AstPtr::new(&decl),
314 candidate: candidate.clone(), 312 candidate: candidate.clone(),
315 }) 313 })
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index fd8245113..b9f40d3dd 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -4,14 +4,15 @@
4//! resolves imports and expands macros. 4//! resolves imports and expands macros.
5 5
6use hir_expand::{ 6use hir_expand::{
7 builtin_derive::find_builtin_derive,
7 builtin_macro::find_builtin_macro, 8 builtin_macro::find_builtin_macro,
8 name::{self, AsName, Name}, 9 name::{name, AsName, Name},
9 HirFileId, MacroCallId, MacroDefId, MacroDefKind, MacroFileKind, 10 HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
10}; 11};
11use ra_cfg::CfgOptions; 12use ra_cfg::CfgOptions;
12use ra_db::{CrateId, FileId}; 13use ra_db::{CrateId, FileId};
13use ra_syntax::ast; 14use ra_syntax::ast;
14use rustc_hash::{FxHashMap, FxHashSet}; 15use rustc_hash::FxHashMap;
15use test_utils::tested_by; 16use test_utils::tested_by;
16 17
17use crate::{ 18use crate::{
@@ -19,13 +20,12 @@ use crate::{
19 db::DefDatabase, 20 db::DefDatabase,
20 nameres::{ 21 nameres::{
21 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, 22 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
22 raw, CrateDefMap, ModuleData, Resolution, ResolveMode, 23 raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode,
23 }, 24 },
24 path::{Path, PathKind}, 25 path::{ModPath, PathKind},
25 per_ns::PerNs, 26 per_ns::PerNs,
26 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplId, 27 AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern,
27 Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructId, 28 LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
28 TraitId, TypeAliasLoc, UnionId,
29}; 29};
30 30
31pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { 31pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
@@ -57,68 +57,63 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C
57 def_map, 57 def_map,
58 glob_imports: FxHashMap::default(), 58 glob_imports: FxHashMap::default(),
59 unresolved_imports: Vec::new(), 59 unresolved_imports: Vec::new(),
60 resolved_imports: Vec::new(),
61
60 unexpanded_macros: Vec::new(), 62 unexpanded_macros: Vec::new(),
63 unexpanded_attribute_macros: Vec::new(),
61 mod_dirs: FxHashMap::default(), 64 mod_dirs: FxHashMap::default(),
62 macro_stack_monitor: MacroStackMonitor::default(),
63 poison_macros: FxHashSet::default(),
64 cfg_options, 65 cfg_options,
65 }; 66 };
66 collector.collect(); 67 collector.collect();
67 collector.finish() 68 collector.finish()
68} 69}
69 70
70#[derive(Default)] 71#[derive(Copy, Clone, Debug, Eq, PartialEq)]
71struct MacroStackMonitor { 72enum PartialResolvedImport {
72 counts: FxHashMap<MacroDefId, u32>, 73 /// None of any namespaces is resolved
73 74 Unresolved,
74 /// Mainly use for test 75 /// One of namespaces is resolved
75 validator: Option<Box<dyn Fn(u32) -> bool>>, 76 Indeterminate(PerNs),
77 /// All namespaces are resolved, OR it is came from other crate
78 Resolved(PerNs),
76} 79}
77 80
78impl MacroStackMonitor { 81impl PartialResolvedImport {
79 fn increase(&mut self, macro_def_id: MacroDefId) { 82 fn namespaces(&self) -> PerNs {
80 *self.counts.entry(macro_def_id).or_default() += 1; 83 match self {
81 } 84 PartialResolvedImport::Unresolved => PerNs::none(),
82 85 PartialResolvedImport::Indeterminate(ns) => *ns,
83 fn decrease(&mut self, macro_def_id: MacroDefId) { 86 PartialResolvedImport::Resolved(ns) => *ns,
84 *self.counts.entry(macro_def_id).or_default() -= 1; 87 }
85 } 88 }
89}
86 90
87 fn is_poison(&self, macro_def_id: MacroDefId) -> bool { 91#[derive(Clone, Debug, Eq, PartialEq)]
88 let cur = *self.counts.get(&macro_def_id).unwrap_or(&0); 92struct ImportDirective {
93 module_id: LocalModuleId,
94 import_id: raw::Import,
95 import: raw::ImportData,
96 status: PartialResolvedImport,
97}
89 98
90 if let Some(validator) = &self.validator { 99#[derive(Clone, Debug, Eq, PartialEq)]
91 validator(cur) 100struct MacroDirective {
92 } else { 101 module_id: LocalModuleId,
93 cur > 100 102 ast_id: AstId<ast::MacroCall>,
94 } 103 path: ModPath,
95 } 104 legacy: Option<MacroCallId>,
96} 105}
97 106
98/// Walks the tree of module recursively 107/// Walks the tree of module recursively
99struct DefCollector<'a, DB> { 108struct DefCollector<'a, DB> {
100 db: &'a DB, 109 db: &'a DB,
101 def_map: CrateDefMap, 110 def_map: CrateDefMap,
102 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, LocalImportId)>>, 111 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, raw::Import)>>,
103 unresolved_imports: Vec<(LocalModuleId, LocalImportId, raw::ImportData)>, 112 unresolved_imports: Vec<ImportDirective>,
104 unexpanded_macros: Vec<(LocalModuleId, AstId<ast::MacroCall>, Path)>, 113 resolved_imports: Vec<ImportDirective>,
114 unexpanded_macros: Vec<MacroDirective>,
115 unexpanded_attribute_macros: Vec<(LocalModuleId, AstId<ast::ModuleItem>, ModPath)>,
105 mod_dirs: FxHashMap<LocalModuleId, ModDir>, 116 mod_dirs: FxHashMap<LocalModuleId, ModDir>,
106
107 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly
108 /// To prevent stack overflow, we add a deep counter here for prevent that.
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>,
121
122 cfg_options: &'a CfgOptions, 117 cfg_options: &'a CfgOptions,
123} 118}
124 119
@@ -131,7 +126,7 @@ where
131 let file_id = crate_graph.crate_root(self.def_map.krate); 126 let file_id = crate_graph.crate_root(self.def_map.krate);
132 let raw_items = self.db.raw_items(file_id.into()); 127 let raw_items = self.db.raw_items(file_id.into());
133 let module_id = self.def_map.root; 128 let module_id = self.def_map.root;
134 self.def_map.modules[module_id].definition = Some(file_id); 129 self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id };
135 ModCollector { 130 ModCollector {
136 def_collector: &mut *self, 131 def_collector: &mut *self,
137 module_id, 132 module_id,
@@ -145,9 +140,11 @@ where
145 let mut i = 0; 140 let mut i = 0;
146 loop { 141 loop {
147 self.db.check_canceled(); 142 self.db.check_canceled();
148 match (self.resolve_imports(), self.resolve_macros()) { 143 self.resolve_imports();
149 (ReachedFixedPoint::Yes, ReachedFixedPoint::Yes) => break, 144
150 _ => i += 1, 145 match self.resolve_macros() {
146 ReachedFixedPoint::Yes => break,
147 ReachedFixedPoint::No => i += 1,
151 } 148 }
152 if i == 1000 { 149 if i == 1000 {
153 log::error!("name resolution is stuck"); 150 log::error!("name resolution is stuck");
@@ -155,10 +152,26 @@ where
155 } 152 }
156 } 153 }
157 154
155 // Resolve all indeterminate resolved imports again
156 // As some of the macros will expand newly import shadowing partial resolved imports
157 // FIXME: We maybe could skip this, if we handle the Indetermine imports in `resolve_imports`
158 // correctly
159 let partial_resolved = self.resolved_imports.iter().filter_map(|directive| {
160 if let PartialResolvedImport::Indeterminate(_) = directive.status {