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