diff options
author | Aleksey Kladov <[email protected]> | 2019-03-26 15:27:22 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-03-26 15:27:22 +0000 |
commit | 8f324773127c733b12d1c5ee98a3d9c6a5360db0 (patch) | |
tree | 4cc6186b417ae6cff6bec44f17ce53b1af574010 /crates/ra_hir/src | |
parent | 071a19537d4399fd04d1e9594ab7878502a12d21 (diff) |
more type safety
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/ids.rs | 32 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/collector.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/raw.rs | 48 | ||||
-rw-r--r-- | crates/ra_hir/src/source_id.rs | 40 |
5 files changed, 82 insertions, 63 deletions
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index b503e0ee5..c2df5ce00 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs | |||
@@ -1,5 +1,4 @@ | |||
1 | use std::{ | 1 | use std::{ |
2 | marker::PhantomData, | ||
3 | hash::{Hash, Hasher}, | 2 | hash::{Hash, Hasher}, |
4 | sync::Arc, | 3 | sync::Arc, |
5 | }; | 4 | }; |
@@ -10,7 +9,7 @@ use ra_arena::{RawId, ArenaId, impl_arena_id}; | |||
10 | use mbe::MacroRules; | 9 | use mbe::MacroRules; |
11 | 10 | ||
12 | use crate::{ | 11 | use crate::{ |
13 | Module, DefDatabase, SourceItemId, SourceFileItemId, AstId, | 12 | Module, DefDatabase, AstId, FileAstId, |
14 | }; | 13 | }; |
15 | 14 | ||
16 | #[derive(Debug, Default)] | 15 | #[derive(Debug, Default)] |
@@ -123,6 +122,7 @@ impl From<MacroCallId> for HirFileId { | |||
123 | } | 122 | } |
124 | 123 | ||
125 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 124 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
125 | |||
126 | pub struct MacroDefId(pub(crate) AstId<ast::MacroCall>); | 126 | pub struct MacroDefId(pub(crate) AstId<ast::MacroCall>); |
127 | 127 | ||
128 | pub(crate) fn macro_def_query(db: &impl DefDatabase, id: MacroDefId) -> Option<Arc<MacroRules>> { | 128 | pub(crate) fn macro_def_query(db: &impl DefDatabase, id: MacroDefId) -> Option<Arc<MacroRules>> { |
@@ -161,26 +161,25 @@ impl MacroCallLoc { | |||
161 | #[derive(Debug)] | 161 | #[derive(Debug)] |
162 | pub struct ItemLoc<N: AstNode> { | 162 | pub struct ItemLoc<N: AstNode> { |
163 | pub(crate) module: Module, | 163 | pub(crate) module: Module, |
164 | raw: SourceItemId, | 164 | ast_id: AstId<N>, |
165 | _ty: PhantomData<N>, | ||
166 | } | 165 | } |
167 | 166 | ||
168 | impl<N: AstNode> PartialEq for ItemLoc<N> { | 167 | impl<N: AstNode> PartialEq for ItemLoc<N> { |
169 | fn eq(&self, other: &Self) -> bool { | 168 | fn eq(&self, other: &Self) -> bool { |
170 | self.module == other.module && self.raw == other.raw | 169 | self.module == other.module && self.ast_id == other.ast_id |
171 | } | 170 | } |
172 | } | 171 | } |
173 | impl<N: AstNode> Eq for ItemLoc<N> {} | 172 | impl<N: AstNode> Eq for ItemLoc<N> {} |
174 | impl<N: AstNode> Hash for ItemLoc<N> { | 173 | impl<N: AstNode> Hash for ItemLoc<N> { |
175 | fn hash<H: Hasher>(&self, hasher: &mut H) { | 174 | fn hash<H: Hasher>(&self, hasher: &mut H) { |
176 | self.module.hash(hasher); | 175 | self.module.hash(hasher); |
177 | self.raw.hash(hasher); | 176 | self.ast_id.hash(hasher); |
178 | } | 177 | } |
179 | } | 178 | } |
180 | 179 | ||
181 | impl<N: AstNode> Clone for ItemLoc<N> { | 180 | impl<N: AstNode> Clone for ItemLoc<N> { |
182 | fn clone(&self) -> ItemLoc<N> { | 181 | fn clone(&self) -> ItemLoc<N> { |
183 | ItemLoc { module: self.module, raw: self.raw, _ty: PhantomData } | 182 | ItemLoc { module: self.module, ast_id: self.ast_id } |
184 | } | 183 | } |
185 | } | 184 | } |
186 | 185 | ||
@@ -208,25 +207,18 @@ pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone { | |||
208 | fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<N>, Self>; | 207 | fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<N>, Self>; |
209 | fn from_ast(ctx: LocationCtx<&impl DefDatabase>, ast: &N) -> Self { | 208 | fn from_ast(ctx: LocationCtx<&impl DefDatabase>, ast: &N) -> Self { |
210 | let items = ctx.db.file_items(ctx.file_id); | 209 | let items = ctx.db.file_items(ctx.file_id); |
211 | let item_id = items.id_of(ctx.file_id, ast.syntax()); | 210 | let item_id = items.ast_id(ast); |
212 | Self::from_source_item_id_unchecked(ctx, item_id) | 211 | Self::from_ast_id(ctx, item_id) |
213 | } | 212 | } |
214 | fn from_source_item_id_unchecked( | 213 | fn from_ast_id(ctx: LocationCtx<&impl DefDatabase>, ast_id: FileAstId<N>) -> Self { |
215 | ctx: LocationCtx<&impl DefDatabase>, | 214 | let loc = ItemLoc { module: ctx.module, ast_id: ast_id.with_file_id(ctx.file_id) }; |
216 | item_id: SourceFileItemId, | ||
217 | ) -> Self { | ||
218 | let raw = SourceItemId { file_id: ctx.file_id, item_id }; | ||
219 | let loc = ItemLoc { module: ctx.module, raw, _ty: PhantomData }; | ||
220 | |||
221 | Self::interner(ctx.db.as_ref()).loc2id(&loc) | 215 | Self::interner(ctx.db.as_ref()).loc2id(&loc) |
222 | } | 216 | } |
223 | fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<N>) { | 217 | fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<N>) { |
224 | let int = Self::interner(db.as_ref()); | 218 | let int = Self::interner(db.as_ref()); |
225 | let loc = int.id2loc(self); | 219 | let loc = int.id2loc(self); |
226 | let syntax = db.file_item(loc.raw); | 220 | let ast = loc.ast_id.to_node(db); |
227 | let ast = | 221 | (loc.ast_id.file_id(), ast) |
228 | N::cast(&syntax).unwrap_or_else(|| panic!("invalid ItemLoc: {:?}", loc.raw)).to_owned(); | ||
229 | (loc.raw.file_id, ast) | ||
230 | } | 222 | } |
231 | fn module(self, db: &impl DefDatabase) -> Module { | 223 | fn module(self, db: &impl DefDatabase) -> Module { |
232 | let int = Self::interner(db.as_ref()); | 224 | let int = Self::interner(db.as_ref()); |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 3fc08c55c..b1f388b06 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -48,7 +48,7 @@ mod marks; | |||
48 | use crate::{ | 48 | use crate::{ |
49 | db::{HirDatabase, DefDatabase}, | 49 | db::{HirDatabase, DefDatabase}, |
50 | name::{AsName, KnownName}, | 50 | name::{AsName, KnownName}, |
51 | source_id::{SourceFileItemId, FileAstId, AstId}, | 51 | source_id::{FileAstId, AstId}, |
52 | }; | 52 | }; |
53 | 53 | ||
54 | pub use self::{ | 54 | pub use self::{ |
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index b5f02ab80..39cadc94a 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs | |||
@@ -429,23 +429,24 @@ where | |||
429 | fn define_def(&mut self, def: &raw::DefData) { | 429 | fn define_def(&mut self, def: &raw::DefData) { |
430 | let module = Module { krate: self.def_collector.def_map.krate, module_id: self.module_id }; | 430 | let module = Module { krate: self.def_collector.def_map.krate, module_id: self.module_id }; |
431 | let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id.into()); | 431 | let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id.into()); |
432 | macro_rules! id { | 432 | |
433 | () => { | 433 | macro_rules! def { |
434 | AstItemDef::from_source_item_id_unchecked(ctx, def.source_item_id) | 434 | ($kind:ident, $ast_id:ident) => { |
435 | $kind { id: AstItemDef::from_ast_id(ctx, $ast_id) }.into() | ||
435 | }; | 436 | }; |
436 | } | 437 | } |
437 | let name = def.name.clone(); | 438 | let name = def.name.clone(); |
438 | let def: PerNs<ModuleDef> = match def.kind { | 439 | let def: PerNs<ModuleDef> = match def.kind { |
439 | raw::DefKind::Function => PerNs::values(Function { id: id!() }.into()), | 440 | raw::DefKind::Function(ast_id) => PerNs::values(def!(Function, ast_id)), |
440 | raw::DefKind::Struct => { | 441 | raw::DefKind::Struct(ast_id) => { |
441 | let s = Struct { id: id!() }.into(); | 442 | let s = def!(Struct, ast_id); |
442 | PerNs::both(s, s) | 443 | PerNs::both(s, s) |
443 | } | 444 | } |
444 | raw::DefKind::Enum => PerNs::types(Enum { id: id!() }.into()), | 445 | raw::DefKind::Enum(ast_id) => PerNs::types(def!(Enum, ast_id)), |
445 | raw::DefKind::Const => PerNs::values(Const { id: id!() }.into()), | 446 | raw::DefKind::Const(ast_id) => PerNs::values(def!(Const, ast_id)), |
446 | raw::DefKind::Static => PerNs::values(Static { id: id!() }.into()), | 447 | raw::DefKind::Static(ast_id) => PerNs::values(def!(Static, ast_id)), |
447 | raw::DefKind::Trait => PerNs::types(Trait { id: id!() }.into()), | 448 | raw::DefKind::Trait(ast_id) => PerNs::types(def!(Trait, ast_id)), |
448 | raw::DefKind::TypeAlias => PerNs::types(TypeAlias { id: id!() }.into()), | 449 | raw::DefKind::TypeAlias(ast_id) => PerNs::types(def!(TypeAlias, ast_id)), |
449 | }; | 450 | }; |
450 | let resolution = Resolution { def, import: None }; | 451 | let resolution = Resolution { def, import: None }; |
451 | self.def_collector.update(self.module_id, None, &[(name, resolution)]) | 452 | self.def_collector.update(self.module_id, None, &[(name, resolution)]) |
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs index 684bd1d50..984478adc 100644 --- a/crates/ra_hir/src/nameres/raw.rs +++ b/crates/ra_hir/src/nameres/raw.rs | |||
@@ -12,7 +12,7 @@ use ra_syntax::{ | |||
12 | 12 | ||
13 | use crate::{ | 13 | use crate::{ |
14 | DefDatabase, Name, AsName, Path, HirFileId, ModuleSource, | 14 | DefDatabase, Name, AsName, Path, HirFileId, ModuleSource, |
15 | SourceFileItemId, SourceFileItems, FileAstId, | 15 | SourceFileItems, FileAstId, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | /// `RawItems` is a set of top-level items in a file (except for impls). | 18 | /// `RawItems` is a set of top-level items in a file (except for impls). |
@@ -138,20 +138,19 @@ impl_arena_id!(Def); | |||
138 | 138 | ||
139 | #[derive(Debug, PartialEq, Eq)] | 139 | #[derive(Debug, PartialEq, Eq)] |
140 | pub(super) struct DefData { | 140 | pub(super) struct DefData { |
141 | pub(super) source_item_id: SourceFileItemId, | ||
142 | pub(super) name: Name, | 141 | pub(super) name: Name, |
143 | pub(super) kind: DefKind, | 142 | pub(super) kind: DefKind, |
144 | } | 143 | } |
145 | 144 | ||
146 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] | 145 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] |
147 | pub(super) enum DefKind { | 146 | pub(super) enum DefKind { |
148 | Function, | 147 | Function(FileAstId<ast::FnDef>), |
149 | Struct, | 148 | Struct(FileAstId<ast::StructDef>), |
150 | Enum, | 149 | Enum(FileAstId<ast::EnumDef>), |
151 | Const, | 150 | Const(FileAstId<ast::ConstDef>), |
152 | Static, | 151 | Static(FileAstId<ast::StaticDef>), |
153 | Trait, | 152 | Trait(FileAstId<ast::TraitDef>), |
154 | TypeAlias, | 153 | TypeAlias(FileAstId<ast::TypeAliasDef>), |
155 | } | 154 | } |
156 | 155 | ||
157 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 156 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -200,18 +199,31 @@ impl RawItemsCollector { | |||
200 | // impls don't participate in name resolution | 199 | // impls don't participate in name resolution |
201 | return; | 200 | return; |
202 | } | 201 | } |
203 | ast::ModuleItemKind::StructDef(it) => (DefKind::Struct, it.name()), | 202 | ast::ModuleItemKind::StructDef(it) => { |
204 | ast::ModuleItemKind::EnumDef(it) => (DefKind::Enum, it.name()), | 203 | (DefKind::Struct(self.source_file_items.ast_id(it)), it.name()) |
205 | ast::ModuleItemKind::FnDef(it) => (DefKind::Function, it.name()), | 204 | } |
206 | ast::ModuleItemKind::TraitDef(it) => (DefKind::Trait, it.name()), | 205 | ast::ModuleItemKind::EnumDef(it) => { |
207 | ast::ModuleItemKind::TypeAliasDef(it) => (DefKind::TypeAlias, it.name()), | 206 | (DefKind::Enum(self.source_file_items.ast_id(it)), it.name()) |
208 | ast::ModuleItemKind::ConstDef(it) => (DefKind::Const, it.name()), | 207 | } |
209 | ast::ModuleItemKind::StaticDef(it) => (DefKind::Static, it.name()), | 208 | ast::ModuleItemKind::FnDef(it) => { |
209 | (DefKind::Function(self.source_file_items.ast_id(it)), it.name()) | ||
210 | } | ||
211 | ast::ModuleItemKind::TraitDef(it) => { | ||
212 | (DefKind::Trait(self.source_file_items.ast_id(it)), it.name()) | ||
213 | } | ||
214 | ast::ModuleItemKind::TypeAliasDef(it) => { | ||
215 | (DefKind::TypeAlias(self.source_file_items.ast_id(it)), it.name()) | ||
216 | } | ||
217 | ast::ModuleItemKind::ConstDef(it) => { | ||
218 | (DefKind::Const(self.source_file_items.ast_id(it)), it.name()) | ||
219 | } | ||
220 | ast::ModuleItemKind::StaticDef(it) => { | ||
221 | (DefKind::Static(self.source_file_items.ast_id(it)), it.name()) | ||
222 | } | ||
210 | }; | 223 | }; |
211 | if let Some(name) = name { | 224 | if let Some(name) = name { |
212 | let name = name.as_name(); | 225 | let name = name.as_name(); |
213 | let source_item_id = self.source_file_items.id_of_unchecked(item.syntax()); | 226 | let def = self.raw_items.defs.alloc(DefData { name, kind }); |
214 | let def = self.raw_items.defs.alloc(DefData { name, kind, source_item_id }); | ||
215 | self.push_item(current_module, RawItem::Def(def)) | 227 | self.push_item(current_module, RawItem::Def(def)) |
216 | } | 228 | } |
217 | } | 229 | } |
diff --git a/crates/ra_hir/src/source_id.rs b/crates/ra_hir/src/source_id.rs index 1dadd76c5..2c855897a 100644 --- a/crates/ra_hir/src/source_id.rs +++ b/crates/ra_hir/src/source_id.rs | |||
@@ -1,11 +1,11 @@ | |||
1 | use std::{marker::PhantomData, sync::Arc}; | 1 | use std::{marker::PhantomData, sync::Arc, hash::{Hash, Hasher}}; |
2 | 2 | ||
3 | use ra_arena::{Arena, RawId, impl_arena_id}; | 3 | use ra_arena::{Arena, RawId, impl_arena_id}; |
4 | use ra_syntax::{SyntaxNodePtr, TreeArc, SyntaxNode, SourceFile, AstNode, ast}; | 4 | use ra_syntax::{SyntaxNodePtr, TreeArc, SyntaxNode, SourceFile, AstNode, ast}; |
5 | 5 | ||
6 | use crate::{HirFileId, DefDatabase}; | 6 | use crate::{HirFileId, DefDatabase}; |
7 | 7 | ||
8 | #[derive(Debug, PartialEq, Eq, Hash)] | 8 | #[derive(Debug)] |
9 | pub(crate) struct AstId<N: AstNode> { | 9 | pub(crate) struct AstId<N: AstNode> { |
10 | file_id: HirFileId, | 10 | file_id: HirFileId, |
11 | file_ast_id: FileAstId<N>, | 11 | file_ast_id: FileAstId<N>, |
@@ -16,9 +16,20 @@ impl<N: AstNode> Clone for AstId<N> { | |||
16 | *self | 16 | *self |
17 | } | 17 | } |
18 | } | 18 | } |
19 | |||
20 | impl<N: AstNode> Copy for AstId<N> {} | 19 | impl<N: AstNode> Copy for AstId<N> {} |
21 | 20 | ||
21 | impl<N: AstNode> PartialEq for AstId<N> { | ||
22 | fn eq(&self, other: &Self) -> bool { | ||
23 | (self.file_id, self.file_ast_id) == (other.file_id, other.file_ast_id) | ||
24 | } | ||
25 | } | ||
26 | impl<N: AstNode> Eq for AstId<N> {} | ||
27 | impl<N: AstNode> Hash for AstId<N> { | ||
28 | fn hash<H: Hasher>(&self, hasher: &mut H) { | ||
29 | (self.file_id, self.file_ast_id).hash(hasher); | ||
30 | } | ||
31 | } | ||
32 | |||
22 | impl<N: AstNode> AstId<N> { | 33 | impl<N: AstNode> AstId<N> { |
23 | pub(crate) fn file_id(&self) -> HirFileId { | 34 | pub(crate) fn file_id(&self) -> HirFileId { |
24 | self.file_id | 35 | self.file_id |
@@ -30,7 +41,7 @@ impl<N: AstNode> AstId<N> { | |||
30 | } | 41 | } |
31 | } | 42 | } |
32 | 43 | ||
33 | #[derive(Debug, PartialEq, Eq, Hash)] | 44 | #[derive(Debug)] |
34 | pub(crate) struct FileAstId<N: AstNode> { | 45 | pub(crate) struct FileAstId<N: AstNode> { |
35 | raw: SourceFileItemId, | 46 | raw: SourceFileItemId, |
36 | _ty: PhantomData<N>, | 47 | _ty: PhantomData<N>, |
@@ -41,9 +52,20 @@ impl<N: AstNode> Clone for FileAstId<N> { | |||
41 | *self | 52 | *self |
42 | } | 53 | } |
43 | } | 54 | } |
44 | |||
45 | impl<N: AstNode> Copy for FileAstId<N> {} | 55 | impl<N: AstNode> Copy for FileAstId<N> {} |
46 | 56 | ||
57 | impl<N: AstNode> PartialEq for FileAstId<N> { | ||
58 | fn eq(&self, other: &Self) -> bool { | ||
59 | self.raw == other.raw | ||
60 | } | ||
61 | } | ||
62 | impl<N: AstNode> Eq for FileAstId<N> {} | ||
63 | impl<N: AstNode> Hash for FileAstId<N> { | ||
64 | fn hash<H: Hasher>(&self, hasher: &mut H) { | ||
65 | self.raw.hash(hasher); | ||
66 | } | ||
67 | } | ||
68 | |||
47 | impl<N: AstNode> FileAstId<N> { | 69 | impl<N: AstNode> FileAstId<N> { |
48 | pub(crate) fn with_file_id(self, file_id: HirFileId) -> AstId<N> { | 70 | pub(crate) fn with_file_id(self, file_id: HirFileId) -> AstId<N> { |
49 | AstId { file_id, file_ast_id: self } | 71 | AstId { file_id, file_ast_id: self } |
@@ -116,14 +138,6 @@ impl SourceFileItems { | |||
116 | fn alloc(&mut self, item: &SyntaxNode) -> SourceFileItemId { | 138 | fn alloc(&mut self, item: &SyntaxNode) -> SourceFileItemId { |
117 | self.arena.alloc(SyntaxNodePtr::new(item)) | 139 | self.arena.alloc(SyntaxNodePtr::new(item)) |
118 | } | 140 | } |
119 | pub(crate) fn id_of(&self, file_id: HirFileId, item: &SyntaxNode) -> SourceFileItemId { | ||
120 | assert_eq!( | ||
121 | self.file_id, file_id, | ||
122 | "SourceFileItems: wrong file, expected {:?}, got {:?}", | ||
123 | self.file_id, file_id | ||
124 | ); | ||
125 | self.id_of_unchecked(item) | ||
126 | } | ||
127 | pub(crate) fn id_of_unchecked(&self, item: &SyntaxNode) -> SourceFileItemId { | 141 | pub(crate) fn id_of_unchecked(&self, item: &SyntaxNode) -> SourceFileItemId { |
128 | let ptr = SyntaxNodePtr::new(item); | 142 | let ptr = SyntaxNodePtr::new(item); |
129 | if let Some((id, _)) = self.arena.iter().find(|(_id, i)| **i == ptr) { | 143 | if let Some((id, _)) = self.arena.iter().find(|(_id, i)| **i == ptr) { |