diff options
author | Florian Diebold <[email protected]> | 2019-01-26 21:52:04 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-02-01 21:45:23 +0000 |
commit | 6b076f1931d7dc324d7bbbc4c1df9f7c1c1db8b7 (patch) | |
tree | 131f12f5b0c9ea0ea499b8d4e9ff0c5112192352 /crates/ra_hir/src/resolve.rs | |
parent | 758bc72873efe36f579236d1abf240d14866fd82 (diff) |
Use new Resolver API in type inference
Diffstat (limited to 'crates/ra_hir/src/resolve.rs')
-rw-r--r-- | crates/ra_hir/src/resolve.rs | 116 |
1 files changed, 82 insertions, 34 deletions
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index b7fbf6df2..36daed65b 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs | |||
@@ -1,30 +1,29 @@ | |||
1 | #![allow(unused_variables, dead_code)] | ||
2 | //! Name resolution. | 1 | //! Name resolution. |
3 | use std::sync::Arc; | 2 | use std::sync::Arc; |
4 | 3 | ||
5 | use rustc_hash::FxHashMap; | 4 | use rustc_hash::FxHashMap; |
6 | 5 | ||
7 | use crate::{ | 6 | use crate::{ |
8 | ModuleDef, | 7 | ModuleDef, Module, |
9 | name::Name, | 8 | db::HirDatabase, |
10 | nameres::{PerNs, lower::ImportId, ItemMap}, | 9 | name::{Name, KnownName}, |
11 | module_tree::ModuleId, | 10 | nameres::{PerNs, ItemMap}, |
12 | generics::GenericParams, | 11 | generics::GenericParams, |
13 | expr::{Body, scope::{ExprScopes, ScopeId}, PatId}, | 12 | expr::{scope::{ExprScopes, ScopeId}, PatId}, |
14 | impl_block::ImplBlock, | 13 | impl_block::ImplBlock, |
15 | path::Path, | 14 | path::Path, |
16 | }; | 15 | }; |
17 | 16 | ||
18 | #[derive(Debug, Clone, Default)] | 17 | #[derive(Debug, Clone, Default)] |
19 | pub struct Resolver { | 18 | pub struct Resolver { |
20 | scopes: Vec<Scope>, // maybe a 'linked list' of scopes? or allow linking a Resolver to a parent Resolver? that's an optimization that might not be necessary, though | 19 | scopes: Vec<Scope>, |
21 | } | 20 | } |
22 | 21 | ||
23 | // TODO how to store these best | 22 | // TODO how to store these best |
24 | #[derive(Debug, Clone)] | 23 | #[derive(Debug, Clone)] |
25 | pub(crate) struct ModuleItemMap { | 24 | pub(crate) struct ModuleItemMap { |
26 | item_map: Arc<ItemMap>, | 25 | item_map: Arc<ItemMap>, |
27 | module_id: ModuleId, | 26 | module: Module, |
28 | } | 27 | } |
29 | 28 | ||
30 | #[derive(Debug, Clone)] | 29 | #[derive(Debug, Clone)] |
@@ -39,8 +38,6 @@ pub(crate) enum Scope { | |||
39 | ModuleScope(ModuleItemMap), | 38 | ModuleScope(ModuleItemMap), |
40 | /// Brings the generic parameters of an item into scope | 39 | /// Brings the generic parameters of an item into scope |
41 | GenericParams(Arc<GenericParams>), | 40 | GenericParams(Arc<GenericParams>), |
42 | /// Brings the function parameters into scope | ||
43 | FunctionParams(Arc<Body>), | ||
44 | /// Brings `Self` into scope | 41 | /// Brings `Self` into scope |
45 | ImplBlockScope(ImplBlock), | 42 | ImplBlockScope(ImplBlock), |
46 | /// Local bindings | 43 | /// Local bindings |
@@ -49,36 +46,64 @@ pub(crate) enum Scope { | |||
49 | 46 | ||
50 | #[derive(Debug, Clone, PartialEq, Eq)] | 47 | #[derive(Debug, Clone, PartialEq, Eq)] |
51 | pub enum Resolution { | 48 | pub enum Resolution { |
49 | // FIXME make these tuple variants | ||
52 | /// An item | 50 | /// An item |
53 | Def { | 51 | Def { |
54 | def: ModuleDef, | 52 | def: ModuleDef, |
55 | import: Option<ImportId>, | ||
56 | }, | 53 | }, |
57 | /// A local binding (only value namespace) | 54 | /// A local binding (only value namespace) |
58 | LocalBinding { pat: PatId }, | 55 | LocalBinding { |
56 | pat: PatId, | ||
57 | }, | ||
59 | /// A generic parameter | 58 | /// A generic parameter |
60 | GenericParam { idx: u32 }, | 59 | GenericParam { |
61 | // TODO how does `Self` resolve? | 60 | idx: u32, |
61 | }, | ||
62 | SelfType(ImplBlock), | ||
62 | } | 63 | } |
63 | 64 | ||
64 | impl Resolver { | 65 | impl Resolver { |
65 | pub fn resolve_name(&self, name: &Name) -> PerNs<Resolution> { | 66 | pub fn resolve_name(&self, name: &Name) -> PerNs<Resolution> { |
67 | let mut resolution = PerNs::none(); | ||
66 | for scope in self.scopes.iter().rev() { | 68 | for scope in self.scopes.iter().rev() { |
67 | let resolution = scope.resolve_name(name); | 69 | resolution = resolution.combine(scope.resolve_name(name)); |
68 | if !resolution.is_none() { | 70 | if resolution.is_both() { |
69 | return resolution; | 71 | return resolution; |
70 | } | 72 | } |
71 | } | 73 | } |
72 | PerNs::none() | 74 | resolution |
73 | } | 75 | } |
74 | 76 | ||
75 | pub fn resolve_path(&self, path: &Path) -> PerNs<Resolution> { | 77 | pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs<Resolution> { |
76 | unimplemented!() | 78 | if let Some(name) = path.as_ident() { |
79 | self.resolve_name(name) | ||
80 | } else if path.is_self() { | ||
81 | self.resolve_name(&Name::self_param()) | ||
82 | } else { | ||
83 | let (item_map, module) = match self.module() { | ||
84 | Some(m) => m, | ||
85 | _ => return PerNs::none(), | ||
86 | }; | ||
87 | let module_res = item_map.resolve_path(db, module, path); | ||
88 | module_res.map(|def| Resolution::Def { def }) | ||
89 | } | ||
77 | } | 90 | } |
78 | 91 | ||
79 | pub fn all_names(&self) -> FxHashMap<Name, Resolution> { | 92 | pub fn all_names(&self) -> FxHashMap<Name, Resolution> { |
80 | unimplemented!() | 93 | unimplemented!() |
81 | } | 94 | } |
95 | |||
96 | fn module(&self) -> Option<(&ItemMap, Module)> { | ||
97 | for scope in self.scopes.iter().rev() { | ||
98 | match scope { | ||
99 | Scope::ModuleScope(m) => { | ||
100 | return Some((&m.item_map, m.module.clone())); | ||
101 | } | ||
102 | _ => {} | ||
103 | } | ||
104 | } | ||
105 | None | ||
106 | } | ||
82 | } | 107 | } |
83 | 108 | ||
84 | impl Resolver { | 109 | impl Resolver { |
@@ -95,11 +120,8 @@ impl Resolver { | |||
95 | self.push_scope(Scope::ImplBlockScope(impl_block)) | 120 | self.push_scope(Scope::ImplBlockScope(impl_block)) |
96 | } | 121 | } |
97 | 122 | ||
98 | pub(crate) fn push_module_scope(self, item_map: Arc<ItemMap>, module_id: ModuleId) -> Resolver { | 123 | pub(crate) fn push_module_scope(self, item_map: Arc<ItemMap>, module: Module) -> Resolver { |
99 | self.push_scope(Scope::ModuleScope(ModuleItemMap { | 124 | self.push_scope(Scope::ModuleScope(ModuleItemMap { item_map, module })) |
100 | item_map, | ||
101 | module_id, | ||
102 | })) | ||
103 | } | 125 | } |
104 | 126 | ||
105 | pub(crate) fn push_expr_scope( | 127 | pub(crate) fn push_expr_scope( |
@@ -112,19 +134,45 @@ impl Resolver { | |||
112 | scope_id, | 134 | scope_id, |
113 | })) | 135 | })) |
114 | } | 136 | } |
115 | |||
116 | pub(crate) fn push_function_params(self, body: Arc<Body>) -> Resolver { | ||
117 | self.push_scope(Scope::FunctionParams(body)) | ||
118 | } | ||
119 | |||
120 | pub(crate) fn pop_scope(mut self) -> Resolver { | ||
121 | self.scopes.pop(); | ||
122 | self | ||
123 | } | ||
124 | } | 137 | } |
125 | 138 | ||
126 | impl Scope { | 139 | impl Scope { |
127 | fn resolve_name(&self, name: &Name) -> PerNs<Resolution> { | 140 | fn resolve_name(&self, name: &Name) -> PerNs<Resolution> { |
128 | unimplemented!() | 141 | match self { |
142 | Scope::ModuleScope(m) => { | ||
143 | if let Some(KnownName::SelfParam) = name.as_known_name() { | ||
144 | PerNs::types(Resolution::Def { | ||
145 | def: m.module.into(), | ||
146 | }) | ||
147 | } else { | ||
148 | match m.item_map[m.module.module_id].get(name) { | ||
149 | Some(res) => res.def.map(|def| Resolution::Def { def }), | ||
150 | None => PerNs::none(), | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | Scope::GenericParams(gp) => match gp.find_by_name(name) { | ||
155 | Some(gp) => PerNs::types(Resolution::GenericParam { idx: gp.idx }), | ||
156 | None => PerNs::none(), | ||
157 | }, | ||
158 | Scope::ImplBlockScope(i) => { | ||
159 | if name.as_known_name() == Some(KnownName::SelfType) { | ||
160 | PerNs::types(Resolution::SelfType(i.clone())) | ||
161 | } else { | ||
162 | PerNs::none() | ||
163 | } | ||
164 | } | ||
165 | Scope::ExprScope(e) => { | ||
166 | let entry = e | ||
167 | .expr_scopes | ||
168 | .entries(e.scope_id) | ||
169 | .iter() | ||
170 | .find(|entry| entry.name() == name); | ||
171 | match entry { | ||
172 | Some(e) => PerNs::values(Resolution::LocalBinding { pat: e.pat() }), | ||
173 | None => PerNs::none(), | ||
174 | } | ||
175 | } | ||
176 | } | ||
129 | } | 177 | } |
130 | } | 178 | } |