aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-04-10 08:50:57 +0100
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-04-10 08:50:57 +0100
commit37eb12f2dd6f36570a27b4e4aaf9048860b5a06b (patch)
treef5640991cbf0db2bfdad29b911435827cadfb4a8 /crates/ra_hir
parentb863272899a1bae63c7d9411d0ebff74652bae8e (diff)
parent10726fdb65fda9144a5f9201272d065a268fc1b7 (diff)
Merge #1128
1128: A touch of type-safety r=matklad a=matklad Note that we intentionally don't use `Either` from crates.io: I like A/B naming more then left/rigth, I feel like we might need Either3 with C at some point, and I'd love the ability to write inherent impls Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/code_model_api.rs12
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs14
-rw-r--r--crates/ra_hir/src/either.rs28
-rw-r--r--crates/ra_hir/src/expr.rs28
-rw-r--r--crates/ra_hir/src/expr/scope.rs15
-rw-r--r--crates/ra_hir/src/lib.rs5
-rw-r--r--crates/ra_hir/src/nameres.rs2
-rw-r--r--crates/ra_hir/src/nameres/raw.rs33
-rw-r--r--crates/ra_hir/src/ty/tests.rs2
9 files changed, 74 insertions, 65 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 9e6170440..f13a6b37a 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -4,7 +4,7 @@ use ra_db::{CrateId, SourceRootId, Edition};
4use ra_syntax::{ast::self, TreeArc}; 4use ra_syntax::{ast::self, TreeArc};
5 5
6use crate::{ 6use crate::{
7 Name, ScopesWithSourceMap, Ty, HirFileId, ImportSource, 7 Name, ScopesWithSourceMap, Ty, HirFileId, Either,
8 HirDatabase, DefDatabase, 8 HirDatabase, DefDatabase,
9 type_ref::TypeRef, 9 type_ref::TypeRef,
10 nameres::{ModuleScope, Namespace, ImportId, CrateModuleId}, 10 nameres::{ModuleScope, Namespace, ImportId, CrateModuleId},
@@ -117,8 +117,14 @@ impl Module {
117 } 117 }
118 118
119 /// Returns the syntax of the last path segment corresponding to this import 119 /// Returns the syntax of the last path segment corresponding to this import
120 pub fn import_source(&self, db: &impl HirDatabase, import: ImportId) -> ImportSource { 120 pub fn import_source(
121 self.import_source_impl(db, import) 121 &self,
122 db: &impl HirDatabase,
123 import: ImportId,
124 ) -> Either<TreeArc<ast::UseTree>, TreeArc<ast::ExternCrateItem>> {
125 let (file_id, source) = self.definition_source(db);
126 let (_, source_map) = db.raw_items_with_source_map(file_id);
127 source_map.get(&source, import)
122 } 128 }
123 129
124 /// Returns the crate this module is part of. 130 /// Returns the crate this module is part of.
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index 88dee3a69..5c2ea73ce 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -3,9 +3,9 @@ use ra_syntax::{ast, TreeArc};
3 3
4use crate::{ 4use crate::{
5 Module, ModuleSource, Name, AstId, 5 Module, ModuleSource, Name, AstId,
6 nameres::{CrateModuleId, ImportId}, 6 nameres::CrateModuleId,
7 HirDatabase, DefDatabase, 7 HirDatabase, DefDatabase,
8 HirFileId, ImportSource, 8 HirFileId,
9}; 9};
10 10
11impl ModuleSource { 11impl ModuleSource {
@@ -68,16 +68,6 @@ impl Module {
68 Some((decl.file_id(), ast)) 68 Some((decl.file_id(), ast))
69 } 69 }
70 70
71 pub(crate) fn import_source_impl(
72 &self,
73 db: &impl HirDatabase,
74 import: ImportId,
75 ) -> ImportSource {
76 let (file_id, source) = self.definition_source(db);
77 let (_, source_map) = db.raw_items_with_source_map(file_id);
78 source_map.get(&source, import)
79 }
80
81 pub(crate) fn crate_root_impl(&self, db: &impl DefDatabase) -> Module { 71 pub(crate) fn crate_root_impl(&self, db: &impl DefDatabase) -> Module {
82 let def_map = db.crate_def_map(self.krate); 72 let def_map = db.crate_def_map(self.krate);
83 self.with_module_id(def_map.root()) 73 self.with_module_id(def_map.root())
diff --git a/crates/ra_hir/src/either.rs b/crates/ra_hir/src/either.rs
new file mode 100644
index 000000000..4073cc82e
--- /dev/null
+++ b/crates/ra_hir/src/either.rs
@@ -0,0 +1,28 @@
1#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
2pub enum Either<A, B> {
3 A(A),
4 B(B),
5}
6
7impl<A, B> Either<A, B> {
8 pub fn either<R, F1, F2>(self, f1: F1, f2: F2) -> R
9 where
10 F1: FnOnce(A) -> R,
11 F2: FnOnce(B) -> R,
12 {
13 match self {
14 Either::A(a) => f1(a),
15 Either::B(b) => f2(b),
16 }
17 }
18 pub fn map<U, V, F1, F2>(self, f1: F1, f2: F2) -> Either<U, V>
19 where
20 F1: FnOnce(A) -> U,
21 F2: FnOnce(B) -> V,
22 {
23 match self {
24 Either::A(a) => Either::A(f1(a)),
25 Either::B(b) => Either::B(f2(b)),
26 }
27 }
28}
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 589a9b2db..a2840c15d 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -10,7 +10,7 @@ use ra_syntax::{
10}; 10};
11 11
12use crate::{ 12use crate::{
13 Path, Name, HirDatabase, Resolver,DefWithBody, 13 Path, Name, HirDatabase, Resolver,DefWithBody, Either,
14 name::AsName, 14 name::AsName,
15 type_ref::{Mutability, TypeRef}, 15 type_ref::{Mutability, TypeRef},
16}; 16};
@@ -51,11 +51,13 @@ pub struct Body {
51pub struct BodySourceMap { 51pub struct BodySourceMap {
52 expr_map: FxHashMap<SyntaxNodePtr, ExprId>, 52 expr_map: FxHashMap<SyntaxNodePtr, ExprId>,
53 expr_map_back: ArenaMap<ExprId, SyntaxNodePtr>, 53 expr_map_back: ArenaMap<ExprId, SyntaxNodePtr>,
54 pat_map: FxHashMap<SyntaxNodePtr, PatId>, 54 pat_map: FxHashMap<PatPrr, PatId>,
55 pat_map_back: ArenaMap<PatId, SyntaxNodePtr>, 55 pat_map_back: ArenaMap<PatId, PatPrr>,
56 field_map: FxHashMap<(ExprId, usize), AstPtr<ast::NamedField>>, 56 field_map: FxHashMap<(ExprId, usize), AstPtr<ast::NamedField>>,
57} 57}
58 58
59type PatPrr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
60
59impl Body { 61impl Body {
60 pub fn params(&self) -> &[PatId] { 62 pub fn params(&self) -> &[PatId] {
61 &self.params 63 &self.params
@@ -127,16 +129,16 @@ impl BodySourceMap {
127 self.expr_map.get(&SyntaxNodePtr::new(node.syntax())).cloned() 129 self.expr_map.get(&SyntaxNodePtr::new(node.syntax())).cloned()
128 } 130 }
129 131
130 pub fn pat_syntax(&self, pat: PatId) -> Option<SyntaxNodePtr> { 132 pub fn pat_syntax(&self, pat: PatId) -> Option<PatPrr> {
131 self.pat_map_back.get(pat).cloned() 133 self.pat_map_back.get(pat).cloned()
132 } 134 }
133 135
134 pub fn syntax_pat(&self, ptr: SyntaxNodePtr) -> Option<PatId> { 136 pub fn syntax_pat(&self, ptr: PatPrr) -> Option<PatId> {
135 self.pat_map.get(&ptr).cloned() 137 self.pat_map.get(&ptr).cloned()
136 } 138 }
137 139
138 pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> { 140 pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> {
139 self.pat_map.get(&SyntaxNodePtr::new(node.syntax())).cloned() 141 self.pat_map.get(&Either::A(AstPtr::new(node))).cloned()
140 } 142 }
141 143
142 pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::NamedField> { 144 pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::NamedField> {
@@ -504,10 +506,10 @@ impl ExprCollector {
504 id 506 id
505 } 507 }
506 508
507 fn alloc_pat(&mut self, pat: Pat, syntax_ptr: SyntaxNodePtr) -> PatId { 509 fn alloc_pat(&mut self, pat: Pat, ptr: PatPrr) -> PatId {
508 let id = self.pats.alloc(pat); 510 let id = self.pats.alloc(pat);
509 self.source_map.pat_map.insert(syntax_ptr, id); 511 self.source_map.pat_map.insert(ptr, id);
510 self.source_map.pat_map_back.insert(id, syntax_ptr); 512 self.source_map.pat_map_back.insert(id, ptr);
511 id 513 id
512 } 514 }
513 515
@@ -886,8 +888,8 @@ impl ExprCollector {
886 ast::PatKind::LiteralPat(_) => Pat::Missing, 888 ast::PatKind::LiteralPat(_) => Pat::Missing,
887 ast::PatKind::SlicePat(_) | ast::PatKind::RangePat(_) => Pat::Missing, 889 ast::PatKind::SlicePat(_) | ast::PatKind::RangePat(_) => Pat::Missing,
888 }; 890 };
889 let syntax_ptr = SyntaxNodePtr::new(pat.syntax()); 891 let ptr = AstPtr::new(pat);
890 self.alloc_pat(pattern, syntax_ptr) 892 self.alloc_pat(pattern, Either::A(ptr))
891 } 893 }
892 894
893 fn collect_pat_opt(&mut self, pat: Option<&ast::Pat>) -> PatId { 895 fn collect_pat_opt(&mut self, pat: Option<&ast::Pat>) -> PatId {
@@ -911,14 +913,14 @@ impl ExprCollector {
911 fn collect_fn_body(&mut self, node: &ast::FnDef) { 913 fn collect_fn_body(&mut self, node: &ast::FnDef) {
912 if let Some(param_list) = node.param_list() { 914 if let Some(param_list) = node.param_list() {
913 if let Some(self_param) = param_list.self_param() { 915 if let Some(self_param) = param_list.self_param() {
914 let self_param = SyntaxNodePtr::new(self_param.syntax()); 916 let ptr = AstPtr::new(self_param);
915 let param_pat = self.alloc_pat( 917 let param_pat = self.alloc_pat(
916 Pat::Bind { 918 Pat::Bind {
917 name: Name::self_param(), 919 name: Name::self_param(),
918 mode: BindingAnnotation::Unannotated, 920 mode: BindingAnnotation::Unannotated,
919 subpat: None, 921 subpat: None,
920 }, 922 },
921 self_param, 923 Either::B(ptr),
922 ); 924 );
923 self.params.push(param_pat); 925 self.params.push(param_pat);
924 } 926 }
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs
index f1e6e0f02..725b6c00e 100644
--- a/crates/ra_hir/src/expr/scope.rs
+++ b/crates/ra_hir/src/expr/scope.rs
@@ -3,14 +3,14 @@ use std::sync::Arc;
3use rustc_hash::{FxHashMap, FxHashSet}; 3use rustc_hash::{FxHashMap, FxHashSet};
4 4
5use ra_syntax::{ 5use ra_syntax::{
6 AstNode, SyntaxNode, TextUnit, TextRange, SyntaxNodePtr, 6 AstNode, SyntaxNode, TextUnit, TextRange, SyntaxNodePtr, AstPtr,
7 algo::generate, 7 algo::generate,
8 ast, 8 ast,
9}; 9};
10use ra_arena::{Arena, RawId, impl_arena_id}; 10use ra_arena::{Arena, RawId, impl_arena_id};
11 11
12use crate::{ 12use crate::{
13 Name, AsName,DefWithBody, 13 Name, AsName,DefWithBody, Either,
14 expr::{PatId, ExprId, Pat, Expr, Body, Statement, BodySourceMap}, 14 expr::{PatId, ExprId, Pat, Expr, Body, Statement, BodySourceMap},
15 HirDatabase, 15 HirDatabase,
16}; 16};
@@ -116,7 +116,7 @@ pub struct ScopesWithSourceMap {
116#[derive(Debug, Clone, PartialEq, Eq)] 116#[derive(Debug, Clone, PartialEq, Eq)]
117pub struct ScopeEntryWithSyntax { 117pub struct ScopeEntryWithSyntax {
118 name: Name, 118 name: Name,
119 ptr: SyntaxNodePtr, 119 ptr: Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>,
120} 120}
121 121
122impl ScopeEntryWithSyntax { 122impl ScopeEntryWithSyntax {
@@ -124,7 +124,7 @@ impl ScopeEntryWithSyntax {
124 &self.name 124 &self.name
125 } 125 }
126 126
127 pub fn ptr(&self) -> SyntaxNodePtr { 127 pub fn ptr(&self) -> Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>> {
128 self.ptr 128 self.ptr
129 } 129 }
130} 130}
@@ -192,14 +192,14 @@ impl ScopesWithSourceMap {
192 192
193 pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> { 193 pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> {
194 let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); 194 let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap();
195 let name_ptr = SyntaxNodePtr::new(pat.syntax()); 195 let ptr = Either::A(AstPtr::new(pat.into()));
196 fn_def 196 fn_def
197 .syntax() 197 .syntax()
198 .descendants() 198 .descendants()
199 .filter_map(ast::NameRef::cast) 199 .filter_map(ast::NameRef::cast)
200 .filter(|name_ref| match self.resolve_local_name(*name_ref) { 200 .filter(|name_ref| match self.resolve_local_name(*name_ref) {
201 None => false, 201 None => false,
202 Some(entry) => entry.ptr() == name_ptr, 202 Some(entry) => entry.ptr() == ptr,
203 }) 203 })
204 .map(|name_ref| ReferenceDescriptor { 204 .map(|name_ref| ReferenceDescriptor {
205 name: name_ref.syntax().text().to_string(), 205 name: name_ref.syntax().text().to_string(),
@@ -429,7 +429,8 @@ mod tests {
429 let scopes = 429 let scopes =
430 ScopesWithSourceMap { scopes: Arc::new(scopes), source_map: Arc::new(source_map) }; 430 ScopesWithSourceMap { scopes: Arc::new(scopes), source_map: Arc::new(source_map) };
431 let local_name_entry = scopes.resolve_local_name(name_ref).unwrap(); 431 let local_name_entry = scopes.resolve_local_name(name_ref).unwrap();
432 let local_name = local_name_entry.ptr(); 432 let local_name =
433 local_name_entry.ptr().either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr());
433 assert_eq!(local_name.range(), expected_name.syntax().range()); 434 assert_eq!(local_name.range(), expected_name.syntax().range());
434 } 435 }
435 436
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 4d337d2e3..0881939a2 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -17,6 +17,8 @@ macro_rules! impl_froms {
17 } 17 }
18} 18}
19 19
20mod either;
21
20pub mod db; 22pub mod db;
21#[macro_use] 23#[macro_use]
22pub mod mock; 24pub mod mock;
@@ -52,11 +54,12 @@ use crate::{
52}; 54};
53 55
54pub use self::{ 56pub use self::{
57 either::Either,
55 path::{Path, PathKind}, 58 path::{Path, PathKind},
56 name::Name, 59 name::Name,
57 source_id::{AstIdMap, ErasedFileAstId}, 60 source_id::{AstIdMap, ErasedFileAstId},
58 ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc}, 61 ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc},
59 nameres::{PerNs, Namespace, ImportId, ImportSource}, 62 nameres::{PerNs, Namespace, ImportId},
60 ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay}, 63 ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay},
61 impl_block::{ImplBlock, ImplItem}, 64 impl_block::{ImplBlock, ImplItem},
62 docs::{Docs, Documentation}, 65 docs::{Docs, Documentation},
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 4ae04514a..0eddfab12 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -75,7 +75,7 @@ pub(crate) use self::raw::{RawItems, ImportSourceMap};
75 75
76pub use self::{ 76pub use self::{
77 per_ns::{PerNs, Namespace}, 77 per_ns::{PerNs, Namespace},
78 raw::{ImportId, ImportSource}, 78 raw::ImportId,
79}; 79};
80 80
81/// Contans all top-level defs from a macro-expanded crate 81/// Contans all top-level defs from a macro-expanded crate
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs
index b7416ede6..43c97a0bf 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
13use crate::{ 13use crate::{
14 DefDatabase, Name, AsName, Path, HirFileId, ModuleSource, 14 DefDatabase, Name, AsName, Path, HirFileId, ModuleSource,
15 AstIdMap, FileAstId, 15 AstIdMap, FileAstId, Either,
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).
@@ -34,28 +34,15 @@ pub struct ImportSourceMap {
34 map: ArenaMap<ImportId, ImportSourcePtr>, 34 map: ArenaMap<ImportId, ImportSourcePtr>,
35} 35}
36 36
37#[derive(Debug, PartialEq, Eq, Clone, Copy)] 37type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>;
38enum ImportSourcePtr { 38type ImportSource = Either<TreeArc<ast::UseTree>, TreeArc<ast::ExternCrateItem>>;
39 UseTree(AstPtr<ast::UseTree>),
40 ExternCrate(AstPtr<ast::ExternCrateItem>),
41}
42 39
43impl ImportSourcePtr { 40impl ImportSourcePtr {
44 fn to_node(self, file: &SourceFile) -> ImportSource { 41 fn to_node(self, file: &SourceFile) -> ImportSource {
45 match self { 42 self.map(|ptr| ptr.to_node(file).to_owned(), |ptr| ptr.to_node(file).to_owned())
46 ImportSourcePtr::UseTree(ptr) => ImportSource::UseTree(ptr.to_node(file).to_owned()),
47 ImportSourcePtr::ExternCrate(ptr) => {
48 ImportSource::ExternCrate(ptr.to_node(file).to_owned())
49 }
50 }
51 } 43 }
52} 44}
53 45
54pub enum ImportSource {
55 UseTree(TreeArc<ast::UseTree>),
56 ExternCrate(TreeArc<ast::ExternCrateItem>),
57}
58
59impl ImportSourceMap { 46impl ImportSourceMap {
60 fn insert(&mut self, import: ImportId, ptr: ImportSourcePtr) { 47 fn insert(&mut self, import: ImportId, ptr: ImportSourcePtr) {
61 self.map.insert(import, ptr) 48 self.map.insert(import, ptr)
@@ -281,11 +268,7 @@ impl RawItemsCollector {
281 Path::expand_use_item(use_item, |path, use_tree, is_glob, alias| { 268 Path::expand_use_item(use_item, |path, use_tree, is_glob, alias| {
282 let import_data = 269 let import_data =
283 ImportData { path, alias, is_glob, is_prelude, is_extern_crate: false }; 270 ImportData { path, alias, is_glob, is_prelude, is_extern_crate: false };
284 self.push_import( 271 self.push_import(current_module, import_data, Either::A(AstPtr::new(use_tree)));
285 current_module,
286 import_data,
287 ImportSourcePtr::UseTree(AstPtr::new(use_tree)),
288 );
289 }) 272 })
290 } 273 }
291 274
@@ -304,11 +287,7 @@ impl RawItemsCollector {
304 is_prelude: false, 287 is_prelude: false,
305 is_extern_crate: true, 288 is_extern_crate: true,
306 }; 289 };
307 self.push_import( 290 self.push_import(current_module, import_data, Either::B(AstPtr::new(extern_crate)));
308 current_module,
309 import_data,
310 ImportSourcePtr::ExternCrate(AstPtr::new(extern_crate)),
311 );
312 } 291 }
313 } 292 }
314 293
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index f6a325033..ecc63f376 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -2324,7 +2324,7 @@ fn infer(content: &str) -> String {
2324 2324
2325 for (pat, ty) in inference_result.type_of_pat.iter() { 2325 for (pat, ty) in inference_result.type_of_pat.iter() {
2326 let syntax_ptr = match body_source_map.pat_syntax(pat) { 2326 let syntax_ptr = match body_source_map.pat_syntax(pat) {
2327 Some(sp) => sp, 2327 Some(sp) => sp.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()),
2328 None => continue, 2328 None => continue,
2329 }; 2329 };
2330 types.push((syntax_ptr, ty)); 2330 types.push((syntax_ptr, ty));