aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_arena/src/lib.rs2
-rw-r--r--crates/ra_arena/src/map.rs70
-rw-r--r--crates/ra_hir/src/expr.rs18
-rw-r--r--crates/ra_hir/src/ty.rs24
-rw-r--r--crates/ra_hir/src/ty/tests.rs8
5 files changed, 97 insertions, 25 deletions
diff --git a/crates/ra_arena/src/lib.rs b/crates/ra_arena/src/lib.rs
index a5eeb4118..040977dc4 100644
--- a/crates/ra_arena/src/lib.rs
+++ b/crates/ra_arena/src/lib.rs
@@ -6,6 +6,8 @@ use std::{
6 ops::{Index, IndexMut}, 6 ops::{Index, IndexMut},
7}; 7};
8 8
9pub mod map;
10
9#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 11#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub struct RawId(u32); 12pub struct RawId(u32);
11 13
diff --git a/crates/ra_arena/src/map.rs b/crates/ra_arena/src/map.rs
new file mode 100644
index 000000000..2f09d677f
--- /dev/null
+++ b/crates/ra_arena/src/map.rs
@@ -0,0 +1,70 @@
1//! A map from arena IDs to some other type. Space requirement is O(highest ID).
2
3use std::marker::PhantomData;
4
5use super::ArenaId;
6
7/// A map from arena IDs to some other type. Space requirement is O(highest ID).
8#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
9pub struct ArenaMap<ID, T> {
10 v: Vec<Option<T>>,
11 _ty: PhantomData<ID>,
12}
13
14impl<ID: ArenaId, T> ArenaMap<ID, T> {
15 pub fn insert(&mut self, id: ID, t: T) {
16 let idx = Self::to_idx(id);
17 if self.v.capacity() <= idx {
18 self.v.reserve(idx + 1 - self.v.capacity());
19 }
20 if self.v.len() <= idx {
21 while self.v.len() <= idx {
22 self.v.push(None);
23 }
24 }
25 self.v[idx] = Some(t);
26 }
27
28 pub fn get(&self, id: ID) -> Option<&T> {
29 self.v.get(Self::to_idx(id)).and_then(|it| it.as_ref())
30 }
31
32 pub fn values(&self) -> impl Iterator<Item = &T> {
33 self.v.iter().filter_map(|o| o.as_ref())
34 }
35
36 pub fn values_mut(&mut self) -> impl Iterator<Item = &mut T> {
37 self.v.iter_mut().filter_map(|o| o.as_mut())
38 }
39
40 pub fn iter(&self) -> impl Iterator<Item = (ID, &T)> {
41 self.v
42 .iter()
43 .enumerate()
44 .filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_ref()?)))
45 }
46
47 fn to_idx(id: ID) -> usize {
48 u32::from(id.into_raw()) as usize
49 }
50
51 fn from_idx(idx: usize) -> ID {
52 ID::from_raw((idx as u32).into())
53 }
54}
55
56impl<ID: ArenaId, T> std::ops::Index<ID> for ArenaMap<ID, T> {
57 type Output = T;
58 fn index(&self, id: ID) -> &T {
59 self.v[Self::to_idx(id)].as_ref().unwrap()
60 }
61}
62
63impl<ID, T> Default for ArenaMap<ID, T> {
64 fn default() -> Self {
65 ArenaMap {
66 v: Vec::new(),
67 _ty: PhantomData,
68 }
69 }
70}
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index c87d76735..69144e94f 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -3,7 +3,7 @@ use std::sync::Arc;
3 3
4use rustc_hash::FxHashMap; 4use rustc_hash::FxHashMap;
5 5
6use ra_arena::{Arena, RawId, impl_arena_id}; 6use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
7use ra_db::{LocalSyntaxPtr, Cancelable}; 7use ra_db::{LocalSyntaxPtr, Cancelable};
8use ra_syntax::{SyntaxNodeRef, ast::{self, AstNode, LoopBodyOwner, ArgListOwner, NameOwner}}; 8use ra_syntax::{SyntaxNodeRef, ast::{self, AstNode, LoopBodyOwner, ArgListOwner, NameOwner}};
9 9
@@ -39,9 +39,9 @@ pub struct Body {
39pub struct BodySyntaxMapping { 39pub struct BodySyntaxMapping {
40 body: Arc<Body>, 40 body: Arc<Body>,
41 expr_syntax_mapping: FxHashMap<LocalSyntaxPtr, ExprId>, 41 expr_syntax_mapping: FxHashMap<LocalSyntaxPtr, ExprId>,
42 expr_syntax_mapping_back: FxHashMap<ExprId, LocalSyntaxPtr>, 42 expr_syntax_mapping_back: ArenaMap<ExprId, LocalSyntaxPtr>,
43 pat_syntax_mapping: FxHashMap<LocalSyntaxPtr, PatId>, 43 pat_syntax_mapping: FxHashMap<LocalSyntaxPtr, PatId>,
44 pat_syntax_mapping_back: FxHashMap<PatId, LocalSyntaxPtr>, 44 pat_syntax_mapping_back: ArenaMap<PatId, LocalSyntaxPtr>,
45} 45}
46 46
47impl Body { 47impl Body {
@@ -72,7 +72,7 @@ impl Index<PatId> for Body {
72 72
73impl BodySyntaxMapping { 73impl BodySyntaxMapping {
74 pub fn expr_syntax(&self, expr: ExprId) -> Option<LocalSyntaxPtr> { 74 pub fn expr_syntax(&self, expr: ExprId) -> Option<LocalSyntaxPtr> {
75 self.expr_syntax_mapping_back.get(&expr).cloned() 75 self.expr_syntax_mapping_back.get(expr).cloned()
76 } 76 }
77 pub fn syntax_expr(&self, ptr: LocalSyntaxPtr) -> Option<ExprId> { 77 pub fn syntax_expr(&self, ptr: LocalSyntaxPtr) -> Option<ExprId> {
78 self.expr_syntax_mapping.get(&ptr).cloned() 78 self.expr_syntax_mapping.get(&ptr).cloned()
@@ -83,7 +83,7 @@ impl BodySyntaxMapping {
83 .cloned() 83 .cloned()
84 } 84 }
85 pub fn pat_syntax(&self, pat: PatId) -> Option<LocalSyntaxPtr> { 85 pub fn pat_syntax(&self, pat: PatId) -> Option<LocalSyntaxPtr> {
86 self.pat_syntax_mapping_back.get(&pat).cloned() 86 self.pat_syntax_mapping_back.get(pat).cloned()
87 } 87 }
88 pub fn syntax_pat(&self, ptr: LocalSyntaxPtr) -> Option<PatId> { 88 pub fn syntax_pat(&self, ptr: LocalSyntaxPtr) -> Option<PatId> {
89 self.pat_syntax_mapping.get(&ptr).cloned() 89 self.pat_syntax_mapping.get(&ptr).cloned()
@@ -334,9 +334,9 @@ struct ExprCollector {
334 exprs: Arena<ExprId, Expr>, 334 exprs: Arena<ExprId, Expr>,
335 pats: Arena<PatId, Pat>, 335 pats: Arena<PatId, Pat>,
336 expr_syntax_mapping: FxHashMap<LocalSyntaxPtr, ExprId>, 336 expr_syntax_mapping: FxHashMap<LocalSyntaxPtr, ExprId>,
337 expr_syntax_mapping_back: FxHashMap<ExprId, LocalSyntaxPtr>, 337 expr_syntax_mapping_back: ArenaMap<ExprId, LocalSyntaxPtr>,
338 pat_syntax_mapping: FxHashMap<LocalSyntaxPtr, PatId>, 338 pat_syntax_mapping: FxHashMap<LocalSyntaxPtr, PatId>,
339 pat_syntax_mapping_back: FxHashMap<PatId, LocalSyntaxPtr>, 339 pat_syntax_mapping_back: ArenaMap<PatId, LocalSyntaxPtr>,
340} 340}
341 341
342impl ExprCollector { 342impl ExprCollector {
@@ -345,9 +345,9 @@ impl ExprCollector {
345 exprs: Arena::default(), 345 exprs: Arena::default(),
346 pats: Arena::default(), 346 pats: Arena::default(),
347 expr_syntax_mapping: FxHashMap::default(), 347 expr_syntax_mapping: FxHashMap::default(),
348 expr_syntax_mapping_back: FxHashMap::default(), 348 expr_syntax_mapping_back: ArenaMap::default(),
349 pat_syntax_mapping: FxHashMap::default(), 349 pat_syntax_mapping: FxHashMap::default(),
350 pat_syntax_mapping_back: FxHashMap::default(), 350 pat_syntax_mapping_back: ArenaMap::default(),
351 } 351 }
352 } 352 }
353 353
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 6bdfdd7b4..d57990cd2 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -22,8 +22,8 @@ use std::sync::Arc;
22use std::{fmt, mem}; 22use std::{fmt, mem};
23 23
24use log; 24use log;
25use rustc_hash::FxHashMap;
26use ena::unify::{InPlaceUnificationTable, UnifyKey, UnifyValue, NoError}; 25use ena::unify::{InPlaceUnificationTable, UnifyKey, UnifyValue, NoError};
26use ra_arena::map::ArenaMap;
27 27
28use ra_db::Cancelable; 28use ra_db::Cancelable;
29 29
@@ -470,15 +470,15 @@ pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name)
470/// The result of type inference: A mapping from expressions and patterns to types. 470/// The result of type inference: A mapping from expressions and patterns to types.
471#[derive(Clone, PartialEq, Eq, Debug)] 471#[derive(Clone, PartialEq, Eq, Debug)]
472pub struct InferenceResult { 472pub struct InferenceResult {
473 type_of_expr: FxHashMap<ExprId, Ty>, 473 type_of_expr: ArenaMap<ExprId, Ty>,
474 type_of_pat: FxHashMap<PatId, Ty>, 474 type_of_pat: ArenaMap<PatId, Ty>,
475} 475}
476 476
477impl Index<ExprId> for InferenceResult { 477impl Index<ExprId> for InferenceResult {
478 type Output = Ty; 478 type Output = Ty;
479 479
480 fn index(&self, expr: ExprId) -> &Ty { 480 fn index(&self, expr: ExprId) -> &Ty {
481 self.type_of_expr.get(&expr).unwrap_or(&Ty::Unknown) 481 self.type_of_expr.get(expr).unwrap_or(&Ty::Unknown)
482 } 482 }
483} 483}
484 484
@@ -486,7 +486,7 @@ impl Index<PatId> for InferenceResult {
486 type Output = Ty; 486 type Output = Ty;
487 487
488 fn index(&self, pat: PatId) -> &Ty { 488 fn index(&self, pat: PatId) -> &Ty {
489 self.type_of_pat.get(&pat).unwrap_or(&Ty::Unknown) 489 self.type_of_pat.get(pat).unwrap_or(&Ty::Unknown)
490 } 490 }
491} 491}
492 492
@@ -499,8 +499,8 @@ struct InferenceContext<'a, D: HirDatabase> {
499 module: Module, 499 module: Module,
500 impl_block: Option<ImplBlock>, 500 impl_block: Option<ImplBlock>,
501 var_unification_table: InPlaceUnificationTable<TypeVarId>, 501 var_unification_table: InPlaceUnificationTable<TypeVarId>,
502 type_of_expr: FxHashMap<ExprId, Ty>, 502 type_of_expr: ArenaMap<ExprId, Ty>,
503 type_of_pat: FxHashMap<PatId, Ty>, 503 type_of_pat: ArenaMap<PatId, Ty>,
504 /// The return type of the function being inferred. 504 /// The return type of the function being inferred.
505 return_ty: Ty, 505 return_ty: Ty,
506} 506}
@@ -528,8 +528,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
528 impl_block: Option<ImplBlock>, 528 impl_block: Option<ImplBlock>,
529 ) -> Self { 529 ) -> Self {
530 InferenceContext { 530 InferenceContext {
531 type_of_expr: FxHashMap::default(), 531 type_of_expr: ArenaMap::default(),
532 type_of_pat: FxHashMap::default(), 532 type_of_pat: ArenaMap::default(),
533 var_unification_table: InPlaceUnificationTable::new(), 533 var_unification_table: InPlaceUnificationTable::new(),
534 return_ty: Ty::Unknown, // set in collect_fn_signature 534 return_ty: Ty::Unknown, // set in collect_fn_signature
535 db, 535 db,
@@ -541,12 +541,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
541 } 541 }
542 542
543 fn resolve_all(mut self) -> InferenceResult { 543 fn resolve_all(mut self) -> InferenceResult {
544 let mut expr_types = mem::replace(&mut self.type_of_expr, FxHashMap::default()); 544 let mut expr_types = mem::replace(&mut self.type_of_expr, ArenaMap::default());
545 for ty in expr_types.values_mut() { 545 for ty in expr_types.values_mut() {
546 let resolved = self.resolve_ty_completely(mem::replace(ty, Ty::Unknown)); 546 let resolved = self.resolve_ty_completely(mem::replace(ty, Ty::Unknown));
547 *ty = resolved; 547 *ty = resolved;
548 } 548 }
549 let mut pat_types = mem::replace(&mut self.type_of_pat, FxHashMap::default()); 549 let mut pat_types = mem::replace(&mut self.type_of_pat, ArenaMap::default());
550 for ty in pat_types.values_mut() { 550 for ty in pat_types.values_mut() {
551 let resolved = self.resolve_ty_completely(mem::replace(ty, Ty::Unknown)); 551 let resolved = self.resolve_ty_completely(mem::replace(ty, Ty::Unknown));
552 *ty = resolved; 552 *ty = resolved;
@@ -666,7 +666,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
666 // resolve locally 666 // resolve locally
667 let name = path.as_ident().cloned().unwrap_or_else(Name::self_param); 667 let name = path.as_ident().cloned().unwrap_or_else(Name::self_param);
668 if let Some(scope_entry) = self.scopes.resolve_local_name(expr, name) { 668 if let Some(scope_entry) = self.scopes.resolve_local_name(expr, name) {
669 let ty = ctry!(self.type_of_pat.get(&scope_entry.pat())); 669 let ty = ctry!(self.type_of_pat.get(scope_entry.pat()));
670 let ty = self.resolve_ty_as_possible(ty.clone()); 670 let ty = self.resolve_ty_as_possible(ty.clone());
671 return Ok(Some(ty)); 671 return Ok(Some(ty));
672 }; 672 };
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 20fb783b8..030a20f1b 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -195,16 +195,16 @@ fn infer(content: &str) -> String {
195 let inference_result = func.infer(&db).unwrap(); 195 let inference_result = func.infer(&db).unwrap();
196 let body_syntax_mapping = func.body_syntax_mapping(&db).unwrap(); 196 let body_syntax_mapping = func.body_syntax_mapping(&db).unwrap();
197 let mut types = Vec::new(); 197 let mut types = Vec::new();
198 for (pat, ty) in &inference_result.type_of_pat { 198 for (pat, ty) in inference_result.type_of_pat.iter() {
199 let syntax_ptr = if let Some(sp) = body_syntax_mapping.pat_syntax(*pat) { 199 let syntax_ptr = if let Some(sp) = body_syntax_mapping.pat_syntax(pat) {
200 sp 200 sp
201 } else { 201 } else {
202 continue; 202 continue;
203 }; 203 };
204 types.push((syntax_ptr, ty)); 204 types.push((syntax_ptr, ty));
205 } 205 }
206 for (expr, ty) in &inference_result.type_of_expr { 206 for (expr, ty) in inference_result.type_of_expr.iter() {
207 let syntax_ptr = if let Some(sp) = body_syntax_mapping.expr_syntax(*expr) { 207 let syntax_ptr = if let Some(sp) = body_syntax_mapping.expr_syntax(expr) {
208 sp 208 sp
209 } else { 209 } else {
210 continue; 210 continue;