aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src')
-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
35 files changed, 2419 insertions, 1514 deletions
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 {
161 let mut directive = directive.clone();
162 directive.status = PartialResolvedImport::Unresolved;
163 Some(directive)
164 } else {
165 None
166 }
167 });
168 self.unresolved_imports.extend(partial_resolved);
169 self.resolve_imports();
170
158 let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); 171 let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
159 // show unresolved imports in completion, etc 172 // show unresolved imports in completion, etc
160 for (module_id, import, import_data) in unresolved_imports { 173 for directive in unresolved_imports {
161 self.record_resolved_import(module_id, PerNs::none(), import, &import_data) 174 self.record_resolved_import(&directive)
162 } 175 }
163 } 176 }
164 177
@@ -201,24 +214,20 @@ where
201 // In Rust, `#[macro_export]` macros are unconditionally visible at the 214 // In Rust, `#[macro_export]` macros are unconditionally visible at the
202 // crate root, even if the parent modules is **not** visible. 215 // crate root, even if the parent modules is **not** visible.
203 if export { 216 if export {
204 self.update( 217 self.update(self.def_map.root, &[(name, PerNs::macros(macro_))]);
205 self.def_map.root,
206 None,
207 &[(name, Resolution { def: PerNs::macros(macro_), import: None })],
208 );
209 } 218 }
210 } 219 }
211 220
212 /// Define a legacy textual scoped macro in module 221 /// Define a legacy textual scoped macro in module
213 /// 222 ///
214 /// We use a map `legacy_macros` to store all legacy textual scoped macros visable per module. 223 /// We use a map `legacy_macros` to store all legacy textual scoped macros visible per module.
215 /// It will clone all macros from parent legacy scope, whose definition is prior to 224 /// It will clone all macros from parent legacy scope, whose definition is prior to
216 /// the definition of current module. 225 /// the definition of current module.
217 /// And also, `macro_use` on a module will import all legacy macros visable inside to 226 /// And also, `macro_use` on a module will import all legacy macros visible inside to
218 /// current legacy scope, with possible shadowing. 227 /// current legacy scope, with possible shadowing.
219 fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, macro_: MacroDefId) { 228 fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, mac: MacroDefId) {
220 // Always shadowing 229 // Always shadowing
221 self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_); 230 self.def_map.modules[module_id].scope.define_legacy_macro(name, mac);
222 } 231 }
223 232
224 /// Import macros from `#[macro_use] extern crate`. 233 /// Import macros from `#[macro_use] extern crate`.
@@ -259,31 +268,43 @@ where
259 } 268 }
260 } 269 }
261 270
262 fn resolve_imports(&mut self) -> ReachedFixedPoint { 271 /// Import resolution
263 let mut imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); 272 ///
264 let mut resolved = Vec::new(); 273 /// This is a fix point algorithm. We resolve imports until no forward
265 imports.retain(|(module_id, import, import_data)| { 274 /// progress in resolving imports is made
266 let (def, fp) = self.resolve_import(*module_id, import_data); 275 fn resolve_imports(&mut self) {
267 if fp == ReachedFixedPoint::Yes { 276 let mut n_previous_unresolved = self.unresolved_imports.len() + 1;
268 resolved.push((*module_id, def, *import, import_data.clone())) 277
278 while self.unresolved_imports.len() < n_previous_unresolved {
279 n_previous_unresolved = self.unresolved_imports.len();
280 let imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
281 for mut directive in imports {
282 directive.status = self.resolve_import(directive.module_id, &directive.import);
283
284 match directive.status {
285 PartialResolvedImport::Indeterminate(_) => {
286 self.record_resolved_import(&directive);
287 // FIXME: For avoid performance regression,
288 // we consider an imported resolved if it is indeterminate (i.e not all namespace resolved)
289 self.resolved_imports.push(directive)
290 }
291 PartialResolvedImport::Resolved(_) => {
292 self.record_resolved_import(&directive);
293 self.resolved_imports.push(directive)
294 }
295 PartialResolvedImport::Unresolved => {
296 self.unresolved_imports.push(directive);
297 }
298 }
269 } 299 }
270 fp == ReachedFixedPoint::No
271 });
272 self.unresolved_imports = imports;
273 // Resolves imports, filling-in module scopes
274 let result =
275 if resolved.is_empty() { ReachedFixedPoint::Yes } else { ReachedFixedPoint::No };
276 for (module_id, def, import, import_data) in resolved {
277 self.record_resolved_import(module_id, def, import, &import_data)
278 } 300 }
279 result
280 } 301 }
281 302
282 fn resolve_import( 303 fn resolve_import(
283 &self, 304 &self,
284 module_id: LocalModuleId, 305 module_id: LocalModuleId,
285 import: &raw::ImportData, 306 import: &raw::ImportData,
286 ) -> (PerNs, ReachedFixedPoint) { 307 ) -> PartialResolvedImport {
287 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); 308 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
288 if import.is_extern_crate { 309 if import.is_extern_crate {
289 let res = self.def_map.resolve_name_in_extern_prelude( 310 let res = self.def_map.resolve_name_in_extern_prelude(
@@ -292,26 +313,45 @@ where
292 .as_ident() 313 .as_ident()
293 .expect("extern crate should have been desugared to one-element path"), 314 .expect("extern crate should have been desugared to one-element path"),
294 ); 315 );
295 (res, ReachedFixedPoint::Yes) 316 PartialResolvedImport::Resolved(res)
296 } else { 317 } else {
297 let res = self.def_map.resolve_path_fp_with_macro( 318 let res = self.def_map.resolve_path_fp_with_macro(
298 self.db, 319 self.db,
299 ResolveMode::Import, 320 ResolveMode::Import,
300 module_id, 321 module_id,
301 &import.path, 322 &import.path,
323 BuiltinShadowMode::Module,
302 ); 324 );
303 325
304 (res.resolved_def, res.reached_fixedpoint) 326 let def = res.resolved_def;
327 if res.reached_fixedpoint == ReachedFixedPoint::No {
328 return PartialResolvedImport::Unresolved;
329 }
330
331 if let Some(krate) = res.krate {
332 if krate != self.def_map.krate {
333 return PartialResolvedImport::Resolved(def);
334 }
335 }
336
337 // Check whether all namespace is resolved
338 if def.take_types().is_some()
339 && def.take_values().is_some()
340 && def.take_macros().is_some()
341 {
342 PartialResolvedImport::Resolved(def)
343 } else {
344 PartialResolvedImport::Indeterminate(def)
345 }
305 } 346 }
306 } 347 }
307 348
308 fn record_resolved_import( 349 fn record_resolved_import(&mut self, directive: &ImportDirective) {
309 &mut self, 350 let module_id = directive.module_id;
310 module_id: LocalModuleId, 351 let import_id = directive.import_id;
311 def: PerNs, 352 let import = &directive.import;
312 import_id: LocalImportId, 353 let def = directive.status.namespaces();
313 import: &raw::ImportData, 354
314 ) {
315 if import.is_glob { 355 if import.is_glob {
316 log::debug!("glob import: {:?}", import); 356 log::debug!("glob import: {:?}", import);
317 match def.take_types() { 357 match def.take_types() {
@@ -326,13 +366,9 @@ where
326 let scope = &item_map[m.local_id].scope; 366 let scope = &item_map[m.local_id].scope;
327 367
328 // Module scoped macros is included 368 // Module scoped macros is included
329 let items = scope 369 let items = scope.collect_resolutions();
330 .items
331 .iter()
332 .map(|(name, res)| (name.clone(), res.clone()))
333 .collect::<Vec<_>>();
334 370
335 self.update(module_id, Some(import_id), &items); 371 self.update(module_id, &items);
336 } else { 372 } else {
337 // glob import from same crate => we do an initial 373 // glob import from same crate => we do an initial
338 // import, and then need to propagate any further 374 // import, and then need to propagate any further
@@ -340,18 +376,14 @@ where
340 let scope = &self.def_map[m.local_id].scope; 376 let scope = &self.def_map[m.local_id].scope;
341 377
342 // Module scoped macros is included 378 // Module scoped macros is included
343 let items = scope 379 let items = scope.collect_resolutions();
344 .items
345 .iter()
346 .map(|(name, res)| (name.clone(), res.clone()))
347 .collect::<Vec<_>>();
348 380
349 self.update(module_id, Some(import_id), &items); 381 self.update(module_id, &items);
350 // record the glob import in case we add further items 382 // record the glob import in case we add further items
351 self.glob_imports 383 let glob = self.glob_imports.entry(m.local_id).or_default();
352 .entry(m.local_id) 384 if !glob.iter().any(|it| *it == (module_id, import_id)) {
353 .or_default() 385 glob.push((module_id, import_id));
354 .push((module_id, import_id)); 386 }
355 } 387 }
356 } 388 }
357 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => { 389 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
@@ -361,17 +393,14 @@ where
361 let resolutions = enum_data 393 let resolutions = enum_data
362 .variants 394 .variants
363 .iter() 395 .iter()
364 .filter_map(|(local_id, variant_data)| { 396 .map(|(local_id, variant_data)| {
365 let name = variant_data.name.clone(); 397 let name = variant_data.name.clone();
366 let variant = EnumVariantId { parent: e, local_id }; 398 let variant = EnumVariantId { parent: e, local_id };
367 let res = Resolution { 399 let res = PerNs::both(variant.into(), variant.into());
368 def: PerNs::both(variant.into(), variant.into()), 400 (name, res)
369 import: Some(import_id),
370 };
371 Some((name, res))
372 }) 401 })
373 .collect::<Vec<_>>(); 402 .collect::<Vec<_>>();
374 self.update(module_id, Some(import_id), &resolutions); 403 self.update(module_id, &resolutions);
375 } 404 }
376 Some(d) => { 405 Some(d) => {
377 log::debug!("glob import {:?} from non-module/enum {:?}", import, d); 406 log::debug!("glob import {:?} from non-module/enum {:?}", import, d);
@@ -383,7 +412,7 @@ where
383 } else { 412 } else {
384 match import.path.segments.last() { 413 match import.path.segments.last() {
385 Some(last_segment) => { 414 Some(last_segment) => {
386 let name = import.alias.clone().unwrap_or_else(|| last_segment.name.clone()); 415 let name = import.alias.clone().unwrap_or_else(|| last_segment.clone());
387 log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); 416 log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
388 417
389 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 418 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
@@ -393,62 +422,31 @@ where
393 } 422 }
394 } 423 }
395 424
396 let resolution = Resolution { def, import: Some(import_id) }; 425 self.update(module_id, &[(name, def)]);
397 self.update(module_id, Some(import_id), &[(name, resolution)]);
398 } 426 }
399 None => tested_by!(bogus_paths), 427 None => tested_by!(bogus_paths),
400 } 428 }
401 } 429 }
402 } 430 }
403 431
404 fn update( 432 fn update(&mut self, module_id: LocalModuleId, resolutions: &[(Name, PerNs)]) {
405 &mut self, 433 self.update_recursive(module_id, resolutions, 0)
406 module_id: LocalModuleId,
407 import: Option<LocalImportId>,
408 resolutions: &[(Name, Resolution)],
409 ) {
410 self.update_recursive(module_id, import, resolutions, 0)
411 } 434 }
412 435
413 fn update_recursive( 436 fn update_recursive(
414 &mut self, 437 &mut self,
415 module_id: LocalModuleId, 438 module_id: LocalModuleId,
416 import: Option<LocalImportId>, 439 resolutions: &[(Name, PerNs)],
417 resolutions: &[(Name, Resolution)],
418 depth: usize, 440 depth: usize,
419 ) { 441 ) {
420 if depth > 100 { 442 if depth > 100 {
421 // prevent stack overflows (but this shouldn't be possible) 443 // prevent stack overflows (but this shouldn't be possible)
422 panic!("infinite recursion in glob imports!"); 444 panic!("infinite recursion in glob imports!");
423 } 445 }
424 let module_items = &mut self.def_map.modules[module_id].scope; 446 let scope = &mut self.def_map.modules[module_id].scope;
425 let mut changed = false; 447 let mut changed = false;
426 for (name, res) in resolutions { 448 for (name, res) in resolutions {
427 let existing = module_items.items.entry(name.clone()).or_default(); 449 changed |= scope.push_res(name.clone(), *res);
428
429 if existing.def.types.is_none() && res.def.types.is_some() {
430 existing.def.types = res.def.types;
431 existing.import = import.or(res.import);
432 changed = true;
433 }
434 if existing.def.values.is_none() && res.def.values.is_some() {
435 existing.def.values = res.def.values;
436 existing.import = import.or(res.import);
437 changed = true;
438 }
439 if existing.def.macros.is_none() && res.def.macros.is_some() {
440 existing.def.macros = res.def.macros;
441 existing.import = import.or(res.import);
442 changed = true;
443 }
444
445 if existing.def.is_none()
446 && res.def.is_none()
447 && existing.import.is_none()
448 && res.import.is_some()
449 {
450 existing.import = res.import;
451 }
452 } 450 }
453 451
454 if !changed { 452 if !changed {
@@ -461,27 +459,48 @@ where
461 .flat_map(|v| v.iter()) 459 .flat_map(|v| v.iter())
462 .cloned() 460 .cloned()
463 .collect::<Vec<_>>(); 461 .collect::<Vec<_>>();
464 for (glob_importing_module, glob_import) in glob_imports { 462 for (glob_importing_module, _glob_import) in glob_imports {
465 // We pass the glob import so that the tracked import in those modules is that glob import 463 // We pass the glob import so that the tracked import in those modules is that glob import
466 self.update_recursive(glob_importing_module, Some(glob_import), resolutions, depth + 1); 464 self.update_recursive(glob_importing_module, resolutions, depth + 1);
467 } 465 }
468 } 466 }
469 467
470 fn resolve_macros(&mut self) -> ReachedFixedPoint { 468 fn resolve_macros(&mut self) -> ReachedFixedPoint {
471 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new()); 469 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new());
470 let mut attribute_macros =
471 std::mem::replace(&mut self.unexpanded_attribute_macros, Vec::new());
472 let mut resolved = Vec::new(); 472 let mut resolved = Vec::new();
473 let mut res = ReachedFixedPoint::Yes; 473 let mut res = ReachedFixedPoint::Yes;
474 macros.retain(|(module_id, ast_id, path)| { 474 macros.retain(|directive| {
475 if let Some(call_id) = directive.legacy {
476 res = ReachedFixedPoint::No;
477 resolved.push((directive.module_id, call_id));
478 return false;
479 }
480
475 let resolved_res = self.def_map.resolve_path_fp_with_macro( 481 let resolved_res = self.def_map.resolve_path_fp_with_macro(
476 self.db, 482 self.db,
477 ResolveMode::Other, 483 ResolveMode::Other,
478 *module_id, 484 directive.module_id,
479 path, 485 &directive.path,
486 BuiltinShadowMode::Module,
480 ); 487 );
481 488
482 if let Some(def) = resolved_res.resolved_def.take_macros() { 489 if let Some(def) = resolved_res.resolved_def.take_macros() {
483 let call_id = def.as_call_id(self.db, *ast_id); 490 let call_id = def.as_call_id(self.db, MacroCallKind::FnLike(directive.ast_id));
484 resolved.push((*module_id, call_id, def)); 491 resolved.push((directive.module_id, call_id));
492 res = ReachedFixedPoint::No;
493 return false;
494 }
495
496 true
497 });
498 attribute_macros.retain(|(module_id, ast_id, path)| {
499 let resolved_res = self.resolve_attribute_macro(path);
500
501 if let Some(def) = resolved_res {
502 let call_id = def.as_call_id(self.db, MacroCallKind::Attr(*ast_id));
503 resolved.push((*module_id, call_id));
485 res = ReachedFixedPoint::No; 504 res = ReachedFixedPoint::No;
486 return false; 505 return false;
487 } 506 }
@@ -490,44 +509,41 @@ where
490 }); 509 });
491 510
492 self.unexpanded_macros = macros; 511 self.unexpanded_macros = macros;
512 self.unexpanded_attribute_macros = attribute_macros;
493 513
494 for (module_id, macro_call_id, macro_def_id) in resolved { 514 for (module_id, macro_call_id) in resolved {
495 self.collect_macro_expansion(module_id, macro_call_id, macro_def_id); 515 self.collect_macro_expansion(module_id, macro_call_id);
496 } 516 }
497 517
498 res 518 res
499 } 519 }
500 520
501 fn collect_macro_expansion( 521 fn resolve_attribute_macro(&self, path: &ModPath) -> Option<MacroDefId> {
502 &mut self, 522 // FIXME this is currently super hacky, just enough to support the
503 module_id: LocalModuleId, 523 // built-in derives
504 macro_call_id: MacroCallId, 524 if let Some(name) = path.as_ident() {
505 macro_def_id: MacroDefId, 525 // FIXME this should actually be handled with the normal name
506 ) { 526 // resolution; the std lib defines built-in stubs for the derives,
507 if self.poison_macros.contains(&macro_def_id) { 527 // but these are new-style `macro`s, which we don't support yet
508 return; 528 if let Some(def_id) = find_builtin_derive(name) {
509 } 529 return Some(def_id);
510
511 self.macro_stack_monitor.increase(macro_def_id);
512
513 if !self.macro_stack_monitor.is_poison(macro_def_id) {
514 let file_id: HirFileId = macro_call_id.as_file(MacroFileKind::Items);
515 let raw_items = self.db.raw_items(file_id);
516 let mod_dir = self.mod_dirs[&module_id].clone();
517 ModCollector {
518 def_collector: &mut *self,
519 file_id,
520 module_id,
521 raw_items: &raw_items,
522 mod_dir,
523 } 530 }
524 .collect(raw_items.items());
525 } else {
526 log::error!("Too deep macro expansion: {:?}", macro_call_id);
527 self.poison_macros.insert(macro_def_id);
528 } 531 }
532 None
533 }
529 534
530 self.macro_stack_monitor.decrease(macro_def_id); 535 fn collect_macro_expansion(&mut self, module_id: LocalModuleId, macro_call_id: MacroCallId) {
536 let file_id: HirFileId = macro_call_id.as_file();
537 let raw_items = self.db.raw_items(file_id);
538 let mod_dir = self.mod_dirs[&module_id].clone();
539 ModCollector {
540 def_collector: &mut *self,
541 file_id,
542 module_id,
543 raw_items: &raw_items,
544 mod_dir,
545 }
546 .collect(raw_items.items());
531 } 547 }
532 548
533 fn finish(self) -> CrateDefMap { 549 fn finish(self) -> CrateDefMap {
@@ -581,20 +597,31 @@ where
581 raw::RawItemKind::Module(m) => { 597 raw::RawItemKind::Module(m) => {
582 self.collect_module(&self.raw_items[m], &item.attrs) 598 self.collect_module(&self.raw_items[m], &item.attrs)
583 } 599 }
584 raw::RawItemKind::Import(import_id) => self 600 raw::RawItemKind::Import(import_id) => {
585 .def_collector 601 self.def_collector.unresolved_imports.push(ImportDirective {
586 .unresolved_imports 602 module_id: self.module_id,
587 .push((self.module_id, import_id, self.raw_items[import_id].clone())), 603 import_id,
588 raw::RawItemKind::Def(def) => self.define_def(&self.raw_items[def]), 604 import: self.raw_items[import_id].clone(),
605 status: PartialResolvedImport::Unresolved,
606 })
607 }
608 raw::RawItemKind::Def(def) => {
609 self.define_def(&self.raw_items[def], &item.attrs)
610 }
589 raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]), 611 raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]),
590 raw::RawItemKind::Impl(imp) => { 612 raw::RawItemKind::Impl(imp) => {
591 let module = ModuleId { 613 let module = ModuleId {
592 krate: self.def_collector.def_map.krate, 614 krate: self.def_collector.def_map.krate,
593 local_id: self.module_id, 615 local_id: self.module_id,
594 }; 616 };
595 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id); 617 let container = ContainerId::ModuleId(module);
596 let imp_id = ImplId::from_ast_id(ctx, self.raw_items[imp].ast_id); 618 let ast_id = self.raw_items[imp].ast_id;
597 self.def_collector.def_map.modules[self.module_id].impls.push(imp_id) 619 let impl_id =
620 ImplLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
621 .intern(self.def_collector.db);
622 self.def_collector.def_map.modules[self.module_id]
623 .scope
624 .define_impl(impl_id)
598 } 625 }
599 } 626 }
600 } 627 }
@@ -667,72 +694,91 @@ where
667 let modules = &mut self.def_collector.def_map.modules; 694 let modules = &mut self.def_collector.def_map.modules;
668 let res = modules.alloc(ModuleData::default()); 695 let res = modules.alloc(ModuleData::default());
669 modules[res].parent = Some(self.module_id); 696 modules[res].parent = Some(self.module_id);
670 modules[res].declaration = Some(declaration); 697 modules[res].origin = ModuleOrigin::not_sure_file(definition, declaration);
671 modules[res].definition = definition; 698 for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() {
672 modules[res].scope.legacy_macros = modules[self.module_id].scope.legacy_macros.clone(); 699 modules[res].scope.define_legacy_macro(name, mac)
700 }
673 modules[self.module_id].children.insert(name.clone(), res); 701 modules[self.module_id].children.insert(name.clone(), res);
674 let resolution = Resolution { 702 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res };
675 def: PerNs::types( 703 let def: ModuleDefId = module.into();
676 ModuleId { krate: self.def_collector.def_map.krate, local_id: res }.into(), 704 self.def_collector.def_map.modules[self.module_id].scope.define_def(def);
677 ), 705 self.def_collector.update(self.module_id, &[(name, def.into())]);
678 import: None,
679 };
680 self.def_collector.update(self.module_id, None, &[(name, resolution)]);
681 res 706 res
682 } 707 }
683 708
684 fn define_def(&mut self, def: &raw::DefData) { 709 fn define_def(&mut self, def: &raw::DefData, attrs: &Attrs) {
685 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id }; 710 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id };
686 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id); 711 // FIXME: check attrs to see if this is an attribute macro invocation;
712 // in which case we don't add the invocation, just a single attribute
713 // macro invocation
687 714
688 let name = def.name.clone(); 715 self.collect_derives(attrs, def);
689 let def: PerNs = match def.kind {
690 raw::DefKind::Function(ast_id) => {
691 let def = FunctionLoc {
692 container: ContainerId::ModuleId(module),
693 ast_id: AstId::new(self.file_id, ast_id),
694 }
695 .intern(self.def_collector.db);
696 716
697 PerNs::values(def.into()) 717 let name = def.name.clone();
718 let container = ContainerId::ModuleId(module);
719 let def: ModuleDefId = match def.kind {
720 raw::DefKind::Function(ast_id) => FunctionLoc {
721 container: container.into(),
722 ast_id: AstId::new(self.file_id, ast_id),
698 } 723 }
724 .intern(self.def_collector.db)
725 .into(),
699 raw::DefKind::Struct(ast_id) => { 726 raw::DefKind::Struct(ast_id) => {
700 let id = StructId::from_ast_id(ctx, ast_id).into(); 727 StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
701 PerNs::both(id, id) 728 .intern(self.def_collector.db)
729 .into()
702 } 730 }
703 raw::DefKind::Union(ast_id) => { 731 raw::DefKind::Union(ast_id) => {
704 let id = UnionId::from_ast_id(ctx, ast_id).into(); 732 UnionLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
705 PerNs::both(id, id) 733 .intern(self.def_collector.db)
734 .into()
735 }
736 raw::DefKind::Enum(ast_id) => {
737 EnumLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
738 .intern(self.def_collector.db)
739 .into()
706 } 740 }
707 raw::DefKind::Enum(ast_id) => PerNs::types(EnumId::from_ast_id(ctx, ast_id).into()),
708 raw::DefKind::Const(ast_id) => { 741 raw::DefKind::Const(ast_id) => {
709 let def = ConstLoc { 742 ConstLoc { container: container.into(), ast_id: AstId::new(self.file_id, ast_id) }
710 container: ContainerId::ModuleId(module), 743 .intern(self.def_collector.db)
711 ast_id: AstId::new(self.file_id, ast_id), 744 .into()
712 }
713 .intern(self.def_collector.db);
714
715 PerNs::values(def.into())
716 } 745 }
717 raw::DefKind::Static(ast_id) => { 746 raw::DefKind::Static(ast_id) => {
718 let def = StaticLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } 747 StaticLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
719 .intern(self.def_collector.db); 748 .intern(self.def_collector.db)
720 749 .into()
721 PerNs::values(def.into())
722 } 750 }
723 raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()), 751 raw::DefKind::Trait(ast_id) => {
724 raw::DefKind::TypeAlias(ast_id) => { 752 TraitLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
725 let def = TypeAliasLoc { 753 .intern(self.def_collector.db)
726 container: ContainerId::ModuleId(module), 754 .into()
727 ast_id: AstId::new(self.file_id, ast_id),
728 }
729 .intern(self.def_collector.db);
730
731 PerNs::types(def.into())
732 } 755 }
756 raw::DefKind::TypeAlias(ast_id) => TypeAliasLoc {
757 container: container.into(),
758 ast_id: AstId::new(self.file_id, ast_id),
759 }
760 .intern(self.def_collector.db)
761 .into(),
733 }; 762 };
734 let resolution = Resolution { def, import: None }; 763 self.def_collector.def_map.modules[self.module_id].scope.define_def(def);
735 self.def_collector.update(self.module_id, None, &[(name, resolution)]) 764 self.def_collector.update(self.module_id, &[(name, def.into())])
765 }
766
767 fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) {
768 for derive_subtree in attrs.by_key("derive").tt_values() {
769 // for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree
770 for tt in &derive_subtree.token_trees {
771 let ident = match &tt {
772 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident,
773 tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => continue, // , is ok
774 _ => continue, // anything else would be an error (which we currently ignore)
775 };
776 let path = ModPath::from_tt_ident(ident);
777
778 let ast_id = AstId::new(self.file_id, def.kind.ast_id());
779 self.def_collector.unexpanded_attribute_macros.push((self.module_id, ast_id, path));
780 }
781 }
736 } 782 }
737 783
738 fn collect_macro(&mut self, mac: &raw::MacroData) { 784 fn collect_macro(&mut self, mac: &raw::MacroData) {
@@ -758,8 +804,8 @@ where
758 if is_macro_rules(&mac.path) { 804 if is_macro_rules(&mac.path) {
759 if let Some(name) = &mac.name { 805 if let Some(name) = &mac.name {
760 let macro_id = MacroDefId { 806 let macro_id = MacroDefId {
761 ast_id, 807 ast_id: Some(ast_id),
762 krate: self.def_collector.def_map.krate, 808 krate: Some(self.def_collector.def_map.krate),
763 kind: MacroDefKind::Declarative, 809 kind: MacroDefKind::Declarative,
764 }; 810 };
765 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export); 811 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export);
@@ -767,14 +813,20 @@ where
767 return; 813 return;
768 } 814 }
769 815
770 // Case 2: try to resolve in legacy scope and expand macro_rules, triggering 816 // Case 2: try to resolve in legacy scope and expand macro_rules
771 // recursive item collection.
772 if let Some(macro_def) = mac.path.as_ident().and_then(|name| { 817 if let Some(macro_def) = mac.path.as_ident().and_then(|name| {
773 self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) 818 self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name)
774 }) { 819 }) {
775 let macro_call_id = macro_def.as_call_id(self.def_collector.db, ast_id); 820 let macro_call_id =
821 macro_def.as_call_id(self.def_collector.db, MacroCallKind::FnLike(ast_id));
822
823 self.def_collector.unexpanded_macros.push(MacroDirective {
824 module_id: self.module_id,
825 path: mac.path.clone(),
826 ast_id,
827 legacy: Some(macro_call_id),
828 });
776 829
777 self.def_collector.collect_macro_expansion(self.module_id, macro_call_id, macro_def);
778 return; 830 return;
779 } 831 }
780 832
@@ -782,13 +834,19 @@ where
782 // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only. 834 // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only.
783 let mut path = mac.path.clone(); 835 let mut path = mac.path.clone();
784 if path.is_ident() { 836 if path.is_ident() {
785 path.kind = PathKind::Self_; 837 path.kind = PathKind::Super(0);
786 } 838 }
787 self.def_collector.unexpanded_macros.push((self.module_id, ast_id, path)); 839
840 self.def_collector.unexpanded_macros.push(MacroDirective {
841 module_id: self.module_id,
842 path,
843 ast_id,
844 legacy: None,
845 });
788 } 846 }
789 847
790 fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) { 848 fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
791 let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone(); 849 let macros = self.def_collector.def_map[module_id].scope.collect_legacy_macros();
792 for (name, macro_) in macros { 850 for (name, macro_) in macros {
793 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_); 851 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
794 } 852 }
@@ -803,45 +861,35 @@ where
803 } 861 }
804} 862}
805 863
806fn is_macro_rules(path: &Path) -> bool { 864fn is_macro_rules(path: &ModPath) -> bool {
807 path.as_ident() == Some(&name::MACRO_RULES) 865 path.as_ident() == Some(&name![macro_rules])
808} 866}
809 867
810#[cfg(test)] 868#[cfg(test)]
811mod tests { 869mod tests {
870 use crate::{db::DefDatabase, test_db::TestDB};
812 use ra_arena::Arena; 871 use ra_arena::Arena;
813 use ra_db::{fixture::WithFixture, SourceDatabase}; 872 use ra_db::{fixture::WithFixture, SourceDatabase};
814 use rustc_hash::FxHashSet;
815
816 use crate::{db::DefDatabase, test_db::TestDB};
817 873
818 use super::*; 874 use super::*;
819 875
820 fn do_collect_defs( 876 fn do_collect_defs(db: &impl DefDatabase, def_map: CrateDefMap) -> CrateDefMap {
821 db: &impl DefDatabase,
822 def_map: CrateDefMap,
823 monitor: MacroStackMonitor,
824 ) -> (CrateDefMap, FxHashSet<MacroDefId>) {
825 let mut collector = DefCollector { 877 let mut collector = DefCollector {
826 db, 878 db,
827 def_map, 879 def_map,
828 glob_imports: FxHashMap::default(), 880 glob_imports: FxHashMap::default(),
829 unresolved_imports: Vec::new(), 881 unresolved_imports: Vec::new(),
882 resolved_imports: Vec::new(),
830 unexpanded_macros: Vec::new(), 883 unexpanded_macros: Vec::new(),
884 unexpanded_attribute_macros: Vec::new(),
831 mod_dirs: FxHashMap::default(), 885 mod_dirs: FxHashMap::default(),
832 macro_stack_monitor: monitor,
833 poison_macros: FxHashSet::default(),
834 cfg_options: &CfgOptions::default(), 886 cfg_options: &CfgOptions::default(),
835 }; 887 };
836 collector.collect(); 888 collector.collect();
837 (collector.def_map, collector.poison_macros) 889 collector.def_map
838 } 890 }
839 891
840 fn do_limited_resolve( 892 fn do_resolve(code: &str) -> CrateDefMap {
841 code: &str,
842 limit: u32,
843 poison_limit: u32,
844 ) -> (CrateDefMap, FxHashSet<MacroDefId>) {
845 let (db, _file_id) = TestDB::with_single_file(&code); 893 let (db, _file_id) = TestDB::with_single_file(&code);
846 let krate = db.test_crate(); 894 let krate = db.test_crate();
847 895
@@ -859,59 +907,18 @@ mod tests {
859 diagnostics: Vec::new(), 907 diagnostics: Vec::new(),
860 } 908 }
861 }; 909 };
862 910 do_collect_defs(&db, def_map)
863 let mut monitor = MacroStackMonitor::default();
864 monitor.validator = Some(Box::new(move |count| {
865 assert!(count < limit);
866 count >= poison_limit
867 }));
868
869 do_collect_defs(&db, def_map, monitor)
870 } 911 }
871 912
872 #[test] 913 #[test]
873 fn test_macro_expand_limit_width() { 914 fn test_macro_expand_will_stop() {
874 do_limited_resolve( 915 do_resolve(
875 r#" 916 r#"
876 macro_rules! foo { 917 macro_rules! foo {
877 ($($ty:ty)*) => { foo!($($ty)*, $($ty)*); } 918 ($($ty:ty)*) => { foo!($($ty)*, $($ty)*); }
878 } 919 }
879foo!(KABOOM); 920foo!(KABOOM);
880 "#, 921 "#,
881 16,
882 1000,
883 ); 922 );
884 } 923 }
885
886 #[test]
887 fn test_macro_expand_poisoned() {
888 let (_, poison_macros) = do_limited_resolve(
889 r#"
890 macro_rules! foo {
891 ($ty:ty) => { foo!($ty); }
892 }
893foo!(KABOOM);
894 "#,
895 100,
896 16,
897 );
898
899 assert_eq!(poison_macros.len(), 1);
900 }
901
902 #[test]
903 fn test_macro_expand_normal() {
904 let (_, poison_macros) = do_limited_resolve(
905 r#"
906 macro_rules! foo {
907 ($ident:ident) => { struct $ident {} }
908 }
909foo!(Bar);
910 "#,
911 16,
912 16,
913 );
914
915 assert_eq!(poison_macros.len(), 0);
916 }
917} 924}
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs
index b72c55bd1..695014c7b 100644
--- a/crates/ra_hir_def/src/nameres/path_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/path_resolution.rs
@@ -10,16 +10,18 @@
10//! 10//!
11//! `ReachedFixedPoint` signals about this. 11//! `ReachedFixedPoint` signals about this.
12 12
13use std::iter::successors;
14
13use hir_expand::name::Name; 15use hir_expand::name::Name;
14use ra_db::Edition; 16use ra_db::Edition;
15use test_utils::tested_by; 17use test_utils::tested_by;
16 18
17use crate::{ 19use crate::{
18 db::DefDatabase, 20 db::DefDatabase,
19 nameres::CrateDefMap, 21 nameres::{BuiltinShadowMode, CrateDefMap},
20 path::{Path, PathKind}, 22 path::{ModPath, PathKind},
21 per_ns::PerNs, 23 per_ns::PerNs,
22 AdtId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, 24 AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId,
23}; 25};
24 26
25#[derive(Debug, Clone, Copy, PartialEq, Eq)] 27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -39,19 +41,21 @@ pub(super) struct ResolvePathResult {
39 pub(super) resolved_def: PerNs, 41 pub(super) resolved_def: PerNs,
40 pub(super) segment_index: Option<usize>, 42 pub(super) segment_index: Option<usize>,
41 pub(super) reached_fixedpoint: ReachedFixedPoint, 43 pub(super) reached_fixedpoint: ReachedFixedPoint,
44 pub(super) krate: Option<CrateId>,
42} 45}
43 46
44impl ResolvePathResult { 47impl ResolvePathResult {
45 fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult { 48 fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult {
46 ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None) 49 ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None, None)
47 } 50 }
48 51
49 fn with( 52 fn with(
50 resolved_def: PerNs, 53 resolved_def: PerNs,
51 reached_fixedpoint: ReachedFixedPoint, 54 reached_fixedpoint: ReachedFixedPoint,
52 segment_index: Option<usize>, 55 segment_index: Option<usize>,
56 krate: Option<CrateId>,
53 ) -> ResolvePathResult { 57 ) -> ResolvePathResult {
54 ResolvePathResult { resolved_def, reached_fixedpoint, segment_index } 58 ResolvePathResult { resolved_def, reached_fixedpoint, segment_index, krate }
55 } 59 }
56} 60}
57 61
@@ -67,8 +71,18 @@ impl CrateDefMap {
67 db: &impl DefDatabase, 71 db: &impl DefDatabase,
68 mode: ResolveMode, 72 mode: ResolveMode,
69 original_module: LocalModuleId, 73 original_module: LocalModuleId,
70 path: &Path, 74 path: &ModPath,
75 shadow: BuiltinShadowMode,
71 ) -> ResolvePathResult { 76 ) -> ResolvePathResult {
77 // if it is not the last segment, we prefer the module to the builtin
78 let prefer_module = |index| {
79 if index == path.segments.len() - 1 {
80 shadow
81 } else {
82 BuiltinShadowMode::Module
83 }
84 };
85
72 let mut segments = path.segments.iter().enumerate(); 86 let mut segments = path.segments.iter().enumerate();
73 let mut curr_per_ns: PerNs = match path.kind { 87 let mut curr_per_ns: PerNs = match path.kind {
74 PathKind::DollarCrate(krate) => { 88 PathKind::DollarCrate(krate) => {
@@ -85,9 +99,6 @@ impl CrateDefMap {
85 PathKind::Crate => { 99 PathKind::Crate => {
86 PerNs::types(ModuleId { krate: self.krate, local_id: self.root }.into()) 100 PerNs::types(ModuleId { krate: self.krate, local_id: self.root }.into())
87 } 101 }
88 PathKind::Self_ => {
89 PerNs::types(ModuleId { krate: self.krate, local_id: original_module }.into())
90 }
91 // plain import or absolute path in 2015: crate-relative with 102 // plain import or absolute path in 2015: crate-relative with
92 // fallback to extern prelude (with the simplification in 103 // fallback to extern prelude (with the simplification in
93 // rust-lang/rust#57745) 104 // rust-lang/rust#57745)
@@ -96,24 +107,26 @@ impl CrateDefMap {
96 if self.edition == Edition::Edition2015 107 if self.edition == Edition::Edition2015
97 && (path.kind == PathKind::Abs || mode == ResolveMode::Import) => 108 && (path.kind == PathKind::Abs || mode == ResolveMode::Import) =>
98 { 109 {
99 let segment = match segments.next() { 110 let (idx, segment) = match segments.next() {
100 Some((_, segment)) => segment, 111 Some((idx, segment)) => (idx, segment),
101 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), 112 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
102 }; 113 };
103 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); 114 log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
104 self.resolve_name_in_crate_root_or_extern_prelude(&segment.name) 115 self.resolve_name_in_crate_root_or_extern_prelude(&segment, prefer_module(idx))
105 } 116 }
106 PathKind::Plain => { 117 PathKind::Plain => {
107 let segment = match segments.next() { 118 let (idx, segment) = match segments.next() {
108 Some((_, segment)) => segment, 119 Some((idx, segment)) => (idx, segment),
109 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), 120 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
110 }; 121 };
111 log::debug!("resolving {:?} in module", segment); 122 log::debug!("resolving {:?} in module", segment);
112 self.resolve_name_in_module(db, original_module, &segment.name) 123 self.resolve_name_in_module(db, original_module, &segment, prefer_module(idx))
113 } 124 }
114 PathKind::Super => { 125 PathKind::Super(lvl) => {
115 if let Some(p) = self.modules[original_module].parent { 126 let m = successors(Some(original_module), |m| self.modules[*m].parent)
116 PerNs::types(ModuleId { krate: self.krate, local_id: p }.into()) 127 .nth(lvl as usize);
128 if let Some(local_id) = m {
129 PerNs::types(ModuleId { krate: self.krate, local_id }.into())
117 } else { 130 } else {
118 log::debug!("super path in root module"); 131 log::debug!("super path in root module");
119 return ResolvePathResult::empty(ReachedFixedPoint::Yes); 132 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
@@ -125,18 +138,13 @@ impl CrateDefMap {
125 Some((_, segment)) => segment, 138 Some((_, segment)) => segment,
126 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), 139 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
127 }; 140 };
128 if let Some(def) = self.extern_prelude.get(&segment.name) { 141 if let Some(def) = self.extern_prelude.get(&segment) {
129 log::debug!("absolute path {:?} resolved to crate {:?}", path, def); 142 log::debug!("absolute path {:?} resolved to crate {:?}", path, def);
130 PerNs::types(*def) 143 PerNs::types(*def)
131 } else { 144 } else {
132 return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude 145 return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
133 } 146 }
134 } 147 }
135 PathKind::Type(_) => {
136 // This is handled in `infer::infer_path_expr`
137 // The result returned here does not matter
138 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
139 }
140 }; 148 };
141 149
142 for (i, segment) in segments { 150 for (i, segment) in segments {
@@ -156,32 +164,29 @@ impl CrateDefMap {
156 curr_per_ns = match curr { 164 curr_per_ns = match curr {
157 ModuleDefId::ModuleId(module) => { 165 ModuleDefId::ModuleId(module) => {
158 if module.krate != self.krate { 166 if module.krate != self.krate {
159 let path = 167 let path = ModPath {
160 Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ }; 168 segments: path.segments[i..].to_vec(),
169 kind: PathKind::Super(0),
170 };
161 log::debug!("resolving {:?} in other crate", path); 171 log::debug!("resolving {:?} in other crate", path);
162 let defp_map = db.crate_def_map(module.krate); 172 let defp_map = db.crate_def_map(module.krate);
163 let (def, s) = defp_map.resolve_path(db, module.local_id, &path); 173 let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow);
164 return ResolvePathResult::with( 174 return ResolvePathResult::with(
165 def, 175 def,
166 ReachedFixedPoint::Yes, 176 ReachedFixedPoint::Yes,
167 s.map(|s| s + i), 177 s.map(|s| s + i),
178 Some(module.krate),
168 ); 179 );
169 } 180 }
170 181
171 // Since it is a qualified path here, it should not contains legacy macros 182 // Since it is a qualified path here, it should not contains legacy macros
172 match self[module.local_id].scope.get(&segment.name) { 183 self[module.local_id].scope.get(&segment, prefer_module(i))
173 Some(res) => res.def,
174 _ => {
175 log::debug!("path segment {:?} not found", segment.name);
176 return ResolvePathResult::empty(ReachedFixedPoint::No);
177 }
178 }
179 } 184 }
180 ModuleDefId::AdtId(AdtId::EnumId(e)) => { 185 ModuleDefId::AdtId(AdtId::EnumId(e)) => {
181 // enum variant 186 // enum variant
182 tested_by!(can_import_enum_variant); 187 tested_by!(can_import_enum_variant);
183 let enum_data = db.enum_data(e); 188 let enum_data = db.enum_data(e);
184 match enum_data.variant(&segment.name) { 189 match enum_data.variant(&segment) {
185 Some(local_id) => { 190 Some(local_id) => {
186 let variant = EnumVariantId { parent: e, local_id }; 191 let variant = EnumVariantId { parent: e, local_id };
187 PerNs::both(variant.into(), variant.into()) 192 PerNs::both(variant.into(), variant.into())
@@ -191,6 +196,7 @@ impl CrateDefMap {
191 PerNs::types(e.into()), 196 PerNs::types(e.into()),
192 ReachedFixedPoint::Yes, 197 ReachedFixedPoint::Yes,
193 Some(i), 198 Some(i),
199 Some(self.krate),
194 ); 200 );
195 } 201 }
196 } 202 }
@@ -200,7 +206,7 @@ impl CrateDefMap {
200 // (`Struct::method`), or some other kind of associated item 206 // (`Struct::method`), or some other kind of associated item
201 log::debug!( 207 log::debug!(
202 "path segment {:?} resolved to non-module {:?}, but is not last", 208 "path segment {:?} resolved to non-module {:?}, but is not last",
203 segment.name, 209 segment,
204 curr, 210 curr,
205 ); 211 );
206 212
@@ -208,11 +214,13 @@ impl CrateDefMap {
208 PerNs::types(s), 214 PerNs::types(s),
209 ReachedFixedPoint::Yes, 215 ReachedFixedPoint::Yes,
210 Some(i), 216 Some(i),
217 Some(self.krate),
211 ); 218 );
212 } 219 }
213 }; 220 };
214 } 221 }
215 ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None) 222
223 ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None, Some(self.krate))
216 } 224 }
217 225
218 fn resolve_name_in_module( 226 fn resolve_name_in_module(
@@ -220,6 +228,7 @@ impl CrateDefMap {
220 db: &impl DefDatabase, 228 db: &impl DefDatabase,
221 module: LocalModuleId, 229 module: LocalModuleId,
222 name: &Name, 230 name: &Name,
231 shadow: BuiltinShadowMode,
223 ) -> PerNs { 232 ) -> PerNs {
224 // Resolve in: 233 // Resolve in:
225 // - legacy scope of macro 234 // - legacy scope of macro
@@ -228,23 +237,31 @@ impl CrateDefMap {
228 // - std prelude 237 // - std prelude
229 let from_legacy_macro = 238 let from_legacy_macro =
230 self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros); 239 self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros);
231 let from_scope = self[module].scope.get(name).map_or_else(PerNs::none, |res| res.def); 240 let from_scope = self[module].scope.get(name, shadow);
232 let from_extern_prelude = 241 let from_extern_prelude =
233 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); 242 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
234 let from_prelude = self.resolve_in_prelude(db, name); 243 let from_prelude = self.resolve_in_prelude(db, name, shadow);
235 244
236 from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude) 245 from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude)
237 } 246 }
238 247
239 fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs { 248 fn resolve_name_in_crate_root_or_extern_prelude(
240 let from_crate_root = 249 &self,
241 self[self.root].scope.get(name).map_or_else(PerNs::none, |res| res.def); 250 name: &Name,
251 shadow: BuiltinShadowMode,
252 ) -> PerNs {
253 let from_crate_root = self[self.root].scope.get(name, shadow);
242 let from_extern_prelude = self.resolve_name_in_extern_prelude(name); 254 let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
243 255
244 from_crate_root.or(from_extern_prelude) 256 from_crate_root.or(from_extern_prelude)
245 } 257 }
246 258
247 fn resolve_in_prelude(&self, db: &impl DefDatabase, name: &Name) -> PerNs { 259 fn resolve_in_prelude(
260 &self,
261 db: &impl DefDatabase,
262 name: &Name,
263 shadow: BuiltinShadowMode,
264 ) -> PerNs {
248 if let Some(prelude) = self.prelude { 265 if let Some(prelude) = self.prelude {
249 let keep; 266 let keep;
250 let def_map = if prelude.krate == self.krate { 267 let def_map = if prelude.krate == self.krate {
@@ -254,7 +271,7 @@ impl CrateDefMap {
254 keep = db.crate_def_map(prelude.krate); 271 keep = db.crate_def_map(prelude.krate);
255 &keep 272 &keep
256 }; 273 };
257 def_map[prelude.local_id].scope.get(name).map_or_else(PerNs::none, |res| res.def) 274 def_map[prelude.local_id].scope.get(name, shadow)
258 } else { 275 } else {
259 PerNs::none() 276 PerNs::none()
260 } 277 }
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 6eb106094..73dc08745 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -10,21 +10,18 @@ use std::{ops::Index, sync::Arc};
10use hir_expand::{ 10use hir_expand::{
11 ast_id_map::AstIdMap, 11 ast_id_map::AstIdMap,
12 db::AstDatabase, 12 db::AstDatabase,
13 either::Either,
14 hygiene::Hygiene, 13 hygiene::Hygiene,
15 name::{AsName, Name}, 14 name::{AsName, Name},
16}; 15};
17use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; 16use ra_arena::{impl_arena_id, Arena, RawId};
17use ra_prof::profile;
18use ra_syntax::{ 18use ra_syntax::{
19 ast::{self, AttrsOwner, NameOwner}, 19 ast::{self, AttrsOwner, NameOwner},
20 AstNode, AstPtr, 20 AstNode,
21}; 21};
22use test_utils::tested_by; 22use test_utils::tested_by;
23 23
24use crate::{ 24use crate::{attr::Attrs, db::DefDatabase, path::ModPath, FileAstId, HirFileId, InFile};
25 attr::Attrs, db::DefDatabase, path::Path, trace::Trace, FileAstId, HirFileId, LocalImportId,
26 Source,
27};
28 25
29/// `RawItems` is a set of top-level items in a file (except for impls). 26/// `RawItems` is a set of top-level items in a file (except for impls).
30/// 27///
@@ -33,7 +30,7 @@ use crate::{
33#[derive(Debug, Default, PartialEq, Eq)] 30#[derive(Debug, Default, PartialEq, Eq)]
34pub struct RawItems { 31pub struct RawItems {
35 modules: Arena<Module, ModuleData>, 32 modules: Arena<Module, ModuleData>,
36 imports: Arena<LocalImportId, ImportData>, 33 imports: Arena<Import, ImportData>,
37 defs: Arena<Def, DefData>, 34 defs: Arena<Def, DefData>,
38 macros: Arena<Macro, MacroData>, 35 macros: Arena<Macro, MacroData>,
39 impls: Arena<Impl, ImplData>, 36 impls: Arena<Impl, ImplData>,
@@ -41,35 +38,15 @@ pub struct RawItems {
41 items: Vec<RawItem>, 38 items: Vec<RawItem>,
42} 39}
43 40
44#[derive(Debug, Default, PartialEq, Eq)]
45pub struct ImportSourceMap {
46 map: ArenaMap<LocalImportId, ImportSourcePtr>,
47}
48
49type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>;
50
51impl ImportSourceMap {
52 pub fn get(&self, import: LocalImportId) -> ImportSourcePtr {
53 self.map[import].clone()
54 }
55}
56
57impl RawItems { 41impl RawItems {
58 pub(crate) fn raw_items_query( 42 pub(crate) fn raw_items_query(
59 db: &(impl DefDatabase + AstDatabase), 43 db: &(impl DefDatabase + AstDatabase),
60 file_id: HirFileId, 44 file_id: HirFileId,
61 ) -> Arc<RawItems> { 45 ) -> Arc<RawItems> {
62 db.raw_items_with_source_map(file_id).0 46 let _p = profile("raw_items_query");
63 }
64
65 pub(crate) fn raw_items_with_source_map_query(
66 db: &(impl DefDatabase + AstDatabase),
67 file_id: HirFileId,
68 ) -> (Arc<RawItems>, Arc<ImportSourceMap>) {
69 let mut collector = RawItemsCollector { 47 let mut collector = RawItemsCollector {
70 raw_items: RawItems::default(), 48 raw_items: RawItems::default(),
71 source_ast_id_map: db.ast_id_map(file_id), 49 source_ast_id_map: db.ast_id_map(file_id),
72 imports: Trace::new(),
73 file_id, 50 file_id,
74 hygiene: Hygiene::new(db, file_id), 51 hygiene: Hygiene::new(db, file_id),
75 }; 52 };
@@ -80,11 +57,8 @@ impl RawItems {
80 collector.process_module(None, item_list); 57 collector.process_module(None, item_list);
81 } 58 }
82 } 59 }
83 let mut raw_items = collector.raw_items; 60 let raw_items = collector.raw_items;
84 let (arena, map) = collector.imports.into_arena_and_map(); 61 Arc::new(raw_items)
85 raw_items.imports = arena;
86 let source_map = ImportSourceMap { map };
87 (Arc::new(raw_items), Arc::new(source_map))
88 } 62 }
89 63
90 pub(super) fn items(&self) -> &[RawItem] { 64 pub(super) fn items(&self) -> &[RawItem] {
@@ -99,9 +73,9 @@ impl Index<Module> for RawItems {
99 } 73 }
100} 74}
101 75
102impl Index<LocalImportId> for RawItems { 76impl Index<Import> for RawItems {
103 type Output = ImportData; 77 type Output = ImportData;
104 fn index(&self, idx: LocalImportId) -> &ImportData { 78 fn index(&self, idx: Import) -> &ImportData {
105 &self.imports[idx] 79 &self.imports[idx]
106 } 80 }
107} 81}
@@ -136,7 +110,7 @@ pub(super) struct RawItem {
136#[derive(Debug, PartialEq, Eq, Clone, Copy)] 110#[derive(Debug, PartialEq, Eq, Clone, Copy)]
137pub(super) enum RawItemKind { 111pub(super) enum RawItemKind {
138 Module(Module), 112 Module(Module),
139 Import(LocalImportId), 113 Import(Import),
140 Def(Def), 114 Def(Def),
141 Macro(Macro), 115 Macro(Macro),
142 Impl(Impl), 116 Impl(Impl),
@@ -152,9 +126,13 @@ pub(super) enum ModuleData {
152 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> }, 126 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> },
153} 127}
154 128
129#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
130pub(crate) struct Import(RawId);
131impl_arena_id!(Import);
132
155#[derive(Debug, Clone, PartialEq, Eq)] 133#[derive(Debug, Clone, PartialEq, Eq)]
156pub struct ImportData { 134pub struct ImportData {
157 pub(super) path: Path, 135 pub(super) path: ModPath,
158 pub(super) alias: Option<Name>, 136 pub(super) alias: Option<Name>,
159 pub(super) is_glob: bool, 137 pub(super) is_glob: bool,
160 pub(super) is_prelude: bool, 138 pub(super) is_prelude: bool,
@@ -184,6 +162,21 @@ pub(super) enum DefKind {
184 TypeAlias(FileAstId<ast::TypeAliasDef>), 162 TypeAlias(FileAstId<ast::TypeAliasDef>),
185} 163}
186 164
165impl DefKind {
166 pub fn ast_id(&self) -> FileAstId<ast::ModuleItem> {
167 match self {
168 DefKind::Function(it) => it.upcast(),
169 DefKind::Struct(it) => it.upcast(),
170 DefKind::Union(it) => it.upcast(),
171 DefKind::Enum(it) => it.upcast(),
172 DefKind::Const(it) => it.upcast(),
173 DefKind::Static(it) => it.upcast(),
174 DefKind::Trait(it) => it.upcast(),
175 DefKind::TypeAlias(it) => it.upcast(),
176 }
177 }
178}
179
187#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 180#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
188pub(super) struct Macro(RawId); 181pub(super) struct Macro(RawId);
189impl_arena_id!(Macro); 182impl_arena_id!(Macro);
@@ -191,7 +184,7 @@ impl_arena_id!(Macro);
191#[derive(Debug, PartialEq, Eq)] 184#[derive(Debug, PartialEq, Eq)]
192pub(super) struct MacroData { 185pub(super) struct MacroData {
193 pub(super) ast_id: FileAstId<ast::MacroCall>, 186 pub(super) ast_id: FileAstId<ast::MacroCall>,
194 pub(super) path: Path, 187 pub(super) path: ModPath,
195 pub(super) name: Option<Name>, 188 pub(super) name: Option<Name>,
196 pub(super) export: bool, 189 pub(super) export: bool,
197 pub(super) builtin: bool, 190 pub(super) builtin: bool,
@@ -208,7 +201,6 @@ pub(super) struct ImplData {
208 201
209struct RawItemsCollector { 202struct RawItemsCollector {
210 raw_items: RawItems, 203 raw_items: RawItems,
211 imports: Trace<LocalImportId, ImportData, ImportSourcePtr>,
212 source_ast_id_map: Arc<AstIdMap>, 204 source_ast_id_map: Arc<AstIdMap>,
213 file_id: HirFileId, 205 file_id: HirFileId,
214 hygiene: Hygiene, 206 hygiene: Hygiene,
@@ -312,10 +304,10 @@ impl RawItemsCollector {
312 let attrs = self.parse_attrs(&use_item); 304 let attrs = self.parse_attrs(&use_item);
313 305
314 let mut buf = Vec::new(); 306 let mut buf = Vec::new();
315 Path::expand_use_item( 307 ModPath::expand_use_item(
316 Source { value: use_item, file_id: self.file_id }, 308 InFile { value: use_item, file_id: self.file_id },
317 &self.hygiene, 309 &self.hygiene,
318 |path, use_tree, is_glob, alias| { 310 |path, _use_tree, is_glob, alias| {
319 let import_data = ImportData { 311 let import_data = ImportData {
320 path, 312 path,
321 alias, 313 alias,
@@ -324,11 +316,11 @@ impl RawItemsCollector {
324 is_extern_crate: false, 316 is_extern_crate: false,
325 is_macro_use: false, 317 is_macro_use: false,
326 }; 318 };
327 buf.push((import_data, Either::A(AstPtr::new(use_tree)))); 319 buf.push(import_data);
328 }, 320 },
329 ); 321 );
330 for (import_data, ptr) in buf { 322 for import_data in buf {
331 self.push_import(current_module, attrs.clone(), import_data, ptr); 323 self.push_import(current_module, attrs.clone(), import_data);
332 } 324 }
333 } 325 }
334 326
@@ -338,7 +330,7 @@ impl RawItemsCollector {
338 extern_crate: ast::ExternCrateItem, 330 extern_crate: ast::ExternCrateItem,
339 ) { 331 ) {
340 if let Some(name_ref) = extern_crate.name_ref() { 332 if let Some(name_ref) = extern_crate.name_ref() {
341 let path = Path::from_name_ref(&name_ref); 333 let path = ModPath::from_name_ref(&name_ref);
342 let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name()); 334 let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name());
343 let attrs = self.parse_attrs(&extern_crate); 335 let attrs = self.parse_attrs(&extern_crate);
344 // FIXME: cfg_attr 336 // FIXME: cfg_attr
@@ -351,18 +343,13 @@ impl RawItemsCollector {
351 is_extern_crate: true, 343 is_extern_crate: true,
352 is_macro_use, 344 is_macro_use,
353 }; 345 };
354 self.push_import( 346 self.push_import(current_module, attrs, import_data);
355 current_module,
356 attrs,
357 import_data,
358 Either::B(AstPtr::new(&extern_crate)),
359 );
360 } 347 }
361 } 348 }
362 349
363 fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) { 350 fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) {
364 let attrs = self.parse_attrs(&m); 351 let attrs = self.parse_attrs(&m);
365 let path = match m.path().and_then(|path| Path::from_src(path, &self.hygiene)) { 352 let path = match m.path().and_then(|path| ModPath::from_src(path, &self.hygiene)) {
366 Some(it) => it, 353 Some(it) => it,
367 _ => return, 354 _ => return,
368 }; 355 };
@@ -387,14 +374,8 @@ impl RawItemsCollector {
387 self.push_item(current_module, attrs, RawItemKind::Impl(imp)) 374 self.push_item(current_module, attrs, RawItemKind::Impl(imp))
388 } 375 }
389 376
390 fn push_import( 377 fn push_import(&mut self, current_module: Option<Module>, attrs: Attrs, data: ImportData) {
391 &mut self, 378 let import = self.raw_items.imports.alloc(data);
392 current_module: Option<Module>,
393 attrs: Attrs,
394 data: ImportData,
395 source: ImportSourcePtr,
396 ) {
397 let import = self.imports.alloc(|| source, || data);
398 self.push_item(current_module, attrs, RawItemKind::Import(import)) 379 self.push_item(current_module, attrs, RawItemKind::Import(import))
399 } 380 }
400 381
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs
index 87fcd617c..ff474b53b 100644
--- a/crates/ra_hir_def/src/nameres/tests.rs
+++ b/crates/ra_hir_def/src/nameres/tests.rs
@@ -32,27 +32,22 @@ fn render_crate_def_map(map: &CrateDefMap) -> String {
32 *buf += path; 32 *buf += path;
33 *buf += "\n"; 33 *buf += "\n";
34 34
35 let mut entries = map.modules[module] 35 let mut entries = map.modules[module].scope.collect_resolutions();
36 .scope 36 entries.sort_by_key(|(name, _)| name.clone());
37 .items 37
38 .iter() 38 for (name, def) in entries {
39 .map(|(name, res)| (name, res.def))
40 .collect::<Vec<_>>();
41 entries.sort_by_key(|(name, _)| *name);
42
43 for (name, res) in entries {
44 *buf += &format!("{}:", name); 39 *buf += &format!("{}:", name);
45 40
46 if res.types.is_some() { 41 if def.types.is_some() {
47 *buf += " t"; 42 *buf += " t";
48 } 43 }
49 if res.values.is_some() { 44 if def.values.is_some() {
50 *buf += " v"; 45 *buf += " v";
51 } 46 }
52 if res.macros.is_some() { 47 if def.macros.is_some() {
53 *buf += " m"; 48 *buf += " m";
54 } 49 }
55 if res.is_none() { 50 if def.is_none() {
56 *buf += " _"; 51 *buf += " _";
57 } 52 }
58 53
@@ -558,3 +553,35 @@ fn cfg_test() {
558 â‹®Foo: t v 553 â‹®Foo: t v
559 "###); 554 "###);
560} 555}
556
557#[test]
558fn infer_multiple_namespace() {
559 let map = def_map(
560 r#"
561//- /main.rs
562mod a {
563 pub type T = ();
564 pub use crate::b::*;
565}
566
567use crate::a::T;
568
569mod b {
570 pub const T: () = ();
571}
572"#,
573 );
574
575 assert_snapshot!(map, @r###"
576 â‹®crate
577 â‹®T: t v
578 â‹®a: t
579 â‹®b: t
580 â‹®
581 â‹®crate::b
582 â‹®T: v
583 â‹®
584 â‹®crate::a
585 â‹®T: t v
586"###);
587}
diff --git a/crates/ra_hir_def/src/nameres/tests/globs.rs b/crates/ra_hir_def/src/nameres/tests/globs.rs
index 5b03fe365..5e24cb94d 100644
--- a/crates/ra_hir_def/src/nameres/tests/globs.rs
+++ b/crates/ra_hir_def/src/nameres/tests/globs.rs
@@ -112,3 +112,24 @@ fn glob_enum() {
112 "### 112 "###
113 ); 113 );
114} 114}
115
116#[test]
117fn glob_enum_group() {
118 covers!(glob_enum_group);
119 let map = def_map(
120 "
121 //- /lib.rs
122 enum Foo {
123 Bar, Baz
124 }
125 use self::Foo::{*};
126 ",
127 );
128 assert_snapshot!(map, @r###"
129 â‹®crate
130 â‹®Bar: t v
131 â‹®Baz: t v
132 â‹®Foo: t
133 "###
134 );
135}
diff --git a/crates/ra_hir_def/src/nameres/tests/incremental.rs b/crates/ra_hir_def/src/nameres/tests/incremental.rs
index 903a22771..ef2e9435c 100644
--- a/crates/ra_hir_def/src/nameres/tests/incremental.rs
+++ b/crates/ra_hir_def/src/nameres/tests/incremental.rs
@@ -116,7 +116,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() {
116 let events = db.log_executed(|| { 116 let events = db.log_executed(|| {
117 let crate_def_map = db.crate_def_map(krate); 117 let crate_def_map = db.crate_def_map(krate);
118 let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); 118 let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
119 assert_eq!(module_data.scope.items.len(), 1); 119 assert_eq!(module_data.scope.collect_resolutions().len(), 1);
120 }); 120 });
121 assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) 121 assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
122 } 122 }
@@ -126,7 +126,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() {
126 let events = db.log_executed(|| { 126 let events = db.log_executed(|| {
127 let crate_def_map = db.crate_def_map(krate); 127 let crate_def_map = db.crate_def_map(krate);
128 let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); 128 let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
129 assert_eq!(module_data.scope.items.len(), 1); 129 assert_eq!(module_data.scope.collect_resolutions().len(), 1);
130 }); 130 });
131 assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) 131 assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
132 } 132 }
diff --git a/crates/ra_hir_def/src/nameres/tests/macros.rs b/crates/ra_hir_def/src/nameres/tests/macros.rs
index 704065633..d104f5993 100644
--- a/crates/ra_hir_def/src/nameres/tests/macros.rs
+++ b/crates/ra_hir_def/src/nameres/tests/macros.rs
@@ -600,3 +600,27 @@ fn macro_dollar_crate_is_correct_in_indirect_deps() {
600 â‹®bar: t v 600 â‹®bar: t v
601 "###); 601 "###);
602} 602}
603
604#[test]
605fn expand_derive() {
606 let map = compute_crate_def_map(
607 "
608 //- /main.rs
609 #[derive(Clone)]
610 struct Foo;
611 ",
612 );
613 assert_eq!(map.modules[map.root].scope.impls().len(), 1);
614}
615
616#[test]
617fn expand_multiple_derive() {
618 let map = compute_crate_def_map(
619 "
620 //- /main.rs
621 #[derive(Copy, Clone)]
622 struct Foo;
623 ",
624 );
625 assert_eq!(map.modules[map.root].scope.impls().len(), 2);
626}
diff --git a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
index e11530062..e800cc68e 100644
--- a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
@@ -668,7 +668,7 @@ fn unresolved_module_diagnostics() {
668 module: LocalModuleId( 668 module: LocalModuleId(
669 0, 669 0,
670 ), 670 ),
671 declaration: AstId { 671 declaration: InFile {
672 file_id: HirFileId( 672 file_id: HirFileId(
673 FileId( 673 FileId(
674 FileId( 674 FileId(
@@ -676,7 +676,7 @@ fn unresolved_module_diagnostics() {
676 ), 676 ),
677 ), 677 ),
678 ), 678 ),
679 file_ast_id: FileAstId { 679 value: FileAstId {
680 raw: ErasedFileAstId( 680 raw: ErasedFileAstId(
681 1, 681 1,
682 ), 682 ),
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index 6810a26db..8e1294201 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -1,35 +1,97 @@
1//! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`. 1//! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`.
2mod lower;
2 3
3use std::{iter, sync::Arc}; 4use std::{iter, sync::Arc};
4 5
5use hir_expand::{ 6use hir_expand::{
6 either::Either,
7 hygiene::Hygiene, 7 hygiene::Hygiene,
8 name::{self, AsName, Name}, 8 name::{AsName, Name},
9}; 9};
10use ra_db::CrateId; 10use ra_db::CrateId;
11use ra_syntax::{ 11use ra_syntax::ast;
12 ast::{self, NameOwner, TypeAscriptionOwner},
13 AstNode,
14};
15 12
16use crate::{type_ref::TypeRef, Source}; 13use crate::{type_ref::TypeRef, InFile};
17 14
18#[derive(Debug, Clone, PartialEq, Eq, Hash)] 15#[derive(Debug, Clone, PartialEq, Eq, Hash)]
19pub struct Path { 16pub struct ModPath {
20 pub kind: PathKind, 17 pub kind: PathKind,
21 pub segments: Vec<PathSegment>, 18 pub segments: Vec<Name>,
22} 19}
23 20
24#[derive(Debug, Clone, PartialEq, Eq, Hash)] 21#[derive(Debug, Clone, PartialEq, Eq, Hash)]
25pub struct PathSegment { 22pub enum PathKind {
26 pub name: Name, 23 Plain,
27 pub args_and_bindings: Option<Arc<GenericArgs>>, 24 /// `self::` is `Super(0)`
25 Super(u8),
26 Crate,
27 /// Absolute path (::foo)
28 Abs,
29 /// `$crate` from macro expansion
30 DollarCrate(CrateId),
31}
32
33impl ModPath {
34 pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> {
35 lower::lower_path(path, hygiene).map(|it| it.mod_path)
36 }
37
38 pub fn from_simple_segments(
39 kind: PathKind,
40 segments: impl IntoIterator<Item = Name>,
41 ) -> ModPath {
42 let segments = segments.into_iter().collect::<Vec<_>>();
43 ModPath { kind, segments }
44 }
45
46 pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> ModPath {
47 name_ref.as_name().into()
48 }
49
50 /// Converts an `tt::Ident` into a single-identifier `Path`.
51 pub(crate) fn from_tt_ident(ident: &tt::Ident) -> ModPath {
52 ident.as_name().into()
53 }
54
55 /// Calls `cb` with all paths, represented by this use item.
56 pub(crate) fn expand_use_item(
57 item_src: InFile<ast::UseItem>,
58 hygiene: &Hygiene,
59 mut cb: impl FnMut(ModPath, &ast::UseTree, /* is_glob */ bool, Option<Name>),
60 ) {
61 if let Some(tree) = item_src.value.use_tree() {
62 lower::lower_use_tree(None, tree, hygiene, &mut cb);
63 }
64 }
65
66 pub fn is_ident(&self) -> bool {
67 self.kind == PathKind::Plain && self.segments.len() == 1
68 }
69
70 pub fn is_self(&self) -> bool {
71 self.kind == PathKind::Super(0) && self.segments.is_empty()
72 }
73
74 /// If this path is a single identifier, like `foo`, return its name.
75 pub fn as_ident(&self) -> Option<&Name> {
76 if self.kind != PathKind::Plain || self.segments.len() > 1 {
77 return None;
78 }
79 self.segments.first()
80 }
81}
82
83#[derive(Debug, Clone, PartialEq, Eq, Hash)]
84pub struct Path {
85 /// Type based path like `<T>::foo`.
86 /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`.
87 type_anchor: Option<Box<TypeRef>>,
88 mod_path: ModPath,
89 /// Invariant: the same len as self.path.segments
90 generic_args: Vec<Option<Arc<GenericArgs>>>,
28} 91}
29 92
30/// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This 93/// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This
31/// can (in the future) also include bindings of associated types, like in 94/// also includes bindings of associated types, like in `Iterator<Item = Foo>`.
32/// `Iterator<Item = Foo>`.
33#[derive(Debug, Clone, PartialEq, Eq, Hash)] 95#[derive(Debug, Clone, PartialEq, Eq, Hash)]
34pub struct GenericArgs { 96pub struct GenericArgs {
35 pub args: Vec<GenericArg>, 97 pub args: Vec<GenericArg>,
@@ -50,234 +112,111 @@ pub enum GenericArg {
50 // or lifetime... 112 // or lifetime...
51} 113}
52 114
53#[derive(Debug, Clone, PartialEq, Eq, Hash)]
54pub enum PathKind {
55 Plain,
56 Self_,
57 Super,
58 Crate,
59 // Absolute path
60 Abs,
61 // Type based path like `<T>::foo`
62 Type(Box<TypeRef>),
63 // `$crate` from macro expansion
64 DollarCrate(CrateId),
65}
66
67impl Path { 115impl Path {
68 /// Calls `cb` with all paths, represented by this use item.
69 pub(crate) fn expand_use_item(
70 item_src: Source<ast::UseItem>,
71 hygiene: &Hygiene,
72 mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>),
73 ) {
74 if let Some(tree) = item_src.value.use_tree() {
75 expand_use_tree(None, tree, hygiene, &mut cb);
76 }
77 }
78
79 pub(crate) fn from_simple_segments(
80 kind: PathKind,
81 segments: impl IntoIterator<Item = Name>,
82 ) -> Path {
83 Path {
84 kind,
85 segments: segments
86 .into_iter()
87 .map(|name| PathSegment { name, args_and_bindings: None })
88 .collect(),
89 }
90 }
91
92 /// Converts an `ast::Path` to `Path`. Works with use trees. 116 /// Converts an `ast::Path` to `Path`. Works with use trees.
93 /// DEPRECATED: It does not handle `$crate` from macro call. 117 /// DEPRECATED: It does not handle `$crate` from macro call.
94 pub fn from_ast(path: ast::Path) -> Option<Path> { 118 pub fn from_ast(path: ast::Path) -> Option<Path> {
95 Path::from_src(path, &Hygiene::new_unhygienic()) 119 lower::lower_path(path, &Hygiene::new_unhygienic())
96 } 120 }
97 121
98 /// Converts an `ast::Path` to `Path`. Works with use trees. 122 /// Converts an `ast::Path` to `Path`. Works with use trees.
99 /// It correctly handles `$crate` based path from macro call. 123 /// It correctly handles `$crate` based path from macro call.
100 pub fn from_src(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> { 124 pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
101 let mut kind = PathKind::Plain; 125 lower::lower_path(path, hygiene)
102 let mut segments = Vec::new();
103 loop {
104 let segment = path.segment()?;
105
106 if segment.has_colon_colon() {
107 kind = PathKind::Abs;
108 }
109
110 match segment.kind()? {
111 ast::PathSegmentKind::Name(name_ref) => {
112 // FIXME: this should just return name
113 match hygiene.name_ref_to_name(name_ref) {
114 Either::A(name) => {
115 let args = segment
116 .type_arg_list()
117 .and_then(GenericArgs::from_ast)
118 .or_else(|| {
119 GenericArgs::from_fn_like_path_ast(
120 segment.param_list(),
121 segment.ret_type(),
122 )
123 })
124 .map(Arc::new);
125 let segment = PathSegment { name, args_and_bindings: args };
126 segments.push(segment);
127 }
128 Either::B(crate_id) => {
129 kind = PathKind::DollarCrate(crate_id);
130 break;
131 }
132 }
133 }
134 ast::PathSegmentKind::Type { type_ref, trait_ref } => {
135 assert!(path.qualifier().is_none()); // this can only occur at the first segment
136
137 let self_type = TypeRef::from_ast(type_ref?);
138
139 match trait_ref {
140 // <T>::foo
141 None => {
142 kind = PathKind::Type(Box::new(self_type));
143 }
144 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
145 Some(trait_ref) => {
146 let path = Path::from_src(trait_ref.path()?, hygiene)?;
147 kind = path.kind;
148 let mut prefix_segments = path.segments;
149 prefix_segments.reverse();
150 segments.extend(prefix_segments);
151 // Insert the type reference (T in the above example) as Self parameter for the trait
152 let mut last_segment = segments.last_mut()?;
153 if last_segment.args_and_bindings.is_none() {
154 last_segment.args_and_bindings =
155 Some(Arc::new(GenericArgs::empty()));
156 };
157 let args = last_segment.args_and_bindings.as_mut().unwrap();
158 let mut args_inner = Arc::make_mut(args);
159 args_inner.has_self_type = true;
160 args_inner.args.insert(0, GenericArg::Type(self_type));
161 }
162 }
163 }
164 ast::PathSegmentKind::CrateKw => {
165 kind = PathKind::Crate;
166 break;
167 }
168 ast::PathSegmentKind::SelfKw => {
169 kind = PathKind::Self_;
170 break;
171 }
172 ast::PathSegmentKind::SuperKw => {
173 kind = PathKind::Super;
174 break;
175 }
176 }
177 path = match qualifier(&path) {
178 Some(it) => it,
179 None => break,
180 };
181 }
182 segments.reverse();
183 return Some(Path { kind, segments });
184
185 fn qualifier(path: &ast::Path) -> Option<ast::Path> {
186 if let Some(q) = path.qualifier() {
187 return Some(q);
188 }
189 // FIXME: this bottom up traversal is not too precise.
190 // Should we handle do a top-down analysis, recording results?
191 let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?;
192 let use_tree = use_tree_list.parent_use_tree();
193 use_tree.path()
194 }
195 } 126 }
196 127
197 /// Converts an `ast::NameRef` into a single-identifier `Path`. 128 /// Converts an `ast::NameRef` into a single-identifier `Path`.
198 pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path { 129 pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path {
199 name_ref.as_name().into() 130 Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] }
200 } 131 }
201 132
202 /// `true` is this path is a single identifier, like `foo` 133 pub fn kind(&self) -> &PathKind {
203 pub fn is_ident(&self) -> bool { 134 &self.mod_path.kind
204 self.kind == PathKind::Plain && self.segments.len() == 1
205 } 135 }
206 136
207 /// `true` if this path is just a standalone `self` 137 pub fn type_anchor(&self) -> Option<&TypeRef> {
208 pub fn is_self(&self) -> bool { 138 self.type_anchor.as_deref()
209 self.kind == PathKind::Self_ && self.segments.is_empty()
210 } 139 }
211 140
212 /// If this path is a single identifier, like `foo`, return its name. 141 pub fn segments(&self) -> PathSegments<'_> {
213 pub fn as_ident(&self) -> Option<&Name> { 142 PathSegments {
214 if self.kind != PathKind::Plain || self.segments.len() > 1 { 143 segments: self.mod_path.segments.as_slice(),
215 return None; 144 generic_args: self.generic_args.as_slice(),
216 } 145 }
217 self.segments.first().map(|s| &s.name)
218 } 146 }
219 147
220 pub fn expand_macro_expr(&self) -> Option<Name> { 148 pub fn mod_path(&self) -> &ModPath {
221 self.as_ident().and_then(|name| Some(name.clone())) 149 &self.mod_path
222 } 150 }
223 151
224 pub fn is_type_relative(&self) -> bool { 152 pub fn qualifier(&self) -> Option<Path> {
225 match self.kind { 153 if self.mod_path.is_ident() {
226 PathKind::Type(_) => true, 154 return None;
227 _ => false,
228 } 155 }
156 let res = Path {
157 type_anchor: self.type_anchor.clone(),
158 mod_path: ModPath {
159 kind: self.mod_path.kind.clone(),
160 segments: self.mod_path.segments[..self.mod_path.segments.len() - 1].to_vec(),
161 },
162 generic_args: self.generic_args[..self.generic_args.len() - 1].to_vec(),
163 };
164 Some(res)
229 } 165 }
230} 166}
231 167
232impl GenericArgs { 168#[derive(Debug, Clone, PartialEq, Eq, Hash)]
233 pub(crate) fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> { 169pub struct PathSegment<'a> {
234 let mut args = Vec::new(); 170 pub name: &'a Name,
235 for type_arg in node.type_args() { 171 pub args_and_bindings: Option<&'a GenericArgs>,
236 let type_ref = TypeRef::from_ast_opt(type_arg.type_ref()); 172}
237 args.push(GenericArg::Type(type_ref)); 173
238 } 174pub struct PathSegments<'a> {
239 // lifetimes ignored for now 175 segments: &'a [Name],
240 let mut bindings = Vec::new(); 176 generic_args: &'a [Option<Arc<GenericArgs>>],
241 for assoc_type_arg in node.assoc_type_args() { 177}
242 if let Some(name_ref) = assoc_type_arg.name_ref() { 178
243 let name = name_ref.as_name(); 179impl<'a> PathSegments<'a> {
244 let type_ref = TypeRef::from_ast_opt(assoc_type_arg.type_ref()); 180 pub const EMPTY: PathSegments<'static> = PathSegments { segments: &[], generic_args: &[] };
245 bindings.push((name, type_ref)); 181 pub fn is_empty(&self) -> bool {
246 } 182 self.len() == 0
247 } 183 }
248 if args.is_empty() && bindings.is_empty() { 184 pub fn len(&self) -> usize {
249 None 185 self.segments.len()
250 } else { 186 }
251 Some(GenericArgs { args, has_self_type: false, bindings }) 187 pub fn first(&self) -> Option<PathSegment<'a>> {
252 } 188 self.get(0)
189 }
190 pub fn last(&self) -> Option<PathSegment<'a>> {
191 self.get(self.len().checked_sub(1)?)
192 }
193 pub fn get(&self, idx: usize) -> Option<PathSegment<'a>> {
194 assert_eq!(self.segments.len(), self.generic_args.len());
195 let res = PathSegment {
196 name: self.segments.get(idx)?,
197 args_and_bindings: self.generic_args.get(idx).unwrap().as_ref().map(|it| &**it),
198 };
199 Some(res)
200 }
201 pub fn skip(&self, len: usize) -> PathSegments<'a> {
202 assert_eq!(self.segments.len(), self.generic_args.len());
203 PathSegments { segments: &self.segments[len..], generic_args: &self.generic_args[len..] }
204 }
205 pub fn take(&self, len: usize) -> PathSegments<'a> {
206 assert_eq!(self.segments.len(), self.generic_args.len());
207 PathSegments { segments: &self.segments[..len], generic_args: &self.generic_args[..len] }
208 }
209 pub fn iter(&self) -> impl Iterator<Item = PathSegment<'a>> {
210 self.segments.iter().zip(self.generic_args.iter()).map(|(name, args)| PathSegment {
211 name,
212 args_and_bindings: args.as_ref().map(|it| &**it),
213 })
253 } 214 }
215}
254 216
255 /// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y) 217impl GenericArgs {
256 /// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`). 218 pub(crate) fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> {
257 pub(crate) fn from_fn_like_path_ast( 219 lower::lower_generic_args(node)
258 params: Option<ast::ParamList>,
259 ret_type: Option<ast::RetType>,
260 ) -> Option<GenericArgs> {
261 let mut args = Vec::new();
262 let mut bindings = Vec::new();
263 if let Some(params) = params {
264 let mut param_types = Vec::new();
265 for param in params.params() {
266 let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
267 param_types.push(type_ref);
268 }
269 let arg = GenericArg::Type(TypeRef::Tuple(param_types));
270 args.push(arg);
271 }
272 if let Some(ret_type) = ret_type {
273 let type_ref = TypeRef::from_ast_opt(ret_type.type_ref());
274 bindings.push((name::OUTPUT_TYPE, type_ref))
275 }
276 if args.is_empty() && bindings.is_empty() {
277 None
278 } else {
279 Some(GenericArgs { args, has_self_type: false, bindings })
280 }
281 } 220 }
282 221
283 pub(crate) fn empty() -> GenericArgs { 222 pub(crate) fn empty() -> GenericArgs {
@@ -287,137 +226,51 @@ impl GenericArgs {
287 226
288impl From<Name> for Path { 227impl From<Name> for Path {
289 fn from(name: Name) -> Path { 228 fn from(name: Name) -> Path {
290 Path::from_simple_segments(PathKind::Plain, iter::once(name)) 229 Path {
230 type_anchor: None,
231 mod_path: ModPath::from_simple_segments(PathKind::Plain, iter::once(name)),
232 generic_args: vec![None],
233 }
291 } 234 }
292} 235}
293 236
294fn expand_use_tree( 237impl From<Name> for ModPath {
295 prefix: Option<Path>, 238 fn from(name: Name) -> ModPath {
296 tree: ast::UseTree, 239 ModPath::from_simple_segments(PathKind::Plain, iter::once(name))
297 hygiene: &Hygiene,
298 cb: &mut dyn FnMut(Path, &ast::UseTree, bool, Option<Name>),
299) {
300 if let Some(use_tree_list) = tree.use_tree_list() {
301 let prefix = match tree.path() {
302 // E.g. use something::{{{inner}}};
303 None => prefix,
304 // E.g. `use something::{inner}` (prefix is `None`, path is `something`)
305 // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`)
306 Some(path) => match convert_path(prefix, path, hygiene) {
307 Some(it) => Some(it),
308 None => return, // FIXME: report errors somewhere
309 },
310 };
311 for child_tree in use_tree_list.use_trees() {
312 expand_use_tree(prefix.clone(), child_tree, hygiene, cb);
313 }
314 } else {
315 let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name());
316 if let Some(ast_path) = tree.path() {
317 // Handle self in a path.
318 // E.g. `use something::{self, <...>}`
319 if ast_path.qualifier().is_none() {
320 if let Some(segment) = ast_path.segment() {
321 if segment.kind() == Some(ast::PathSegmentKind::SelfKw) {
322 if let Some(prefix) = prefix {
323 cb(prefix, &tree, false, alias);
324 return;
325 }
326 }
327 }
328 }
329 if let Some(path) = convert_path(prefix, ast_path, hygiene) {
330 let is_glob = tree.has_star();
331 cb(path, &tree, is_glob, alias)
332 }
333 // FIXME: report errors somewhere
334 // We get here if we do
335 }
336 } 240 }
337} 241}
338 242
339fn convert_path(prefix: Option<Path>, path: ast::Path, hygiene: &Hygiene) -> Option<Path> { 243pub use hir_expand::name as __name;
340 let prefix = if let Some(qual) = path.qualifier() { 244
341 Some(convert_path(prefix, qual, hygiene)?) 245#[macro_export]
342 } else { 246macro_rules! __known_path {
343 prefix 247 (std::iter::IntoIterator) => {};
344 }; 248 (std::result::Result) => {};
345 249 (std::ops::Range) => {};
346 let segment = path.segment()?; 250 (std::ops::RangeFrom) => {};
347 let res = match segment.kind()? { 251 (std::ops::RangeFull) => {};
348 ast::PathSegmentKind::Name(name_ref) => { 252 (std::ops::RangeTo) => {};
349 match hygiene.name_ref_to_name(name_ref) { 253 (std::ops::RangeToInclusive) => {};
350 Either::A(name) => { 254 (std::ops::RangeInclusive) => {};
351 // no type args in use 255 (std::boxed::Box) => {};
352 let mut res = prefix.unwrap_or_else(|| Path { 256 (std::future::Future) => {};
353 kind: PathKind::Plain, 257 (std::ops::Try) => {};
354 segments: Vec::with_capacity(1), 258 (std::ops::Neg) => {};
355 }); 259 (std::ops::Not) => {};
356 res.segments.push(PathSegment { 260 (std::ops::Index) => {};
357 name, 261 ($path:path) => {
358 args_and_bindings: None, // no type args in use 262 compile_error!("Please register your known path in the path module")
359 });
360 res
361 }
362 Either::B(crate_id) => {
363 return Some(Path::from_simple_segments(
364 PathKind::DollarCrate(crate_id),
365 iter::empty(),
366 ))
367 }
368 }
369 }
370 ast::PathSegmentKind::CrateKw => {
371 if prefix.is_some() {
372 return None;
373 }
374 Path::from_simple_segments(PathKind::Crate, iter::empty())
375 }
376 ast::PathSegmentKind::SelfKw => {
377 if prefix.is_some() {
378 return None;
379 }
380 Path::from_simple_segments(PathKind::Self_, iter::empty())
381 }
382 ast::PathSegmentKind::SuperKw => {
383 if prefix.is_some() {
384 return None;
385 }
386 Path::from_simple_segments(PathKind::Super, iter::empty())
387 }
388 ast::PathSegmentKind::Type { .. } => {
389 // not allowed in imports
390 return None;
391 }
392 }; 263 };
393 Some(res)
394} 264}
395 265
396pub mod known { 266#[macro_export]
397 use hir_expand::name; 267macro_rules! __path {
398 268 ($start:ident $(:: $seg:ident)*) => ({
399 use super::{Path, PathKind}; 269 $crate::__known_path!($start $(:: $seg)*);
400 270 $crate::path::ModPath::from_simple_segments($crate::path::PathKind::Abs, vec![
401 pub fn std_iter_into_iterator() -> Path { 271 $crate::path::__name![$start], $($crate::path::__name![$seg],)*
402 Path::from_simple_segments( 272 ])
403 PathKind::Abs, 273 });
404 vec![name::STD, name::ITER, name::INTO_ITERATOR_TYPE],
405 )
406 }
407
408 pub fn std_ops_try() -> Path {
409 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::TRY_TYPE])
410 }
411
412 pub fn std_result_result() -> Path {
413 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::RESULT, name::RESULT_TYPE])
414 }
415
416 pub fn std_future_future() -> Path {
417 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::FUTURE, name::FUTURE_TYPE])
418 }
419
420 pub fn std_boxed_box() -> Path {
421 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::BOXED, name::BOX_TYPE])
422 }
423} 274}
275
276pub use crate::__path as path;
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs
new file mode 100644
index 000000000..62aafd508
--- /dev/null
+++ b/crates/ra_hir_def/src/path/lower.rs
@@ -0,0 +1,178 @@
1//! Transforms syntax into `Path` objects, ideally with accounting for hygiene
2
3mod lower_use;
4
5use std::sync::Arc;
6
7use either::Either;
8use hir_expand::{
9 hygiene::Hygiene,
10 name::{name, AsName},
11};
12use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner};
13
14use crate::{
15 path::{GenericArg, GenericArgs, ModPath, Path, PathKind},
16 type_ref::TypeRef,
17};
18
19pub(super) use lower_use::lower_use_tree;
20
21/// Converts an `ast::Path` to `Path`. Works with use trees.
22/// It correctly handles `$crate` based path from macro call.
23pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
24 let mut kind = PathKind::Plain;
25 let mut type_anchor = None;
26 let mut segments = Vec::new();
27 let mut generic_args = Vec::new();
28 loop {
29 let segment = path.segment()?;
30
31 if segment.has_colon_colon() {
32 kind = PathKind::Abs;
33 }
34
35 match segment.kind()? {
36 ast::PathSegmentKind::Name(name_ref) => {
37 // FIXME: this should just return name
38 match hygiene.name_ref_to_name(name_ref) {
39 Either::Left(name) => {
40 let args = segment
41 .type_arg_list()
42 .and_then(lower_generic_args)
43 .or_else(|| {
44 lower_generic_args_from_fn_path(
45 segment.param_list(),
46 segment.ret_type(),
47 )
48 })
49 .map(Arc::new);
50 segments.push(name);
51 generic_args.push(args)
52 }
53 Either::Right(crate_id) => {
54 kind = PathKind::DollarCrate(crate_id);
55 break;
56 }
57 }
58 }
59 ast::PathSegmentKind::Type { type_ref, trait_ref } => {
60 assert!(path.qualifier().is_none()); // this can only occur at the first segment
61
62 let self_type = TypeRef::from_ast(type_ref?);
63
64 match trait_ref {
65 // <T>::foo
66 None => {
67 type_anchor = Some(Box::new(self_type));
68 kind = PathKind::Plain;
69 }
70 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
71 Some(trait_ref) => {
72 let path = Path::from_src(trait_ref.path()?, hygiene)?;
73 kind = path.mod_path.kind;
74
75 let mut prefix_segments = path.mod_path.segments;
76 prefix_segments.reverse();
77 segments.extend(prefix_segments);
78
79 let mut prefix_args = path.generic_args;
80 prefix_args.reverse();
81 generic_args.extend(prefix_args);
82
83 // Insert the type reference (T in the above example) as Self parameter for the trait
84 let last_segment = generic_args.last_mut()?;
85 if last_segment.is_none() {
86 *last_segment = Some(Arc::new(GenericArgs::empty()));
87 };
88 let args = last_segment.as_mut().unwrap();
89 let mut args_inner = Arc::make_mut(args);
90 args_inner.has_self_type = true;
91 args_inner.args.insert(0, GenericArg::Type(self_type));
92 }
93 }
94 }
95 ast::PathSegmentKind::CrateKw => {
96 kind = PathKind::Crate;
97 break;
98 }
99 ast::PathSegmentKind::SelfKw => {
100 kind = PathKind::Super(0);
101 break;
102 }
103 ast::PathSegmentKind::SuperKw => {
104 kind = PathKind::Super(1);
105 break;
106 }
107 }
108 path = match qualifier(&path) {
109 Some(it) => it,
110 None => break,
111 };
112 }
113 segments.reverse();
114 generic_args.reverse();
115 let mod_path = ModPath { kind, segments };
116 return Some(Path { type_anchor, mod_path, generic_args });
117
118 fn qualifier(path: &ast::Path) -> Option<ast::Path> {
119 if let Some(q) = path.qualifier() {
120 return Some(q);
121 }
122 // FIXME: this bottom up traversal is not too precise.
123 // Should we handle do a top-down analysis, recording results?
124 let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?;
125 let use_tree = use_tree_list.parent_use_tree();
126 use_tree.path()
127 }
128}
129
130pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs> {
131 let mut args = Vec::new();
132 for type_arg in node.type_args() {
133 let type_ref = TypeRef::from_ast_opt(type_arg.type_ref());
134 args.push(GenericArg::Type(type_ref));
135 }
136 // lifetimes ignored for now
137 let mut bindings = Vec::new();
138 for assoc_type_arg in node.assoc_type_args() {
139 if let Some(name_ref) = assoc_type_arg.name_ref() {
140 let name = name_ref.as_name();
141 let type_ref = TypeRef::from_ast_opt(assoc_type_arg.type_ref());
142 bindings.push((name, type_ref));
143 }
144 }
145 if args.is_empty() && bindings.is_empty() {
146 None
147 } else {
148 Some(GenericArgs { args, has_self_type: false, bindings })
149 }
150}
151
152/// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y)
153/// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`).
154fn lower_generic_args_from_fn_path(
155 params: Option<ast::ParamList>,
156 ret_type: Option<ast::RetType>,
157) -> Option<GenericArgs> {
158 let mut args = Vec::new();
159 let mut bindings = Vec::new();
160 if let Some(params) = params {
161 let mut param_types = Vec::new();
162 for param in params.params() {
163 let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
164 param_types.push(type_ref);
165 }
166 let arg = GenericArg::Type(TypeRef::Tuple(param_types));
167 args.push(arg);
168 }
169 if let Some(ret_type) = ret_type {
170 let type_ref = TypeRef::from_ast_opt(ret_type.type_ref());
171 bindings.push((name![Output], type_ref))
172 }
173 if args.is_empty() && bindings.is_empty() {
174 None
175 } else {
176 Some(GenericArgs { args, has_self_type: false, bindings })
177 }
178}
diff --git a/crates/ra_hir_def/src/path/lower/lower_use.rs b/crates/ra_hir_def/src/path/lower/lower_use.rs
new file mode 100644
index 000000000..3218eaf0a
--- /dev/null
+++ b/crates/ra_hir_def/src/path/lower/lower_use.rs
@@ -0,0 +1,118 @@
1//! Lowers a single complex use like `use foo::{bar, baz};` into a list of paths like
2//! `foo::bar`, `foo::baz`;
3
4use std::iter;
5
6use either::Either;
7use hir_expand::{
8 hygiene::Hygiene,
9 name::{AsName, Name},
10};
11use ra_syntax::ast::{self, NameOwner};
12use test_utils::tested_by;
13
14use crate::path::{ModPath, PathKind};
15
16pub(crate) fn lower_use_tree(
17 prefix: Option<ModPath>,
18 tree: ast::UseTree,
19 hygiene: &Hygiene,
20 cb: &mut dyn FnMut(ModPath, &ast::UseTree, bool, Option<Name>),
21) {
22 if let Some(use_tree_list) = tree.use_tree_list() {
23 let prefix = match tree.path() {
24 // E.g. use something::{{{inner}}};
25 None => prefix,
26 // E.g. `use something::{inner}` (prefix is `None`, path is `something`)
27 // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`)
28 Some(path) => match convert_path(prefix, path, hygiene) {
29 Some(it) => Some(it),
30 None => return, // FIXME: report errors somewhere
31 },
32 };
33 for child_tree in use_tree_list.use_trees() {
34 lower_use_tree(prefix.clone(), child_tree, hygiene, cb);
35 }
36 } else {
37 let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name());
38 let is_glob = tree.has_star();
39 if let Some(ast_path) = tree.path() {
40 // Handle self in a path.
41 // E.g. `use something::{self, <...>}`
42 if ast_path.qualifier().is_none() {
43 if let Some(segment) = ast_path.segment() {
44 if segment.kind() == Some(ast::PathSegmentKind::SelfKw) {
45 if let Some(prefix) = prefix {
46 cb(prefix, &tree, false, alias);
47 return;
48 }
49 }
50 }
51 }
52 if let Some(path) = convert_path(prefix, ast_path, hygiene) {
53 cb(path, &tree, is_glob, alias)
54 }
55 // FIXME: report errors somewhere
56 // We get here if we do
57 } else if is_glob {
58 tested_by!(glob_enum_group);
59 if let Some(prefix) = prefix {
60 cb(prefix, &tree, is_glob, None)
61 }
62 }
63 }
64}
65
66fn convert_path(prefix: Option<ModPath>, path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> {
67 let prefix = if let Some(qual) = path.qualifier() {
68 Some(convert_path(prefix, qual, hygiene)?)
69 } else {
70 prefix
71 };
72
73 let segment = path.segment()?;
74 let res = match segment.kind()? {
75 ast::PathSegmentKind::Name(name_ref) => {
76 match hygiene.name_ref_to_name(name_ref) {
77 Either::Left(name) => {
78 // no type args in use
79 let mut res = prefix.unwrap_or_else(|| ModPath {
80 kind: PathKind::Plain,
81 segments: Vec::with_capacity(1),
82 });
83 res.segments.push(name);
84 res
85 }
86 Either::Right(crate_id) => {
87 return Some(ModPath::from_simple_segments(
88 PathKind::DollarCrate(crate_id),
89 iter::empty(),
90 ))
91 }
92 }
93 }
94 ast::PathSegmentKind::CrateKw => {
95 if prefix.is_some() {
96 return None;
97 }
98 ModPath::from_simple_segments(PathKind::Crate, iter::empty())
99 }
100 ast::PathSegmentKind::SelfKw => {
101 if prefix.is_some() {
102 return None;
103 }
104 ModPath::from_simple_segments(PathKind::Super(0), iter::empty())
105 }
106 ast::PathSegmentKind::SuperKw => {
107 if prefix.is_some() {
108 return None;
109 }
110 ModPath::from_simple_segments(PathKind::Super(1), iter::empty())
111 }
112 ast::PathSegmentKind::Type { .. } => {
113 // not allowed in imports
114 return None;
115 }
116 };
117 Some(res)
118}
diff --git a/crates/ra_hir_def/src/per_ns.rs b/crates/ra_hir_def/src/per_ns.rs
index 00e866bf9..3a5105028 100644
--- a/crates/ra_hir_def/src/per_ns.rs
+++ b/crates/ra_hir_def/src/per_ns.rs
@@ -11,8 +11,6 @@ use crate::ModuleDefId;
11pub struct PerNs { 11pub struct PerNs {
12 pub types: Option<ModuleDefId>, 12 pub types: Option<ModuleDefId>,
13 pub values: Option<ModuleDefId>, 13 pub values: Option<ModuleDefId>,
14 /// Since macros has different type, many methods simply ignore it.
15 /// We can only use special method like `get_macros` to access it.
16 pub macros: Option<MacroDefId>, 14 pub macros: Option<MacroDefId>,
17} 15}
18 16
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index 0847f6dcf..cf3c33d78 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -2,7 +2,7 @@
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use hir_expand::{ 4use hir_expand::{
5 name::{self, Name}, 5 name::{name, Name},
6 MacroDefId, 6 MacroDefId,
7}; 7};
8use ra_db::CrateId; 8use ra_db::CrateId;
@@ -10,20 +10,23 @@ use rustc_hash::FxHashSet;
10 10
11use crate::{ 11use crate::{
12 body::scope::{ExprScopes, ScopeId}, 12 body::scope::{ExprScopes, ScopeId},
13 body::Body,
13 builtin_type::BuiltinType, 14 builtin_type::BuiltinType,
14 db::DefDatabase, 15 db::DefDatabase,
15 expr::{ExprId, PatId}, 16 expr::{ExprId, PatId},
16 generics::GenericParams, 17 generics::GenericParams,
18 item_scope::BuiltinShadowMode,
17 nameres::CrateDefMap, 19 nameres::CrateDefMap,
18 path::{Path, PathKind}, 20 path::{ModPath, PathKind},
19 per_ns::PerNs, 21 per_ns::PerNs,
20 AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, 22 AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId,
21 GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, 23 FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId,
22 StructId, TraitId, TypeAliasId, 24 StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId,
23}; 25};
24 26
25#[derive(Debug, Clone, Default)] 27#[derive(Debug, Clone, Default)]
26pub struct Resolver { 28pub struct Resolver {
29 // FIXME: all usages generally call `.rev`, so maybe reverse once in consturciton?
27 scopes: Vec<Scope>, 30 scopes: Vec<Scope>,
28} 31}
29 32
@@ -53,12 +56,14 @@ enum Scope {
53 AdtScope(AdtId), 56 AdtScope(AdtId),
54 /// Local bindings 57 /// Local bindings
55 ExprScope(ExprScope), 58 ExprScope(ExprScope),
59 /// Temporary hack to support local items.
60 LocalItemsScope(Arc<Body>),
56} 61}
57 62
58#[derive(Debug, Clone, PartialEq, Eq, Hash)] 63#[derive(Debug, Clone, PartialEq, Eq, Hash)]
59pub enum TypeNs { 64pub enum TypeNs {
60 SelfType(ImplId), 65 SelfType(ImplId),
61 GenericParam(u32), 66 GenericParam(TypeParamId),
62 AdtId(AdtId), 67 AdtId(AdtId),
63 AdtSelfType(AdtId), 68 AdtSelfType(AdtId),
64 // Yup, enum variants are added to the types ns, but any usage of variant as 69 // Yup, enum variants are added to the types ns, but any usage of variant as
@@ -90,8 +95,8 @@ pub enum ValueNs {
90 95
91impl Resolver { 96impl Resolver {
92 /// Resolve known trait from std, like `std::futures::Future` 97 /// Resolve known trait from std, like `std::futures::Future`
93 pub fn resolve_known_trait(&self, db: &impl DefDatabase, path: &Path) -> Option<TraitId> { 98 pub fn resolve_known_trait(&self, db: &impl DefDatabase, path: &ModPath) -> Option<TraitId> {
94 let res = self.resolve_module_path(db, path).take_types()?; 99 let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?;
95 match res { 100 match res {
96 ModuleDefId::TraitId(it) => Some(it), 101 ModuleDefId::TraitId(it) => Some(it),
97 _ => None, 102 _ => None,
@@ -99,8 +104,8 @@ impl Resolver {
99 } 104 }
100 105
101 /// Resolve known struct from std, like `std::boxed::Box` 106 /// Resolve known struct from std, like `std::boxed::Box`
102 pub fn resolve_known_struct(&self, db: &impl DefDatabase, path: &Path) -> Option<StructId> { 107 pub fn resolve_known_struct(&self, db: &impl DefDatabase, path: &ModPath) -> Option<StructId> {
103 let res = self.resolve_module_path(db, path).take_types()?; 108 let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?;
104 match res { 109 match res {
105 ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it), 110 ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it),
106 _ => None, 111 _ => None,
@@ -108,87 +113,116 @@ impl Resolver {
108 } 113 }
109 114
110 /// Resolve known enum from std, like `std::result::Result` 115 /// Resolve known enum from std, like `std::result::Result`
111 pub fn resolve_known_enum(&self, db: &impl DefDatabase, path: &Path) -> Option<EnumId> { 116 pub fn resolve_known_enum(&self, db: &impl DefDatabase, path: &ModPath) -> Option<EnumId> {
112 let res = self.resolve_module_path(db, path).take_types()?; 117 let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?;
113 match res { 118 match res {
114 ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it), 119 ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it),
115 _ => None, 120 _ => None,
116 } 121 }
117 } 122 }
118 123
119 /// pub only for source-binder 124 fn resolve_module_path(
120 pub fn resolve_module_path(&self, db: &impl DefDatabase, path: &Path) -> PerNs { 125 &self,
126 db: &impl DefDatabase,
127 path: &ModPath,
128 shadow: BuiltinShadowMode,
129 ) -> PerNs {
121 let (item_map, module) = match self.module() { 130 let (item_map, module) = match self.module() {
122 Some(it) => it, 131 Some(it) => it,
123 None => return PerNs::none(), 132 None => return PerNs::none(),
124 }; 133 };
125 let (module_res, segment_index) = item_map.resolve_path(db, module, path); 134 let (module_res, segment_index) = item_map.resolve_path(db, module, &path, shadow);
126 if segment_index.is_some() { 135 if segment_index.is_some() {
127 return PerNs::none(); 136 return PerNs::none();
128 } 137 }
129 module_res 138 module_res
130 } 139 }
131 140
141 pub fn resolve_module_path_in_items(&self, db: &impl DefDatabase, path: &ModPath) -> PerNs {
142 self.resolve_module_path(db, path, BuiltinShadowMode::Module)
143 }
144
132 pub fn resolve_path_in_type_ns( 145 pub fn resolve_path_in_type_ns(
133 &self, 146 &self,
134 db: &impl DefDatabase, 147 db: &impl DefDatabase,
135 path: &Path, 148 path: &ModPath,
136 ) -> Option<(TypeNs, Option<usize>)> { 149 ) -> Option<(TypeNs, Option<usize>)> {
137 if path.is_type_relative() { 150 let first_name = path.segments.first()?;
138 return None;
139 }
140 let first_name = &path.segments.first()?.name;
141 let skip_to_mod = path.kind != PathKind::Plain; 151 let skip_to_mod = path.kind != PathKind::Plain;
142 for scope in self.scopes.iter().rev() { 152 for scope in self.scopes.iter().rev() {
143 match scope { 153 match scope {
144 Scope::ExprScope(_) => continue, 154 Scope::ExprScope(_) => continue,
145 Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue, 155 Scope::GenericParams { .. }
156 | Scope::ImplBlockScope(_)
157 | Scope::LocalItemsScope(_)
158 if skip_to_mod =>
159 {
160 continue
161 }
146 162
147 Scope::GenericParams { params, .. } => { 163 Scope::GenericParams { params, def } => {
148 if let Some(param) = params.find_by_name(first_name) { 164 if let Some(local_id) = params.find_by_name(first_name) {
149 let idx = if path.segments.len() == 1 { None } else { Some(1) }; 165 let idx = if path.segments.len() == 1 { None } else { Some(1) };
150 return Some((TypeNs::GenericParam(param.idx), idx)); 166 return Some((
167 TypeNs::GenericParam(TypeParamId { local_id, parent: *def }),
168 idx,
169 ));
151 } 170 }
152 } 171 }
153 Scope::ImplBlockScope(impl_) => { 172 Scope::ImplBlockScope(impl_) => {
154 if first_name == &name::SELF_TYPE { 173 if first_name == &name![Self] {
155 let idx = if path.segments.len() == 1 { None } else { Some(1) }; 174 let idx = if path.segments.len() == 1 { None } else { Some(1) };
156 return Some((TypeNs::SelfType(*impl_), idx)); 175 return Some((TypeNs::SelfType(*impl_), idx));
157 } 176 }
158 } 177 }
159 Scope::AdtScope(adt) => { 178 Scope::AdtScope(adt) => {
160 if first_name == &name::SELF_TYPE { 179 if first_name == &name![Self] {
161 let idx = if path.segments.len() == 1 { None } else { Some(1) }; 180 let idx = if path.segments.len() == 1 { None } else { Some(1) };
162 return Some((TypeNs::AdtSelfType(*adt), idx)); 181 return Some((TypeNs::AdtSelfType(*adt), idx));
163 } 182 }
164 } 183 }
165 Scope::ModuleScope(m) => { 184 Scope::ModuleScope(m) => {
166 let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path); 185 let (module_def, idx) = m.crate_def_map.resolve_path(
167 let res = match module_def.take_types()? { 186 db,
168 ModuleDefId::AdtId(it) => TypeNs::AdtId(it), 187 m.module_id,
169 ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it), 188 &path,
170 189 BuiltinShadowMode::Other,
171 ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), 190 );
172 ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), 191 let res = to_type_ns(module_def)?;
173
174 ModuleDefId::TraitId(it) => TypeNs::TraitId(it),
175
176 ModuleDefId::FunctionId(_)
177 | ModuleDefId::ConstId(_)
178 | ModuleDefId::StaticId(_)
179 | ModuleDefId::ModuleId(_) => return None,
180 };
181 return Some((res, idx)); 192 return Some((res, idx));
182 } 193 }
194 Scope::LocalItemsScope(body) => {
195 let def = body.item_scope.get(first_name, BuiltinShadowMode::Other);
196 if let Some(res) = to_type_ns(def) {
197 return Some((res, None));
198 }
199 }
183 } 200 }
184 } 201 }
185 None 202 return None;
203 fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> {
204 let res = match per_ns.take_types()? {
205 ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
206 ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it),
207
208 ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it),
209 ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it),
210
211 ModuleDefId::TraitId(it) => TypeNs::TraitId(it),
212
213 ModuleDefId::FunctionId(_)
214 | ModuleDefId::ConstId(_)
215 | ModuleDefId::StaticId(_)
216 | ModuleDefId::ModuleId(_) => return None,
217 };
218 Some(res)
219 }
186 } 220 }
187 221
188 pub fn resolve_path_in_type_ns_fully( 222 pub fn resolve_path_in_type_ns_fully(
189 &self, 223 &self,
190 db: &impl DefDatabase, 224 db: &impl DefDatabase,
191 path: &Path, 225 path: &ModPath,
192 ) -> Option<TypeNs> { 226 ) -> Option<TypeNs> {
193 let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?; 227 let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?;
194 if unresolved.is_some() { 228 if unresolved.is_some() {
@@ -197,17 +231,14 @@ impl Resolver {
197 Some(res) 231 Some(res)
198 } 232 }
199 233
200 pub fn resolve_path_in_value_ns<'p>( 234 pub fn resolve_path_in_value_ns(
201 &self, 235 &self,
202 db: &impl DefDatabase, 236 db: &impl DefDatabase,
203 path: &'p Path, 237 path: &ModPath,
204 ) -> Option<ResolveValueResult> { 238 ) -> Option<ResolveValueResult> {
205 if path.is_type_relative() {
206 return None;
207 }
208 let n_segments = path.segments.len(); 239 let n_segments = path.segments.len();
209 let tmp = name::SELF_PARAM; 240 let tmp = name![self];
210 let first_name = if path.is_self() { &tmp } else { &path.segments.first()?.name }; 241 let first_name = if path.is_self() { &tmp } else { &path.segments.first()? };
211 let skip_to_mod = path.kind != PathKind::Plain && !path.is_self(); 242 let skip_to_mod = path.kind != PathKind::Plain && !path.is_self();
212 for scope in self.scopes.iter().rev() { 243 for scope in self.scopes.iter().rev() {
213 match scope { 244 match scope {
@@ -215,6 +246,7 @@ impl Resolver {
215 | Scope::ExprScope(_) 246 | Scope::ExprScope(_)
216 | Scope::GenericParams { .. } 247 | Scope::GenericParams { .. }
217 | Scope::ImplBlockScope(_) 248 | Scope::ImplBlockScope(_)
249 | Scope::LocalItemsScope(_)
218 if skip_to_mod => 250 if skip_to_mod =>
219 { 251 {
220 continue 252 continue
@@ -233,22 +265,22 @@ impl Resolver {
233 } 265 }
234 Scope::ExprScope(_) => continue, 266 Scope::ExprScope(_) => continue,
235 267
236 Scope::GenericParams { params, .. } if n_segments > 1 => { 268 Scope::GenericParams { params, def } if n_segments > 1 => {
237 if let Some(param) = params.find_by_name(first_name) { 269 if let Some(local_id) = params.find_by_name(first_name) {
238 let ty = TypeNs::GenericParam(param.idx); 270 let ty = TypeNs::GenericParam(TypeParamId { local_id, parent: *def });
239 return Some(ResolveValueResult::Partial(ty, 1)); 271 return Some(ResolveValueResult::Partial(ty, 1));
240 } 272 }
241 } 273 }
242 Scope::GenericParams { .. } => continue, 274 Scope::GenericParams { .. } => continue,
243 275
244 Scope::ImplBlockScope(impl_) if n_segments > 1 => { 276 Scope::ImplBlockScope(impl_) if n_segments > 1 => {
245 if first_name == &name::SELF_TYPE { 277 if first_name == &name![Self] {
246 let ty = TypeNs::SelfType(*impl_); 278 let ty = TypeNs::SelfType(*impl_);
247 return Some(ResolveValueResult::Partial(ty, 1)); 279 return Some(ResolveValueResult::Partial(ty, 1));
248 } 280 }
249 } 281 }
250 Scope::AdtScope(adt) if n_segments > 1 => { 282 Scope::AdtScope(adt) if n_segments > 1 => {
251 if first_name == &name::SELF_TYPE { 283 if first_name == &name![Self] {
252 let ty = TypeNs::AdtSelfType(*adt); 284 let ty = TypeNs::AdtSelfType(*adt);
253 return Some(ResolveValueResult::Partial(ty, 1)); 285 return Some(ResolveValueResult::Partial(ty, 1));
254 } 286 }
@@ -256,23 +288,15 @@ impl Resolver {
256 Scope::ImplBlockScope(_) | Scope::AdtScope(_) => continue, 288 Scope::ImplBlockScope(_) | Scope::AdtScope(_) => continue,
257 289
258 Scope::ModuleScope(m) => { 290 Scope::ModuleScope(m) => {
259 let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path); 291 let (module_def, idx) = m.crate_def_map.resolve_path(
292 db,
293 m.module_id,
294 &path,
295 BuiltinShadowMode::Other,
296 );
260 return match idx { 297 return match idx {
261 None => { 298 None => {
262 let value = match module_def.take_values()? { 299 let value = to_value_ns(module_def)?;
263 ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it),
264 ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it),
265 ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it),
266 ModuleDefId::ConstId(it) => ValueNs::ConstId(it),
267 ModuleDefId::StaticId(it) => ValueNs::StaticId(it),
268
269 ModuleDefId::AdtId(AdtId::EnumId(_))
270 | ModuleDefId::AdtId(AdtId::UnionId(_))
271 | ModuleDefId::TraitId(_)
272 | ModuleDefId::TypeAliasId(_)
273 | ModuleDefId::BuiltinType(_)
274 | ModuleDefId::ModuleId(_) => return None,
275 };
276 Some(ResolveValueResult::ValueNs(value)) 300 Some(ResolveValueResult::ValueNs(value))
277 } 301 }
278 Some(idx) => { 302 Some(idx) => {
@@ -292,15 +316,39 @@ impl Resolver {
292 } 316 }
293 }; 317 };
294 } 318 }
319 Scope::LocalItemsScope(body) => {
320 let def = body.item_scope.get(first_name, BuiltinShadowMode::Other);
321 if let Some(res) = to_value_ns(def) {
322 return Some(ResolveValueResult::ValueNs(res));
323 }
324 }
295 } 325 }
296 } 326 }
297 None 327 return None;
328
329 fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> {
330 let res = match per_ns.take_values()? {
331 ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it),
332 ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it),
333 ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it),
334 ModuleDefId::ConstId(it) => ValueNs::ConstId(it),
335 ModuleDefId::StaticId(it) => ValueNs::StaticId(it),
336
337 ModuleDefId::AdtId(AdtId::EnumId(_))
338 | ModuleDefId::AdtId(AdtId::UnionId(_))
339 | ModuleDefId::TraitId(_)
340 | ModuleDefId::TypeAliasId(_)
341 | ModuleDefId::BuiltinType(_)
342 | ModuleDefId::ModuleId(_) => return None,
343 };
344 Some(res)
345 }
298 } 346 }
299 347
300 pub fn resolve_path_in_value_ns_fully( 348 pub fn resolve_path_in_value_ns_fully(
301 &self, 349 &self,
302 db: &impl DefDatabase, 350 db: &impl DefDatabase,
303 path: &Path, 351 path: &ModPath,
304 ) -> Option<ValueNs> { 352 ) -> Option<ValueNs> {
305 match self.resolve_path_in_value_ns(db, path)? { 353 match self.resolve_path_in_value_ns(db, path)? {
306 ResolveValueResult::ValueNs(it) => Some(it), 354 ResolveValueResult::ValueNs(it) => Some(it),
@@ -308,9 +356,13 @@ impl Resolver {
308 } 356 }
309 } 357 }
310 358
311 pub fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> { 359 pub fn resolve_path_as_macro(
360 &self,
361 db: &impl DefDatabase,
362 path: &ModPath,
363 ) -> Option<MacroDefId> {
312 let (item_map, module) = self.module()?; 364 let (item_map, module) = self.module()?;
313 item_map.resolve_path(db, module, path).0.take_macros() 365 item_map.resolve_path(db, module, &path, BuiltinShadowMode::Other).0.take_macros()
314 } 366 }
315 367
316 pub fn process_all_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) { 368 pub fn process_all_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) {
@@ -350,6 +402,7 @@ impl Resolver {
350 ) -> impl Iterator<Item = &'a crate::generics::WherePredicate> + 'a { 402 ) -> impl Iterator<Item = &'a crate::generics::WherePredicate> + 'a {
351 self.scopes 403 self.scopes
352 .iter() 404 .iter()
405 .rev()
353 .filter_map(|scope| match scope { 406 .filter_map(|scope| match scope {
354 Scope::GenericParams { params, .. } => Some(params), 407 Scope::GenericParams { params, .. } => Some(params),
355 _ => None, 408 _ => None,
@@ -358,14 +411,14 @@ impl Resolver {
358 } 411 }
359 412
360 pub fn generic_def(&self) -> Option<GenericDefId> { 413 pub fn generic_def(&self) -> Option<GenericDefId> {
361 self.scopes.iter().find_map(|scope| match scope { 414 self.scopes.iter().rev().find_map(|scope| match scope {
362 Scope::GenericParams { def, .. } => Some(*def), 415 Scope::GenericParams { def, .. } => Some(*def),
363 _ => None, 416 _ => None,
364 }) 417 })
365 } 418 }
366 419
367 pub fn body_owner(&self) -> Option<DefWithBodyId> { 420 pub fn body_owner(&self) -> Option<DefWithBodyId> {
368 self.scopes.iter().find_map(|scope| match scope { 421 self.scopes.iter().rev().find_map(|scope| match scope {
369 Scope::ExprScope(it) => Some(it.owner), 422 Scope::ExprScope(it) => Some(it.owner),
370 _ => None, 423 _ => None,
371 }) 424 })
@@ -376,7 +429,7 @@ pub enum ScopeDef {
376 PerNs(PerNs), 429 PerNs(PerNs),
377 ImplSelfType(ImplId), 430 ImplSelfType(ImplId),
378 AdtSelfType(AdtId), 431 AdtSelfType(AdtId),
379 GenericParam(u32), 432 GenericParam(TypeParamId),
380 Local(PatId), 433 Local(PatId),
381} 434}
382 435
@@ -391,8 +444,8 @@ impl Scope {
391 // def: m.module.into(), 444 // def: m.module.into(),
392 // }), 445 // }),
393 // ); 446 // );
394 m.crate_def_map[m.module_id].scope.entries().for_each(|(name, res)| { 447 m.crate_def_map[m.module_id].scope.entries().for_each(|(name, def)| {
395 f(name.clone(), ScopeDef::PerNs(res.def)); 448 f(name.clone(), ScopeDef::PerNs(def));
396 }); 449 });
397 m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| { 450 m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| {
398 f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_))); 451 f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_)));
@@ -402,21 +455,29 @@ impl Scope {
402 }); 455 });
403 if let Some(prelude) = m.crate_def_map.prelude { 456 if let Some(prelude) = m.crate_def_map.prelude {
404 let prelude_def_map = db.crate_def_map(prelude.krate); 457 let prelude_def_map = db.crate_def_map(prelude.krate);
405 prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, res)| { 458 prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| {
406 f(name.clone(), ScopeDef::PerNs(res.def)); 459 f(name.clone(), ScopeDef::PerNs(def));
407 }); 460 });
408 } 461 }
409 } 462 }
410 Scope::GenericParams { params, .. } => { 463 Scope::LocalItemsScope(body) => {
411 for param in params.params.iter() { 464 body.item_scope.entries_without_primitives().for_each(|(name, def)| {
412 f(param.name.clone(), ScopeDef::GenericParam(param.idx)) 465 f(name.clone(), ScopeDef::PerNs(def));
466 })
467 }
468 Scope::GenericParams { params, def } => {
469 for (local_id, param) in params.types.iter() {
470 f(
471 param.name.clone(),
472 ScopeDef::GenericParam(TypeParamId { local_id, parent: *def }),
473 )
413 } 474 }
414 } 475 }
415 Scope::ImplBlockScope(i) => { 476 Scope::ImplBlockScope(i) => {
416 f(name::SELF_TYPE, ScopeDef::ImplSelfType((*i).into())); 477 f(name![Self], ScopeDef::ImplSelfType((*i).into()));
417 } 478 }
418 Scope::AdtScope(i) => { 479 Scope::AdtScope(i) => {
419 f(name::SELF_TYPE, ScopeDef::AdtSelfType((*i).into())); 480 f(name![Self], ScopeDef::AdtSelfType((*i).into()));
420 } 481 }
421 Scope::ExprScope(scope) => { 482 Scope::ExprScope(scope) => {
422 scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| { 483 scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| {
@@ -439,6 +500,7 @@ pub fn resolver_for_scope(
439 scope_id: Option<ScopeId>, 500 scope_id: Option<ScopeId>,
440) -> Resolver { 501) -> Resolver {
441 let mut r = owner.resolver(db); 502 let mut r = owner.resolver(db);
503 r = r.push_local_items_scope(db.body(owner));
442 let scopes = db.expr_scopes(owner); 504 let scopes = db.expr_scopes(owner);
443 let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>(); 505 let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>();
444 for scope in scope_chain.into_iter().rev() { 506 for scope in scope_chain.into_iter().rev() {
@@ -455,7 +517,7 @@ impl Resolver {
455 517
456 fn push_generic_params_scope(self, db: &impl DefDatabase, def: GenericDefId) -> Resolver { 518 fn push_generic_params_scope(self, db: &impl DefDatabase, def: GenericDefId) -> Resolver {
457 let params = db.generic_params(def); 519 let params = db.generic_params(def);
458 if params.params.is_empty() { 520 if params.types.is_empty() {
459 self 521 self
460 } else { 522 } else {
461 self.push_scope(Scope::GenericParams { def, params }) 523 self.push_scope(Scope::GenericParams { def, params })
@@ -474,6 +536,10 @@ impl Resolver {
474 self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) 536 self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id }))
475 } 537 }
476 538
539 fn push_local_items_scope(self, body: Arc<Body>) -> Resolver {
540 self.push_scope(Scope::LocalItemsScope(body))
541 }
542
477 fn push_expr_scope( 543 fn push_expr_scope(
478 self, 544 self,
479 owner: DefWithBodyId, 545 owner: DefWithBodyId,
@@ -498,7 +564,7 @@ impl HasResolver for ModuleId {
498 564
499impl HasResolver for TraitId { 565impl HasResolver for TraitId {
500 fn resolver(self, db: &impl DefDatabase) -> Resolver { 566 fn resolver(self, db: &impl DefDatabase) -> Resolver {
501 self.module(db).resolver(db).push_generic_params_scope(db, self.into()) 567 self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into())
502 } 568 }
503} 569}
504 570
@@ -518,16 +584,6 @@ impl HasResolver for FunctionId {
518 } 584 }
519} 585}
520 586
521impl HasResolver for DefWithBodyId {
522 fn resolver(self, db: &impl DefDatabase) -> Resolver {
523 match self {
524 DefWithBodyId::ConstId(c) => c.resolver(db),
525 DefWithBodyId::FunctionId(f) => f.resolver(db),
526 DefWithBodyId::StaticId(s) => s.resolver(db),
527 }
528 }
529}
530
531impl HasResolver for ConstId { 587impl HasResolver for ConstId {
532 fn resolver(self, db: &impl DefDatabase) -> Resolver { 588 fn resolver(self, db: &impl DefDatabase) -> Resolver {
533 self.lookup(db).container.resolver(db) 589 self.lookup(db).container.resolver(db)
@@ -546,12 +602,41 @@ impl HasResolver for TypeAliasId {
546 } 602 }
547} 603}
548 604
605impl HasResolver for ImplId {
606 fn resolver(self, db: &impl DefDatabase) -> Resolver {
607 self.lookup(db)
608 .container
609 .resolver(db)
610 .push_generic_params_scope(db, self.into())
611 .push_impl_block_scope(self)
612 }
613}
614
615impl HasResolver for DefWithBodyId {
616 fn resolver(self, db: &impl DefDatabase) -> Resolver {
617 match self {
618 DefWithBodyId::ConstId(c) => c.resolver(db),
619 DefWithBodyId::FunctionId(f) => f.resolver(db),
620 DefWithBodyId::StaticId(s) => s.resolver(db),
621 }
622 }
623}
624
549impl HasResolver for ContainerId { 625impl HasResolver for ContainerId {
550 fn resolver(self, db: &impl DefDatabase) -> Resolver { 626 fn resolver(self, db: &impl DefDatabase) -> Resolver {
551 match self { 627 match self {
552 ContainerId::TraitId(it) => it.resolver(db),
553 ContainerId::ImplId(it) => it.resolver(db),
554 ContainerId::ModuleId(it) => it.resolver(db), 628 ContainerId::ModuleId(it) => it.resolver(db),
629 ContainerId::DefWithBodyId(it) => it.resolver(db),
630 }
631 }
632}
633
634impl HasResolver for AssocContainerId {
635 fn resolver(self, db: &impl DefDatabase) -> Resolver {
636 match self {
637 AssocContainerId::ContainerId(it) => it.resolver(db),
638 AssocContainerId::TraitId(it) => it.resolver(db),
639 AssocContainerId::ImplId(it) => it.resolver(db),
555 } 640 }
556 } 641 }
557} 642}
@@ -570,11 +655,12 @@ impl HasResolver for GenericDefId {
570 } 655 }
571} 656}
572 657
573impl HasResolver for ImplId { 658impl HasResolver for VariantId {
574 fn resolver(self, db: &impl DefDatabase) -> Resolver { 659 fn resolver(self, db: &impl DefDatabase) -> Resolver {
575 self.module(db) 660 match self {
576 .resolver(db) 661 VariantId::EnumVariantId(it) => it.parent.resolver(db),
577 .push_generic_params_scope(db, self.into()) 662 VariantId::StructId(it) => it.resolver(db),
578 .push_impl_block_scope(self) 663 VariantId::UnionId(it) => it.resolver(db),
664 }
579 } 665 }
580} 666}
diff --git a/crates/ra_hir_def/src/src.rs b/crates/ra_hir_def/src/src.rs
new file mode 100644
index 000000000..499375b80
--- /dev/null
+++ b/crates/ra_hir_def/src/src.rs
@@ -0,0 +1,36 @@
1//! Utilities for mapping between hir IDs and the surface syntax.
2
3use hir_expand::InFile;
4use ra_arena::map::ArenaMap;
5use ra_syntax::AstNode;
6
7use crate::{db::DefDatabase, AssocItemLoc, ItemLoc};
8
9pub trait HasSource {
10 type Value;
11 fn source(&self, db: &impl DefDatabase) -> InFile<Self::Value>;
12}
13
14impl<N: AstNode> HasSource for AssocItemLoc<N> {
15 type Value = N;
16
17 fn source(&self, db: &impl DefDatabase) -> InFile<N> {
18 let node = self.ast_id.to_node(db);
19 InFile::new(self.ast_id.file_id, node)
20 }
21}
22
23impl<N: AstNode> HasSource for ItemLoc<N> {
24 type Value = N;
25
26 fn source(&self, db: &impl DefDatabase) -> InFile<N> {
27 let node = self.ast_id.to_node(db);
28 InFile::new(self.ast_id.file_id, node)
29 }
30}
31
32pub trait HasChildSource {
33 type ChildId;
34 type Value;
35 fn child_source(&self, db: &impl DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>>;
36}
diff --git a/crates/ra_hir_def/src/trace.rs b/crates/ra_hir_def/src/trace.rs
index 2bcd707bc..9769e88df 100644
--- a/crates/ra_hir_def/src/trace.rs
+++ b/crates/ra_hir_def/src/trace.rs
@@ -18,10 +18,6 @@ pub(crate) struct Trace<ID: ArenaId, T, V> {
18} 18}
19 19
20impl<ID: ra_arena::ArenaId + Copy, T, V> Trace<ID, T, V> { 20impl<ID: ra_arena::ArenaId + Copy, T, V> Trace<ID, T, V> {
21 pub(crate) fn new() -> Trace<ID, T, V> {
22 Trace { arena: Some(Arena::default()), map: Some(ArenaMap::default()), len: 0 }
23 }
24
25 pub(crate) fn new_for_arena() -> Trace<ID, T, V> { 21 pub(crate) fn new_for_arena() -> Trace<ID, T, V> {
26 Trace { arena: Some(Arena::default()), map: None, len: 0 } 22 Trace { arena: Some(Arena::default()), map: None, len: 0 }
27 } 23 }
@@ -52,8 +48,4 @@ impl<ID: ra_arena::ArenaId + Copy, T, V> Trace<ID, T, V> {
52 pub(crate) fn into_map(mut self) -> ArenaMap<ID, V> { 48 pub(crate) fn into_map(mut self) -> ArenaMap<ID, V> {
53 self.map.take().unwrap() 49 self.map.take().unwrap()
54 } 50 }
55
56 pub(crate) fn into_arena_and_map(mut self) -> (Arena<ID, T>, ArenaMap<ID, V>) {
57 (self.arena.take().unwrap(), self.map.take().unwrap())
58 }
59} 51}